DirectShow CSourceStream::FillBuffer 暂停和查找后对第一帧的不可预测的调用数
DirectShow CSourceStream::FillBuffer unpredictable number of calls after Pause and Seek to the first frame
我有一个Directshow文件源过滤器,它有音频和帧输出引脚。它是根据 MSDN 上的本教程以C++编写的。我的筛选器使用 Medialook 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;
}
来自 Microsoft DirectShow 文档:
CSourceSeeking类是一个用于实现的抽象类 在具有一个输出引脚的源滤波器中查找。
不建议将 CSourceSeek 用于具有多个筛选器的筛选器 输出引脚。主要问题是只有一个引脚应该响应 寻求请求。通常,这需要引脚之间的通信 和过滤器。
源筛选器中有两个输出引脚。
可以扩展 CSourceSeeking 类,以使用自定义编码管理多个输出引脚。当搜索命令传入时,它们将通过两个输入引脚,因此您需要确定哪个引脚控制查找并忽略到达另一个输入引脚的查找命令。
相关文章:
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 如何检测是否在缓冲绘画动画中绘制最后一帧?
- 不可预测的C++睡眠/等待行为
- C++ 尝试优化每一帧将数据打印到二进制文件
- 当我在每一帧中多次使用正则表达式时,FPS 下降了
- 超过 N 时出现不可预测的位移结果
- 为什么除了最后一帧之外,每一帧都没有调用命令
- DirectShow CSourceStream::FillBuffer 暂停和查找后对第一帧的不可预测的调用数
- 多线程文件 IO 程序在线程数增加时行为不可预测
- 使用 std::find 查找从二进制文件中读取的字符并转换为 std::vector 中的 std::string<string> 会产生这种不可预测的行为?
- std::sleep_for在Windows 10上的不可预测行为
- WinApi 在每一帧中绘制
- 不可预测的文件描述符泄漏
- Opencv 视频帧.我只能看到最后一帧
- 循环程序的行为是不可预测的
- 访问视频的每一帧并对其进行处理
- Qt:显示实时视频,一次一帧
- Haar检测-保存图像的Mat,以便获得并显示前一帧
- C++中不可预测的输出
- 当来自外部库的线程不可预测地崩溃我的应用程序时,我该怎么办