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

クラッシュ スタックから、イメージ自体が他のスレッドでリリースされているように見えます。おそらくCGImageRetain(). あなたがここに電話しているという事実は、あなたがCGImageRetain()それを期待していることを示唆しています。しかし、その場合、競合状態が発生するため、retain は不十分です。イメージを保持しようとする前に、イメージが破壊されている可能性があります。したがって、CGImageRetainは不要か、不十分です。どちらの場合も、ここにあるべきではありません (また、そのバランスもCGImageRelease)。

これは、他のスレッドでこのイメージを非常に危険に使用していることを示しています。これは、このメソッドを奇妙に呼び出しているか、スレッドが複雑になりすぎていることを示しています。たとえば、NSThread直接使用している場合は、おそらく複雑になりすぎています。

このイメージの他の保持とリリースを監査し、このメソッドの呼び出し中にそれらが発生しないようにします。私はそれが起こっていると確信しています。

補足:必要のない冗長なCGContextRetain/CGContextReleaseがあります。を呼び出したときCGBitmapContextCreate()、保持が含まれていました (名前に「作成」が含まれています)。とはいえ、これはパフォーマンス上の小さな問題にすぎません。あなたはそれらを適切にバランスさせました。ただし、他の場所でのメモリ管理もおかしくなっている可能性があるため、監査する必要があります。

于 2012-12-07T18:26:54.780 に答える