gpt4 book ai didi

c++ - DirectShow CSourceStream::FillBuffer 在暂停和搜索到第一帧后不可预测的调用次数

转载 作者:太空宇宙 更新时间:2023-11-04 12:50:11 25 4
gpt4 key购买 nike

我有一个 Directshow 文件源过滤器,它有音频和帧输出引脚。它是基于此用 C++ 编写的 tutorial在 MSDN 上。我的过滤器使用 Medialooks MFormats SDK 打开视频并向输出引脚提供原始数据。两个引脚在渲染时直接连接到渲染器过滤器。

当我运行图表、暂停视频并寻找帧号 0 时出现问题。在输出帧引脚中调用 ChangeStart 方法后,有时 FillBuffer被调用三次,屏幕上显示第 1 帧而不是第 0 帧。当被调用两次时,它显示正确的帧,即第 0 帧。

输出引脚继承自 CSourceStreamCSourceSeeking 类。这是我的输出帧引脚的 FillBufferChangeStart 方法;

填充缓冲区方法

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;
}

最佳答案

来自 Microsoft DirectShow 文档:

The CSourceSeeking class is an abstract class for implementing seeking in source filters with one output pin.

CSourceSeeking is not recommended for a filter with more than one output pin. The main issue is that only one pin should respond to seeking requests. Typically this requires communication among the pins and the filter.

并且您的源过滤器中有两个 输出引脚。

可以扩展 CSourceSeeking 类以使用自定义编码管理多个输出引脚。当搜索命令进入时,它们将通过两个输入引脚发出,因此您需要确定哪个引脚控制搜索并忽略到达另一个输入引脚的搜索命令。

关于c++ - DirectShow CSourceStream::FillBuffer 在暂停和搜索到第一帧后不可预测的调用次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49425008/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com