C# 媒体基金会:将G711 PCMU写入mp4

C# 媒体基金会:将G711 PCMU写入mp4,c#,windows,audio,pcm,ms-media-foundation,C#,Windows,Audio,Pcm,Ms Media Foundation,我们要求(Windows UWP应用程序)以mp4格式存储从摄像机接收的音频和视频数据(RTP数据包)。视频格式为h264,音频格式为g711 pcmu 我们正在使用媒体基金会(c#使用MF.Net)sinkWriter将视频数据写入mp4,效果良好。我想知道如何将音频样本写入mp4。我尝试了以下方法: private void SetupAudioMediaType(out IMFMediaType mediaType, in Guid audioSubType) { HRes

我们要求(Windows UWP应用程序)以mp4格式存储从摄像机接收的音频和视频数据(RTP数据包)。视频格式为h264,音频格式为g711 pcmu

我们正在使用媒体基金会(c#使用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(1)和3)阅读以下内容:

第2页)

  • 将G711解码至PCM(编码:92B66080-5E2D-449E-90C4-C41F268E5514)
  • 使用音频重采样器()
  • 将重新采样的PCM编码为AAC()
也许CLSID_MULawCodecWrapper能够进行重新采样。
可能您会遇到音频/视频同步问题。

非常感谢。我将检查CLSID_MulawcodecRapper,还将检查音频重采样器。如果我通过PCM输入(48000Hz,每个样本16位),我想检查我的代码是否有效。我的代码工作正常,我可以播放音频(.m4a文件aac编解码器)。但如果我改为mp3(.mp3文件和音频子类型为.mp3),我会得到MF_E_INVALIDMEDIATYPE。为什么mp3媒体类型给出错误。从文档中我看到它支持PCM,采样率为48000Hz,每个采样位16,通道计数1。我应该提供更多的属性吗。我的配置有什么问题?如果你用的是C#,那么解码音频的快速方法就是使用NAudio。要深入了解,请参阅。