CGBitmapContextCreateImage - vm_copy failed - iPhone SDK CGBitmapContextCreateImage函数-vm_copy失败-iPhone SDK

10

我在使用CGBitmapContextCreateImage时遇到了问题,这是在我的iPhone应用程序中。

我正在使用AV Foundation框架来使用此方法抓取相机帧:

- (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);

} 

然而,我在调试控制台中看到了一个错误,因为它正在运行:

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

有人见过这个问题吗?通过注释掉一些行,我已经缩小了问题所在的范围:

CGImageRef newImage = CGBitmapContextCreateImage(newContext);

但我不确定如何摆脱它。从功能上讲,它运行得很好。因此,CGImage正在被创建,但我需要知道是什么导致错误,以便它不会影响其他部分。

非常感谢。任何帮助/建议都将是极好的! Brett


1
我遇到了同样的问题,使用相同的代码。但是这个问题只在iOS 4上的iPhone 3G设备上出现。在iPhone 4或iPhone 3GS上没有任何问题。你能确认一下吗? - Sascha Konietzke
1
我可以确认下面我提供的修复方法确实有效。我在一台安装了iOS 4的3G手机上收到了vm_copy消息。 - mvds
1个回答

11

免责声明:这只是纯粹的猜测。 不再是了。

vm_copy()是一个内核调用,用于从一个地方复制虚拟内存到另一个地方 (manpage)。

你得到的返回值是KERN_PROTECTION_FAILURE,"源区域被保护不允许读取,或目标区域被保护不允许写入。"

所以由于某种原因,CGDataProviderCreateWithCopyOfData调用这个函数来复制一些内存,但失败了。可能它只是先尝试使用vm_copy作为快速方法,然后回退到更慢的方法(因为你说一切正常)。

如果你malloc一块内存,将内存从baseAddress复制到自己的内存中,并使用它来创建图像,警告就会消失。所以:

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);

PS:是的,我知道 manpage 是关于 Mac OS X 的随机链接,但我想它也适用于 iOS。 - mvds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接