diff --git a/SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.m b/SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.m index 422baffc..e5eb2614 100644 --- a/SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.m +++ b/SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.m @@ -10,6 +10,7 @@ #import "SGFrame+Internal.h" #import "SGPacket+Internal.h" #import "SGDescriptor+Internal.h" +#import "SGAudioFormatter.h" #import "SGCodecContext.h" #import "SGAudioFrame.h" #import "SGSonic.h" @@ -26,6 +27,7 @@ @interface SGAudioDecoder () } @property (nonatomic, strong, readonly) SGSonic *sonic; +@property (nonatomic, strong, readonly) SGAudioFormatter *formatter; @property (nonatomic, strong, readonly) SGCodecContext *codecContext; @property (nonatomic, strong, readonly) SGCodecDescriptor *codecDescriptor; @property (nonatomic, strong, readonly) SGAudioDescriptor *audioDescriptor; @@ -64,6 +66,7 @@ - (void)destroy [self->_codecContext close]; self->_codecContext = nil; self->_audioDescriptor = nil; + self->_formatter = nil; } #pragma mark - Control @@ -75,11 +78,12 @@ - (void)flush self->_flags.needsResetSonic = YES; self->_flags.lastEndTimeStamp = kCMTimeInvalid; [self->_codecContext flush]; + [self->_formatter flush]; } - (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet { - NSMutableArray<__kindof SGFrame *> *ret = [NSMutableArray array]; + NSMutableArray *ret = [NSMutableArray array]; SGCodecDescriptor *cd = packet.codecDescriptor; NSAssert(cd, @"Invalid codec descriptor."); BOOL isEqual = [cd isEqualToDescriptor:self->_codecDescriptor]; @@ -122,8 +126,9 @@ - (void)flush [ret addObject:obj]; } } - if (ret.count) { - self->_flags.lastEndTimeStamp = CMTimeAdd(ret.lastObject.timeStamp, ret.lastObject.duration); + if (ret.count > 0) { + SGFrame *obj = ret.lastObject; + self->_flags.lastEndTimeStamp = CMTimeAdd(obj.timeStamp, obj.duration); } return ret; } @@ -170,6 +175,7 @@ - (void)flush NSArray *objs = [self->_codecContext decode:packet]; objs = [self processFrames:objs done:!packet]; objs = [self clipFrames:objs timeRange:cd.timeRange]; + objs = [self formatFrames:objs]; return objs; } @@ -276,6 +282,37 @@ - (void)flush return ret; } +- (NSArray<__kindof SGFrame *> *)formatFrames:(NSArray<__kindof SGFrame *> *)frames +{ + NSArray *descriptors = self->_options.supportedAudioDescriptors; + if (descriptors.count <= 0) { + return frames; + } + NSMutableArray *ret = [NSMutableArray array]; + for (SGAudioFrame *obj in frames) { + BOOL supported = NO; + for (SGAudioDescriptor *descriptor in descriptors) { + if ([obj.descriptor isEqualToDescriptor:descriptor]) { + supported = YES; + break; + } + } + if (supported) { + [ret addObject:obj]; + continue; + } + if (!self->_formatter) { + self->_formatter = [[SGAudioFormatter alloc] init]; + self->_formatter.descriptor = descriptors.firstObject; + } + SGAudioFrame *newObj = [self->_formatter format:obj]; + if (newObj) { + [ret addObject:newObj]; + } + } + return ret; +} + - (SGAudioFrame *)readSonicFrame:(int64_t)pts { int nb_samples = [self->_sonic samplesAvailable]; diff --git a/SGPlayer/Classes/Core/SGDecoder/SGVideoDecoder.m b/SGPlayer/Classes/Core/SGDecoder/SGVideoDecoder.m index c487cf6a..1a504c66 100644 --- a/SGPlayer/Classes/Core/SGDecoder/SGVideoDecoder.m +++ b/SGPlayer/Classes/Core/SGDecoder/SGVideoDecoder.m @@ -11,6 +11,7 @@ #import "SGPacket+Internal.h" #import "SGCodecContext.h" #import "SGVideoFrame.h" +#import "SGSWScale.h" @interface SGVideoDecoder () @@ -23,9 +24,10 @@ @interface SGVideoDecoder () } _flags; } +@property (nonatomic, strong, readonly) SGSWScale *scaler; +@property (nonatomic, strong, readonly) SGCodecContext *codecContext; @property (nonatomic, strong, readonly) SGVideoFrame *lastDecodeFrame; @property (nonatomic, strong, readonly) SGVideoFrame *lastOutputFrame; -@property (nonatomic, strong, readonly) SGCodecContext *codecContext; @property (nonatomic, strong, readonly) SGCodecDescriptor *codecDescriptor; @end @@ -193,6 +195,7 @@ - (void)flush objs = [self processFrames:objs done:!packet]; objs = [self clipKeyFrames:objs]; objs = [self clipFrames:objs timeRange:cd.timeRange]; + objs = [self formatFrames:objs]; return objs; } @@ -280,4 +283,56 @@ - (void)flush return ret; } +- (NSArray<__kindof SGFrame *> *)formatFrames:(NSArray<__kindof SGFrame *> *)frames +{ + NSArray *formats = self->_options.supportedPixelFormats; + if (formats.count <= 0) { + return frames; + } + NSMutableArray *ret = [NSMutableArray array]; + for (SGVideoFrame *obj in frames) { + BOOL supported = NO; + for (NSNumber *format in formats) { + if (obj.pixelBuffer || + obj.descriptor.format == format.intValue) { + supported = YES; + break; + } + } + if (supported) { + [ret addObject:obj]; + continue; + } + int format = formats.firstObject.intValue; + if (![self->_scaler.inputDescriptor isEqualToDescriptor:obj.descriptor]) { + SGSWScale *scaler = [[SGSWScale alloc] init]; + scaler.inputDescriptor = obj.descriptor; + scaler.outputDescriptor = obj.descriptor.copy; + scaler.outputDescriptor.format = format; + if ([scaler open]) { + self->_scaler = scaler; + } + } + if (!self->_scaler) { + [obj unlock]; + continue; + } + SGVideoFrame *newObj = [SGVideoFrame frameWithDescriptor:self->_scaler.outputDescriptor]; + int result = [self->_scaler convert:(void *)obj.data + inputLinesize:obj.linesize + outputData:newObj.core->data + outputLinesize:newObj.core->linesize]; + if (result < 0) { + [newObj unlock]; + [obj unlock]; + continue; + } + [newObj setCodecDescriptor:obj.codecDescriptor]; + [newObj fillWithTimeStamp:obj.timeStamp decodeTimeStamp:obj.decodeTimeStamp duration:obj.duration]; + [ret addObject:newObj]; + [obj unlock]; + } + return ret; +} + @end diff --git a/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.h b/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.h index 8f5d3565..1925c0b2 100644 --- a/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.h +++ b/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.h @@ -7,6 +7,7 @@ // #import +#import "SGAudioDescriptor.h" @interface SGDecoderOptions : NSObject @@ -58,4 +59,18 @@ */ @property (nonatomic) OSType preferredPixelFormat; +/*! + @property supportedPixelFormats + @abstract + Indicates the supported pixel formats. + */ +@property (nonatomic, copy) NSArray *supportedPixelFormats; + +/*! + @property supportedAudioDescriptors + @abstract + Indicates the supported audio descriptors. + */ +@property (nonatomic, copy) NSArray *supportedAudioDescriptors; + @end diff --git a/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.m b/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.m index 07d47644..b19aaa6c 100644 --- a/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.m +++ b/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.m @@ -7,6 +7,8 @@ // #import "SGDecoderOptions.h" +#import "SGAudioRenderer.h" +#import "SGVideoRenderer.h" #import "SGMapping.h" @implementation SGDecoderOptions @@ -20,6 +22,8 @@ - (id)copyWithZone:(NSZone *)zone obj->_hardwareDecodeH264 = self->_hardwareDecodeH264; obj->_hardwareDecodeH265 = self->_hardwareDecodeH265; obj->_preferredPixelFormat = self->_preferredPixelFormat; + obj->_supportedPixelFormats = self->_supportedPixelFormats.copy; + obj->_supportedAudioDescriptors = self->_supportedAudioDescriptors.copy; return obj; } @@ -32,6 +36,8 @@ - (instancetype)init self->_hardwareDecodeH264 = YES; self->_hardwareDecodeH265 = YES; self->_preferredPixelFormat = SGPixelFormatFF2AV(AV_PIX_FMT_NV12); + self->_supportedPixelFormats = [SGVideoRenderer supportedPixelFormats]; + self->_supportedAudioDescriptors = @[[SGAudioRenderer supportedAudioDescriptor]]; } return self; } diff --git a/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.h b/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.h index 31554949..51b4295d 100644 --- a/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.h +++ b/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.h @@ -7,7 +7,6 @@ // #import -#import "SGAudioDescriptor.h" @interface SGProcessorOptions : NSObject @@ -27,18 +26,4 @@ */ @property (nonatomic, copy) Class videoClass; -/*! - @property supportedPixelFormats - @abstract - Indicates the supported pixel formats. - */ -@property (nonatomic, copy) NSArray *supportedPixelFormats; - -/*! - @property supportedAudioDescriptor - @abstract - Indicates the supported audio descriptor. - */ -@property (nonatomic, copy) SGAudioDescriptor *supportedAudioDescriptor; - @end diff --git a/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.m b/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.m index cab4c3f9..a7332c6d 100644 --- a/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.m +++ b/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.m @@ -9,8 +9,6 @@ #import "SGProcessorOptions.h" #import "SGAudioProcessor.h" #import "SGVideoProcessor.h" -#import "SGAudioRenderer.h" -#import "SGVideoRenderer.h" @implementation SGProcessorOptions @@ -27,8 +25,6 @@ - (instancetype)init if (self = [super init]) { self->_audioClass = [SGAudioProcessor class]; self->_videoClass = [SGVideoProcessor class]; - self->_supportedPixelFormats = [SGVideoRenderer supportedPixelFormats]; - self->_supportedAudioDescriptor = [SGAudioRenderer supportedAudioDescriptor]; } return self; } diff --git a/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.h b/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.h index c814f7a4..df5b5192 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.h +++ b/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.h @@ -19,12 +19,7 @@ /** * */ -- (instancetype)initWithTracks:(NSArray *)tracks weights:(NSArray *)weights descriptor:(SGAudioDescriptor *)descriptor; - -/** - * - */ -@property (nonatomic, copy, readonly) SGAudioDescriptor *descriptor; +- (instancetype)initWithTracks:(NSArray *)tracks weights:(NSArray *)weights; /** * diff --git a/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.m b/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.m index f629cfe4..c49d4a5e 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.m +++ b/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.m @@ -13,18 +13,18 @@ @interface SGAudioMixer () @property (nonatomic, readonly) CMTime startTime; +@property (nonatomic, strong, readonly) SGAudioDescriptor *descriptor; @property (nonatomic, strong, readonly) NSMutableDictionary *units; @end @implementation SGAudioMixer -- (instancetype)initWithTracks:(NSArray *)tracks weights:(NSArray *)weights descriptor:(SGAudioDescriptor *)descriptor +- (instancetype)initWithTracks:(NSArray *)tracks weights:(NSArray *)weights { if (self = [super init]) { self->_tracks = [tracks copy]; self->_weights = [weights copy]; - self->_descriptor = [descriptor copy]; self->_startTime = kCMTimeNegativeInfinity; self->_units = [NSMutableDictionary dictionary]; for (SGTrack *obj in self->_tracks) { @@ -45,6 +45,9 @@ - (SGAudioFrame *)putFrame:(SGAudioFrame *)frame [frame unlock]; return nil; } + if (!self->_descriptor) { + self->_descriptor = frame.descriptor.copy; + } NSAssert([self->_descriptor isEqualToDescriptor:frame.descriptor], @"Invalid Format."); NSAssert(self->_descriptor.format == AV_SAMPLE_FMT_FLTP, @"Invalid Format."); SGAudioMixerUnit *unit = [self->_units objectForKey:@(frame.track.index)]; diff --git a/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.h b/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.h index 26627443..c4e6816f 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.h +++ b/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.h @@ -11,9 +11,4 @@ @interface SGAudioProcessor : NSObject -/** - * - */ -- (void)setDescriptor:(SGAudioDescriptor *)descriptor; - @end diff --git a/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.m b/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.m index d1d9b71d..01ad48a1 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.m +++ b/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.m @@ -7,36 +7,22 @@ // #import "SGAudioProcessor.h" -#import "SGAudioFormatter.h" #import "SGAudioMixer.h" @interface SGAudioProcessor () @property (nonatomic, strong, readonly) SGAudioMixer *mixer; @property (nonatomic, strong, readonly) SGTrackSelection *selection; -@property (nonatomic, strong, readonly) SGAudioDescriptor *descriptor; -@property (nonatomic, strong, readonly) NSMutableDictionary *formatters; @end @implementation SGAudioProcessor -- (void)setDescriptor:(SGAudioDescriptor *)descriptor -{ - self->_descriptor = [descriptor copy]; -} - - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionAction)action { self->_selection = [selection copy]; if (action & SGTrackSelectionActionTracks) { - self->_mixer = [[SGAudioMixer alloc] initWithTracks:selection.tracks weights:selection.weights descriptor:self->_descriptor]; - self->_formatters = [NSMutableDictionary dictionary]; - for (SGTrack *track in selection.tracks) { - SGAudioFormatter *formatter = [[SGAudioFormatter alloc] init]; - formatter.descriptor = self->_descriptor; - [self->_formatters setObject:formatter forKey:@(track.index)]; - } + self->_mixer = [[SGAudioMixer alloc] initWithTracks:selection.tracks weights:selection.weights]; } else if (action & SGTrackSelectionActionWeights) { self->_mixer.weights = selection.weights; } @@ -44,15 +30,12 @@ - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionActio - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame { - if (![self->_selection.tracks containsObject:frame.track]) { + if (![frame isKindOfClass:[SGAudioFrame class]] || + ![self->_selection.tracks containsObject:frame.track]) { [frame unlock]; return nil; } - frame = [self->_formatters[@(frame.track.index)] format:frame]; - if (frame) { - return [self->_mixer putFrame:frame]; - } - return nil; + return [self->_mixer putFrame:frame]; } - (SGAudioFrame *)finish @@ -68,15 +51,11 @@ - (SGCapacity)capacity - (void)flush { [self->_mixer flush]; - [self->_formatters enumerateKeysAndObjectsUsingBlock:^(id key, SGAudioFormatter *obj, BOOL *stop) { - [obj flush]; - }]; } - (void)close { self->_mixer = nil; - self->_formatters = nil; } @end diff --git a/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.h b/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.h index fc41b1d5..a4f24831 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.h +++ b/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.h @@ -10,9 +10,4 @@ @interface SGVideoProcessor : NSObject -/** - * - */ -- (void)setSupportedPixelFormats:(NSArray *)supportedPixelFormats; - @end diff --git a/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.m b/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.m index e5277789..470b4743 100644 --- a/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.m +++ b/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.m @@ -7,32 +7,19 @@ // #import "SGVideoProcessor.h" -#import "SGFrame+Internal.h" -#import "SGVideoRenderer.h" -#import "SGSWScale.h" -#import "SGFFmpeg.h" +#import "SGVideoFrame.h" @interface SGVideoProcessor () @property (nonatomic, strong, readonly) SGTrackSelection *selection; -@property (nonatomic, strong, readonly) NSArray *supportedPixelFormats; -@property (nonatomic, strong, readonly) NSMutableDictionary *scalers; @end @implementation SGVideoProcessor -- (void)setSupportedPixelFormats:(NSArray *)supportedPixelFormats -{ - self->_supportedPixelFormats = [supportedPixelFormats copy]; -} - - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionAction)action { self->_selection = [selection copy]; - if (action & SGTrackSelectionActionTracks) { - self->_scalers = [NSMutableDictionary dictionary]; - } } - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame @@ -42,47 +29,7 @@ - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame [frame unlock]; return nil; } - if (!self->_supportedPixelFormats) { - return frame; - } - SGVideoFrame *videoFrame = frame; - BOOL isSupported = NO; - for (NSNumber *obj in self->_supportedPixelFormats) { - if (obj.intValue == videoFrame.descriptor.format) { - isSupported = YES; - } - } - if (isSupported || videoFrame.pixelBuffer) { - return frame; - } - int format = self->_supportedPixelFormats.firstObject.intValue; - SGSWScale *scaler = self->_scalers[@(frame.track.index)]; - if (![scaler.inputDescriptor isEqualToDescriptor:videoFrame.descriptor]) { - scaler = [[SGSWScale alloc] init]; - scaler.inputDescriptor = videoFrame.descriptor; - scaler.outputDescriptor = [videoFrame.descriptor copy]; - scaler.outputDescriptor.format = format; - if ([scaler open]) { - self->_scalers[@(frame.track.index)] = scaler; - } else { - [frame unlock]; - return nil; - } - } - SGVideoFrame *newFrame = [SGVideoFrame frameWithDescriptor:scaler.outputDescriptor]; - int result = [scaler convert:(void *)videoFrame.data - inputLinesize:videoFrame.linesize - outputData:newFrame.core->data - outputLinesize:newFrame.core->linesize]; - if (result < 0) { - [newFrame unlock]; - [frame unlock]; - return nil; - } - [newFrame setCodecDescriptor:frame.codecDescriptor]; - [newFrame fillWithTimeStamp:frame.timeStamp decodeTimeStamp:frame.decodeTimeStamp duration:frame.duration]; - [frame unlock]; - return newFrame; + return frame; } - (__kindof SGFrame *)finish diff --git a/SGPlayer/Classes/Core/SGSession/SGPlayerItem.m b/SGPlayer/Classes/Core/SGSession/SGPlayerItem.m index 664c869e..5ea14768 100644 --- a/SGPlayer/Classes/Core/SGSession/SGPlayerItem.m +++ b/SGPlayer/Classes/Core/SGSession/SGPlayerItem.m @@ -316,7 +316,6 @@ - (void)frameOutput:(SGFrameOutput *)frameOutput didChangeState:(SGFrameOutputSt self->_audioSelection.tracks = @[audio.firstObject]; self->_audioSelection.weights = @[@(1.0)]; self->_audioProcessor = [[self->_processorOptions.audioClass alloc] init]; - [self->_audioProcessor setDescriptor:self->_processorOptions.supportedAudioDescriptor]; [self->_audioProcessor setSelection:self->_audioSelection action:action]; } if (video.count > 0) { @@ -327,7 +326,6 @@ - (void)frameOutput:(SGFrameOutput *)frameOutput didChangeState:(SGFrameOutputSt self->_videoSelection.tracks = @[video.firstObject]; self->_videoSelection.weights = @[@(1.0)]; self->_videoProcessor = [[self->_processorOptions.videoClass alloc] init]; - [self->_videoProcessor setSupportedPixelFormats:self->_processorOptions.supportedPixelFormats]; [self->_videoProcessor setSelection:self->_videoSelection action:action]; } return [self setState:SGPlayerItemStateOpened];