Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASSETWriterInput for making Video from UIImages on Iphone Issues

I try the following 2 methods of appending UIImages pixelbuffer to ASSETWriterInput. Everything looks good except there's No data in the video file. What's wrong?

1 Adaptor class

AVAssetWriterInputPixelBufferAdaptor * avAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:NULL];  [avAdaptor appendPixelBufferixelBuffer withPresentationTime:CMTimeMake(1, 10)]; 

2 Making the

// Create sample buffer. CMSampleBufferRef sampleBuffer = NULL; result = CMSampleBufferCreateForImageBuffer(kCFAllocatorDef ault, pixelBuffer, true, NULL, NULL, videoInfo, &timing, &sampleBuffer);  // Ship out the frame. NSParameterAssert(CMSampleBufferDataIsReady(sample Buffer)); NSParameterAssert([writerInput isReadyForMoreMediaData]); BOOL success = [writerInput appendSampleBuffer:sampleBuffer]; 
like image 857
lilzz Avatar asked Oct 21 '10 02:10

lilzz


2 Answers

I found that for some reason I needed to append the buffer more than once. The timing in this example from a test app I made might not be proper, but since it works it should give you a good idea.

+ (void)writeImageAsMovie:(UIImage*)image toPath:(NSString*)path size:(CGSize)size duration:(int)duration  {     NSError *error = nil;     AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:                                   [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie                                                               error:&error];     NSParameterAssert(videoWriter);      NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:                                    AVVideoCodecH264, AVVideoCodecKey,                                    [NSNumber numberWithInt:size.width], AVVideoWidthKey,                                    [NSNumber numberWithInt:size.height], AVVideoHeightKey,                                    nil];     AVAssetWriterInput* writerInput = [[AVAssetWriterInput                                         assetWriterInputWithMediaType:AVMediaTypeVideo                                         outputSettings:videoSettings] retain];      AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor                                                      assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput                                                      sourcePixelBufferAttributes:nil];     NSParameterAssert(writerInput);     NSParameterAssert([videoWriter canAddInput:writerInput]);     [videoWriter addInput:writerInput];      //Start a session:     [videoWriter startWriting];     [videoWriter startSessionAtSourceTime:kCMTimeZero];      //Write samples:     CVPixelBufferRef buffer = [Utils pixelBufferFromCGImage:image.CGImage size:size];     [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];     [adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(duration-1, 2)];      //Finish the session:     [writerInput markAsFinished];     [videoWriter endSessionAtSourceTime:CMTimeMake(duration, 2)];     [videoWriter finishWriting]; } 

This method is not required, but is used here as an example of a pixel buffer source:

+ (CVPixelBufferRef) pixelBufferFromCGImage:(CGImageRef)image size:(CGSize)size {     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:                              [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,                              [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,                              nil];     CVPixelBufferRef pxbuffer = NULL;     CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width,                           size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,                            &pxbuffer);     status=status;//Added to make the stupid compiler not show a stupid warning.     NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);      CVPixelBufferLockBaseAddress(pxbuffer, 0);     void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);     NSParameterAssert(pxdata != NULL);      CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();     CGContextRef context = CGBitmapContextCreate(pxdata, size.width,                                                  size.height, 8, 4*size.width, rgbColorSpace,                                                   kCGImageAlphaNoneSkipFirst);     NSParameterAssert(context);      //CGContextTranslateCTM(context, 0, CGImageGetHeight(image));     //CGContextScaleCTM(context, 1.0, -1.0);//Flip vertically to account for different origin      CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),                                           CGImageGetHeight(image)), image);     CGColorSpaceRelease(rgbColorSpace);     CGContextRelease(context);      CVPixelBufferUnlockBaseAddress(pxbuffer, 0);      return pxbuffer; } 
like image 188
Peter DeWeese Avatar answered Sep 20 '22 02:09

Peter DeWeese


I've had a bit of a problem with this code. It geave me a skewed image as a result.

Changing:

CGContextRef context = CGBitmapContextCreate(pxdata,                                              size.width,                                              size.height,                                              8,                                              4 * size.width,                                              rgbColorSpace,                                              kCGImageAlphaNoneSkipFirst); 

To:

CGContextRef context = CGBitmapContextCreate(pxdata,                                              size.width,                                              size.height,                                              8,                                              CVPixelBufferGetBytesPerRow(pxbuffer),                                              rgbColorSpace,                                              kCGImageAlphaNoneSkipFirst); 

helped.

like image 28
Szymon Kuczur Avatar answered Sep 24 '22 02:09

Szymon Kuczur