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

标签 c++ c++11 video ms-media-foundation

我在使用 Media Foundation 将视频录制完成为 .mp4 时遇到问题,其中对 IMFSinkWriter->Finalize(); 的调用永远挂起。它并不总是发生,并且几乎可以在任何机器上发生(在 Windows 服务器上看到,7、8、10)。 Flush() 预先在音频和视频流上调用,并且在 FlushFinalize 之间没有添加新样本。关于什么可能导致 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();

最佳答案

媒体基础应用程序可能会挂起的情况有很多:

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

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

关于c++ - 视频录制在 IMFSinkWriter->Finalize() 上挂起;,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33767688/

相关文章:

c++ - Qcheckbox 在 QT -c++ 中始终选中至少一个选项

c++11 std::atomic compare_exchange_weak 和堆栈容器

php - 录制视频和音频

iOS 无法使用 UIDocumentInteractionController 将视频分享到 Whatsapp

c++ - HLSL:SV_Position,为什么/如何从 float3 到 float4?

c++ - 如何在 OpenVDB 中对网格进行下采样

c++ - 在具有可调用对象的线程中生成线程

c++ - 将指向成员函数的指针转换为 std::function

c++ - 混合 C++11 原子和 OpenMP

javascript - Youtube API 和跟踪嵌入式视频