directshow - MS Mpeg-2 解复用器滤波器内的缓冲区匮乏

标签 directshow ffdshow

我的捕获图快要死了。我已将问题追溯到 Microsoft Mpeg-2 解复用器过滤器内的媒体样本缓冲区不足。

处理在 CBaseAllocator::GetBuffer 内停止。池已耗尽,线程处于休眠状态,无限期地等待缓冲区被回收。

0:866> ~~[3038]s
ntdll!NtWaitForSingleObject+0x14:
00007ffe`49199f74 c3              ret
0:094> k
 # Child-SP          RetAddr           Call Site
00 00000035`807fede8 00007ffe`460b9252 ntdll!NtWaitForSingleObject+0x14
01 00000035`807fedf0 00007ffe`22a35f4e KERNELBASE!WaitForSingleObjectEx+0xa2
02 00000035`807fee90 00007ffe`35609460 QUARTZ!CBaseAllocator::GetBuffer+0x7e
03 00000035`807feec0 00007ffe`3560697a mpg2splt!CMediaSampleCopyBuffer::GetCopyBuffer+0x60
04 00000035`807fef60 00007ffe`35606cc9 mpg2splt!CBufferSourceManager::GetNewCopyBuffer+0x3a
05 00000035`807fefa0 00007ffe`356073de mpg2splt!CStreamParser::CopyStream+0x89
06 00000035`807feff0 00007ffe`35608325 mpg2splt!CMpeg2PESStreamParser::ProcessBuffer_+0x15a
07 00000035`807ff040 00007ffe`35610724 mpg2splt!CMpeg2PESStreamParser::ProcessSysBuffer+0x135
08 00000035`807ff090 00007ffe`3560fb2e mpg2splt!CStreamMapContext::Process+0xb4
09 00000035`807ff110 00007ffe`3560f621 mpg2splt!CTransportStreamMapper::ProcessTSPacket_+0x30e
0a 00000035`807ff2d0 00007ffe`355fd0c1 mpg2splt!CTransportStreamMapper::Process+0xf1
0b 00000035`807ff320 00007ffe`355f4eb8 mpg2splt!CMPEG2Controller::ProcessMediaSampleLocked+0x111
0c 00000035`807ff3a0 00007ffe`355f98a7 mpg2splt!CMPEG2Demultiplexer::ProcessMediaSampleLocked+0x7c
0d 00000035`807ff3f0 00007ffd`ba58cba3 mpg2splt!CMPEG2DemuxInputPin::Receive+0x87
0e 00000035`807ff480 00007ffd`ba58ca4d 0x00007ffd`ba58cba3
0f 00000035`807ff530 00007ffd`ba58c92e 0x00007ffd`ba58ca4d
10 00000035`807ff590 00007ffe`19b5222e 0x00007ffd`ba58c92e
11 00000035`807ff5d0 00007ffe`246e5402 clr!UMThunkStub+0x6e
12 00000035`807ff660 00007ffe`2472aa23 qedit!CSampleGrabber::Receive+0x1b2
13 00000035`807ff6d0 00007ffe`287ea6d6 qedit!CTransformInputPin::Receive+0x53
14 00000035`807ff700 00007ffe`287ea459 Obsidian_DSP_DirectShow!MulticastSourceFilter::UDP_consumerThreadProc+0x276 [s:\library\obsidian.dsp.directshow\multicastsourcefilter.cpp @ 475] 
15 00000035`807ff7f0 00007ffe`46f73034 Obsidian_DSP_DirectShow!MulticastSourceFilter::UDP_consumerThreadEntry+0x9 [s:\library\obsidian.dsp.directshow\multicastsourcefilter.cpp @ 445] 
16 00000035`807ff820 00007ffe`49171461 KERNEL32!BaseThreadInitThunk+0x14
17 00000035`807ff850 00000000`00000000 ntdll!RtlUserThreadStart+0x21

以下是有关此特定图表的一些事实:

  • 源媒体采用高度复用的 MPEG2-TS UDP 形式 溪流。
  • 该流包含 14 个标清电视节目,消耗 37.5Mbps 网络带宽。
  • 问题会在经期期间发生,这是可以预见的 流变得严重碎片化(音频和视频解码器 使用 IsDiscontinuity()TRUE 发出一系列样本。
  • 根据 Windbg(和 SOS),不存在托管或非托管锁争用(不存在死锁的可能性)。
  • 没有证据表明“逃跑” 线程(不会陷入无限循环)。
  • 图表的最终过滤器是 GDCL 桥接盒,然后将解码的样本桥接到 MP4 复用器 盒子。
  • 解复用器视频输出连接到 ffdshow 的实例 解码器滤波器。多路分配器音频输出连接到实例 lav音频解码器过滤器。

我怀疑问题可能出在 ffdshow 或 lav 过滤器内部,这样正确吗? (还有谁可以持有解复用器缓冲区?)

有关如何跟踪多路分配器内的缓冲池耗尽的原因的任何指示或建议?

最佳答案

看起来某些引脚连接上的内存分配器拥有用户中具有外部引用的所有缓冲区,因此它睡着了,等待新缓冲区返回以供回收。

这是预期的行为,问题要么是缓冲区太少,要么是引用过多。

您似乎能够使用调用堆栈来识别引脚连接,并且您可以增加缓冲区数量或提供按需扩展的自定义内存分配器。

最简单的情况是当您的过滤器是连接的一部分时,您可以在协商阶段通过提供分配器要求或直接更新分配器属性来影响分配器。在更复杂的情况下,您可以在激活之前找到现有连接并更改属性。在更复杂的情况下,您可以将无操作过滤器插入到处理链中,只是为了介于两者之间并直接访问有效分配器。

关于directshow - MS Mpeg-2 解复用器滤波器内的缓冲区匮乏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53311776/

相关文章:

c++ - IMMDevice::Activate() 与 IBaseFilter 返回 REGDB_E_CLASSNOTREG 类未注册

c# - 用于DirectShow的Matroska Muxer过滤器

c++ - 强制第 3 方 DirectShow 过滤器使用自定义分配器

ffmpeg - 将实时视频流保存到本地存储

python - 为 ffdshow 制作一个 python gui

video - 通过降低质量来提高 ffmpeg CPU 使用率

c++ - DirectShow 获取视频属性

ffmpeg - 使用 directshow 输入和 JPEG 图像序列输出为 FFmpeg 启用 QSV

c++ - AVFrame 的线宽为负

ffmpeg - 减少 FFMPEG h264 视频流延迟