Using AVAssetWriter to create a movie from images does not work properly on a 3GS device

Calling appendPixelBuffer returns NO on a 3GS device (iOS 4.1), but works well on iPhone 4 devices.

The following call to appendPixelBuffer is the source of the problem:

CVPixelBufferRef buffer = NULL; buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@"frame1.png"] CGImage]]; BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; if (result == NO) //failes on 3GS, but works on iphone 4 NSLog(@"failed to append buffer"); 

}

Full code:

 -(void)writeImagesAsMovie:(NSArray *)array toPath:(NSString*)path { NSLog(path); NSError *error = nil; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie error:&error]; if(error) { NSLog(@"error creating AssetWriter: %@",[error description]); } 

Error (ONLY on 3GS, iphone 4 ok)

Domain Error = AVFoundationErrorDomain Code = -11800 "Operation could not be completed. (AVFoundationErrorDomain error -11800.)" UserInfo = 0x4970530 {NSUnderlyingError = 0x496d2c0 "operation could not be completed. (Error OSStatus -12908.)"}}

 NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:frameSize.width], AVVideoWidthKey, [NSNumber numberWithInt:frameSize.height], AVVideoHeightKey, nil]; AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; NSMutableDictionary *attributes = [[NSMutableDictionary alloc]init]; [attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey]; [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString*)kCVPixelBufferWidthKey]; [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString*)kCVPixelBufferHeightKey]; AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:attributes]; [videoWriter addInput:writerInput]; // fixes all errors writerInput.expectsMediaDataInRealTime = YES; //Start a session: BOOL start = [videoWriter startWriting]; NSLog(@"Session started? %d", start); [videoWriter startSessionAtSourceTime:kCMTimeZero]; CVPixelBufferRef buffer = NULL; buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@"frame1.png"] CGImage]]; BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; if (result == NO) //failes on 3GS, but works on iphone 4 NSLog(@"failed to append buffer"); if(buffer) CVBufferRelease(buffer); [NSThread sleepForTimeInterval:0.05]; //for (int i = 1;i<[array count]; i++) for (int i = 1;i<20; i++) { if (adaptor.assetWriterInput.readyForMoreMediaData) { NSLog(@"inside for loop %d",i); CMTime frameTime = CMTimeMake(1, 15); CMTime lastTime=CMTimeMake(i, 15); CMTime presentTime=CMTimeAdd(lastTime, frameTime); NSString *imgName = [NSString stringWithFormat:@"frame%d.png",i]; UIImage *imgFrame = [UIImage imageNamed:imgName] ; buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]]; BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]; if (result == NO) //failes on 3GS, but works on iphone 4 { NSLog(@"failed to append buffer"); NSLog(@"The error is %@", [videoWriter error]); } if(buffer) CVBufferRelease(buffer); [NSThread sleepForTimeInterval:0.05]; } else { NSLog(@"error"); i--; } } //Finish the session: [writerInput markAsFinished]; [videoWriter finishWriting]; CVPixelBufferPoolRelease(adaptor.pixelBufferPool); [videoWriter release]; [writerInput release]; NSLog(@"Movie created successfully"); } - (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image { NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; CVPixelBufferRef pxbuffer = NULL; CVPixelBufferCreate(kCFAllocatorDefault, self.view.frame.size.width, self.view.frame.size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options, &pxbuffer); CVPixelBufferLockBaseAddress(pxbuffer, 0); void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(pxdata, self.view.frame.size.width, self.view.frame.size.height, 8, 4*self.view.frame.size.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer; } 
+4
source share
2 answers

Check Console Log in to Organizer for the device. I got the same error on the 2nd generation iPod and console log.

com.apple.mediaserverd [18]: VTSelectAndCreateVideoEncoderInstance: no video encoder found for 'avc1'

Exactly what this means is still working, however it is pointing me in the direction.

+3
source

use https://github.com/caferrara/img-to-video , it works on the iPhone 3gs device.

+3
source

All Articles