我正在尝试将原始PCM音频数据编码为u-law,听起来很奇怪(当听起来...时)。我不太了解如何初始化AVCodecContext结构(以及输入的AVFrame)。

这是我的参数:

  • 输入:PCM(16位带符号),MONO,44.1kHz(采样率)(来自我的Android设备MIC)
  • 必需的输出:G.711 u-law,MONO,8kHz(采样率),64 kbits / s(比特率)(来自我的输出目标设备的文档)

  • 我也知道我的输入nb样本,这是我所拥有的全部信息。

    所以我像这样初始化AVCodecContext:
    AVCodec* pCodec = avcodec_find_encoder(AV_CODEC_ID_PCM_MULAW);
    // ...
    AVCodecContext* pCodecContext = avcodec_alloc_context3(pCodec);
    // ...
    // Do I need input or output params in following lines?
    pCodecContext->channels = 1:
    pCodecContext->channel_layout = AV_CH_LAYOUT_MONO;
    pCodecContext->sample_rate = 8000;
    pCodecContext->bit_rate = 64000
    pCodecContext->sample_fmt = AV_SAMPLE_FMT_S16;
    

    和我的AVFrame像:
    AVFrame* pFrame = av_frame_alloc();
    pFrame->channels = 1;
    pFrame->channel_layout = AV_CH_LAYOUT_MONO;
    pFrame->sample_rate = 44100;
    pFrame->format = AV_SAMPLE_FMT_S16;
    pFrame->nb_samples = /*my audio data samples count*/;
    avcodec_fill_audio_frame(pFrame, 1, AV_SAMPLE_FMT_S16, /*my audio data*/, /*my audio data size*/, 0);
    

    然后,我使用avcodec_send_frame()avcodec_receive_packet()进行编码。

    所以我的问题是我不确定是否必须将输入或输出所需的值放在不同的参数中。可能我必须使用swresample lib对编码进行“重采样”。但就目前而言,我很确定自己编码不正确。有什么建议吗?谢谢!

    最佳答案

    G.711要求您的输入为8kHz单声道(例如sample_rate为8000)。因此,在将原始的pcm音频样本传递给libavcodec之前,您必须使用swresample或任何其他可以实现此目的的lib将它们转换为8kHz。如果您自己捕获原始pcm,通常可以从os sound api请求8kHz采样率。

    我很确定在android设备上可以请求8kHz音频。 G.711是这么简单的编解码器,您不需要libavcodec。您可以使用任何可用的g711.c,并且只需为每个样本调用linear2alawlinear2ulaw。基本上linear2alawlinear2ulaw将每个16位音频样本转换为g711比特流的字节。

    您还应确保正确初始化AVCodecContext:

    pCodecContext->channels = 1;
    pCodecContext->channel_layout = AV_CH_LAYOUT_MONO;
    ...
    

    07-27 19:42