Created
March 22, 2020 04:03
-
-
Save christianselig/6f2a341038122032ef60859413cbc993 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "ObjCRootViewController.h" | |
@import AVFoundation; | |
@import MobileCoreServices; | |
@import Photos; | |
@interface ObjCRootViewController () | |
@end | |
@implementation ObjCRootViewController | |
- (void)viewDidAppear:(BOOL)animated { | |
[super viewDidAppear:animated]; | |
[self startVideoToGIFProgess]; | |
} | |
- (void)startVideoToGIFProgess { | |
NSLog(@"Downloading!"); | |
NSString *urlString = @"https://v.redd.it/naxqsasl2nn41/DASH_720?source=fallback"; | |
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]]; | |
NSString *fileName = [NSString stringWithFormat:@"%@_%@", [[NSProcessInfo processInfo] globallyUniqueString], @"html5gif.mp4"]; | |
NSURL *fileURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:fileName]; | |
[data writeToURL:fileURL atomically:YES]; | |
NSLog(@"Downloaded!"); | |
[self createGIFFromVideoAtURL:fileURL]; | |
} | |
- (void)createGIFFromVideoAtURL:(NSURL *)URL { | |
CFTimeInterval startTime = CACurrentMediaTime(); | |
AVURLAsset *asset = [AVURLAsset assetWithURL:URL]; | |
AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:asset error:nil]; | |
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject]; | |
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: | |
[NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, | |
[NSNumber numberWithInt:328], kCVPixelBufferWidthKey, | |
[NSNumber numberWithInt:480], kCVPixelBufferHeightKey, | |
nil]; | |
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:outputSettings]; | |
[reader addOutput:readerOutput]; | |
[reader startReading]; | |
CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer]; | |
CGFloat delayBetweenFrames = 0.033333; | |
NSDictionary *fileProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount] forKey:(NSString *)kCGImagePropertyGIFDictionary]; | |
NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:delayBetweenFrames] forKey:(NSString *)kCGImagePropertyGIFDelayTime] forKey:(NSString *)kCGImagePropertyGIFDictionary]; | |
NSString *resultingFilename = [NSString stringWithFormat:@"%@_%@", [[NSProcessInfo processInfo] globallyUniqueString], @"html5gif.gif"]; | |
NSURL *resultingFileURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:resultingFilename]; | |
NSInteger totalFrames = 1086; | |
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)resultingFileURL, (CFStringRef)kUTTypeGIF, totalFrames, nil); | |
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties); | |
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; | |
operationQueue.maxConcurrentOperationCount = 1; | |
while (sample) { | |
if (sample) { | |
CGImageRef cgImage = [self cgImageFromSampleBuffer:sample]; | |
[operationQueue addOperationWithBlock:^{ | |
CGImageDestinationAddImage(destination, cgImage, (__bridge CFDictionaryRef)frameProperties); | |
CGImageRelease(cgImage); // Memory never gets out of control | |
}]; | |
} | |
CFRelease(sample); | |
sample = [readerOutput copyNextSampleBuffer]; | |
} | |
[operationQueue waitUntilAllOperationsAreFinished]; | |
CFTimeInterval endTime = CACurrentMediaTime(); | |
NSLog(@"Total Runtime: %g s", endTime - startTime); | |
BOOL result = CGImageDestinationFinalize(destination); | |
NSLog(@"%d did complete", result); | |
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ | |
[PHAssetCreationRequest creationRequestForAssetFromImageAtFileURL:resultingFileURL]; | |
} completionHandler:^(BOOL success, NSError * _Nullable error) { | |
NSLog(@"Saved successfully? %d", success); | |
}]; | |
} | |
- (CGImageRef)cgImageFromSampleBuffer:(CMSampleBufferRef)buffer { | |
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(buffer); | |
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); | |
void* baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer); | |
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer); | |
size_t width = CVPixelBufferGetWidth(pixelBuffer); | |
size_t height = CVPixelBufferGetHeight(pixelBuffer); | |
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedFirst); | |
CGImageRef image = CGBitmapContextCreateImage(context); | |
CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); | |
CGContextRelease(context); | |
return image; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment