媒体基础 MP4 编码:IMFSinkWriter 不接受 PCM 输入

Posted

技术标签:

【中文标题】媒体基础 MP4 编码:IMFSinkWriter 不接受 PCM 输入【英文标题】:Media Foundation MP4 Encoding: IMFSinkWriter doesn't accept PCM input 【发布时间】:2017-01-03 16:05:28 【问题描述】:

我正在使用 Windows Media Foundation 对 H264 视频进行编码。 (我通过 C# 使用 MFNet Wrapper)。

视频编码完美运行。我拿出一个带有 H264 视频的 MP4。

现在我尝试添加音频。我想从内存中传入未压缩的 PCM,然后取出编码的 AAC。我将音频流添加到我的 SinkWriter。 ö但是当调用SetInputMediaType 时,我得到MF_E_INVALIDMEDIATYPE

这是为什么呢?

这是我的代码:

IMFMediaType audioTypeOut, audioTypeIn, videoTypeOut, videoTypeIn;
IMFSinkWriter sinkWriter;

Check = MFCreateSinkWriterFromURL(outputFile.Replace(".avi",".mp4"), null, attributes, out sinkWriter); // the assignment to "Check" throws an exception if a method fails.

//[ ... setup video input & output - works perfectly ...]
Check = sinkWriter.AddStream(videoTypeOut, out videoStreamIndex);
Check = sinkWriter.SetInputMediaType(videoStreamIndex, videoTypeIn, null);

// Now setup Audio:
// Input PCM from memory
Check = MFExtern.MFCreateMediaType(out audioTypeIn);
Check = audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
Check = audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.PCM); // this .PCM enum value is equal to MFAudioFormat_PCM in the C++ api (I checked)
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BLOCK_ALIGNMENT, 4);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 4);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_ALL_SAMPLES_INDEPENDENT, 1);

// and output AAC to the MP4 file
Check = MFExtern.MFCreateMediaType(out audioTypeOut);
Check = audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
Check = audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.AAC);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_ALL_SAMPLES_INDEPENDENT, 0);

// pass it to the sinkWriter
Check = sinkWriter.AddStream(audioTypeOut, out audiostreamIndex);
Check = sinkWriter.SetInputMediaType(audioStreamIndex, audioTypeIn, null); // this call fails

现在,当我尝试传入 AAC 时,设置代码完美运行。让我觉得我错误地配置了 PCM IMFMediaType,但我无法发现错误。

【问题讨论】:

仅供参考,库存 AAC 编码器的输入必须是 MFAudioFormat_PCM。您的 LPCM 可能需要进行不可自动转换的转换。 @RomanR。谢谢,我把它改成PCM。没有变化 - 出现相同的错误。 (并且我确认我在 C# api 中的“PCM”与官方 SDK 中的 MFAudioFormat_PCM 具有相同的值) 好的,接下来看起来不太好的事情是你的MF_MT_ALL_SAMPLES_INDEPENDENT AAC 类型。你为什么不把它完全注释掉。 太棒了,解决了!非常感谢。 【参考方案1】:

音频媒体类型可以这样初始化:

// Input PCM from memory
Check = MFExtern.MFCreateMediaType(out audioTypeIn);
Check = audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
Check = audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.PCM);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
Check = audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);

// and output AAC to the MP4 file
Check = MFExtern.MFCreateMediaType(out audioTypeOut);
Check = audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
Check = audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.AAC);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
Check = audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);

将派生其他属性,并且在原始代码中错误使用MF_MT_ALL_SAMPLES_INDEPENDENT sn-p 会阻止编解码器的初始化。

【讨论】:

以上是关于媒体基础 MP4 编码:IMFSinkWriter 不接受 PCM 输入的主要内容,如果未能解决你的问题,请参考以下文章

使用 IMFSinkWriter 更改标题、作者等元数据

通过 ICodecAPI 为 H.264 IMFSinkWriter 编码器设置属性

“无法解码媒体资源 FILEPATH/FILENAME.mp4。”尝试在 Firefox 35 上播放 h264 编码文件时

IMFSinkWriter :请求无效,因为已调用 Shutdown()

IMFSinkWriter 中的错误?

媒体基础 SinkWriter (MP4 FastStart)