2010-07-29 2 views
10

iPhone 응용 프로그램에서 CGBitmapContextCreateImage를 사용하는 데 문제가 있습니다. 그러나CGBitmapContextCreateImage - vm_copy failed - iPhone SDK

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

} 

, 나는 그것의 실행과 디버그 콘솔에서 오류를보고하고있다 : 나는이 방법을 사용하여 카메라 프레임을 잡아 AV 재단 프레임 워크를 사용하고

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

지금까지 누군가를 가지고 본거야? 라인을 주석으로 처리하여 문제의 라인을 좁혔습니다 :

CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

그러나 나는 그것을 제거하는 방법을 잘 모르겠습니다. 기능적으로 훌륭하게 작동합니다. 그래서 명확하게 CGImage가 생성되고 있지만 다른 부분에는 영향을 미치지 않도록 오류의 원인을 알아야합니다.

감사합니다. 어떤 도움/조언이 좋을 것입니다! 브렛

+1

동일한 코드에서 동일한 문제가 발생합니다. 그러나 문제는 iOS 4의 iPhone 3G 기기에만 나타납니다. iPhone 4 또는 iPhone 3GS에서도 문제없이 작동합니다. 이거 확인할 수 있니? –

+1

아래 제시된 해결 방법이 효과가 있음을 확인할 수 있습니다. iOS 4를 사용하는 3G에서 vm_copy 메시지가 나타납니다. – mvds

답변

11

면책 조항 : 이것은 순수한 추측입니다. 더 이상 없습니다.

vm_copy()은 가상 메모리를 한 곳에서 다른 곳으로 복사하는 커널 호출입니다 (manpage).

반환 값은 KERN_PROTECTION_FAILURE입니다. "소스 영역이 읽기 금지 상태이거나 대상 영역이 쓰기 금지 상태입니다."

그래서 CGDataProviderCreateWithCopyOfData는 일부 메모리를 복사하기 위해 이것을 호출하고 실패합니다. 어쩌면 빠른 방법으로 vm_copy를 먼저 시도한 다음 모든 방법이 작동한다고 느껴질수록 느린 방법으로 되돌아갑니다.

malloc 메모리 덩어리, 기본 주소에서 메모리에 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. 예, 저는 맨페지가 맥 오에스텐에 대한 임의의 링크라는 것을 알고 있습니다. 그러나 그것은 iOS에도 적용됩니다. – mvds