【问题标题】:CGBitmapContextCreateImage - vm_copy failed - iPhone SDKCGBitmapContextCreateImage - vm_copy 失败 - iPhone SDK
【发布时间】:2010-07-29 23:53:26
【问题描述】:

我在 iPhone 应用程序中使用 CGBitmapContextCreateImage 时遇到问题。

我正在使用 AV Foundation Framework 使用这种方法抓取相机帧:

- (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,但我需要知道导致错误的原因,以免影响其他部分。

非常感谢。任何帮助/建议都会很棒! 布雷特

【问题讨论】:

  • 我在使用相同的代码时遇到了同样的问题。但是这个问题只出现在 iOS 4 上的 iPhone 3G 设备上。它在 iPhone 4 或 iPhone 3GS 上没有任何问题。你能确认一下吗?
  • 我可以确认我在下面提出的修复确实有效。我在使用 iOS 4 的 3G 设备上收到了 vm_copy 消息。

标签: iphone objective-c cgimage


【解决方案1】:

免责声明:这纯属猜测。不再。

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。是的,我知道手册页是关于 Mac OS X 的随机链接,但我想它也适用于 iOS。
猜你喜欢
  • 2011-05-22
  • 2010-11-28
  • 1970-01-01
  • 2012-03-18
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多