// // QXGiftPlayer.m // QXLive // // Created by 启星 on 2025/5/8. // #import "QXGiftPlayerManager.h" #import "QXEffectSvgaView.h" #import "QXFileManager.h" @interface QXGiftPlayerManager() @property (nonatomic,strong) UIView *bgEffectView; // 礼物、坐骑【全屏位置】特效 @property (nonatomic,strong) QXEffectContentView *fullEffectView; // 坐骑【公屏信息流位置】特效 @property (nonatomic,strong) QXEffectContentView *chatEffectView; @end @implementation QXGiftPlayerManager + (instancetype)shareManager{ static QXGiftPlayerManager *manager; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[QXGiftPlayerManager alloc] init]; }); return manager; } - (UIView *)defaultBgEffectView { return self.bgEffectView; } /// 礼物、坐骑【全屏位置】特效 - (QXEffectContentView *)defaultFullEffectView { return self.fullEffectView; } /// 坐骑【公屏信息流位置】特效 - (QXEffectContentView *)defaultChatEffectView { return self.chatEffectView; } - (void)displayFullEffectView:(QXGiftModel *)gift { [self.fullEffectView displayEffectView:gift]; } - (void)displayChatEffectView:(QXGiftModel *)gift { [self.chatEffectView displayEffectView:gift]; } /// 关闭打开动效 - (void)openOrCloseEffectViewWith:(BOOL)isShow { [self.fullEffectView openOrCloseEffectViewWith:isShow]; [self.chatEffectView openOrCloseEffectViewWith:isShow]; } /// 销毁 - (void)destroyEffectSvga { [self.fullEffectView destroyEffectView]; [self.chatEffectView destroyEffectView]; [self.fullEffectView removeFromSuperview]; [self.chatEffectView removeFromSuperview]; [self.bgEffectView removeFromSuperview]; _fullEffectView = nil; _chatEffectView = nil; _bgEffectView = nil; } -(void)stopPlay{ [self.fullEffectView stopPlay]; [self.chatEffectView stopPlay]; } - (UIView *)bgEffectView { if (!_bgEffectView) { _bgEffectView = [[UIView alloc] init]; _bgEffectView.userInteractionEnabled = NO; [_bgEffectView addSubview:self.fullEffectView]; [_bgEffectView addSubview:self.chatEffectView]; } return _bgEffectView; } - (QXEffectContentView *)fullEffectView { if (!_fullEffectView) { _fullEffectView = [[QXEffectContentView alloc] initWithFrame:CGRectZero]; _fullEffectView.queue = dispatch_queue_create("qx_room_full_svga_message.com", NULL); } return _fullEffectView; } - (QXEffectContentView *)chatEffectView { if (!_chatEffectView) { _chatEffectView = [[QXEffectContentView alloc] initWithFrame:CGRectZero]; [_chatEffectView.playerMp4View mas_remakeConstraints:^(MASConstraintMaker *make) { // make.centerX.centerY.equalTo(_chatEffectView); // make.width.mas_equalTo(ScaleWidth(375)); // make.height.mas_equalTo(ScaleWidth(375)); make.edges.equalTo(_chatEffectView); }]; _chatEffectView.queue = dispatch_queue_create("qx_room_chat_svga_message.com", NULL); } return _chatEffectView; } @end @interface QXEffectContentView () @property (nonatomic,strong) QXEffectSvgaView *svagView; @property (nonatomic,strong) QXGiftModel *playModel; @property (nonatomic, assign) BOOL isLoadEffect; ///< 是否正在加载 @property (nonatomic, strong) NSRecursiveLock *lock; @property (nonatomic, strong) NSMutableArray *giftArray; @end @implementation QXEffectContentView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.userInteractionEnabled = NO; self.isLoadEffect = NO; [self addSubview:self.effectView]; [self addSubview:self.playerMp4View]; [self.effectView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }]; [self.playerMp4View mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }]; } return self; } - (void)displayEffectView:(QXGiftModel *)gift { dispatch_async(self.queue, ^{ if (![gift.play_image isExist]) { return; } NSString *pathExtension = [gift.play_image pathExtension].lowercaseString; if (!([pathExtension isEqualToString:@"svga"] || [pathExtension isEqualToString:@"mp4"])) { return; } [self.lock lock]; [self.giftArray addObject:gift]; [self.lock unlock]; if (self.isLoadEffect == NO) { self.isLoadEffect = YES; [self loadStartSVGAPlayer]; } }); } - (void)openOrCloseEffectViewWith:(BOOL)isShow { _isShow = isShow; [self removeSvgaQueueData]; [self.effectView stopEffectSvgaPlay]; // [self.playerView stop]; [self.playerMp4View stopHWDMP4]; // [self.alphaVideoView stop]; self.playerMp4View.hidden = YES; [self setHidden:!isShow]; } -(void)stopPlay{ [self removeSvgaQueueData]; [self.effectView stopEffectSvgaPlay]; // [self.playerView stop]; [self.playerMp4View stopHWDMP4]; // [self.alphaVideoView stop]; self.playerMp4View.hidden = YES; } -(void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container{ dispatch_async(dispatch_get_main_queue(), ^{ self.playerMp4View.hidden = YES; }); [self loadStartSVGAPlayer]; } - (void)loadStartSVGAPlayer { if (!_isShow) { return; } QXGiftModel *giftModel = nil; [self.lock lock]; if (self.giftArray.count > 0) { giftModel = self.giftArray.firstObject; [self.giftArray removeObjectAtIndex:0]; self.isLoadEffect = YES; }else { self.isLoadEffect = NO; } [self.lock unlock]; if (self.isLoadEffect && [giftModel.play_image isExist]) { dispatch_async(dispatch_get_main_queue(), ^{ if ([giftModel.play_image hasSuffix:@"mp4"]) { __weak typeof(self)weakSelf = self; [[QXRequset shareInstance] downloadVideoPlayerWithUrl:giftModel.play_image completion:^(BOOL result, NSString * _Nonnull fileName) { NSString *videoPath = [QXFileManager getGiftVideoPath:fileName]; weakSelf.playerMp4View.hidden = NO; [weakSelf.playerMp4View playHWDMP4:videoPath delegate:self]; }]; }else if ([giftModel.play_image hasSuffix:@"svg"] || [giftModel.play_image hasSuffix:@"svga"]) { __weak typeof(self)weakSelf = self; [[QXRequset shareInstance] downloadVideoPlayerWithUrl:giftModel.play_image completion:^(BOOL result, NSString * _Nonnull fileName) { NSString *filePath = [QXFileManager getGiftVideoPath:fileName]; [weakSelf.effectView loadSVGAPlayerWith:filePath]; }]; }else { [self.lock lock]; self.isLoadEffect = NO; [self.lock unlock]; } }); } } - (void)loadEndSvgaPlayer { dispatch_async(self.queue, ^{ [self loadStartSVGAPlayer]; }); } - (void)destroyEffectView { [self removeSvgaQueueData]; [self.svagView destroySvga]; // [self.playerView destroyPlayer]; [self.playerMp4View stopHWDMP4]; [self.effectView removeFromSuperview]; [self.playerMp4View removeFromSuperview]; _svagView = nil; // _playerView = nil; _playModel = nil; _playerMp4View = nil; // _alphaVideoView = nil; } - (void)removeSvgaQueueData { [self.lock lock]; [self.giftArray removeAllObjects]; self.isLoadEffect = NO; [self.lock unlock]; } -(NSMutableArray *)giftArray{ if (!_giftArray) { _giftArray = [NSMutableArray array]; } return _giftArray; } - (QXEffectSvgaView *)effectView { if (!_svagView) { _svagView = [[QXEffectSvgaView alloc] initWithFrame:CGRectZero isAutoPlay:YES]; __weak typeof(self)weakSelf = self; _svagView.didFinishedDisplay = ^(QXEffectSvgaView * _Nonnull svgaView) { [svgaView destroySvga]; [weakSelf loadEndSvgaPlayer]; }; } return _svagView; } -(VAPView *)playerMp4View{ if (!_playerMp4View) { _playerMp4View = [[VAPView alloc] initWithFrame:CGRectZero]; _playerMp4View.hwd_enterBackgroundOP = HWDMP4EBOperationTypePauseAndResume; _playerMp4View.contentMode = UIViewContentModeScaleAspectFit; _playerMp4View.userInteractionEnabled = NO; _playerMp4View.backgroundColor = [UIColor clearColor]; // _playerMp4View.hwd_Delegate = self; } return _playerMp4View; } @end