Directshow MS Mpeg-2解复用器滤波器内的缓冲区不足

Directshow MS Mpeg-2解复用器滤波器内的缓冲区不足,directshow,ffdshow,Directshow,Ffdshow,我的捕获图快死了。我已经追踪到问题的根源是微软Mpeg-2解复用器过滤器内的媒体样本缓冲区不足 处理在CBASELocator::GetBuffer内停止。池耗尽,线程休眠,无限期地等待缓冲区被回收 0:866> ~~[3038]s ntdll!NtWaitForSingleObject+0x14: 00007ffe`49199f74 c3 ret 0:094> k # Child-SP RetAddr Call Si

我的捕获图快死了。我已经追踪到问题的根源是微软Mpeg-2解复用器过滤器内的媒体样本缓冲区不足

处理在CBASELocator::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个SD电视节目,消耗37.5Mbps的视频 网络带宽
  • 可以预见,问题会在不同时期出现 流变得严重碎片化(音频和视频解码器 以
    TRUE
    中的
    IsDiscontinuity()
    发出一组样本
  • 根据windbg(和SOS)的说法,没有托管锁或非托管锁(不存在死锁的可能性)
  • 没有“逃跑”的证据 线程(未卡在无限循环上)
  • 图形的最终过滤器是一个 GDCL桥接盒,然后将解码样本桥接到MP4多路复用器 盒子
  • 解复用器视频输出连接到ffdshow的实例 解码器过滤器。解复用器音频输出连接到一个实例 lav音频解码滤波器的设计
我怀疑问题可能在ffdshow或lav过滤器内部,对吗?(还有谁可能持有解复用器缓冲区?)


关于如何跟踪解复用器内缓冲池耗尽原因的任何指针或建议?

某些pin连接上的内存分配器似乎在用户中拥有所有具有外部引用的缓冲区,因此它在等待新缓冲区返回以供回收时睡着了

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

您似乎能够使用调用堆栈识别pin连接,并且您可以增加缓冲区的数量,或者提供一个定制的内存分配器,它可以根据需要进行扩展


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

问题描述总体上讲是有意义的,关键部分周围不会出现争用。相反,耗尽的池只会等待指示回收缓冲区可用性的事件。存在这意味着分配器上的缓冲区太少,你很难理解为什么:要么有人滥用它们,一次持有太多缓冲区,要么所有引用都是合法的,你应该拥有更多缓冲区。或者,你要提供一个自定义分配器,可以按需自扩展。罗曼,请注意,问题在我这边。我的Multicast UDP源筛选器确实有一个动态自定义分配器(按需自扩展,以最大限度地减少高负载期间的UDP数据包丢失),但分配器属性没有反映这一点。我总是在
GetProperties()上返回1的恒定缓冲区计数
,嗯……请随意发表您的评论作为回答,我将很乐意接受。谢谢!!!