我有一个Directshow文件源过滤器,它有音频和帧输出引脚。它是基于MSDN上的tutorial基于C ++编写的。我的过滤器使用Medialooks MFormats SDK打开视频,并将原始数据提供给输出引脚。两个引脚在渲染时直接连接到渲染器滤镜。
当我运行图形,暂停视频并寻找帧编号0时出现问题。在输出帧引脚中调用ChangeStart
方法后,有时会调用FillBuffer
三次和帧1显示在屏幕上而不是0.当它被调用两次时,它显示正确的帧,即帧0。
输出引脚继承自CSourceStream
和CSourceSeeking
类。以下是输出帧引脚的FillBuffer
和ChangeStart
方法;
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;
}
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 :(得分:0)
从Microsoft DirectShow文档中:
CSourceSeeking类是用于实现的抽象类 使用一个输出引脚查找源滤波器。
对于不止一个过滤器,不建议使用CSourceSeeking 输出引脚。主要问题是只有一个针脚可以响应 寻找请求。通常,这需要引脚之间的通信 和过滤器。
您的源滤波器中有两个输出引脚。
可以使用自定义编码扩展CSourceSeeking类以管理多个输出引脚。当搜索命令进入时,它们将同时通过两个输入引脚,因此您需要确定哪个引脚在控制搜索,而忽略到达另一个输入引脚的搜索命令。