视频记录挂在IMFSinkWriter-> Finalize上

时间:2018-08-08 19:12:59

标签: c++ windows windows-10 h.264 ms-media-foundation

我已经实现了自定义IMFMediaSink以用于接收器编写器。可以正常工作,接收h264视频样本。我没有任何容器,正在使用原始的h264视频样本。我尚未实现自定义编写器,我正在使用MFCreateSinkWriterFromMediaSink API将自定义媒体接收器包装到框架提供的编写器中。

我无法执行正常关机,IMFSinkWriter::Finalize()再也不会返回。当我实现IMFSinkWriterCallback时,IMFSinkWriter::Finalize()立即返回,但从未调用过我的IMFSinkWriterCallback::OnFinalize

使用nvenc和MS软件编码器进行的100%测试中都会重现该问题。

作家属性:

MF_LOW_LATENCY = TRUE
MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS = TRUE (1)
MF_READWRITE_DISABLE_CONVERTERS = FALSE (2)
MF_SINK_WRITER_DISABLE_THROTTLING = TRUE
MF_SINK_WRITER_D3D_MANAGER
MF_SINK_WRITER_ASYNC_CALLBACK

(1)都尝试过,结果相同

(2)需要转换器,因为nvenc仅支持YUV,并且我在输入上具有RGB纹理。

输出媒体类型(它是固定的,我使用的是MFCreateSimpleTypeHandler API创建的内置处理程序)。

MF_MT_MAJOR_TYPE = MFMediaType_Video
MF_MT_SUBTYPE = MFVideoFormat_H264
MF_MT_INTERLACE_MODE = MFVideoInterlace_Progressive
MF_MT_AVG_BITRATE = 40*1000*1000
MF_MT_FRAME_SIZE = { 3840, 2160 }
MF_MT_FRAME_RATE = { 60, 1 }
MF_MT_PIXEL_ASPECT_RATIO = { 1, 1 }

输入媒体类型:

MF_MT_MAJOR_TYPE = MFMediaType_Video
MF_MT_SUBTYPE = MFVideoFormat_RGB32
MF_MT_INTERLACE_MODE = MFVideoInterlace_Progressive
MF_MT_FRAME_SIZE = { 3840, 2160 }
MF_MT_FRAME_RATE = { 60, 1 }
MF_MT_PIXEL_ASPECT_RATIO = { 1, 1 }

当不使用IMFSinkWriterCallback时,这是挂起时的调用堆栈:

ntdll.dll!_NtWaitForSingleObject@12 ()
KernelBase.dll!WaitForSingleObjectEx()
mfreadwrite.dll!CMFSinkWriter::InternalFinalize(void)
mfreadwrite.dll!CMFSinkWriter::Finalize(void)

即使使用-k All,MFTrace也没有任何与完成有关的内容:

13700,3C60 19:01:25.79566 CMFTransformDetours::ProcessOutput @02EA6E3C failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT
13700,2A98 19:01:25.80250 CMFTransformDetours::ProcessOutput @1A6CEF38 Stream ID 0, Sample @1C244F30, Time 1216ms, Duration 16ms, Buffers 1, Size 12441600B, MFSampleExtension_CleanPoint=1;MFSampleExtension_Interlaced=0
13700,2098 19:01:25.80254 CMFTransformDetours::ProcessInput @02EA6E3C Stream ID 0, Sample @1C244F30, Time 1216ms, Duration 16ms, Buffers 1, Size 12441600B, MFSampleExtension_CleanPoint=1;MFSampleExtension_Interlaced=0
13700,2A98 19:01:25.80256 CMFTransformDetours::ProcessOutput @1A6CEF38 failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT
13700,2A98 19:01:25.80266 CMFTransformDetours::ProcessMessage @1A6CEF38 Message type=0x00000001 MFT_MESSAGE_COMMAND_DRAIN, param=00000000
13700,2A98 19:01:25.80267 CMFTransformDetours::ProcessOutput @1A6CEF38 failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT
13700,2098 19:01:25.81669 CMFTransformDetours::ProcessOutput @02EA6E3C Stream ID 0, Sample @1FB68CF8, Time 1216ms, Duration 16ms, Buffers 1, Size 680B, {2B5D5457-5547-4F07-B8C8-B4A3A9A1DAAC}=1;{73A954D4-09E2-4861-BEFC-94BD97C08E6E}=12166667 (0,12166667);{9154733F-E1BD-41BF-81D3-FCD918F71332}=65535;{973704E6-CD14-483C-8F20-C9FC0928BAD5}=1;MFSampleExtension_CleanPoint=0;{B2EFE478-F979-4C66-B95E-EE2B82C82F36}=16 (0,16)
13700,82C 19:01:25.81674 CMFTransformDetours::ProcessOutput @02EA6E3C failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT
13700,82C 19:01:25.81674 CMFTransformDetours::ProcessMessage @02EA6E3C Message type=0x00000001 MFT_MESSAGE_COMMAND_DRAIN, param=00000000
13700,82C 19:01:25.81674 CMFTransformDetours::ProcessOutput @02EA6E3C failed hr=0xC00D6D72 MF_E_TRANSFORM_NEED_MORE_INPUT
13700,1F54 19:01:27.24237 CKernel32ExportDetours::OutputDebugStringA @ D3D11 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN] 
13700,1F54 19:01:27.24255 CKernel32ExportDetours::OutputDebugStringA @ D3D11 WARNING: Live Producer at 0x0311D91C, Refcount: 13. [ STATE_CREATION WARNING #0: UNKNOWN] 

在挂起之后我终止了该过程,因此有望获得有关实时D3D资源的警告。

有什么想法吗?我认为作者可能正在等待这些SPS / PPS魔术斑点到达,但从未发生。是否可以指示h264编码器在某处输出SPS / PPS?

1 个答案:

答案 0 :(得分:0)

您已经实现了自定义IMFMediaSink,所以我想您还已经实现了IMFStreamSink。

使用Mediafoundation的常规方法,您在IMFMediaSink和IMFStreamSink之间具有循环COM引用。这就是为什么存在IMFMediaSink接口的Shutdown方法的原因。

如果使用自定义MediaSink的程序未在正确的位置调用Shutdown,则将发生内存泄漏。

关于您的IMFSinkWriterCallback问题,我们没有足够的信息来查找问题所在。

也不清楚“自定义IMFMediaSink”和“ IMFSinkWriter”。您是否还在实现IMFSinkWriter ...

EDIT1

只有两件事:

MFCreateSinkWriterFromMediaSink

在调用此函数之前,请调用CoInitialize(Ex)和MFStartup。

使用完媒体接收器后,请调用媒体接收器的IMFMediaSink :: Shutdown方法。 (接收器写入器不会关闭介质接收器。)在介质接收器上调用“关闭”之前,请释放接收器写入器。

您是否正确释放接口?

IMFSinkWriter::Finalize

在内部,此方法调用IMFStreamSink :: PlaceMarker来将每个流的段结束标记放置在媒体接收器上。

您是否处理了此消息(MFSTREAMSINK_MARKER_ENDOFSEGMENT)?

我们不知道您如何处理CriticalSection / Event / CircularReference,因此很难发现问题。

EDIT2

  

是否可以指示h264编码器在某处输出SPS / PPS?

通常,对于h264视频格式,在IMFStreamSink上调用SetCurrentMediaType时(假设您实现了IMFMediaTypeHandler),您需要获取属性MF_MT_MPEG_SEQUENCE_HEADER(BLOB类型)。

EDIT3

您能提供真实的一个吗(这就是我认为应用程序应该的样子):

topology and dataflow

我不记得您的自定义接收器是否创建了mp4文件。如果是这样,则必须在IMFSinkWriter :: Finalize中生成ftpy / moov原子。

EDIT4

您也可以阅读以下内容:Video Recording Hangs on IMFSinkWriter->Finalize();

没有源代码,这是我唯一能给出的答案。