Буферное истощение внутри фильтра MS Mpeg-2 Демультиплексор - PullRequest
0 голосов
/ 15 ноября 2018

Мой график захвата умирает.Я проследил проблему до истощения буфера мультимедийного образца внутри фильтра демультиплексора 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

Вот несколько фактов об этом конкретном графике:

  • Исходный носитель находится вформа сильно мультиплексированного потока UDP MPEG2-TS.
  • Этот поток содержит 14 программ SD TV, которые используют 37,5 Мбит / с полосы пропускания сети.
  • Проблема возникает предсказуемо в периоды, когда поток становится сильно фрагментированным (аудио и видео декодеры генерируют серию сэмплов с IsDiscontinuity() в TRUE.
  • Согласно windbg (и SOS) Нет утвержденных управляемых или неуправляемых блокировок (нет возможности тупиковой ситуации).
  • Нет признаков "убегающего" потока (не застрявшего в бесконечном цикле).
  • Графикfinal filter представляет собой мостовой блок GDCL, который затем соединяет декодированный семпл с блоком мультиплексора MP4.
  • Видеовыход демультиплексора подключен к экземпляру фильтра декодера ffdshow. Аудиовыход демультиплексора подключен к экземпляруФильтр аудио декодера lav.

Правильно ли я подозреваю, что проблема может быть либо в ffdshow, либо в фильтре lav? (кто еще может содержать буферы демультиплексора?)

Любые указатели или предложения о том, как я могу проследить, почему буферный пул внутри демультиплексора исчерпан?

1 Ответ

0 голосов
/ 15 ноября 2018

Похоже, что у распределителя памяти на определенном контактном соединении есть все буферы в пользователе с внешними ссылками, и поэтому он засыпал в ожидании возврата нового буфера для переработки.

Это ожидаемое поведение, и проблема либо в недостаточном количестве буферов, либо в чрезмерных ссылках.

Кажется, вы можете идентифицировать контактное соединение, используя стек вызовов, и вы можете либо увеличить количество буферов, либо предоставить специальный распределитель памяти, который расширяется по требованию.

Самое простое - это когда ваш фильтр является частью соединения, и вы можете влиять на распределитель на этапе согласования, предоставляя требования распределителя или напрямую обновляя свойства распределителя. В более сложных случаях вы можете найти существующее соединение и изменить свойства, прежде чем активировать. В еще более сложных ситуациях вы можете вставить свой неоперативный фильтр в цепочку обработки только для того, чтобы получить промежуточный доступ и получить прямой доступ к эффективному распределителю.

...