2012-07-06 2 views
5

Sto creando una pipeline semplice che recupera le immagini da AVCaptureSession, le elabora in OpenCV e le esegue quindi in OpenGL. È basato su RosyWriter ma senza le capacità audio e di registrazione. L'elaborazione OpenCV è simile aAcquisire la proprietà della memoria da 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); 
} 

In questa funzione fino ad ora non ho copiato alcuna memoria e vorrei mantenerla in questo modo. Il problema è che pixelBuffer può ancora possedere la memoria contenuta in display_image. Il codice di elaborazione può o non può allocare nuova memoria e memorizzarla nell'immagine. Se l'elaborazione non ha allocato nuova memoria devo passare pixelBuffer in giro con display_matrix per mantenere i dati da cancellare. C'è un modo per me di diventare proprietario della memoria? Voglio distruggere pixelBuffer senza distruggere la memoria che punta troppo.

Su una nota correlata, cosa fa esattamente LockBaseAddress? Se passassi attorno a una coppia cv :: Mat, CVImageBufferRef dovrei bloccare l'indirizzo di base ogni volta che voglio modificare/utilizzare i dati con cv :: Mat?

+0

Hi Hammer, come si esegue il rendering del proprio cv :: Mat in OpenGL ES per favore? Grazie in anticipo – lilouch

risposta

0

È possibile creare il fornitore di dati dai dati dell'indirizzo di base senza copiare, quindi creare UIImage da questo fornitore di dati. Per evitare il riutilizzo del buffer mentre si fa riferimento a questa immagine, è necessario conservare il buffer di campionamento e bloccare l'indirizzo di base. Essi dovrebbero essere sbloccati e rilasciati automaticamente quando si dimentica questo oggetto immagine:

- (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 
} 

Ho imageFromData da questo progetto https://github.com/k06a/UIImage-DecompressAndMap/blob/master/UIImage%2BDecompressAndMap.m e hanno adottato un po ':

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; 
} 

È inoltre necessario fornire :

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