配置AVCodecContext结构以从原始PCM编码到u-law

时间:2017-05-15 08:30:42

标签: c++ audio ffmpeg encode avcodec

我正在尝试将原始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以“重新采样”的方式进行编码。但是现在,我很确定我没有正确编码。有什么建议吗?谢谢!

1 个答案:

答案 0 :(得分:1)

G.711要求您的输入为8kHz单声道(例如,sample_rate为8000)。因此,在将原始pcm音频样本传递给libavcodec之前,您必须使用swresample或任何其他可以执行此操作的库将它们转换为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; 
...