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

Ant*_*ony 5 c++ video c++11 ms-media-foundation

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

我尝试过的事情:

  • 记录所有HRESULTs以检查是否有任何问题(在进行下一行代码之前已经检查了它们)

一切恢复为S_OK,没有看到任何问题

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

自添加此功能以来一直无法复制,但这将为我提供有关工作时发生的一切的最佳信息。

  • 在线搜索代码示例以查看其他人如何设置Sink Writer以及如何Finalize()使用

找不到很多样本,看起来我的代码与发现的代码相似

  • 查看每个系统可用和使用的编码器,包括编码器dll的版本

在可能重现此问题的计算机上,编码器在AMD H.264硬件MFT编码器和H264编码器MFT之间有所不同。版本似乎无关紧要,有些机器是最新的视频驱动程序。

这是一些未经任何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();
Run Code Online (Sandbox Code Playgroud)

停止记录样本:

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

m_sink->Finalize();
Run Code Online (Sandbox Code Playgroud)

mof*_*o77 2

在很多情况下,媒体基础应用程序可能会挂起:

  • 使用媒体基础对象时调用 MFShutDown/CoUninitialize。
  • 使用 GUI,并在多线程应用程序中错误地使用 Windows 消息泵。
  • MTA/STA 组件使用不当。
  • 错误使用临界区/等待事件功能。
  • 使用BeginXXX()函数时忘记调用EndXXX()函数。
  • 回调函数使用不当。
  • 忘记在必要时调用AddRef,并释放另一个线程使用的对象。
  • Media Foundation 中的一个错误(Windows 7 上有一些)。
  • 等等...

当我说最小源代码时,我的意思是,隔离执行编码过程的源代码,如果太大则将其提供给 Github。最好能编译并尝试源代码,因为死锁很难发现。