媒体基金会IMFSinkWriter :: finalize()方法在Windows 7下无法当合并帧的H.264 MP4到 [英] Media Foundation IMFSinkWriter::Finalize() method fails under Windows 7 when muxing H.264 frames into MP4

查看:1282
本文介绍了媒体基金会IMFSinkWriter :: finalize()方法在Windows 7下无法当合并帧的H.264 MP4到的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写在C#中的工具,复用器H.264帧转换成MP4文件,我使用的媒体基金会的媒体下沉水槽作家做到这一点。

I'm writing a tool in C# that muxes H.264 frames into MP4 files, and I'm using Media Foundation's media sink with sink writer to do this.

事情工作得很好的Win8下,但在Windows 7下相同的代码抛出一个异常,HRESULT:0xC00D36E6(MF_E_ATTRIBUTENOTFOUND),调用片作家的Finalize方法时。其结果是,所生成的MP4文件没有正确关闭,并且是(当然)无法播放。

Things work pretty well under Win8, but under Windows 7 the same code throws an exception, HResult: 0xC00D36E6 (MF_E_ATTRIBUTENOTFOUND), when invoking sink writer's Finalize method. As a result, the generated MP4 file is not properly closed, and is (of course) not playable.

mftrace日志显示在Windows 7下失败后(或期间)的地方发生IMFSinkWriter :: PlaceMarker内部通话。 。在Windows 8中的日志中的相应行紧跟一个敲定语句

The mftrace log shows that the failure under Windows 7 occurs somewhere after (or during) the internal call to IMFSinkWriter::PlaceMarker. Under Windows 8 the corresponding line in the log is immediately followed by a "Finalized" statement.

下面是混流代码示例,其次是mftrace日志进一步:

Here is a sample of the muxing code, followed by the mftrace log further:

    // pFrames contains the H264 frames as binaries
    public void Mux(List<byte[]> 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方法:

The CreateMediaBuffer method referred above:

    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日志:

This is the mftrace log:

    __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属性。

Having tried unsuccessfully all sorts of attributes with the media type, sink writer, media samples, and media buffers, I finally got to check the media sink object. Long story short: it's the MF_MT_MPEG_SEQUENCE_HEADER attribute that was missing in the media type passed to the sink.

根据MPEG-4文件接收器的的文档,这个属性是Windows 8自动解决,但必须在所有其他情况下提供。该值应该是一个SPS / PPS序列,提供作为一个字节数组,如出现在H.264头。

According to the MPEG-4 file sink's documentation, this attribute is resolved automatically in Windows 8, but must be supplied in all other cases. The value should be an SPS/PPS sequence, provided as a byte array, as appearing in the H.264 headers.

要看到它的工作,我手动提取的序列(使用十六进制查看器)从H.264样品我。如果非要从我的代码解析的头,我想我得去寻找3或4字节开始在关键帧代码,但我不知道这是否会在所有NALU分离格式。在这个任何意见都欢迎。

To see it work, I extracted a sequence manually (using a hex viewer) from a H.264 sample I have. If I have to parse the headers from my code, I guess I'll have to look for the "3 or 4" byte start codes in the key frames, but I don't know if this will work in all NALU separation formats. Any comments on this are welcome.

这篇关于媒体基金会IMFSinkWriter :: finalize()方法在Windows 7下无法当合并帧的H.264 MP4到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆