2012-12-07 32 views
0

我試圖從CGImage創建CVPixelBufferRef所以這裏是方法:CGContextDrawImage崩潰

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image 
{ 
    CGImageRetain(image); 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 

    CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image), 
         CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (CFDictionaryRef) options, 
         &pxbuffer); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image), 
               CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 
    CGContextRetain(context); 
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
               CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 
    CGContextRelease(context); 
    CGImageRelease(image); 
    return pxbuffer; 
} 

我常常調用這個方法,它是用於生成視頻幀,25fps的。 能正常工作的大部分時間,但在某些時候它崩潰了這一行代碼:

CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
                CGImageGetHeight(image)), image); 

I`ve測試的內存使用率和內存泄漏和接縫都很好,但暗戀STIL發生。

崩潰堆棧: 螺紋6崩潰:

0 ImageIO       0x39270806 CGImageReadGetBytesAtOffset + 34 
1 ImageIO       0x392707d6 CGImageReadSessionGetBytes + 22 
2 ImageIO       0x39280c3c fill_input_buffer + 148 
3 ImageIO       0x3928003a read_markers + 154 
4 ImageIO       0x3927fd82 consume_markers + 34 
5 ImageIO       0x3927fbd2 _cg_jpeg_consume_input + 66 
6 ImageIO       0x3927fb62 _cg_jpeg_read_header + 38 
7 ImageIO       0x39292782 copyImageBlockSetJPEG + 2346 
8 ImageIO       0x3928953e ImageProviderCopyImageBlockSetCallback + 510 
9 CoreGraphics     0x38e0b9d6 CGImageProviderCopyImageBlockSetWithOptions + 158 
10 CoreGraphics     0x38e0b66a img_blocks_create + 370 
11 CoreGraphics     0x38e07a98 img_data_lock + 1488 
12 CoreGraphics     0x38e06d2a CGSImageDataLock + 126 
+0

這樣的:[http://stackoverflow.com/questions/10774392/cgcontextdrawimage-crashes] [1] 嘗試保留pxdata [1]:http://stackoverflow.com/questions/10774392/cgcontextdrawimage-崩潰 – zengcity

回答

1

從崩潰棧,它看起來像你的圖像本身被釋放一些其他線程,可能您的來電CGImageRetain()之前。你在這裏打電話給CGImageRetain()的事實表明你期待這一點。但是,如果是這樣,保留是不夠的,因爲它造成了競爭條件。在嘗試保留圖像之前,圖像可能已被破壞。所以CGImageRetain是不必要的,或者是不夠的。在任何情況下都不應該在這裏(也不要平衡CGImageRelease)。

這表明在其他線程上使用此映像非常危險,這表明您調用此方法的方式很奇怪,或者說您讓線程變得過於複雜。例如,如果您直接使用NSThread,則可能會讓它變得太複雜。

我會審覈您的其他保留和釋放此圖像,並確保它們不能在調用此方法的過程中發生。我很確定那就是發生了什麼事。

備註:您有一個不需要的多餘的CGContextRetain/CGContextRelease。當你調用CGBitmapContextCreate()時,包括一個保留(它在名稱中有「創建」)。這就是說,這只是一個小小的性能問題;你已經適當地平衡了它們。但是這表明你在其他地方的內存管理可能也很奇怪,所以你應該對它進行審計。

+0

按照你的建議,我已努力使圖像的副本: - (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)imageInput { CGImageRef圖像= CGImageCreateCopy(imageInput); 。 。 但事故仍在。如果問題是線程,這需要解決? –

+0

在第一行製作副本並不會改變任何有關競爭條件的內容(它在內存方面與保留相同)。這聽起來像你在沒有保留圖像的時候調用這個方法。也許你已經調用了'image.CGImage',然後發佈了'image'。也許你已經使用了從其他地方傳遞過來的CGImage,然後在另一個線程上使用它而不保留它。但是在切換線程之前你必須解決這個問題。這個問題幾乎肯定存在於這種方法之外。當人們用'NSThread'手動線程時,這些錯誤是最常見的。 –