DirectShow CSourceStream :: FillBuffer непредсказуемое количество вызовов после паузы и поиска до первого кадра

У меня есть фильтр источника файла Directshow, который имеет вывод звука и вывод кадров. Это написано в C ++ на основе этого руководство на MSDN. Мой фильтр открывает видео с помощью Medialooks MFormats SDK и предоставляет необработанные данные для выходных контактов. Два вывода напрямую подключаются к фильтрам рендеринга, когда они отображаются.

Проблема возникает, когда я запускаю график, приостанавливаю видео и ищу кадр № 0. После звонка ChangeStart метод в выводе кадра, иногда FillBuffer вызывается три раза, а кадр 1 отображается на экране вместо 0. Когда он вызывается два раза, он показывает правильный кадр, который является кадром 0.

Выходные контакты наследуются от CSourceStream а также CSourceSeeking классы. Вот мой FillBuffer а также ChangeStart методы вывода кадра на вывод;

Метод FillBuffer

HRESULT frame_pin::FillBuffer(IMediaSample *sample)
{
CheckPointer(sample, E_POINTER);

BYTE *frame_buffer;
sample->GetPointer(&frame_buffer);

// Check if the downstream filter is changing the format.
CMediaType *mt;
HRESULT hr = sample->GetMediaType(reinterpret_cast<AM_MEDIA_TYPE**>(&mt));
if (hr == S_OK)
{
auto new_width = reinterpret_cast<VIDEOINFOHEADER2*>(mt->pbFormat)->bmiHeader.biWidth;
auto old_witdh = reinterpret_cast<VIDEOINFOHEADER2*>(m_mt.pbFormat)->bmiHeader.biWidth;

if(new_width != old_witdh)
format_changed_ = true;

SetMediaType(mt);
DeleteMediaType(mt);
}

ASSERT(m_mt.formattype == FORMAT_VideoInfo2);

VIDEOINFOHEADER2 *vih = reinterpret_cast<VIDEOINFOHEADER2*>(m_mt.pbFormat);

CComPtr<IMFFrame> mf_frame;

{
CAutoLock lock(&shared_state_);

if (source_time_ >= m_rtStop)
return S_FALSE;

// mf_reader_ is a member external SDK instance which gets the frame data with this function call
hr = mf_reader_->SourceFrameConvertedGetByNumber(&av_props_, frame_number_, -1, &mf_frame, CComBSTR(L""));
if (FAILED(hr))
return hr;

REFERENCE_TIME start, stop = 0;

start = stream_time_;
stop = static_cast<REFERENCE_TIME>(tc_.get_stop_time() / m_dRateSeeking);

sample->SetTime(&start, &stop);

stream_time_ = stop;
source_time_ += (stop - start);

frame_number_++;
}

if (format_changed_)
{
CComPtr<IMFFrame> mf_frame_resized;
mf_frame->MFResize(eMFCC_YUY2, std::abs(vih->bmiHeader.biWidth), std::abs(vih->bmiHeader.biHeight), 0, &mf_frame_resized, CComBSTR(L""), CComBSTR(L""));
mf_frame = mf_frame_resized;
}MF_FRAME_INFO mf_frame_info;
mf_frame->MFAllGet(&mf_frame_info);

memcpy(frame_buffer, reinterpret_cast<BYTE*>(mf_frame_info.lpVideo), mf_frame_info.cbVideo);

sample->SetActualDataLength(static_cast<long>(mf_frame_info.cbVideo));
sample->SetSyncPoint(TRUE);
sample->SetPreroll(FALSE);

if (discontinuity_)
{
sample->SetDiscontinuity(TRUE);
discontinuity_ = FALSE;
}

return S_OK;
}

Метод ChangeStart

HRESULT frame_pin::ChangeStart()
{
{
CAutoLock lock(CSourceSeeking::m_pLock);
tc_.reset();
stream_time_ = 0;
source_time_ = m_rtStart;
frame_number_ = static_cast<int>(m_rtStart / frame_lenght_);
}

update_from_seek();
return S_OK;
}

0

Решение

Из документации Microsoft DirectShow:

CSourceSeeking класс является абстрактным классом для реализации
поиск в исходных фильтрах с один выходной контакт.

CSourceSeeking не рекомендуется для фильтра с более чем одним
выходной контакт. Основная проблема заключается в том, что только один контакт должен реагировать на
ищет запросы. Как правило, это требует общения между контактами
и фильтр.

И у тебя есть два выходные выводы в вашем исходном фильтре.

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]