Windows MFT(媒体基础转换)解码器未返回正确的采样时间或持续时间
Posted
技术标签:
【中文标题】Windows MFT(媒体基础转换)解码器未返回正确的采样时间或持续时间【英文标题】:Windows MFT (Media Foundation Transform) decoder not returning proper sample time or duration 【发布时间】:2016-09-26 05:16:56 【问题描述】:要使用 Windows Media Foundation Transform 解码 H264 流,目前的工作流程是这样的:
IMFSample sample;
sample->SetTime(time_in_ns);
sample->SetDuration(duration_in_ns);
sample->AddBuffer(buffer);
// Feed IMFSample to decoder
mDecoder->ProcessInput(0, sample, 0);
// Get output from decoder.
/* create outputsample that will receive content */ ...
MFT_OUTPUT_DATA_BUFFER output = 0;
output.pSample = outputsample;
DWORD status = 0;
HRESULT hr = mDecoder->ProcessOutput(0, 1, &output, &status);
DWORD status = 0;
hr = mDecoder->ProcessOutput(0, 1, &output, &status);
if (output.pEvents)
// We must release this, as per the IMFTransform::ProcessOutput()
// MSDN documentation.
output.pEvents->Release();
output.pEvents = nullptr;
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
// Type change, probably geometric aperture change.
// Reconfigure decoder output type, so that GetOutputMediaType()
else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
// Not enough input to produce output.
else if (!output.pSample)
return S_OK;
else
// Process output
当我们将所有数据输入到 MFT 解码器后,我们必须将其排空:
mDecoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
现在,WMF H264 解码器的一件事是,无论 h264 滑动窗口的大小如何,它通常在使用超过 30 个压缩的 h264 帧调用之前不会输出任何内容。延迟非常高...
我遇到了一个非常麻烦的问题。 对于仅由关键帧组成的视频,并且只有 15 帧,每帧长 2 秒,第一帧的呈现时间非零(此流来自实时内容,因此第一帧通常在 epos 时间) 因此,在没有耗尽解码器的情况下,解码器将不会输出任何内容,因为它没有接收到足够的帧。
但是,一旦解码器耗尽,解码的帧就会出来。但是,MFT 解码器仅将所有持续时间设置为 33.6 毫秒,并且第一个样本的呈现时间始终为 0。 原始时长和演示时间已丢失。
如果您向 h264 解码器提供超过 30 帧,则持续时间和 pts 都有效...
我还没有找到让 WMF 解码器输出具有正确值的样本的方法。 看来,如果您必须在解码器本身输出任何样本之前排空解码器,那么它就完全坏了……
有没有人遇到过这样的问题?你是怎么解决的?
提前谢谢你
编辑:http://people.mozilla.org/~jyavenard/mediatest/fragmented/1301869.mp4 上提供了视频样本 由于上述问题,使用 Firefox 播放此视频会导致播放速度极快。
【问题讨论】:
你应该试试CODECAPI_AVLowLatencyMode
[1, 2]。
低延迟仅适用于 Window 8 及更高版本。此外,与任何包含 B 帧的东西都不兼容。此外,启用时会出现大量驱动程序崩溃......低延迟在这里会有所帮助,但如果我有
恐怕你提到的只是设计行为。输出帧是异步可用的(尤其是在 DXVA 模式下),Windows 8+ 中的低延迟可以稍微改善一些事情,当 H.264 嵌入时间相关数据时改变了时间。当然,驱动程序崩溃需要驱动程序更新。我想,纯软件解码器可能具有更可预测的行为。
所以 MFT 返回错误的时间戳和错误的持续时间是设计使然?我觉得这很难相信:)
如果您考虑 H.264 比特流中的时序信息,则不一定是错误的。它可能比您的时间戳更受欢迎。
【参考方案1】:
我不确定您的工作流程是否正确。我认为你应该这样做:
do
...
hr = mDecoder->ProcessInput(0, sample, 0);
if(FAILED(hr))
break;
...
hr = mDecoder->ProcessOutput(0, 1, &output, &status);
if(FAILED(hr) && hr != MF_E_TRANSFORM_NEED_MORE_INPUT)
break;
while(hr == MF_E_TRANSFORM_NEED_MORE_INPUT);
if(SUCCEEDED(hr))
// You have a valid decoded frame here
这个想法是在 ProcessOutput 返回 MF_E_TRANSFORM_NEED_MORE_INPUT 时继续调用 ProcessInput/ProcessOutut。 MF_E_TRANSFORM_NEED_MORE_INPUT 表示解码器需要更多输入。我认为有了这个循环,你就不需要耗尽解码器了。
【讨论】:
你所描述的和我所拥有的没有什么不同。我只介绍了 ONE 框架的工作流程。当然,如果您有多个帧,您将循环......但是问题是,如果您调用 ProcessInput 的次数少于 30 次,则通常不会从 ProcessOutput 中输出任何内容。这是需要排水的地方。 “MF_E_TRANSFORM_NEED_MORE_INPUT 意味着解码器需要更多输入”当然...但是如果您在到达流的末尾时没有什么可以提供给解码器怎么办? 是的,ProcessOutput 在返回第一个样本之前确实返回了 MF_E_TRANSFORM_STREAM_CHANGE。进一步提到了那里的 h264 时序,我开始深入研究 SPS,确实这个麻烦的视频将timing_info_present_flag 设置为 true,且 fixed_frame_rate_flag = true 也是如此。然后我找到了这个 MS 文档:msdn.microsoft.com/en-us/library/windows/desktop/…,其中提到如果在 SPS 中找不到任何内容,则默认使用 29.976fps。 SPS 确实有 num_units_in_tick = 1 和 time_scale = 50 是的,第一帧在字节流中同时包含 SPS 和 PPS。这是自动添加的,因为 MFT 需要附件 B 内容。将 SPS 和 PPS 复制到字节流是作为 AVCC -> AnnexB 转换的一部分完成的......我也玩过 MFSampleExtension_Discontinuity,它没有区别 “为避免初始格式更改,请在输入类型中提供尽可能多的信息”以上是关于Windows MFT(媒体基础转换)解码器未返回正确的采样时间或持续时间的主要内容,如果未能解决你的问题,请参考以下文章