当将H.264帧复用到MP4时,Media Foundation IMFSinkWriter :: Finalize()方法在Windows 7下失败

我正在用C#编写一个工具,将H.264帧复用到MP4文件中,我正在使用Media Foundation的带有接收器编写器的媒体接收器来完成这项工作。

在Win8下,事情运行良好,但在Windows 7下,同样的代码在调用接收器编写器的Finalize方法时引发exception,HResult:0xC00D36E6(MF_E_ATTRIBUTENOTFOUND)。 结果,生成的MP4文件未正确关闭,并且(当然)不可播放。

mftrace日志显示Windows 7下的故障发生在IMFSinkWriter :: PlaceMarker内部调用之后(或期间)。 在Windows 8下,日志中的相应行后面紧跟着“Finalized”语句。

以下是muxing代码的示例,后面是mftrace日志:

// pFrames contains the H264 frames as binaries public void Mux(List pFrames) { // Start Media Foundation: MFHelper.MFStartup(); // Calculate average frame duration, in HNS, given a 10fps input: double duration = (1 / 10F) * 10000000; _frameDuration = (ulong)duration; // Set up input media type object: _mediaType = MFHelper.MFCreateMediaType(); _mediaType.SetGUID(Constants.MF_MT_MAJOR_TYPE, Constants.MFMediaType_Video); _mediaType.SetGUID(Constants.MF_MT_SUBTYPE, Constants.MFVideoFormat_H264); _mediaType.SetUINT32(Constants.MF_MT_INTERLACE_MODE, (uint)(MFVideoInterlaceMode.MFVideoInterlace_Progressive)); _mediaType.SetUINT64(Constants.MF_MT_FRAME_SIZE, MFHelper.Pack((uint)1920, (uint)1080)); _mediaType.SetUINT64(Constants.MF_MT_FRAME_RATE, MFHelper.Pack((uint)10, (uint)1)); // The input is a GOP of 10 frames, 1 second long _mediaType.SetUINT64(Constants.MF_MT_PIXEL_ASPECT_RATIO, MFHelper.Pack((uint)1, (uint)1)); // Initialize media sink and output file/stream: string filename = "output.mp4"; _byteStream = MFHelper.MFCreateFile(MFFileAccessMode.ReadWrite, MFFileOpenMode.DeleteIfExist, MFFileFlags.None, filename); _mediaSink = MFHelper.MFCreateMPEG4MediaSink(_byteStream, _mediaType, null); // Create sink writer object: IMFAttributes attr = null; MFHelper.MFCreateAttributes(out attr, 2); attr.SetGUID(Constants.MF_TRANSCODE_CONTAINERTYPE, Constants.MFTranscodeContainerType_MPEG4); attr.SetUINT32(Constants.MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0); // Or 1, doesn't make any difference _sinkWriter = MFHelper.MFCreateSinkWriterFromMediaSink(_mediaSink, attr); // Process the input frames: ulong _startTime = 0; _sinkWriter.BeginWriting(); foreach (byte[] pFrame in pFrames) { IMFMediaBuffer mediaBuffer = CreateMediaBuffer(pFrame); IMFSample sample = MFHelper.MFCreateSample(); sample.AddBuffer(mediaBuffer); sample.SetSampleTime(_startTime); sample.SetSampleDuration(_frameDuration); _sinkWriter.WriteSample(0, sample); _startTime += _frameDuration; } // Try to finalize the sink: _sinkWriter.Finalize(); // Exception 0xC00D36E6, "The requested attribute was not found.", MF_E_ATTRIBUTENOTFOUND, under Windows 7 MFHelper.MFShutdown(); } 

上面提到的CreateMediaBuffer方法:

  private IMFMediaBuffer CreateMediaBuffer(byte[] pFrame) { IMFMediaBuffer mediaBuffer = MFHelper.MFCreateMemoryBuffer((uint)pFrame.Length); IntPtr bufEntry; uint maxLength, currentLength; mediaBuffer.Lock(out bufEntry, out maxLength, out currentLength); System.Runtime.InteropServices.Marshal.Copy(pFrame, 0, bufEntry, pFrame.Length); mediaBuffer.Unlock(); mediaBuffer.SetCurrentLength((uint)pFrame.Length); return mediaBuffer; } 

这是mftrace日志:

  __M_F_T_R_A_C_E___LOG__ PID, TID Time (UTC) TraceMessage --------- -------------- ------------ 7580,24A8 14:08:08.22790 TraceOSVersion @ OS version (BuildLabEx): 7601.18409.x86fre.win7sp1_gdr.140303-2144 7580,24A8 14:08:08.22791 TraceMFDetoursVersion @ MFDetours version 1.0.0.1 7580,24A8 14:08:08.22798 TraceEnabledKeywords @ Keywords and levels: Default 4, Detours 4, Kernel32Export 4, MFExport 4, MFPlatExport 4, MFPlayExport 4, MFReadWriteExport 4, Ole32Export 4, wmvCoreExport 4, MFPublic 4, IMFActivate 4, IMFAttributes 4, IMFClock 4, IMFMediaEventGenerator 4, IMFMediaSession 4, IMFMediaSink 4, IMFMediaSource 4, IMFMediaStream 4, IMFPMediaPlayer 4, IMFPMediaItem 4, IMFPMediaPlayerCallback 4, IMFPresentationClock 4 7580,24A8 14:08:08.22808 TraceEnabledKeywords @ Keywords and levels: IMFQualityAdvise 4, IMFQualityAdvise2 4, IMFQualityManager 4, IMFSample 4, IMFSinkWriter 4, IMFSourceReader 4, IMFSourceReaderCallback 4, IMFSourceResolver 4, IMFStreamSink 4, IMFTopology 4, IMFTopologyNode 4, IMFTopoLoader 4, IMFTransform 4, IMediaObject 4, IMFSchemeHandler 4, IMFByteStream 4, IMFByteStreamHandler 4, IMFReadWriteClassFactory 4, IFilterGraph 4, IGraphBuilder 4 7580,24A8 14:08:08.22809 TraceEnabledKeywords @ Keywords and levels: IMediaControl 4, IMemInputPin 4, IWMReader 4, IWMReaderCallback 4 7580,24A8 14:08:08.23053 CMFMediaSessionDetours::Attach @00305E80 Presentation clock @0030A5B0 7580,24A8 14:08:10.97283 CMFPlatExportDetours::MFStartup @ Version=0x00000270, dwFlags=0x00000000 7580,24A8 14:08:10.99038 CMFPlatExportDetours::MFCreateFile @ URL: 'C:\Surveillance\_Test\Segments\output.mp4' 7580,24A8 14:08:10.99255 CMFByteStreamDetours::Write @0030C930 buffer @00382D50 size 24B 7580,24A8 14:08:10.99270 CMFByteStreamDetours::Write @0030C930 wrote 24B 7580,24A8 14:08:10.99271 CMFByteStreamDetours::Write @0030C930 buffer @0017EB44 size 8B 7580,24A8 14:08:10.99279 CMFByteStreamDetours::Write @0030C930 wrote 8B 7580,24A8 14:08:10.99282 CMFExportDetours::MFCreateMPEG4MediaSink @ New sink @003841E0 7580,24A8 14:08:10.99515 COle32ExportDetours::CoCreateInstance @ Created {48E2ED0F-98C2-4A37-BED5-166312DDD83F} MFReadWrite Class Factory (C:\Windows\System32\mfreadwrite.dll) @00382C94 - traced interfaces: IMFReadWriteClassFactory @00382C94, 7580,24A8 14:08:10.99516 CMFReadWriteClassFactoryDetours::CreateInstanceFromObject @00382C94 Object @003841E0, MF_TRANSCODE_CONTAINERTYPE=MFTranscodeContainerType_MPEG4;MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS=0 7580,24A8 14:08:10.99520 CMFReadWriteClassFactoryDetours::HandleObject @ New sink writer @00384E88 7580,24A8 14:08:10.99564 CMFSinkWriterDetours::BeginWriting @00384E88 Began writing 7580,206C 14:08:10.99568 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,206C 14:08:10.99569 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,206C 14:08:10.99570 CMFStreamSinkDetours::EndGetEvent @00384260 Met=301 MEStreamSinkStarted, value (empty), 7580,24A8 14:08:10.99714 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003AF128, Time 0ms, Duration 100ms, Buffers 1, Size 62905B, 7580,24A8 14:08:10.99717 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003AF128, Time 0ms, Duration 100ms, Buffers 1, Size 62905B, 7580,206C 14:08:10.99735 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99735 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @00372728, Time 100ms, Duration 100ms, Buffers 1, Size 31110B, 7580,24A8 14:08:10.99736 CMFStreamSinkDetours::ProcessSample @00384260 Sample @00372728, Time 100ms, Duration 100ms, Buffers 1, Size 31110B, 7580,206C 14:08:10.99746 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99747 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C7B40, Time 200ms, Duration 100ms, Buffers 1, Size 28782B, 7580,24A8 14:08:10.99748 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C7B40, Time 200ms, Duration 100ms, Buffers 1, Size 28782B, 7580,206C 14:08:10.99756 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99759 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C7C30, Time 300ms, Duration 100ms, Buffers 1, Size 27678B, 7580,24A8 14:08:10.99760 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C7C30, Time 300ms, Duration 100ms, Buffers 1, Size 27678B, 7580,206C 14:08:10.99773 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99776 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C8760, Time 400ms, Duration 100ms, Buffers 1, Size 32327B, 7580,24A8 14:08:10.99777 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C8760, Time 400ms, Duration 100ms, Buffers 1, Size 32327B, 7580,1E28 14:08:10.99778 CMFByteStreamDetours::Write @0030C930 buffer @06370048 size 62866B 7580,206C 14:08:10.99786 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,1E28 14:08:10.99787 CMFByteStreamDetours::Write @0030C930 wrote 62866B 7580,1E28 14:08:10.99787 CMFByteStreamDetours::Write @0030C930 buffer @0637F7E8 size 31111B 7580,24A8 14:08:10.99788 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C8A28, Time 500ms, Duration 100ms, Buffers 1, Size 32118B, 7580,24A8 14:08:10.99789 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C8A28, Time 500ms, Duration 100ms, Buffers 1, Size 32118B, 7580,1E28 14:08:10.99791 CMFByteStreamDetours::Write @0030C930 wrote 31111B 7580,1E28 14:08:10.99791 CMFByteStreamDetours::Write @0030C930 buffer @0638E268 size 28783B 7580,1E28 14:08:10.99796 CMFByteStreamDetours::Write @0030C930 wrote 28783B 7580,206C 14:08:10.99797 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99799 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C7BB8, Time 600ms, Duration 100ms, Buffers 1, Size 33946B, 7580,24A8 14:08:10.99799 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C7BB8, Time 600ms, Duration 100ms, Buffers 1, Size 33946B, 7580,206C 14:08:10.99807 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,1E28 14:08:10.99807 CMFByteStreamDetours::Write @0030C930 buffer @0639BF08 size 27679B 7580,24A8 14:08:10.99808 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003C8B18, Time 700ms, Duration 100ms, Buffers 1, Size 28886B, 7580,24A8 14:08:10.99809 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003C8B18, Time 700ms, Duration 100ms, Buffers 1, Size 28886B, 7580,1E28 14:08:10.99812 CMFByteStreamDetours::Write @0030C930 wrote 27679B 7580,1E28 14:08:10.99813 CMFByteStreamDetours::Write @0030C930 buffer @063AA980 size 32328B 7580,206C 14:08:10.99815 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,1E28 14:08:10.99815 CMFByteStreamDetours::Write @0030C930 wrote 32328B 7580,1E28 14:08:10.99816 CMFByteStreamDetours::Write @0030C930 buffer @063BA550 size 32119B 7580,24A8 14:08:10.99816 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @06386940, Time 800ms, Duration 100ms, Buffers 1, Size 25388B, 7580,24A8 14:08:10.99817 CMFStreamSinkDetours::ProcessSample @00384260 Sample @06386940, Time 800ms, Duration 100ms, Buffers 1, Size 25388B, 7580,1E28 14:08:10.99820 CMFByteStreamDetours::Write @0030C930 wrote 32119B 7580,206C 14:08:10.99823 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,24A8 14:08:10.99825 CMFSinkWriterDetours::WriteSample @00384E88 Stream Index 0x0, Sample @003AF258, Time 900ms, Duration 100ms, Buffers 1, Size 22594B, 7580,24A8 14:08:10.99826 CMFStreamSinkDetours::ProcessSample @00384260 Sample @003AF258, Time 900ms, Duration 100ms, Buffers 1, Size 22594B, 7580,1E28 14:08:10.99831 CMFByteStreamDetours::Write @0030C930 buffer @06370048 size 33947B 7580,206C 14:08:10.99831 CMFStreamSinkDetours::EndGetEvent @00384260 Met=305 MEStreamSinkRequestSample, value (empty), 7580,1E28 14:08:10.99834 CMFByteStreamDetours::Write @0030C930 wrote 33947B 7580,1E28 14:08:10.99834 CMFByteStreamDetours::Write @0030C930 buffer @0637F7E8 size 28887B 7580,206C 14:08:10.99835 CMFStreamSinkDetours::EndGetEvent @00384260 Met=306 MEStreamSinkMarker, value @003706B8, 7580,1E28 14:08:10.99839 CMFByteStreamDetours::Write @0030C930 wrote 28887B 7580,1E28 14:08:10.99840 CMFByteStreamDetours::Write @0030C930 buffer @063CA778 size 25389B 7580,1E28 14:08:10.99844 CMFByteStreamDetours::Write @0030C930 wrote 25389B 7580,1C2C 14:08:10.99847 CMFByteStreamDetours::Write @0030C930 buffer @0639BF08 size 22595B 7580,1C2C 14:08:10.99851 CMFByteStreamDetours::Write @0030C930 wrote 22595B 7580,1C2C 14:08:10.99854 CMFByteStreamDetours::Write @0030C930 buffer @0674FB90 size 8B 7580,1C2C 14:08:10.99858 CMFByteStreamDetours::Write @0030C930 wrote 8B __M_F_T_R_A_C_E___LOG__ 

任何想法为什么会在Win7下发生这种情况?

提前致谢!

好的,我自己也在回答这个问题。

在使用媒体类型,接收器编写器,媒体示例和媒体缓冲区尝试了各种属性失败后,我终于检查了媒体接收器对象。 简而言之:它是传递给接收器的媒体类型中缺少的MF_MT_MPEG_SEQUENCE_HEADER属性。

根据MPEG-4文件接收器的文档 ,此属性在Windows 8中自动解析,但必须在所有其他情况下提供。 该值应为SPS / PPS序列,以字节数组的forms提供,如H.264标题中所示。

为了看到它的工作原理,我从我拥有的H.264样本中手动提取了一个序列(使用hex查看器)。 如果我必须解析代码中的标题,我想我必须在关键帧中查找“3或4”字节起始码,但我不知道这是否适用于所有NALU分离格式。 欢迎提出任何意见。