2012-07-06 3 views
5

AVCaptureSession에서 이미지를 가져 와서 OpenCV에서 처리 한 다음 OpenGL에서 렌더링하는 간단한 파이프 라인을 만들고 있습니다. RosyWriter를 기반으로하지만 오디오 및 녹음 기능은 없습니다. 이 기능에CVImageBufferRef에서 메모리 소유권 가져 오기

- (void)processPixelBuffer: (CVImageBufferRef)pixelBuffer 
{ 
CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
int bufferWidth = CVPixelBufferGetWidth(pixelBuffer); 
int bufferHeight = CVPixelBufferGetHeight(pixelBuffer); 
unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer); 

cv::Mat image = cv::Mat(bufferWidth,bufferHeight,CV_8UC4,pixel); 
//do any processing 
[self setDisplay_matrix:image]; 
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 
} 

지금까지 내가 어떤 메모리를 복사하지 않은 내가 그런 식으로 유지하고 싶은 것처럼 OpenCV의 처리 보인다. 문제는 pixelBuffer가 여전히 display_image에 포함 된 메모리를 소유 할 수 있다는 것입니다. 처리 코드는 새 메모리를 할당하거나 할당하지 않을 수도 있고 이미지에 저장할 수도 있습니다. 처리가 새 메모리를 할당하지 않은 경우 데이터가 지워지지 않도록 display_matrix와 함께 pixelBuffer를 전달해야합니다. 기억의 소유권을 가져갈 수있는 방법이 있습니까? 픽셀 버퍼를 손상시키지 않고 pixelBuffer를 파괴하려고합니다.

관련 메모에서 LockBaseAddress는 정확히 무엇을 수행합니까? cv :: Mat, CVImageBufferRef 쌍을 지나가고 있다면, 수정/cv :: Mat으로 데이터를 사용할 때마다 기본 주소를 잠궈 야합니까?

+0

안녕 해머, 당신의 OpenGL ES로 이력서 :: 매트 이미지를하십시오 렌더링 어떻게? 미리 감사드립니다. – lilouch

답변

0

복사하지 않고 기본 주소 데이터에서 데이터 공급자를 만든 다음이 데이터 공급자에서 UIImage를 만들 수 있습니다. 이 이미지를 참조하는 동안 버퍼를 재사용하지 않으려면 샘플 버퍼와 기본 주소를 유지해야합니다. 그들은 잠금을 해제하고 자동으로 해제 당신이이 이미지 객체 잊지 때해야한다 :이 프로젝트 https://github.com/k06a/UIImage-DecompressAndMap/blob/master/UIImage%2BDecompressAndMap.m에서 imageFromData있어

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    // Retain sample buffer and lock base address 
    CFRetain(sampleBuffer); 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    void *baseAddress = (void *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); 

    UIImage *image = imageFromData(baseAddress, width, height, bytesPerRow, sampleBuffer); 

    // Now you can store this UIImage as long as you want 
} 

을하고 그것을 조금 채택 :

UIImage *imageFromData(void *data, size_t width, size_t height, size_t bytesPerRow, CMSampleBufferRef sampleBuffer) 
{ 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGDataProviderRef provider = CGDataProviderCreateWithData((void *)sampleBuffer, data, bytesPerRow * height, munmap_wrapper); 
    CGImageRef inflatedImage = CGImageCreate(width, height, 8, 4*8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, provider, NULL, NO, kCGRenderingIntentDefault); 

    CGColorSpaceRelease(colorSpace); 
    CGDataProviderRelease(provider); 

    UIImage *img = [UIImage imageWithCGImage:inflatedImage scale:scale orientation:UIImageOrientationUp]; 
    CGImageRelease(inflatedImage); 
    return img; 
} 

또한 제공 할 필요를 unlock_function :

void unlock_function(void *info, const void *data, size_t size) 
{ 
    // Unlock base address release sample buffer 
    CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)info; 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 
    CFRelease(sampleBuffer); 
} 
관련 문제