Передача образцов видео MPEG4 в декодер - Как использовать CBaseOutputPin::DeliverNewSegment()?
Я написал свой собственный фильтр DirectShow RTSP Push Source (CBaseFilter), который работает на H264 как шарм! Но, когда я попытался поддержать MPEG4 (поток MP4V-ES), я наткнулся на проблему... Мой поток декодируется (с фильтром ffdshow Video Decoder или DivX Video Decoder) и воспроизводится идеально в течение ровно 10 секунд. Изображение бегло со скоростью 15 кадров в секунду, но через 10 секунд количество кадров в секунду резко падает, и декодируются только IVOP, а PVOP /BVOP отбрасываются... даже если я их получаю и вовремя отправляю их в декодер.
Затем я начал возиться со своим кодом и обнаружил, что правильно распаковываю полезную нагрузку MPEG4 RTP и отправляю образцы мультимедиа в декодер правильно, а также правильно их освобождаю. CBaseOutputPin::DecideBufferSize()
делает свою работу как надо, и я звоню IMediaSample::SetTime()
правильно... НО, если я изменю этот код, который доставляет образец в декодер:
hr = videoPin->Deliver(sample);
sample->Release();
с этим кодом (обратите внимание на первую строку):
videoPin->DeliverNewSegment(REFERENCE_TIME(start), REFERENCE_TIME(end), 1.0);
hr = videoPin->Deliver(sample);
sample->Release();
видео бегло через 10 секунд и более (fps остается на 15), но картинка все испорчена... как будто IVOP не декодируется должным образом, и есть некоторые артефакты в статических частях сцены.
Итак, как мне использовать CBaseOutputPin::DeliverNewSegment()? И какого черта мне это нужно?
Потому что, думаю, мне это нужно, так как это мешает моему видео потоку не быть декодированным бегло...
Я гуглил, но без удачи. Любая помощь будет оценена. Thanx.
ОБНОВИТЬ
В методе videoPin->DeliverNewSegment(tStart, tStop, dRate)
Параметр dRate:
Скорость, с которой этот сегмент должен обрабатываться, в процентах от первоначальной ставки.
Так что если вместо 1.0
я кладу 100.0
поток идет так, как и должно быть, но с некоторой задержкой между кадрами. Но это пока лучшее!
1 ответ
Я не уверен, что NewSegment вызывает проблемы, которые вы видите. NewSegment используется в тех случаях, когда данные, которые вы отправляете в одном пакете, пересекают время начала или время окончания и позволяют декодеру доставлять только до времени остановки. В этом случае вы можете вызвать NewSegment (0, MAX_LONGLONG, 1) один раз в начале потоковой передачи, и все должно быть в порядке.
Если вы видите проблемы, то, возможно, вам следует проверить задержку на выходе декодера (сравнить временную метку с текущим временем потока).
г