CGContextDrawImage崩溃

时间:2012-12-07 17:06:09

标签: iphone objective-c ios core-graphics

我正在尝试从CGImage创建CVPixelBufferRef,所以这是方法:

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

我已经测试了内存使用情况和内存泄漏情况,所有内容都很好,但是崩溃仍然存在。

崩溃堆栈: 线程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

1 个答案:

答案 0 :(得分:1)

从崩溃堆栈中,看起来您的图像本身在其他线程上发布,可能在您致电CGImageRetain()之前。您在此处致电CGImageRetain()这一事实表明您希望如此。但如果是这种情况,保留是不够的,因为它会造成竞争条件。在您尝试保留图像之前,图像可能已被破坏。所以要么CGImageRetain是不必要的,要么是不够的。在任何情况下都不应该在这里(也不是它的平衡CGImageRelease)。

这表明在其他一些帖子上非常危险地使用这个图像,这或者暗示你正在奇怪地调用这个方法,或者你让你的线程变得过于复杂。例如,如果您直接使用NSThread,则可能会让它变得太复杂。

我会在此图像上审核您的其他保留和发布,并确保在调用此方法时不会发生这些情况。我很确定这是发生了什么。

附注:您有一个不需要的冗余CGContextRetain / CGContextRelease。当您调用CGBitmapContextCreate()时,其中包含一个保留(名称中包含“创建”)。也就是说,这只是一个小问题;你已经适当地平衡了它们。但它表明你在其他地方的记忆管理也可能很奇怪,所以你应该审核它。