0

我正在尝试从 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
4

1 回答 1

1

From the crash stack, it looks like your image itself is released on some other thread, probably prior to your call to CGImageRetain(). The fact that you're calling CGImageRetain() here suggests that you expect that. But if that's the case, the retain is insufficient, since it creates a race condition. The image may have been destroyed before you try to retain it. So either the CGImageRetain is unnecessary or it is insufficient. In neither case should it be here (nor its balancing CGImageRelease).

This suggests very dangerous use of this image on some other thread, which either suggests that you're calling this method oddly, or that you've let your threading get over-complicated. For instance, if you're using NSThread directly, you've probably let it get too complicated.

I would audit your other retains and releases on this image and make sure that they cannot happen in the middle of calling this method. I'm pretty sure that's what's happening.

A side note: you have a redundant CGContextRetain/CGContextRelease that are not needed. When you called CGBitmapContextCreate(), that included a retain (it has "Create" in the name). That said, this is just a minor performance problem; you've properly balanced them. But it suggests that your memory management elsewhere may also be odd, and so you should audit it.

于 2012-12-07T18:26:54.780 回答