2010-07-29 88 views
10

我在我的iPhone应用程序中使用CGBitmapContextCreateImage时遇到问题。CGBitmapContextCreateImage - vm_copy失败 - iPhone SDK

我使用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上没有任何问题。你能证实这一点吗? – 2010-08-06 01:26:19

+1

我可以确认我下面介绍的修复方法确实有效。我在iOS 4上获得了vm_copy消息。 – mvds 2010-08-12 13:06:06

回答

11

声明:这是纯粹的推测。 不再。

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

您得到的返回值是KERN_PROTECTION_FAILURE,“源区域受保护而不能读取,或者目标区域受到写保护”。

因此,出于某种原因,CGDataProviderCreateWithCopyOfData调用此方法来复制一些内存,并失败。 也许它只是首先尝试vm_copy作为一种快速方法,然后回落到一个较慢的方法(因为你说一切正常)。

如果你malloc大块的内存,从baseAddress memcpy内存到你自己的内存,并用它来创建图像,警告消失。所以:

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

ps。是的,我知道手册页是关于Mac OS X的随机链接,但我想它也适用于iOS。 – mvds 2010-07-30 01:08:56