VTDecompressionSession-IOSurface分配逐渐增加

时间:2019-02-18 08:40:11

标签: ios objective-c xcode10 decoder iosurface

我正在使用VTDecompressionSession解码.h264流。解码器按预期工作,我得到正确解码的缓冲区。但是,我看到XCode工具“分配”中的“创建且持久”分配逐渐增加。如屏幕截图所示,这些可以归因于解码器在内部分配的IOSurface缓冲区,即使在释放VTDecompressionSession之后也不会释放这些缓冲区。我在同步解码和异步回调decompressionSessionDecodeFrameCallback中都看到了这些情况。剩余的帧数在发生和时间上是随机的。这些缓冲区的大小完全等于解码帧的大小。在使解码器会话无效之前,我确实调用了VTDecompressionSessionWaitForAsynchronousFrames,但是这些分配不会消失。 在解码器会话结束时是否可以释放这些IOSurface缓冲区?

这是我的解码器运行的概述。 创建解码器会话

const void *values[] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &v) };       
attrs                = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);


VTDecompressionOutputCallbackRecord callBackRecord;
callBackRecord.decompressionOutputCallback = decompressionSessionDecodeFrameCallback;
callBackRecord.decompressionOutputRefCon = (__bridge void *)self;
VTDecompressionSessionCreate(kCFAllocatorDefault,
                                          _decoderFormatDescription,
                                          NULL,   
                                          attrs,
                                          &callBackRecord,
                                          &_decoderSession);

在NALU数据包准备就绪时调用进行解码

CMSampleBufferRef sampleBuffer = nil;
const size_t sampleSizeArray[] = {packetLen};    
CMSampleTimingInfo sampleTimeinfo ={CMTimeMake(1,FPS), CMTimeMake(presentationTS, 1000000), kCMTimeInvalid};
CMSampleBufferCreateReady(kCFAllocatorDefault, blockBuffer, _decoderFormatDescription ,
                                       1, 1, &sampleTimeinfo, 1, sampleSizeArray, &sampleBuffer);
flags = kVTDecodeFrame_EnableAsynchronousDecompression;

VTDecompressionSessionDecodeFrame(_decoderSession,
                                          sampleBuffer,
                                          flags,
                                          &sampleBuffer,
                                          &flagOut);

回调

void decompressionSessionDecodeFrameCallback{

    CVPixelBufferLockBaseAddress(imageBuffer,0);
    .... 
    send to display
    ....
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
}

结束解码器会话

VTDecompressionSessionWaitForAsynchronousFrames(_decoderSession);
VTDecompressionSessionInvalidate(_decoderSession);
CFRelease(_decoderSession);

enter image description here

1 个答案:

答案 0 :(得分:0)

那是不正常的,您的代码中肯定存在泄漏。

这与释放decompressionSession无关,这种内存泄漏是不同的,这在关闭和打开流时变得很明显。

我注意到您在调用中引用了sampleBuffer作为sourceFrameRefCon:

VTDecompressionSessionDecodeFrame(_decoderSession,
                                          sampleBuffer,
                                          flags,
                                          &sampleBuffer, //here
                                          &flagOut);

这是错误的,除非您希望在其中提供一个指针以能够引用框架本身(而不是缓冲区),否则将此值保留为NULL。这很可能是您的问题。

由于我们只能看到部分代码,因此我将指出通常会发生类似此问题的其他地方。

如果您致电:

CVBufferRetain(imageBuffer);

CFRetain(imageBuffer);

然后,您还必须致电:

CVBufferRelease(imageBuffer);

CFRelease(imageBuffer);

之后。

请确保接收缓冲区的播放器不会以任何方式保留缓冲区,接收缓冲区后,应立即将缓冲区复制到其自己的缓冲区中,无论如何(除非您使用金属缓冲区直接提供)显示机制的缓冲区,在这种情况下,应在显示后释放缓冲区)。