Skip to content

Commit 32beda4

Browse files
committed
SGPlayer: Decoders.
1 parent ca4fe2a commit 32beda4

12 files changed

Lines changed: 587 additions & 277 deletions

File tree

SGPlayer.xcodeproj/project.pbxproj

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@
173173
9C6F902C219BE154001051CE /* SGMutableAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6F9028219BE154001051CE /* SGMutableAsset.m */; };
174174
9C6F902D219BE154001051CE /* SGMutableAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6F9028219BE154001051CE /* SGMutableAsset.m */; };
175175
9C6F902E219BE154001051CE /* SGMutableAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6F9028219BE154001051CE /* SGMutableAsset.m */; };
176+
9C72614A238B7C0400403272 /* SGCodecContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C726148238B7C0300403272 /* SGCodecContext.h */; };
177+
9C72614B238B7C0400403272 /* SGCodecContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C726148238B7C0300403272 /* SGCodecContext.h */; };
178+
9C72614C238B7C0400403272 /* SGCodecContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C726148238B7C0300403272 /* SGCodecContext.h */; };
179+
9C72614D238B7C0400403272 /* SGCodecContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C726149238B7C0300403272 /* SGCodecContext.m */; };
180+
9C72614E238B7C0400403272 /* SGCodecContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C726149238B7C0300403272 /* SGCodecContext.m */; };
181+
9C72614F238B7C0400403272 /* SGCodecContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C726149238B7C0300403272 /* SGCodecContext.m */; };
176182
9C82EEB121AE356D00E9D523 /* SGAudioProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C82EEAF21AE356D00E9D523 /* SGAudioProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
177183
9C82EEB221AE356D00E9D523 /* SGAudioProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C82EEAF21AE356D00E9D523 /* SGAudioProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
178184
9C82EEB321AE356D00E9D523 /* SGAudioProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C82EEAF21AE356D00E9D523 /* SGAudioProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -703,6 +709,8 @@
703709
9C66E1FD2188550D00B70DAA /* SGSWResample.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SGSWResample.m; sourceTree = "<group>"; };
704710
9C6F9027219BE154001051CE /* SGMutableAsset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGMutableAsset.h; sourceTree = "<group>"; };
705711
9C6F9028219BE154001051CE /* SGMutableAsset.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SGMutableAsset.m; sourceTree = "<group>"; };
712+
9C726148238B7C0300403272 /* SGCodecContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGCodecContext.h; sourceTree = "<group>"; };
713+
9C726149238B7C0300403272 /* SGCodecContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGCodecContext.m; sourceTree = "<group>"; };
706714
9C82EEAF21AE356D00E9D523 /* SGAudioProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGAudioProcessor.h; sourceTree = "<group>"; };
707715
9C82EEB021AE356D00E9D523 /* SGAudioProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SGAudioProcessor.m; sourceTree = "<group>"; };
708716
9C853F1021BFD85D005552C6 /* SGVideoDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGVideoDescriptor.h; sourceTree = "<group>"; };
@@ -1228,12 +1236,14 @@
12281236
9C0B6CB5217DBA1800900F1E /* SGDecodable.h */,
12291237
9CF15DE320118E1100585326 /* SGDecodeLoop.h */,
12301238
9CF15DE420118E1100585326 /* SGDecodeLoop.m */,
1239+
9C3082C521251AC200B44298 /* SGDecodeContext.h */,
1240+
9C3082C621251AC200B44298 /* SGDecodeContext.m */,
12311241
9C3082CE212521AB00B44298 /* SGAudioDecoder.h */,
12321242
9C3082CF212521AB00B44298 /* SGAudioDecoder.m */,
12331243
9C3082C1212518EB00B44298 /* SGVideoDecoder.h */,
12341244
9C3082C2212518EC00B44298 /* SGVideoDecoder.m */,
1235-
9C3082C521251AC200B44298 /* SGDecodeContext.h */,
1236-
9C3082C621251AC200B44298 /* SGDecodeContext.m */,
1245+
9C726148238B7C0300403272 /* SGCodecContext.h */,
1246+
9C726149238B7C0300403272 /* SGCodecContext.m */,
12371247
);
12381248
path = SGDecoder;
12391249
sourceTree = "<group>";
@@ -1633,6 +1643,7 @@
16331643
9C86386821904A0900D730EC /* SGPLFTargets.h in Headers */,
16341644
9C86386921904A0900D730EC /* SGRenderer+Internal.h in Headers */,
16351645
9C17554A22C5B5B3003A93BC /* SGRenderTimer.h in Headers */,
1646+
9C72614B238B7C0400403272 /* SGCodecContext.h in Headers */,
16361647
9CA57933219DAA270061093B /* SGCodecDescriptor.h in Headers */,
16371648
9C86386B21904A0900D730EC /* SGPLFObject.h in Headers */,
16381649
9C8D6B8B22C4A19500985D55 /* SGMetalRenderPipeline.h in Headers */,
@@ -1742,6 +1753,7 @@
17421753
9CD79F132190068E00E39A7D /* SGMacro.h in Headers */,
17431754
9C8D6B8C22C4A19500985D55 /* SGMetalRenderPipeline.h in Headers */,
17441755
9CD79F1B2190068E00E39A7D /* SGFFmpeg.h in Headers */,
1756+
9C72614C238B7C0400403272 /* SGCodecContext.h in Headers */,
17451757
9C17554B22C5B5B3003A93BC /* SGRenderTimer.h in Headers */,
17461758
9CD79F232190068E00E39A7D /* SGPLFTargets.h in Headers */,
17471759
9CD79F242190068E00E39A7D /* SGRenderer+Internal.h in Headers */,
@@ -1827,6 +1839,7 @@
18271839
9C8D4E48200DFFC700ED8A58 /* SGPlayerItem.h in Headers */,
18281840
9C95D2C12152386C00079B38 /* SGURLAsset.h in Headers */,
18291841
9C2C559B2015B87400131E15 /* SGVideoFrame.h in Headers */,
1842+
9C72614A238B7C0400403272 /* SGCodecContext.h in Headers */,
18301843
9C389ACC20108C2E003259FF /* SGFrame.h in Headers */,
18311844
9CF15E1F2011BC5400585326 /* SGAudioFrame.h in Headers */,
18321845
9C935B9C21CCCA58007813F4 /* SGDescriptor+Internal.h in Headers */,
@@ -2041,6 +2054,7 @@
20412054
9CB01C97219E863D00B36CFA /* SGMutilDemuxer.m in Sources */,
20422055
9C86380E21904A0900D730EC /* SGMapping.m in Sources */,
20432056
9C22AE6C237AC19E004D33DE /* SGFrameReader.m in Sources */,
2057+
9C72614E238B7C0400403272 /* SGCodecContext.m in Sources */,
20442058
9CC2AD7A22A65C7B0095A081 /* SGPaddingDemuxer.m in Sources */,
20452059
9C6F902D219BE154001051CE /* SGMutableAsset.m in Sources */,
20462060
9C86381121904A0900D730EC /* SGFrameOutput.m in Sources */,
@@ -2125,6 +2139,7 @@
21252139
9CB01C98219E863D00B36CFA /* SGMutilDemuxer.m in Sources */,
21262140
9CD79EB52190068E00E39A7D /* SGMapping.m in Sources */,
21272141
9C22AE6D237AC19E004D33DE /* SGFrameReader.m in Sources */,
2142+
9C72614F238B7C0400403272 /* SGCodecContext.m in Sources */,
21282143
9CC2AD7B22A65C7B0095A081 /* SGPaddingDemuxer.m in Sources */,
21292144
9C6F902E219BE154001051CE /* SGMutableAsset.m in Sources */,
21302145
9CD79EB82190068E00E39A7D /* SGFrameOutput.m in Sources */,
@@ -2200,6 +2215,7 @@
22002215
9C1378B323026B3A00FE0CFD /* SGTrackSelection.m in Sources */,
22012216
9C2C55B82015D92100131E15 /* SGObjectQueue.m in Sources */,
22022217
9CE71918219C3F7900256485 /* SGURLSegment.m in Sources */,
2218+
9C72614D238B7C0400403272 /* SGCodecContext.m in Sources */,
22032219
9C8D6B5422C4A19500985D55 /* SGMetalTextureLoader.m in Sources */,
22042220
9C03E5F1212E645B001F0E1B /* SGVRProjection.m in Sources */,
22052221
9C525D5421AEC421005C5708 /* SGAudioDescriptor.m in Sources */,

SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#import "SGFrame+Internal.h"
1111
#import "SGPacket+Internal.h"
1212
#import "SGDescriptor+Internal.h"
13-
#import "SGDecodeContext.h"
13+
#import "SGCodecContext.h"
1414
#import "SGAudioFrame.h"
1515
#import "SGSonic.h"
1616

@@ -26,7 +26,7 @@ @interface SGAudioDecoder ()
2626
}
2727

2828
@property (nonatomic, strong, readonly) SGSonic *sonic;
29-
@property (nonatomic, strong, readonly) SGDecodeContext *codecContext;
29+
@property (nonatomic, strong, readonly) SGCodecContext *codecContext;
3030
@property (nonatomic, strong, readonly) SGCodecDescriptor *codecDescriptor;
3131
@property (nonatomic, strong, readonly) SGAudioDescriptor *audioDescriptor;
3232

@@ -46,9 +46,9 @@ - (void)setup
4646
self->_flags.nextTimeStamp = 0;
4747
self->_flags.needsAlignment = YES;
4848
self->_flags.needsResetSonic = YES;
49-
self->_codecContext = [[SGDecodeContext alloc] initWithTimebase:self->_codecDescriptor.timebase
50-
codecpar:self->_codecDescriptor.codecpar
51-
frameGenerator:^__kindof SGFrame *{
49+
self->_codecContext = [[SGCodecContext alloc] initWithTimebase:self->_codecDescriptor.timebase
50+
codecpar:self->_codecDescriptor.codecpar
51+
frameGenerator:^__kindof SGFrame *{
5252
return [SGAudioFrame frame];
5353
}];
5454
self->_codecContext.options = self->_options;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// SGCodecContext.h
3+
// SGPlayer iOS
4+
//
5+
// Created by Single on 2018/8/16.
6+
// Copyright © 2018 single. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
#import "SGCodecDescriptor.h"
11+
#import "SGDecoderOptions.h"
12+
#import "SGPacket.h"
13+
#import "SGFrame.h"
14+
15+
@interface SGCodecContext : NSObject
16+
17+
+ (instancetype)new NS_UNAVAILABLE;
18+
- (instancetype)init NS_UNAVAILABLE;
19+
20+
/**
21+
*
22+
*/
23+
- (instancetype)initWithTimebase:(AVRational)timebase
24+
codecpar:(AVCodecParameters *)codecpar
25+
frameGenerator:(__kindof SGFrame *(^)(void))frameGenerator;
26+
27+
/**
28+
*
29+
*/
30+
@property (nonatomic, strong) SGDecoderOptions *options;
31+
32+
/**
33+
*
34+
*/
35+
- (BOOL)open;
36+
37+
/**
38+
*
39+
*/
40+
- (void)close;
41+
42+
/**
43+
*
44+
*/
45+
- (void)flush;
46+
47+
/**
48+
*
49+
*/
50+
- (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet;
51+
52+
@end
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
//
2+
// SGCodecContext.m
3+
// SGPlayer iOS
4+
//
5+
// Created by Single on 2018/8/16.
6+
// Copyright © 2018 single. All rights reserved.
7+
//
8+
9+
#import "SGCodecContext.h"
10+
#import "SGPacket+Internal.h"
11+
#import "SGFrame+Internal.h"
12+
#import "SGMapping.h"
13+
#import "SGOptions.h"
14+
#import "SGError.h"
15+
#import "SGMacro.h"
16+
17+
@interface SGCodecContext ()
18+
19+
@property (nonatomic, readonly) AVRational timebase;
20+
@property (nonatomic, readonly) AVCodecParameters *codecpar;
21+
@property (nonatomic, readonly) AVCodecContext *codecContext;
22+
@property (nonatomic, copy, readonly) __kindof SGFrame *(^frameGenerator)(void);
23+
24+
@end
25+
26+
@implementation SGCodecContext
27+
28+
- (instancetype)initWithTimebase:(AVRational)timebase
29+
codecpar:(AVCodecParameters *)codecpar
30+
frameGenerator:(__kindof SGFrame *(^)(void))frameGenerator
31+
{
32+
if (self = [super init]) {
33+
self->_timebase = timebase;
34+
self->_codecpar = codecpar;
35+
self->_frameGenerator = frameGenerator;
36+
self->_options = [SGOptions sharedOptions].decoder.copy;
37+
}
38+
return self;
39+
}
40+
41+
- (void)dealloc
42+
{
43+
[self close];
44+
}
45+
46+
#pragma mark - Interface
47+
48+
- (BOOL)open
49+
{
50+
if (!self->_codecpar) {
51+
return NO;
52+
}
53+
self->_codecContext = [self createCcodecContext];
54+
if (!self->_codecContext) {
55+
return NO;
56+
}
57+
return YES;
58+
}
59+
60+
- (void)close
61+
{
62+
if (self->_codecContext) {
63+
avcodec_free_context(&self->_codecContext);
64+
self->_codecContext = nil;
65+
}
66+
}
67+
68+
- (void)flush
69+
{
70+
if (self->_codecContext) {
71+
avcodec_flush_buffers(self->_codecContext);
72+
}
73+
}
74+
75+
- (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet
76+
{
77+
if (!self->_codecContext) {
78+
return nil;
79+
}
80+
int result = avcodec_send_packet(self->_codecContext, packet ? packet.core : NULL);
81+
if (result < 0) {
82+
return nil;
83+
}
84+
NSMutableArray *array = [NSMutableArray array];
85+
while (result != AVERROR(EAGAIN)) {
86+
__kindof SGFrame *frame = self->_frameGenerator();
87+
result = avcodec_receive_frame(self->_codecContext, frame.core);
88+
if (result < 0) {
89+
[frame unlock];
90+
break;
91+
} else {
92+
[array addObject:frame];
93+
}
94+
}
95+
return array;
96+
}
97+
98+
#pragma mark - AVCodecContext
99+
100+
- (AVCodecContext *)createCcodecContext
101+
{
102+
AVCodecContext *codecContext = avcodec_alloc_context3(NULL);
103+
if (!codecContext) {
104+
return nil;
105+
}
106+
codecContext->opaque = (__bridge void *)self;
107+
108+
int result = avcodec_parameters_to_context(codecContext, self->_codecpar);
109+
NSError *error = SGGetFFError(result, SGActionCodeCodecSetParametersToContext);
110+
if (error) {
111+
avcodec_free_context(&codecContext);
112+
return nil;
113+
}
114+
codecContext->pkt_timebase = self->_timebase;
115+
if ((self->_options.hardwareDecodeH264 && self->_codecpar->codec_id == AV_CODEC_ID_H264) ||
116+
(self->_options.hardwareDecodeH265 && self->_codecpar->codec_id == AV_CODEC_ID_H265)) {
117+
codecContext->get_format = SGCodecContextGetFormat;
118+
}
119+
120+
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
121+
if (!codec) {
122+
avcodec_free_context(&codecContext);
123+
return nil;
124+
}
125+
codecContext->codec_id = codec->id;
126+
127+
AVDictionary *opts = SGDictionaryNS2FF(self->_options.options);
128+
if (self->_options.threadsAuto &&
129+
!av_dict_get(opts, "threads", NULL, 0)) {
130+
av_dict_set(&opts, "threads", "auto", 0);
131+
}
132+
if (self->_options.refcountedFrames &&
133+
!av_dict_get(opts, "refcounted_frames", NULL, 0) &&
134+
(codecContext->codec_type == AVMEDIA_TYPE_VIDEO || codecContext->codec_type == AVMEDIA_TYPE_AUDIO)) {
135+
av_dict_set(&opts, "refcounted_frames", "1", 0);
136+
}
137+
138+
result = avcodec_open2(codecContext, codec, &opts);
139+
140+
if (opts) {
141+
av_dict_free(&opts);
142+
}
143+
144+
error = SGGetFFError(result, SGActionCodeCodecOpen2);
145+
if (error) {
146+
avcodec_free_context(&codecContext);
147+
return nil;
148+
}
149+
150+
return codecContext;
151+
}
152+
153+
static enum AVPixelFormat SGCodecContextGetFormat(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
154+
{
155+
SGCodecContext *self = (__bridge SGCodecContext *)s->opaque;
156+
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
157+
if (fmt[i] == AV_PIX_FMT_VIDEOTOOLBOX) {
158+
AVBufferRef *device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VIDEOTOOLBOX);
159+
if (!device_ctx) {
160+
break;
161+
}
162+
AVBufferRef *frames_ctx = av_hwframe_ctx_alloc(device_ctx);
163+
av_buffer_unref(&device_ctx);
164+
if (!frames_ctx) {
165+
break;
166+
}
167+
AVHWFramesContext *frames_ctx_data = (AVHWFramesContext *)frames_ctx->data;
168+
frames_ctx_data->format = AV_PIX_FMT_VIDEOTOOLBOX;
169+
frames_ctx_data->sw_format = SGPixelFormatAV2FF(self->_options.preferredPixelFormat);
170+
frames_ctx_data->width = s->width;
171+
frames_ctx_data->height = s->height;
172+
int err = av_hwframe_ctx_init(frames_ctx);
173+
if (err < 0) {
174+
av_buffer_unref(&frames_ctx);
175+
break;
176+
}
177+
s->hw_frames_ctx = frames_ctx;
178+
return fmt[i];
179+
}
180+
}
181+
return fmt[0];
182+
}
183+
184+
@end

0 commit comments

Comments
 (0)