2010-07-29 10 views
10

Ho riscontrato un problema con CGBitmapContextCreateImage nella mia app per iPhone.CGBitmapContextCreateImage - vm_copy non riuscito - iPhone SDK

Sto usando AV Foundation Framework per afferrare fotogrammi della telecamera con questo metodo:

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

} 

Tuttavia, sto vedendo un errore nella console di debug come le sue piste:

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

qualcuno ha mai Visto? Commentando le linee che ho ridotto la linea problema fuori a:

CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

ma non sono sicuro di come sbarazzarsi di esso. Funzionalmente, funziona alla grande. Quindi, chiaramente, viene creato il CGImage, ma ho bisogno di sapere che cosa sta causando l'errore in modo che non abbia effetto su altre parti.

Molte grazie. Qualsiasi aiuto/consiglio sarebbe fantastico! Brett

+1

Ho lo stesso problema con lo stesso codice. Ma il problema appare solo sui dispositivi iPhone 3G su iOS 4. Funziona senza problemi su un iPhone 4 o iPhone 3GS. Puoi confermare questo? –

+1

Posso confermare che la correzione che ho presentato di seguito funziona. Ho ricevuto il messaggio vm_copy su un 3G con iOS 4. – mvds

risposta

11

Disclaimer: questa è pura speculazione. Non più.

vm_copy() è una chiamata del kernel per copiare la memoria virtuale da un luogo a un altro (manpage).

Il valore di ritorno che si ottiene è KERN_PROTECTION_FAILURE, "La regione di origine è protetta dalla lettura, o la regione di destinazione è protetta dalla scrittura."

Quindi per qualche motivo CGDataProviderCreateWithCopyOfData chiama questo per copiare un po 'di memoria e fallisce. forse si sta provando prima vm_copy come metodo veloce e poi si torna a un metodo più lento (dal momento che si dice che tutto funziona).

Se si malloc un pezzo di memoria, memcpy la memoria da BaseAddress alla propria memoria, e utilizzare quello per creare l'immagine, l'avviso svanisce. Quindi:

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. sì, so che la pagina di manuale è un collegamento casuale su Mac OS X, ma suppongo che si applica anche a iOS. – mvds