我正在使用VTDecompressionSession来解码.h264流。解码器正常工作,我得到了正确的解码缓冲区。然而,我看到XCode工具“分配”中的“创建和持续”分配逐渐增加。如屏幕截图所示,这可以归因于解码器内部分配的IOSurface缓冲区,即使在释放VTDecompressionSession之后,这些缓冲区也不会被释放。我在同步解码和异步回调decompressionSessionDecodeFrameCallback中都看到了这种情况。剩馀帧数在发生时间上是随机的。这些缓冲区的大小与解码帧的大小完全相等。在使解码器会话无效之前,我确实调用了,但是这些分配不会消失。有办法在解码器会话结束时释放这些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);

发布于 2020-05-09 01:39:32
这是不正常的,您的代码中肯定有漏洞。
这并不是释放decompressionSession的问题,这样的内存泄漏是不同的,在关闭和打开流时会变得很明显。
我注意到您在调用中将sampleBuffer引用为sourceFrameRefCon:
VTDecompressionSessionDecodeFrame(_decoderSession,
sampleBuffer,
flags,
&sampleBuffer, //here
&flagOut);这是错误的,除非您希望在那里提供一个指针以便能够引用框架本身(而不是缓冲区),否则将此值保留为NULL。这很可能是你的问题。
由于我们只能看到您代码的一部分,所以我将指出其他问题通常会发生在哪里。
如果你打过电话:
CVBufferRetain(imageBuffer);或
CFRetain(imageBuffer);那么,您还必须调用:
CVBufferRelease(imageBuffer);或
CFRelease(imageBuffer);之后,分别。
请确保接收缓冲区的播放机不会以任何方式保留缓冲区,在接收缓冲区时,它应该立即将缓冲区复制到自己的缓冲区,不管是什么(除非您使用金属缓冲区直接将缓冲区提供给显示机制,在这种情况下,您应该在显示后释放缓冲区)。
https://stackoverflow.com/questions/54743266
复制相似问题