Skip to content

Commit

Permalink
Merge pull request #88 from Tencent/feature/ios_background
Browse files Browse the repository at this point in the history
fix: 修复退后台继续播放导致花屏的问题
  • Loading branch information
Styx-S authored May 18, 2021
2 parents 26d261c + 6a43ddf commit 5846db2
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#import "QGAnimatedImageDecodeThread.h"
#import "QGBaseDFileInfo.h"

extern NSString* kQGVAPDecoderSeekStart;
extern NSString* kQGVAPDecoderSeekFinish;

@interface QGBaseDecoder : NSObject

@property (atomic, assign) NSInteger currentDecodeFrame; //正在解码的帧索引
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#import "QGBaseDecoder.h"
#import "QGAnimatedImageDecodeThreadPool.h"

NSString* kQGVAPDecoderSeekStart = @"kQGVAPDecoderSeekStart";
NSString* kQGVAPDecoderSeekFinish = @"kQGVAPDecoderSeekFinish";

@interface QGBaseDecoder() {

QGBaseDFileInfo *_fileInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ @interface QGMP4FrameHWDecoder() {
/** Video Parameter Set */
@property (nonatomic, strong) NSData *vpsData;

@property (atomic, assign) NSInteger lastDecodeFrame;

@end

NSString *const QGMP4HWDErrorDomain = @"QGMP4HWDErrorDomain";
Expand Down Expand Up @@ -136,6 +138,7 @@ - (instancetype)initWith:(QGMP4HWDFileInfo *)fileInfo error:(NSError *__autorele

if (self = [super initWith:fileInfo error:error]) {
_decodeQueue = dispatch_queue_create("com.qgame.vap.decode", DISPATCH_QUEUE_SERIAL);
_lastDecodeFrame = -1;
_mp4Parser = fileInfo.mp4Parser;
BOOL isOpenSuccess = [self onInputStart];
if (!isOpenSuccess) {
Expand Down Expand Up @@ -166,6 +169,10 @@ - (void)decodeFrame:(NSInteger)frameIndex buffers:(NSMutableArray *)buffers {
self.currentDecodeFrame = frameIndex;
_buffers = buffers;
dispatch_async(self.decodeQueue, ^{
if (frameIndex != self.lastDecodeFrame + 1) {
// 必须是依次增大,否则解出来的画面会异常
return;
}
[self _decodeFrame:frameIndex drop:NO];
});
}
Expand Down Expand Up @@ -294,6 +301,8 @@ - (void)handleDecodePixelBuffer:(CVPixelBufferRef)pixelBuffer
status:(OSStatus)status
needDrop:(BOOL)dropFlag {

self.lastDecodeFrame = frameIndex;

CFRelease(sampleBuffer);

if(status == kVTInvalidSessionErr) {
Expand Down Expand Up @@ -489,6 +498,9 @@ - (void)resetDecoder {
}

- (void)findKeyFrameAndDecodeToCurrent:(NSInteger)frameIndex {

[[NSNotificationCenter defaultCenter] postNotificationName:kQGVAPDecoderSeekStart object:self];

NSArray<NSNumber *> *keyframeIndexes = [_mp4Parser videoSyncSampleIndexes];
NSInteger index = [[keyframeIndexes firstObject] integerValue];
for(NSNumber *number in keyframeIndexes) {
Expand All @@ -506,6 +518,8 @@ - (void)findKeyFrameAndDecodeToCurrent:(NSInteger)frameIndex {
index++;
}
[self _decodeFrame:frameIndex drop:NO];

[[NSNotificationCenter defaultCenter] postNotificationName:kQGVAPDecoderSeekFinish object:self];
}

- (void)_onInputEnd {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@
- (QGBaseAnimatedImageFrame *)consumeDecodedFrame:(NSInteger)frameIndex;

- (void)tryToStartAudioPlay;
- (BOOL)containsThisDeocder:(id)decoder;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,13 @@ - (void)dealloc {

}

- (BOOL)containsThisDeocder:(id)decoder {
for (id d in _decoders) {
if (d == decoder) {
return YES;
}
}
return NO;
}

@end
32 changes: 25 additions & 7 deletions iOS/QGVAPlayer/QGVAPlayer/Classes/UIView+VAP.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ @interface UIView () <QGAnimatedImageDecoderDelegate,QGHWDMP4OpenGLViewDelegate,
@property (nonatomic, strong) QGAnimatedImageDecodeConfig *hwd_decodeConfig; //线程数与buffer数
@property (nonatomic, strong) NSOperationQueue *hwd_callbackQueue; //回调执行队列
@property (nonatomic, assign) BOOL hwd_onPause; //标记是否暂停中
@property (nonatomic, assign) BOOL hwd_onSeek; //正在seek当中,此时继续播放会导致时序混乱
@property (nonatomic, strong) QGHWDMP4OpenGLView *hwd_openGLView; //opengl绘制图层
@property (nonatomic, strong) QGHWDMetalView *hwd_metalView; //metal绘制图层
@property (nonatomic, strong) QGVAPMetalView *vap_metalView; //vap格式mp4渲染图层
Expand All @@ -66,12 +67,27 @@ - (void)hwd_registerNotification {

[[NSNotificationCenter defaultCenter] hwd_addSafeObserver:self selector:@selector(hwd_didReceiveEnterBackgroundNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] hwd_addSafeObserver:self selector:@selector(hwd_didReceiveWillEnterForegroundNotification:) name:UIApplicationWillEnterForegroundNotification object:nil];

[[NSNotificationCenter defaultCenter] hwd_addSafeObserver:self selector:@selector(hwd_didReceiveSeekStartNotification:) name:kQGVAPDecoderSeekStart object:nil];
[[NSNotificationCenter defaultCenter] hwd_addSafeObserver:self selector:@selector(hwd_didReceiveSeekFinishNotification:) name:kQGVAPDecoderSeekFinish object:nil];
}

- (void)hwd_didReceiveEnterBackgroundNotification:(NSNotification *)notification {
[self pauseHWDMP4];
}

- (void)hwd_didReceiveSeekStartNotification:(NSNotification *)notification {
if ([self.hwd_decodeManager containsThisDeocder:notification.object]) {
self.hwd_onSeek = YES;
}
}

- (void)hwd_didReceiveSeekFinishNotification:(NSNotification *)notification {
if ([self.hwd_decodeManager containsThisDeocder:notification.object]) {
self.hwd_onSeek = NO;
}
}

//结束播放
- (void)hwd_stopHWDMP4 {

Expand Down Expand Up @@ -350,7 +366,7 @@ - (void)hwd_renderVideoRun {
if (self.hwd_isFinish) {
break ;
}
if (self.hwd_onPause) {
if (self.hwd_onPause || self.hwd_onSeek) {
lastRenderingInterval = NSDate.timeIntervalSinceReferenceDate;
continue;
}
Expand Down Expand Up @@ -427,12 +443,13 @@ - (void)pauseHWDMP4 {

VAP_Info(kQGVAPModuleCommon, @"pauseHWDMP4");
self.hwd_onPause = YES;
[self.hwd_callbackQueue addOperationWithBlock:^{
//此处必须延迟释放,避免野指针
if ([self.hwd_Delegate respondsToSelector:@selector(viewDidStopPlayMP4:view:)]) {
[self.hwd_Delegate viewDidStopPlayMP4:self.hwd_currentFrame.frameIndex view:self];
}
}];
// pause回调stop会导致一般使用场景将view移除,无法resume,因此暂时去掉该回调触发
// [self.hwd_callbackQueue addOperationWithBlock:^{
// //此处必须延迟释放,避免野指针
// if ([self.hwd_Delegate respondsToSelector:@selector(viewDidStopPlayMP4:view:)]) {
// [self.hwd_Delegate viewDidStopPlayMP4:self.hwd_currentFrame.frameIndex view:self];
// }
// }];
}

- (void)resumeHWDMP4 {
Expand Down Expand Up @@ -542,6 +559,7 @@ - (void)setHwd_Delegate:(id<HWDMP4PlayDelegate>)MP4PlayDelegate {

//category methods
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(hwd_onPause, setHwd_onPause, BOOL)
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(hwd_onSeek, setHwd_onSeek, BOOL)
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(hwd_renderByOpenGL, setHwd_renderByOpenGL, BOOL)
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(hwd_isFinish, setHwd_isFinish, BOOL)
HWDSYNTH_DYNAMIC_PROPERTY_CTYPE(hwd_fps, setHwd_fps, NSInteger)
Expand Down
4 changes: 3 additions & 1 deletion iOS/QGVAPlayerDemo/QGVAPlayerDemo/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ - (void)playVapWithWrapView {
NSString *resPath = [NSString stringWithFormat:@"%@/Resource/demo.mp4", [[NSBundle mainBundle] resourcePath]];
[wrapView vapWrapView_playHWDMP4:resPath repeatCount:-1 delegate:self];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageviewTap:)];
[wrapView addGestureRecognizer:tap];
[wrapView vapWrapView_addVapGesture:tap callback:^(UIGestureRecognizer *gestureRecognizer, BOOL insideSource, QGVAPSourceDisplayItem *source) {

}];
}

#pragma mark - mp4 hwd delegate
Expand Down

0 comments on commit 5846db2

Please sign in to comment.