2
2
// TIPXMP4Codec.m
3
3
// TwitterImagePipeline
4
4
//
5
- // Created by Nolan O'Brien on 3/16/17.
5
+ // Created on 3/16/17.
6
6
// Copyright © 2017 Twitter. All rights reserved.
7
7
//
8
8
11
11
12
12
@import AVFoundation;
13
13
14
+ #ifndef PRIVATE_SELF
15
+ #define PRIVATE_SELF (type ) type * __nullable const self
16
+ #endif
17
+
18
+ NS_ASSUME_NONNULL_BEGIN
19
+
14
20
#pragma mark - Defer support
15
21
16
22
typedef void (^tipx_defer_block_t )(void );
@@ -58,7 +64,7 @@ __strong tipx_defer_block_t tipx_macro_concat(tipx_stack_defer_block_, __LINE__)
58
64
59
65
#pragma mark - Declarations
60
66
61
- static CGImageRef TIPX_CGImageCreateFromCMSampleBuffer (CMSampleBufferRef sample) CF_RETURNS_RETAINED;
67
+ static CGImageRef __nullable TIPX_CGImageCreateFromCMSampleBuffer (CMSampleBufferRef __nullable sample) CF_RETURNS_RETAINED;
62
68
63
69
@interface TIPXMP4DecoderConfigInternal : NSObject <TIPXMP4DecoderConfig>
64
70
- (instancetype )initWithMaxDecodableFramesCount : (NSUInteger )max ;
@@ -90,15 +96,15 @@ - (instancetype)init
90
96
return [self initWithDefaultDecoderConfig: nil ];
91
97
}
92
98
93
- - (instancetype )initWithDefaultDecoderConfig : (id <TIPXMP4DecoderConfig>)decoderConfig
99
+ - (instancetype )initWithDefaultDecoderConfig : (nullable id <TIPXMP4DecoderConfig>)decoderConfig
94
100
{
95
101
if (self = [super init ]) {
96
102
_tip_decoder = [[TIPXMP4Decoder alloc ] initWithDefaultDecoderConfig: decoderConfig];
97
103
}
98
104
return self;
99
105
}
100
106
101
- - (id <TIPXMP4DecoderConfig>)defaultDecoderConfig
107
+ - (nullable id <TIPXMP4DecoderConfig>)defaultDecoderConfig
102
108
{
103
109
return [(TIPXMP4Decoder *)_tip_decoder defaultDecoderConfig ];
104
110
}
@@ -141,7 +147,7 @@ - (NSUInteger)tip_frameCount
141
147
return _frameCount;
142
148
}
143
149
144
- - (instancetype )initWithBuffer : (NSMutableData *)buffer config : (id <TIPXMP4DecoderConfig>)config
150
+ - (instancetype )initWithBuffer : (NSMutableData *)buffer config : (nullable id <TIPXMP4DecoderConfig>)config
145
151
{
146
152
if (self = [super init ]) {
147
153
_data = buffer;
@@ -154,28 +160,34 @@ - (instancetype)initWithBuffer:(NSMutableData *)buffer config:(id<TIPXMP4Decoder
154
160
155
161
_temporaryFilePath = [[tmpDir stringByAppendingPathComponent: [NSUUID UUID ].UUIDString] stringByAppendingPathExtension: @" mp4" ];
156
162
_temporaryFile = fopen (_temporaryFilePath.UTF8String , " w" );
157
- [ self _tipx_writeDataToTemporaryFile: _data] ;
163
+ _writeDataToTemporaryFile ( self, _data) ;
158
164
}
159
165
return self;
160
166
}
161
167
162
168
- (void )dealloc
163
169
{
164
- [ self _tipx_clear ] ;
170
+ _clear ( self) ;
165
171
}
166
172
167
- - (BOOL )_tipx_writeDataToTemporaryFile : (NSData *)data
173
+ static BOOL _writeDataToTemporaryFile (PRIVATE_SELF(TIPXMP4DecoderContext),
174
+ NSData *data)
168
175
{
169
- if (_temporaryFile) {
176
+ if (!self) {
177
+ return NO ;
178
+ }
179
+
180
+ if (self->_temporaryFile ) {
170
181
const size_t byteCount = data.length ;
171
182
if (byteCount) {
172
- const size_t byteOut = fwrite (data.bytes , sizeof (char ), byteCount, _temporaryFile);
183
+ const size_t byteOut = fwrite (data.bytes , sizeof (char ), byteCount, self-> _temporaryFile );
173
184
if (byteCount == byteOut) {
174
185
return YES ;
175
186
} else {
176
- fclose (_temporaryFile);
177
- _temporaryFile = NULL ;
178
- [[NSFileManager defaultManager ] removeItemAtPath: _temporaryFilePath error: NULL ];
187
+ fclose (self->_temporaryFile );
188
+ self->_temporaryFile = NULL ;
189
+ [[NSFileManager defaultManager ] removeItemAtPath: self ->_temporaryFilePath
190
+ error: NULL ];
179
191
}
180
192
}
181
193
}
@@ -190,7 +202,7 @@ - (TIPImageDecoderAppendResult)appendData:(NSData *)data
190
202
_frameCount = 1 ; // seed the frames
191
203
}
192
204
[_data appendData: data];
193
- [ self _tipx_writeDataToTemporaryFile: data] ;
205
+ _writeDataToTemporaryFile ( self, data) ;
194
206
}
195
207
196
208
return TIPImageDecoderAppendResultDidProgress;
@@ -203,9 +215,13 @@ - (TIPImageContainer *)_tipx_firstFrameImageContainer
203
215
@autoreleasepool {
204
216
AVAsset *asset = [AVAsset assetWithURL: [NSURL fileURLWithPath: self ->_temporaryFilePath]];
205
217
AVAssetImageGenerator* imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset: asset];
206
- CGImageRef imageRef = [imageGenerator copyCGImageAtTime: CMTimeMake (0 , 1 ) actualTime: nil error: nil ];
218
+ CGImageRef imageRef = [imageGenerator copyCGImageAtTime: CMTimeMake (0 , 1 )
219
+ actualTime: nil
220
+ error: nil ];
207
221
if (imageRef) {
208
- UIImage* image = [UIImage imageWithCGImage: imageRef scale: [UIScreen mainScreen ].scale orientation: UIImageOrientationUp];
222
+ UIImage* image = [UIImage imageWithCGImage: imageRef
223
+ scale: [UIScreen mainScreen ].scale
224
+ orientation: UIImageOrientationUp];
209
225
CFRelease (imageRef);
210
226
if (image) {
211
227
self->_firstFrame = image;
@@ -218,7 +234,7 @@ - (TIPImageContainer *)_tipx_firstFrameImageContainer
218
234
return _firstFrame ? [[TIPImageContainer alloc ] initWithImage: _firstFrame] : nil ;
219
235
}
220
236
221
- - (TIPImageContainer *)renderImageWithMode : (TIPImageDecoderRenderMode)mode
237
+ - (nullable TIPImageContainer *)renderImageWithMode : (TIPImageDecoderRenderMode)mode
222
238
{
223
239
if (_cachedContainer) {
224
240
return _cachedContainer;
@@ -296,7 +312,8 @@ - (TIPImageContainer *)renderImageWithMode:(TIPImageDecoderRenderMode)mode
296
312
297
313
TIPImageContainer *container = nil ;
298
314
if (self->_frameCount > 1 ) {
299
- UIImage *animatedImage = [UIImage animatedImageWithImages: images duration: CMTimeGetSeconds (self ->_avAsset.duration)];
315
+ UIImage *animatedImage = [UIImage animatedImageWithImages: images
316
+ duration: CMTimeGetSeconds (self ->_avAsset.duration)];
300
317
container = [[TIPImageContainer alloc ] initWithImage: animatedImage];
301
318
} else if (self->_frameCount == 1 ) {
302
319
container = [[TIPImageContainer alloc ] initWithImage: images.firstObject];
@@ -305,7 +322,7 @@ - (TIPImageContainer *)renderImageWithMode:(TIPImageDecoderRenderMode)mode
305
322
self->_cachedContainer = container;
306
323
});
307
324
308
- [ self _tipx_clear ] ;
325
+ _clear ( self) ;
309
326
return _cachedContainer;
310
327
}
311
328
@@ -344,18 +361,23 @@ - (TIPImageDecoderAppendResult)finalizeDecoding
344
361
}
345
362
}
346
363
347
- - ( void ) _tipx_clear
364
+ static void _clear (PRIVATE_SELF(TIPXMP4DecoderContext))
348
365
{
349
- _avTrack = nil ;
350
- _avAsset = nil ;
351
- if (_temporaryFile) {
352
- fflush (_temporaryFile);
353
- fclose (_temporaryFile);
354
- _temporaryFile = NULL ;
366
+ if (!self) {
367
+ return ;
368
+ }
369
+
370
+ self->_avTrack = nil ;
371
+ self->_avAsset = nil ;
372
+ if (self->_temporaryFile ) {
373
+ fflush (self->_temporaryFile );
374
+ fclose (self->_temporaryFile );
375
+ self->_temporaryFile = NULL ;
355
376
}
356
- if (_temporaryFilePath) {
357
- [[NSFileManager defaultManager ] removeItemAtPath: _temporaryFilePath error: NULL ];
358
- _temporaryFilePath = nil ;
377
+ if (self->_temporaryFilePath ) {
378
+ [[NSFileManager defaultManager ] removeItemAtPath: self ->_temporaryFilePath
379
+ error: NULL ];
380
+ self->_temporaryFilePath = nil ;
359
381
}
360
382
}
361
383
@@ -373,7 +395,8 @@ - (instancetype)initWithDefaultDecoderConfig:(nullable id<TIPXMP4DecoderConfig>)
373
395
return self;
374
396
}
375
397
376
- - (TIPImageDecoderDetectionResult)tip_detectDecodableData : (NSData *)data earlyGuessImageType : (NSString *)imageType
398
+ - (TIPImageDecoderDetectionResult)tip_detectDecodableData : (NSData *)data
399
+ earlyGuessImageType : (nullable NSString *)imageType
377
400
{
378
401
if (data.length < kSignatureDataRequiredToCheck ) {
379
402
return TIPImageDecoderDetectionResultNeedMoreData;
@@ -389,7 +412,9 @@ - (TIPImageDecoderDetectionResult)tip_detectDecodableData:(NSData *)data earlyGu
389
412
return TIPImageDecoderDetectionResultNoMatch;
390
413
}
391
414
392
- - (TIPXMP4DecoderContext *)tip_initiateDecoding : (nullable id )config expectedDataLength : (NSUInteger )expectedDataLength buffer : (nullable NSMutableData *)buffer
415
+ - (TIPXMP4DecoderContext *)tip_initiateDecoding : (nullable id )config
416
+ expectedDataLength : (NSUInteger )expectedDataLength
417
+ buffer : (nullable NSMutableData *)buffer
393
418
{
394
419
id <TIPXMP4DecoderConfig> decoderConfig = nil ;
395
420
if ([config respondsToSelector: @selector (maxDecodableFramesCount )]) {
@@ -398,15 +423,18 @@ - (TIPXMP4DecoderContext *)tip_initiateDecoding:(nullable id)config expectedData
398
423
if (!decoderConfig) {
399
424
decoderConfig = self.defaultDecoderConfig ;
400
425
}
401
- return [[TIPXMP4DecoderContext alloc ] initWithBuffer: buffer ?: [[NSMutableData alloc ] initWithCapacity: expectedDataLength] config: decoderConfig];
426
+ return [[TIPXMP4DecoderContext alloc ] initWithBuffer: buffer ?: [[NSMutableData alloc ] initWithCapacity: expectedDataLength]
427
+ config: decoderConfig];
402
428
}
403
429
404
- - (TIPImageDecoderAppendResult)tip_append : (TIPXMP4DecoderContext *)context data : (NSData *)data
430
+ - (TIPImageDecoderAppendResult)tip_append : (TIPXMP4DecoderContext *)context
431
+ data : (NSData *)data
405
432
{
406
433
return [context appendData: data];
407
434
}
408
435
409
- - (TIPImageContainer *)tip_renderImage : (TIPXMP4DecoderContext *)context mode : (TIPImageDecoderRenderMode)mode
436
+ - (nullable TIPImageContainer *)tip_renderImage : (TIPXMP4DecoderContext *)context
437
+ mode : (TIPImageDecoderRenderMode)mode
410
438
{
411
439
return [context renderImageWithMode: mode];
412
440
}
@@ -432,7 +460,7 @@ - (instancetype)initWithMaxDecodableFramesCount:(NSUInteger)max
432
460
433
461
@end
434
462
435
- static CGImageRef TIPX_CGImageCreateFromCMSampleBuffer (CMSampleBufferRef sampleBuffer)
463
+ static CGImageRef __nullable TIPX_CGImageCreateFromCMSampleBuffer (CMSampleBufferRef __nullable sampleBuffer)
436
464
{
437
465
CVImageBufferRef imageBuffer = sampleBuffer ? CMSampleBufferGetImageBuffer (sampleBuffer) : NULL ;
438
466
if (!imageBuffer) {
@@ -468,3 +496,5 @@ static CGImageRef TIPX_CGImageCreateFromCMSampleBuffer(CMSampleBufferRef sampleB
468
496
469
497
return CGBitmapContextCreateImage (newContext);
470
498
}
499
+
500
+ NS_ASSUME_NONNULL_END
0 commit comments