DKWechatHelper/dkhelper/dkhelperDylib/QGVAPlayer/class/Controllers/QGAnimatedImageDecodeManager.m
DKJone 888af8954e [v1.0.7](https://github.com/DKWechatHelper/DKWechatHelper/releases/tag/1.0.7) / 2021-01-29
what's new
* 动态启动图
* 动态聊天背景
* 支持8.0.1
* 更新越狱包8.0.1
* 更新已注入助手的8.0.1未签名包
* 更新越狱源安装包
2021-01-29 16:35:34 +08:00

162 lines
5.1 KiB
Objective-C

// QGAnimatedImageDecodeManager.m
// Tencent is pleased to support the open source community by making vap available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.
#import "QGAnimatedImageDecodeManager.h"
#import "QGAnimatedImageBufferManager.h"
#import "QGBaseDecoder.h"
#import "QGVAPSafeMutableArray.h"
#import "QGMP4FrameHWDecoder.h"
#import "QGVAPLogger.h"
#import <sys/stat.h>
#import <AVFoundation/AVFoundation.h>
@interface QGAnimatedImageDecodeManager() {
QGAnimatedImageDecodeConfig *_config; //解码配置
QGBaseDFileInfo *_fileInfo; //sharpP文件信息
NSMutableArray *_decoders; //解码器
QGAnimatedImageBufferManager *_bufferManager; //缓冲管理
AVAudioPlayer *_audioPlayer;
}
@end
@implementation QGAnimatedImageDecodeManager
- (instancetype)initWith:(QGBaseDFileInfo *)fileInfo
config:(QGAnimatedImageDecodeConfig *)config
delegate:(id<QGAnimatedImageDecoderDelegate>)delegate {
if (self = [super init]) {
_config = config;
_fileInfo = fileInfo;
_decoderDelegate = delegate;
[self createDecodersByConfig:config];
_bufferManager = [[QGAnimatedImageBufferManager alloc] initWithConfig:config];
[self initializeBuffers];
[self setupAudioPlayerIfNeed];
}
return self;
}
/**
取出已解码的一帧并准备下一帧
@param frameIndex 帧索引
@return 帧内容
*/
- (QGBaseAnimatedImageFrame *)consumeDecodedFrame:(NSInteger)frameIndex {
@synchronized (self) {
// 控制何时命中第一帧,缓存满了才命中
if (frameIndex == 0 && _bufferManager.buffers.count < _config.bufferCount) {
return nil;
}
[self checkIfDecodeFinish:frameIndex];
QGBaseAnimatedImageFrame *frame = [_bufferManager popVideoFrame];
if (frame) {
// pts顺序
frame.frameIndex = frameIndex;
[self decodeFrame:frameIndex+_config.bufferCount];
}
return frame;
}
}
- (void)tryToStartAudioPlay {
if (!_audioPlayer) {
return ;
}
[_audioPlayer play];
}
#pragma mark - private methods
- (void)checkIfDecodeFinish:(NSInteger)frameIndex {
NSInteger decoderIndex = _decoders.count==1?0:frameIndex%_decoders.count;
QGBaseDecoder *decoder = _decoders[decoderIndex];
if ([decoder isFrameIndexBeyondEnd:frameIndex]) {
if ([self.decoderDelegate respondsToSelector:@selector(decoderDidFinishDecode:)]) {
[self.decoderDelegate decoderDidFinishDecode:decoder];
}
}
}
- (void)decodeFrame:(NSInteger)frameIndex {
if (!_decoders || _decoders.count == 0) {
//NSLog(@"error! can't find decoder");
return ;
}
NSInteger decoderIndex = _decoders.count==1?0:frameIndex%_decoders.count;
QGBaseDecoder *decoder = _decoders[decoderIndex];
if ([decoder shouldStopDecode:frameIndex]) {
return ;
}
[decoder decodeFrame:frameIndex buffers:_bufferManager.buffers];
}
- (void)createDecodersByConfig:(QGAnimatedImageDecodeConfig *)config {
if (!self.decoderDelegate || ![self.decoderDelegate respondsToSelector:@selector(decoderClassForManager:)]) {
VAP_Event(kQGVAPModuleCommon, @"you MUST implement the delegate in invoker!");
NSAssert(0, @"you MUST implement the delegate in invoker!");
return ;
}
_decoders = [QGVAPSafeMutableArray new];
for (int i = 0; i < config.threadCount; i ++) {
Class class = [self.decoderDelegate decoderClassForManager:self];
NSError *error = nil;
QGBaseDecoder *decoder = [class alloc];
decoder = [decoder initWith:_fileInfo error:&error];
if (!decoder) {
if ([self.decoderDelegate respondsToSelector:@selector(decoderDidFailDecode:error:)]) {
[self.decoderDelegate decoderDidFailDecode:nil error:error];
}
break ;
}
[_decoders addObject:decoder];
}
}
- (void)initializeBuffers {
for (int i = 0; i < _config.bufferCount; i++) {
[self decodeFrame:i];
}
}
- (void)setupAudioPlayerIfNeed {
if ([_fileInfo isKindOfClass:[QGMP4HWDFileInfo class]]) {
QGMP4ParserProxy *mp4Parser = [(QGMP4HWDFileInfo *)_fileInfo mp4Parser];
if (!mp4Parser.audioTrackBox) {
_audioPlayer = nil;
return ;
}
NSError *error;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:_fileInfo.filePath] error:&error];
}
}
- (void)dealloc {
}
@end