4

The call to appendPixelBuffer is returning NO on 3GS device (IOS 4.1), but is working 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]);
}

The error (ONLY ON 3GS, iphone 4 is fine) is

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation couldn’t be completed. (AVFoundationErrorDomain error -11800.)" UserInfo=0x4970530 {NSUnderlyingError=0x496d2c0 "The operation couldn’t be completed. (OSStatus error -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;
}
Till
  • 27,559
  • 13
  • 88
  • 122
jms
  • 41
  • 1
  • 3
  • I'm wondering if it's failing earlier for you. If you check [videoWriter status] while you're initializing everything, where does that start returning **AVAssetWriterStatusFailed**? I ask because I have the same issue (.mp4 creation works on iPhone4 but not on my iPod 3rd gen, which is close to the 3GS). In my case, videoWriter.status changes to AVAssetWriterStatusFailed (with the same generic error message) after I call **startWriting** on it. – Mike Apr 26 '11 at 19:55
  • 1
    I have the same problem on iPhone 3G |no video encoder found for 'avc1'|. Have you found any solution ? The problem also exists on iPhone 3GS ? – TheRonin May 25 '11 at 09:52
  • No solution yet, I've reached out to Apple, but no word from them. I'm assuming this is just not supported on 3GS and older at this point. – jms May 30 '11 at 04:48

1 Answers1

3

Check Console Log in Organizer for device. I got same error on Ipod 2nd Gen and Console Log Reported

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

Exactly what that means still working on, however it points me in a direction.

user747959
  • 31
  • 1