c – 视频录制在IMFSinkWriter-> Finalize()上挂起;

使用Media Foundation将视频录制最终化为.mp4时出现问题,其中调用IMFSinkWriter-> Finalize();永远挂起来.它并不总是发生,几乎可以在任何机器上发生(在 Windows服务器上看到,7,8,10).事先在音频和视频流上调用Flush(),并且在Flush和Finalize之间不添加新样本.关于什么可能导致Finalize永远挂起的任何想法?

我试过的事情:

>记录所有HRESULT以检查是否存在任何问题(在进入下一行代码之前已经检查过它们)

Everything comes back as S_OK, not seeing any issues

>在流上添加了IMFSinkWriterCallback以获取回调
流处理标记(每10个样本添加标记)并完成Finalize()

Haven’t been able to reproduce since adding this but this would give the best information about what’s going on when I get it working.

>在线搜索代码示例,了解其他人如何设置代码
Sink Writer以及如何使用Finalize()

Didn’t find many samples and it looks like my code is similar to the ones that were found

>查看每个系统可用的编码器,包括编码器DLL的版本

Encoders varied between AMD H.264 Hardware MFT Encoder and H264 Encoder MFT on machines that could reproduce the issue. Versions didn’t seem to matter and some of the machines were up to date with video drivers.

以下是一些没有任何HRESULT检查的代码示例(将代码量增加了一倍,因此我将其取出)

构建接收器样本:

CComPtr<IMFAttributes> pAttr;
::MFCreateAttributes( &pAttr, 4 );
pAttr->SetGUID( MF_TRANSCODE_CONTAINERTYPE, GetFileContainerType() );
pAttr->SetUINT32( MF_LOW_LATENCY, FALSE ); // Allows better multithreading
pAttr->SetUINT32( MF_SINK_WRITER_DISABLE_THROTTLING, TRUE ); // Does not block
pAttr->SetUINT32( MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE );

m_pCallback.Attach( new MFSinkWriterCallback() );
pAttr->SetUnknown( MF_SINK_WRITER_ASYNC_CALLBACK, m_pCallback );

::MFCreateSinkWriterFromURL( m_strFilename.c_str(), NULL, pAttr, &m_pSink );

if ( m_pVideoInputType && m_pVideoOutputType )
{
   m_pSink->AddStream( m_pVideoOutputType, &m_dwVideoStreamId );
   // Attributes for encoding?
   CComPtr<IMFAttributes> pAttrVideo;

   // Not sure if these are needed
   //::MFCreateAttributes( &pAttrVideo, 5 );

   m_pSink->SetInputMediaType( m_dwVideoStreamId, m_pVideoInputType, pAttrVideo );
}
if ( m_pAudioInputType && m_pAudioOutputType )
{
   m_pSink->AddStream( m_pAudioOutputType, &m_dwAudioStreamId );
   // Attributes for encoding?
   CComPtr<IMFAttributes> pAttrAudio;

   // Not sure if these are needed
   //::MFCreateAttributes( &pAttrAudio, 2 );
   //pAttrAudio->SetGUID( MF_MT_SUBTYPE, MFAudioFormat_AAC );
   //pAttrAudio->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, 16 );

   m_pSink->SetInputMediaType( m_dwAudioStreamId, m_pAudioInputType, pAttrAudio );
}
m_pSink->BeginWriting();

停止录制样本:

if ( m_dwVideoStreamId != (DWORD)-1 )
{
   m_sink->Flush( m_dwVideoStreamId );
}
if ( m_dwAudioStreamId != (DWORD)-1 )
{
   m_sink->Flush( m_dwAudioStreamId );
}

m_sink->Finalize();

最佳答案 Media Foundation应用程序可以挂起很多情况:

>使用Media Foundation对象时调用MFShutDown / CoUninitialize.
>使用GUI,并在多线程应用程序中错误地使用Windows消息泵.
>错误使用MTA / STA组件.
>关键部分的使用不当/等待事件功能.
>当使用BeginXXX()函数时,忘记调用EndXXX()函数.
>回调函数使用不当.
>忘记在必要时调用AddRef,并释放另一个线程使用的对象.
> Media Foundation中的一个错误(Windows 7上有一些错误).
>依此类推……

当我说一个最小的源代码,我的意思是,隔离执行编码过程的源代码,并将其提供给Github,如果它太大了.如果我们可以编译并尝试源代码,那就更好了,因为很难找到死锁.

点赞