Skip to content

Commit 45d2042

Browse files
authored
V2.10.0 (#35)
* Update TIP to v2.10.0 - Fix MP4 decoder when decoding anamorphic mp4s into animations - drop iOS 7 support - fix miscellaneous bugs - clean up misc style - fix tvOS support - add tvOS target
1 parent fe61c0e commit 45d2042

38 files changed

+970
-224
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
language: objective-c
2-
osx_image: xcode9.3
2+
osx_image: xcode9.4
33
script:
44
./build.sh

CHANGELOG.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,23 @@
22

33
## Info
44

5-
**Document version:** 2.9.3
5+
**Document version:** 2.10.0
66

7-
**Last updated:** 05/16/2018
7+
**Last updated:** 08/17/2018
88

99
**Author:** Nolan O'Brien
1010

1111
## History
1212

13+
### 2.10.0
14+
15+
- drop support for iOS 7
16+
- the code had already diverged to requiring many iOS 8+ only APIs, this just makes it official
17+
18+
### 2.9.4 - Armand Raynor
19+
20+
- Fix MP4 decoder when decoding anamorphic mp4s into animations
21+
1322
### 2.9.3
1423

1524
- Add `notifyAllFetchHelpersToRetryFailedLoads` class method to `TIPImageViewFetchHelper`

Extended/TIPXMP4Codec.m

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,16 @@ __strong tipx_defer_block_t tipx_macro_concat(tipx_stack_defer_block_, __LINE__)
6262
};
6363
static const size_t kSignatureDataRequiredToCheck = sizeof(kComplexSignature1) + 4;
6464

65+
static const CGFloat kAdjustmentEpsilon = (CGFloat)0.005;
66+
6567
#pragma mark - Declarations
6668

6769
static CGImageRef __nullable TIPX_CGImageCreateFromCMSampleBuffer(CMSampleBufferRef __nullable sample) CF_RETURNS_RETAINED;
6870

71+
static BOOL TIPX_imageNeedsScaling(CGImageRef imageRef, CGSize naturalSize);
72+
73+
static UIImage *TIPX_scaledImage(CGImageRef imageRef, CGSize naturalSize, CIContext *context);
74+
6975
@interface TIPXMP4DecoderConfigInternal : NSObject <TIPXMP4DecoderConfig>
7076
- (instancetype)initWithMaxDecodableFramesCount:(NSUInteger)max;
7177
@end
@@ -214,15 +220,24 @@ - (TIPImageContainer *)_tipx_firstFrameImageContainer
214220
if (_temporaryFile || _finalized) {
215221
@autoreleasepool {
216222
AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:self->_temporaryFilePath]];
217-
AVAssetImageGenerator* imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
223+
AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
218224
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:CMTimeMake(0, 1)
219225
actualTime:nil
220226
error:nil];
227+
TIPXDeferRelease(imageRef);
228+
221229
if (imageRef) {
222-
UIImage* image = [UIImage imageWithCGImage:imageRef
223-
scale:[UIScreen mainScreen].scale
224-
orientation:UIImageOrientationUp];
225-
CFRelease(imageRef);
230+
AVAssetTrack *track = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
231+
CGSize naturalSize = track.naturalSize;
232+
UIImage *image;
233+
if (track && TIPX_imageNeedsScaling(imageRef, naturalSize)) {
234+
image = TIPX_scaledImage(imageRef, naturalSize, [[CIContext alloc] init]);
235+
}
236+
if (!image) {
237+
image = [UIImage imageWithCGImage:imageRef
238+
scale:[UIScreen mainScreen].scale
239+
orientation:UIImageOrientationUp];
240+
}
226241
if (image) {
227242
self->_firstFrame = image;
228243
}
@@ -267,6 +282,8 @@ - (nullable TIPImageContainer *)renderImageWithMode:(TIPImageDecoderRenderMode)m
267282
message:error.description];
268283
return;
269284
}
285+
286+
CGSize naturalSize = self->_avTrack.naturalSize;
270287

271288
NSDictionary *outputSettings = @{
272289
(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)
@@ -288,25 +305,32 @@ - (nullable TIPImageContainer *)renderImageWithMode:(TIPImageDecoderRenderMode)m
288305
mod++;
289306
}
290307

291-
CMSampleBufferRef sample = NULL;
292-
do {
293-
sample = [output copyNextSampleBuffer];
294-
TIPXDeferRelease(sample);
295-
296-
if (mod > 1 && ((++count % mod) != 1)) {
297-
continue;
298-
}
308+
CIContext *context;
299309

300-
CGImageRef imageRef = TIPX_CGImageCreateFromCMSampleBuffer(sample);
301-
TIPXDeferRelease(imageRef);
310+
CMSampleBufferRef sample = NULL;
311+
do {
312+
sample = [output copyNextSampleBuffer];
313+
TIPXDeferRelease(sample);
314+
if (mod > 1 && ((++count % mod) != 1)) {
315+
continue;
316+
}
302317

303-
if (imageRef) {
304-
UIImage *image = [UIImage imageWithCGImage:imageRef];
305-
if (image) {
318+
CGImageRef imageRef = TIPX_CGImageCreateFromCMSampleBuffer(sample);
319+
TIPXDeferRelease(imageRef);
320+
if (imageRef) {
321+
UIImage *image = nil;
322+
if (TIPX_imageNeedsScaling(imageRef, naturalSize)) {
323+
if (!context) {
324+
context = [[CIContext alloc] init];
325+
}
326+
image = TIPX_scaledImage(imageRef, naturalSize, context);
327+
}
328+
if (!image) {
329+
image = [[UIImage alloc] initWithCGImage:imageRef];
330+
}
306331
[images addObject:image];
307332
}
308-
}
309-
} while (sample != NULL);
333+
} while (sample != NULL);
310334

311335
self->_frameCount = images.count;
312336

@@ -497,4 +521,44 @@ static CGImageRef __nullable TIPX_CGImageCreateFromCMSampleBuffer(CMSampleBuffer
497521
return CGBitmapContextCreateImage(newContext);
498522
}
499523

524+
static BOOL TIPX_imageNeedsScaling(CGImageRef imageRef, CGSize naturalSize)
525+
{
526+
if (imageRef && CGImageGetWidth(imageRef) > 0 && CGImageGetHeight(imageRef) > 0) {
527+
const CGFloat widthScale = naturalSize.width / CGImageGetWidth(imageRef);
528+
const CGFloat heightScale = naturalSize.height / CGImageGetHeight(imageRef);
529+
530+
if (ABS(widthScale - 1) > kAdjustmentEpsilon || ABS(heightScale - 1) > kAdjustmentEpsilon) {
531+
return YES;
532+
}
533+
}
534+
535+
return NO;
536+
}
537+
538+
static UIImage *TIPX_scaledImage(CGImageRef imageRef, CGSize naturalSize, CIContext *context)
539+
{
540+
CGImageRef finalImageRef = NULL;
541+
542+
@autoreleasepool {
543+
if (imageRef) {
544+
const CGFloat widthScale = naturalSize.width / CGImageGetWidth(imageRef);
545+
const CGFloat heightScale = naturalSize.height / CGImageGetHeight(imageRef);
546+
547+
CIImage *ciimage = [CIImage imageWithCGImage:imageRef];
548+
ciimage = [ciimage imageByApplyingTransform:CGAffineTransformMakeScale(widthScale, heightScale)];
549+
CGImageRef scaledImageRef = [context createCGImage:ciimage fromRect:ciimage.extent];
550+
if (scaledImageRef) {
551+
finalImageRef = scaledImageRef;
552+
}
553+
}
554+
}
555+
556+
if (finalImageRef) {
557+
TIPXDeferRelease(finalImageRef);
558+
return [UIImage imageWithCGImage:finalImageRef];
559+
}
560+
561+
return nil;
562+
}
563+
500564
NS_ASSUME_NONNULL_END

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ for a smaller image than the image in cache, no need to hit the network :)
109109

110110
A great value that the _image pipeline_ offers is the ability to stream progressive scans of an
111111
image, if it is PJPEG, as the image is loaded from the Network. This progressive rendering is
112-
natively supported by iOS 8+, but will not be supported in iOS 7 (the minimum OS for *TIP*).
112+
natively supported by iOS 8+, the same minimum OS for *TIP*.
113113
Progressive support is opt-in and also configurable in how scans should load.
114114

115115
### Resuming Image Downloads
@@ -153,6 +153,7 @@ image pipeline works.
153153
- Image response "Accept-Ranges" must be "bytes" and have "Last-Modified" header
154154
- Uses "Range" and "If-Range" headers to specify continuation
155155
- Pluggable networking (use your own network layer)
156+
- Check out how to integrate [Twitter Network Layer](https://github.com/twitter/ios-twitter-network-layer) as your pluggable downloader with this [gist](https://gist.github.com/NSProgrammer/6e4c93ca9b9518178c9cbc7d950efd9c)
156157
- Custom hydration (useful for authenticated fetches)
157158
- Detailed insights
158159
- Global pipeline observability

TwitterImagePipeline.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
Pod::Spec.new do |s|
22
s.name = 'TwitterImagePipeline'
3-
s.version = '2.9.3'
3+
s.version = '2.10.0'
44
s.summary = 'Twitter Image Pipeline is a robust and performant image loading and caching framework for iOS'
55
s.description = 'Twitter created a framework for image loading/caching in order to fulfill the numerous needs of Twitter for iOS including being fast, safe, modular and versatile.'
66
s.homepage = 'https://github.com/twitter/ios-twitter-logging-service'
77
s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' }
88
s.author = { 'Twitter' => 'opensource@twitter.com' }
99
s.source = { :git => 'https://github.com/twitter/ios-twitter-image-pipeline.git', :tag => s.version.to_s }
10-
s.ios.deployment_target = '7.0'
10+
s.ios.deployment_target = '8.0'
1111

1212
s.subspec 'Default' do |sp|
1313
sp.source_files = 'TwitterImagePipeline/**/*'

0 commit comments

Comments
 (0)