Created
March 5, 2018 08:31
-
-
Save ourui/b1f3fa9672bc6d4b0bcc199d2be7cfef to your computer and use it in GitHub Desktop.
Reversing Video
This file contains hidden or 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 "AVUtilities.h" | |
#import <AVFoundation/AVFoundation.h> | |
@implementation AVUtilities | |
+ (AVAsset *)assetByReversingAsset:(AVAsset *)asset outputURL:(NSURL *)outputURL { | |
NSError *error; | |
// Initialize the reader | |
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; | |
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] lastObject]; | |
NSDictionary *readerOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange], kCVPixelBufferPixelFormatTypeKey, nil]; | |
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack | |
outputSettings:readerOutputSettings]; | |
[reader addOutput:readerOutput]; | |
[reader startReading]; | |
// read in the samples | |
NSMutableArray *samples = [[NSMutableArray alloc] init]; | |
CMSampleBufferRef sample; | |
while(sample = [readerOutput copyNextSampleBuffer]) { | |
[samples addObject:(__bridge id)sample]; | |
CFRelease(sample); | |
} | |
// Initialize the writer | |
AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:outputURL | |
fileType:AVFileTypeMPEG4 | |
error:&error]; | |
NSDictionary *videoCompressionProps = [NSDictionary dictionaryWithObjectsAndKeys: | |
@(videoTrack.estimatedDataRate), AVVideoAverageBitRateKey, | |
nil]; | |
NSDictionary *writerOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: | |
AVVideoCodecH264, AVVideoCodecKey, | |
[NSNumber numberWithInt:videoTrack.naturalSize.width], AVVideoWidthKey, | |
[NSNumber numberWithInt:videoTrack.naturalSize.height], AVVideoHeightKey, | |
videoCompressionProps, AVVideoCompressionPropertiesKey, | |
nil]; | |
AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo | |
outputSettings:writerOutputSettings | |
sourceFormatHint:(__bridge CMFormatDescriptionRef)[videoTrack.formatDescriptions lastObject]]; | |
[writerInput setExpectsMediaDataInRealTime:NO]; | |
// Initialize an input adaptor so that we can append PixelBuffer | |
AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil]; | |
[writer addInput:writerInput]; | |
[writer startWriting]; | |
[writer startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp((__bridge CMSampleBufferRef)samples[0])]; | |
// Append the frames to the output. | |
// Notice we append the frames from the tail end, using the timing of the frames from the front. | |
for(NSInteger i = 0; i < samples.count; i++) { | |
// Get the presentation time for the frame | |
CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp((__bridge CMSampleBufferRef)samples[i]); | |
// take the image/pixel buffer from tail end of the array | |
CVPixelBufferRef imageBufferRef = CMSampleBufferGetImageBuffer((__bridge CMSampleBufferRef)samples[samples.count - i - 1]); | |
while (!writerInput.readyForMoreMediaData) { | |
[NSThread sleepForTimeInterval:0.1]; | |
} | |
[pixelBufferAdaptor appendPixelBuffer:imageBufferRef withPresentationTime:presentationTime]; | |
} | |
[writer finishWriting]; | |
return [AVAsset assetWithURL:outputURL]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment