【问题标题】:VTDecompressionSession - IOSurface allocations gradually increaseVTDecompressionSession - IOSurface分配逐渐增加
【发布时间】:2019-07-11 14:24:24
【问题描述】:

我正在使用 VTDecompressionSession 来解码 .h264 流。解码器按预期工作,我得到正确解码的缓冲区。但是,我看到 XCode 工具“Allocations”中的“Created And Persistent”分配逐渐增加。如屏幕截图所示,这些可以归因于解码器内部分配的 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);

【问题讨论】:

    标签: ios objective-c xcode10 decoder iosurface


    【解决方案1】:

    这不正常,你的代码肯定有泄漏。

    这不是释放decompressionSession的问题,这样的内存泄漏是不同的,在关闭和打开流时会变得很明显。

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

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

    这是错误的,除非您想提供一个指针来引用帧本身(而不是缓冲区),否则请将此值保留为 NULL。这很可能是您的问题。

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

    如果你打电话:

    CVBufferRetain(imageBuffer);
    

    CFRetain(imageBuffer);
    

    那么你还必须调用:

    CVBufferRelease(imageBuffer);
    

    CFRelease(imageBuffer);
    

    分别之后。

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

    【讨论】:

      猜你喜欢
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 2016-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多