2016-09-26 30 views
2

要与Windows Media基础解码H264流变换,工作流程是目前这样的:的Windows MFT(媒体基础变换)解码器没有返回正确的采样时间或持续时间

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秒)的视频,第一帧具有非零的呈现时间(该流来自实况内容,因此第一帧通常在临时时间) 因此,在不消耗解码器的情况下,由于解码器没有收到足够的帧,所以没有东西会从解码器中出来。

但是,一旦解码器被耗尽,解码的帧就会出来。但是,MFT解码器仅将所有时间长度设置为33.6ms,并且第一个样本出现的显示时间始终为0. 原始持续时间和演示时间已经丢失。

如果您提供超过30帧的解码器H264,那么这两个持续时间和点是有效的...

我还没有找到一种方式来获得的WMF解码器输出采样与应有的价值。 看来,如果你必须在它自己输出任何样本之前排空解码器,那么它完全被破坏了......

有没有人遇到过这样的问题?你是如何解决它的?

预先感谢您

编辑:视频的样本可在http://people.mozilla.org/~jyavenard/mediatest/fragmented/1301869.mp4 播放该视频用Firefox会导致它非常快速播放,由于上述问题。

+1

您应该尝试'CODECAPI_AVLowLatencyMode' [[1](https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd797815),[2](https://msdn.microsoft.com /库/窗/台式机/ hh447590)。 –

+0

低延迟仅适用于Window 8及更高版本。此外,与任何包含B帧的内容不兼容。另外,启用时会出现大量的驱动程序崩溃......低延迟会对此有所帮助,但如果我的内容少于8帧,仍然会出现同样的问题。 – jyavenard

+0

恐怕你所提到的只是设计行为。输出帧可异步使用(特别是在DXVA模式下),Windows 8+中的低延迟略微改进,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 
} 

的想法是让调用ProcessInput/ProcessOuptut而ProcessOutput返回MF_E_TRANSFORM_NEED_MORE_INPUT。 MF_E_TRANSFORM_NEED_MORE_INPUT表示解码器需要更多输入。我认为用这个循环你不需要消耗解码器。

+0

你所描述的与我所拥有的没有什么不同。我仅提供了一个帧的工作流程。当然,如果你有多个框架,你会循环....但问题是,如果你调用ProcessInput少于30次,你通常没有任何来自ProcessOutput。这是需要排水的地方。 – jyavenard

+0

“MF_E_TRANSFORM_NEED_MORE_INPUT意味着解码器需要更多的输入”当然......但是如果你已经到达了流的末尾没有什么更多的东西给解码器了? – jyavenard

+0

你如何设置解码器的输入类型?您是否设置了完全描述的IMFMediaType或仅限于主类型和子类型?您是否检查过ProcessOutput是否返回MF_E_TRANSFORM_STREAM_CHANGE?你可以尝试在循环中调用ProcessInput来查看它是否会返回MF_E_NOTACCEPTING?我现在看到你没有足够的帧供给解码器,但在输出采样之前可能需要提供完整的GOP。你是否有每帧中包含的起始码?解码器跳过字节,直到在字节流中找到有效的序列参数集(SPS)和图像参数集(PPS)。 – VuVirt