媒体基础:将G711 PCMU写入mp4
Posted
技术标签:
【中文标题】媒体基础:将G711 PCMU写入mp4【英文标题】:Media foundation: Writing G711 PCMU to mp4 【发布时间】:2020-02-12 16:43:32 【问题描述】:我们有一个要求(Windows UWP 应用程序)将从相机接收的音频和视频数据(RTP 数据包)以 mp4 格式存储。视频格式为 h264,音频为 g711 pcmu
我们正在使用 media Foundation(c# using MF .Net) sinkWriter 将视频数据写入 mp4,效果很好。我想知道如何将音频样本写入 mp4。我尝试了以下方法:
private void SetupAudioMediaType(out IMFMediaType mediaType, in Guid audiosubType)
HResult hr = HResult.S_OK;
hr = MFExtern.MFCreateMediaType(out mediaType);
if (!hr.Succeeded())
Debug.Fail("MFCreateMediaType for audio failed " + hr.ToString());
return;
hr = mediaType.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
if (!hr.Succeeded())
Debug.Fail("Set MF_MT_MAJOR_TYPE media-out failed " + hr.ToString());
return ;
hr = mediaType.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, audioSubType);
if (!hr.Succeeded())
Debug.Fail("Set MF_MT_SUBTYPE media-out failed " + hr.ToString());
return ;
hr = mediaType.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
if (!hr.Succeeded())
Debug.Fail("Set MF_MT_AUDIO_SAMPLES_PER_SECOND media-out failed " + hr.ToString());
return
hr = mediaType.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 1);
if (!hr.Succeeded())
Debug.Fail("Set MF_MT_AUDIO_NUM_CHANNELS media-out failed " + hr.ToString());
return ;
hr = mediaType.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 8);
if (!hr.Succeeded())
Debug.Fail("Set MF_MT_AUDIO_BITS_PER_SAMPLE media-out failed " + hr.ToString());
return ;
return errorCode;
private MultiplexerErrorCode SetupAudio()
HResult hr = HResult.S_OK;
IMFMediaType mediaTypeOut = null;
IMFMediaType mediaTypeIn = null;
SetupAudioMediaType(out mediaTypeOut, MFMediaType.AAC); // or mp3 (MP4 in windows support mp3 or aac)
if (errorCode != MultiplexerErrorCode.Success)
Debug.Fail("setupAudioMediaType output failed:", errorCode.ToString());
else
hr = sinkWriter.AddStream(mediaTypeOut, out audioStreamIndex);
if (!hr.Succeeded())
Debug.Fail("AddStream audio failed " + hr.ToString());
else
Guid PcmuAudioSubType = (new FourCC(7,0,0,0)).ToMediaSubtype(); //PCMU
SetupAudioMediaType(out mediaTypeIn, PcmuAudioSubType);
hr = sinkWriter.SetInputMediaType(audioStreamIndex, mediaTypeIn, null);
if (!hr.Succeeded())
Debug.Fail("SetInputMediaType audio failed " + hr.ToString());
return ;
SetInputMediaType 返回错误 MF_E_INVALIDMEDIATYPE。根据我的分析,以下是错误的原因
1) 我认为 PCMU 输入类型不受支持。应该是PCM。这种理解正确吗?如果是这样,这是否意味着我必须将 PCMU 解码为 PCM。如果是这样,是否有任何 Windows c# API 可以做到这一点?一旦解码完成,输出 pcm 中每个样本的位数是多少。是16吗?
2) 即使我提供 pcm 作为输入类型,SetInputMediaType 也会返回 MF_E_INVALIDMEDIATYPE 错误。是不是因为 aac 编码器只支持 44.1 & 48Khz 的采样率。 (mp3 支持 32 Khz,...)。如果我的理解是正确的,我该如何克服这个问题。我应该上采样吗?如果有怎么办?
3)有没有更简单的方法可以将 pcmu(每秒 8000 个样本,每个样本 8 位)连同视频帧一起写入 mp4
【问题讨论】:
如果您使用的是 C#,那么解码音频的快速方法是使用 NAudio。要深入了解,请参阅codeproject.com/Articles/501521/…。 【参考方案1】:对于 1) 和 3),请阅读:muxing-only-audio-into-mp4-ffmpeg-failed
对于 2)
将 G711 解码为 PCM(CLSID_MULawCodecWrapper:92B66080-5E2D-449E-90C4-C41F268E5514) 使用音频重采样器 (Audio Resampler DSP) 将重新采样的 PCM 编码为 AAC (AAC Encoder)也许 CLSID_MULawCodecWrapper 能够重新采样。 也许您会遇到音频/视频同步问题。
【讨论】:
非常感谢。我将检查 CLSID_MULawCodecWrapper 并检查音频重采样器。如果我通过 PCM 输入(48000Hz,每个样本 16 位),我想检查我的代码是否有效。我的代码有效,我得到了可播放的音频(.m4a 文件 aac 编解码器)。但是,如果我更改为 mp3(.mp3 文件和音频子类型为 .mp3),我会得到 MF_E_INVALIDMEDIATYPE 。为什么 mp3 媒体类型会出错。从文档中我看到它支持 PCM,采样率为 48000Hz,每个样本的位数为 16,通道数为 1。我是否应该提供更多属性。我的配置有什么问题以上是关于媒体基础:将G711 PCMU写入mp4的主要内容,如果未能解决你的问题,请参考以下文章