视频录制在 IMFSinkWriter->Finalize() 上挂起;
Video Recording Hangs on 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 应用程序可能挂起的情况有很多:
- 使用媒体基础对象时调用 MFShutDown/CoUninitialize。
- 使用 GUI,并在多线程应用程序中错误地使用 windows 消息泵。
- MTA/STA 个组件使用不当。
- 事件函数的关键 section/wait 使用不当。
- 使用 BeginXXX() 函数时忘记调用 EndXXX() 函数。
- 回调函数使用不当。
- 忘记在必要时调用AddRef,而释放另一个线程使用的对象。
- Media Foundation 中的一个错误(Windows 七上有一些)。
- 等等...
当我说最小的源代码时,我的意思是隔离执行编码过程的源代码,如果它太大则将其提供给 Github。如果能编译试试源码就更好了,死锁很难发现。
我在使用 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 应用程序可能挂起的情况有很多:
- 使用媒体基础对象时调用 MFShutDown/CoUninitialize。
- 使用 GUI,并在多线程应用程序中错误地使用 windows 消息泵。
- MTA/STA 个组件使用不当。
- 事件函数的关键 section/wait 使用不当。
- 使用 BeginXXX() 函数时忘记调用 EndXXX() 函数。
- 回调函数使用不当。
- 忘记在必要时调用AddRef,而释放另一个线程使用的对象。
- Media Foundation 中的一个错误(Windows 七上有一些)。
- 等等...
当我说最小的源代码时,我的意思是隔离执行编码过程的源代码,如果它太大则将其提供给 Github。如果能编译试试源码就更好了,死锁很难发现。