views:

248

answers:

1

Hi all, I am having an issue using CGBitmapContextCreateImage in my iPhone app.

I am using AV Foundation Framework to grab camera frames using this method:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer,0);
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGImageRef newImage = CGBitmapContextCreateImage(newContext);
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    CGContextRelease(newContext);
    CGColorSpaceRelease(colorSpace);

    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];
    self.imageView.image = image;

    CGImageRelease(newImage);

} 

However, I am seeing an error in the debug console as its runs:

<Error>: CGDataProviderCreateWithCopyOfData: vm_copy failed: status 2.

Has anyone ever seen this? By commenting out lines I have narrowed the problem line out to:

CGImageRef newImage = CGBitmapContextCreateImage(newContext);

but I am not sure how to get rid of it. Functionally, it works great. So clearly, the CGImage is being created, but I need to know what is causing the error so it doesn't affect other parts.

Many thanks. Any help/advice would be great! Brett

+1  A: 

Disclaimer: this is pure speculation. Not anymore.

vm_copy() is a kernel call to copy virtual memory from one place to another (manpage).

The return value you get is KERN_PROTECTION_FAILURE, "The source region is protected against reading, or the destination region is protected against writing."

So for some reason CGDataProviderCreateWithCopyOfData calls this to copy some memory, and fails. maybe it is just trying vm_copy as a fast method first, and then falls back to a slower method (since you say everything works).

If you malloc a chunk of memory, memcpy the memory from baseAddress to your own memory, and use that to create the image, the warning vanishes. So:

uint8_t *tmp = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
int bytes = ... // determine number of bytes from height * bytesperrow
uint8_t *baseAddress = malloc(bytes);
memcpy(baseAddress,tmp,bytes);

// unlock the memory, do other stuff, but don't forget:
free(baseAddress);
mvds
ps. yes I know the manpage is a random link about Mac OS X, but I guess it applies to iOS too.
mvds