2010-07-29 87 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