Ver código fonte

Merge pull request #126 from Tencent/feature/ios_audio_fix

Feature/ios audio fix
Cass 4 anos atrás
pai
commit
864da8afd5

+ 3 - 0
iOS/QGVAPlayer/QGVAPlayer/Classes/Controllers/QGAnimatedImageDecodeManager.h

@@ -53,6 +53,9 @@
 - (QGBaseAnimatedImageFrame *)consumeDecodedFrame:(NSInteger)frameIndex;
 - (QGBaseAnimatedImageFrame *)consumeDecodedFrame:(NSInteger)frameIndex;
 
 
 - (void)tryToStartAudioPlay;
 - (void)tryToStartAudioPlay;
+- (void)tryToStopAudioPlay;
+- (void)tryToPauseAudioPlay;
+- (void)tryToResumeAudioPlay;
 - (BOOL)containsThisDeocder:(id)decoder;
 - (BOOL)containsThisDeocder:(id)decoder;
 
 
 @end
 @end

+ 23 - 0
iOS/QGVAPlayer/QGVAPlayer/Classes/Controllers/QGAnimatedImageDecodeManager.m

@@ -97,6 +97,29 @@
     [_audioPlayer play];
     [_audioPlayer play];
 }
 }
 
 
+- (void)tryToStopAudioPlay {
+    if (!_audioPlayer) {
+        return;
+    }
+    // CoreAudio(AVAudioPlaeyrCpp)回调audioPlayerDidFinishPlaying:successfully:时在子线程,恰巧此时释放将可能导致野指针问题
+    // 如果只是stop不能解决,可以考虑产生循环持有并延迟释放_audioPlayer
+    [_audioPlayer stop];
+}
+
+- (void)tryToPauseAudioPlay {
+    if (!_audioPlayer) {
+        return;
+    }
+    [_audioPlayer pause];
+}
+
+- (void)tryToResumeAudioPlay {
+    if (!_audioPlayer) {
+        return;
+    }
+    [_audioPlayer play];
+}
+
 #pragma mark - private methods
 #pragma mark - private methods
 
 
 - (BOOL)checkIfDecodeFinish:(NSInteger)frameIndex {
 - (BOOL)checkIfDecodeFinish:(NSInteger)frameIndex {

+ 4 - 0
iOS/QGVAPlayer/QGVAPlayer/Classes/UIView+VAP.m

@@ -134,6 +134,7 @@ NSInteger const VapMaxCompatibleVersion = 2;
     if (self.vap_metalView) {
     if (self.vap_metalView) {
         [self.vap_metalView dispose];
         [self.vap_metalView dispose];
     }
     }
+    [self.hwd_decodeManager tryToStopAudioPlay];
     [self.hwd_callbackQueue addOperationWithBlock:^{
     [self.hwd_callbackQueue addOperationWithBlock:^{
         //此处必须延迟释放,避免野指针
         //此处必须延迟释放,避免野指针
         if ([self.hwd_Delegate respondsToSelector:@selector(viewDidStopPlayMP4:view:)]) {
         if ([self.hwd_Delegate respondsToSelector:@selector(viewDidStopPlayMP4:view:)]) {
@@ -461,6 +462,7 @@ NSInteger const VapMaxCompatibleVersion = 2;
     
     
     VAP_Info(kQGVAPModuleCommon, @"pauseHWDMP4");
     VAP_Info(kQGVAPModuleCommon, @"pauseHWDMP4");
     self.hwd_onPause = YES;
     self.hwd_onPause = YES;
+    [self.hwd_decodeManager tryToPauseAudioPlay];
 // pause回调stop会导致一般使用场景将view移除,无法resume,因此暂时去掉该回调触发
 // pause回调stop会导致一般使用场景将view移除,无法resume,因此暂时去掉该回调触发
 //    [self.hwd_callbackQueue addOperationWithBlock:^{
 //    [self.hwd_callbackQueue addOperationWithBlock:^{
 //        //此处必须延迟释放,避免野指针
 //        //此处必须延迟释放,避免野指针
@@ -475,6 +477,8 @@ NSInteger const VapMaxCompatibleVersion = 2;
     VAP_Info(kQGVAPModuleCommon, @"resumeHWDMP4");
     VAP_Info(kQGVAPModuleCommon, @"resumeHWDMP4");
     self.hwd_onPause = NO;
     self.hwd_onPause = NO;
     self.hwd_openGLView.pause = NO;
     self.hwd_openGLView.pause = NO;
+    // 目前音频和视频没有同步逻辑,多次暂停恢复会使音视频差距越来越大
+    [self.hwd_decodeManager tryToResumeAudioPlay];
 }
 }
 
 
 + (void)registerHWDLog:(QGVAPLoggerFunc)logger {
 + (void)registerHWDLog:(QGVAPLoggerFunc)logger {

+ 23 - 1
iOS/QGVAPlayerDemo/QGVAPlayerDemo/ViewController.m

@@ -17,6 +17,8 @@
 #import "UIView+VAP.h"
 #import "UIView+VAP.h"
 #import "QGVAPWrapView.h"
 #import "QGVAPWrapView.h"
 
 
+#import <AVFoundation/AVFoundation.h>
+
 @interface ViewController () <HWDMP4PlayDelegate, VAPWrapViewDelegate>
 @interface ViewController () <HWDMP4PlayDelegate, VAPWrapViewDelegate>
 
 
 @property (nonatomic, strong) UIButton *vapButton;
 @property (nonatomic, strong) UIButton *vapButton;
@@ -48,6 +50,7 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
 
 
 - (void)viewDidLoad {
 - (void)viewDidLoad {
     [super viewDidLoad];
     [super viewDidLoad];
+    [self setupAudioSession];
     
     
     //日志
     //日志
     [UIView registerHWDLog:qg_VAP_Logger_handler];
     [UIView registerHWDLog:qg_VAP_Logger_handler];
@@ -74,6 +77,18 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
     [self.view addSubview:_vapWrapViewButton];
     [self.view addSubview:_vapWrapViewButton];
 }
 }
 
 
+- (void)setupAudioSession {
+    AVAudioSession* avsession = [AVAudioSession sharedInstance];
+    NSError *error = nil;
+    if (![avsession setCategory:AVAudioSessionCategoryPlayback withOptions:0 error:&error]) {
+        if (error) NSLog(@"AVAudioSession setCategory failed : %ld, %s", (long)error.code, [error.localizedDescription UTF8String]);
+        return;
+    }
+    if (![avsession setActive:YES error:&error]) {
+        if (error) NSLog(@"AVAudioSession setActive failed : %ld, %s", (long)error.code, [error.localizedDescription UTF8String]);
+    }
+}
+
 #pragma mark - 各种类型的播放
 #pragma mark - 各种类型的播放
 
 
 - (void)playVap {
 - (void)playVap {
@@ -203,11 +218,18 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
 
 
 //provide the content for tags, maybe text or url string ...
 //provide the content for tags, maybe text or url string ...
 - (NSString *)vapWrapview_contentForVapTag:(NSString *)tag resource:(QGVAPSourceInfo *)info {
 - (NSString *)vapWrapview_contentForVapTag:(NSString *)tag resource:(QGVAPSourceInfo *)info {
-    return nil;
+    NSDictionary *extraInfo = @{@"[sImg1]" : @"http://shp.qlogo.cn/pghead/Q3auHgzwzM6GuU0Y6q6sKHzq3MjY1aGibIzR4xrJc1VY/60",
+                                @"[textAnchor]" : @"我是主播名",
+                                @"[textUser]" : @"我是用户名😂😂",};
+    return extraInfo[tag];
 }
 }
 
 
 //provide image for url from tag content
 //provide image for url from tag content
 - (void)vapWrapView_loadVapImageWithURL:(NSString *)urlStr context:(NSDictionary *)context completion:(VAPImageCompletionBlock)completionBlock {
 - (void)vapWrapView_loadVapImageWithURL:(NSString *)urlStr context:(NSDictionary *)context completion:(VAPImageCompletionBlock)completionBlock {
+    dispatch_async(dispatch_get_main_queue(), ^{
+        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%@/Resource/qq.png", [[NSBundle mainBundle] resourcePath]]];
+        completionBlock(image, nil, urlStr);
+    });
 }
 }
 
 
 @end
 @end