c++audioffmpegencodeavcodec

Configure AVCodecContext structure to encode from raw PCM to u-law


I'm trying to encode raw PCM audio data to u-law and it's sound very weird (when it sounds...). I don't understand pretty much how to initialize my AVCodecContext structure (and my input AVFrame).

Here are my parameters:

I also know my input nb samples and this is all informations I have.

So I initialize my AVCodecContext like that:

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;

And my AVFrames like:

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);

Then, I encode with avcodec_send_frame() and avcodec_receive_packet().

So my problem is that I'm not sure if I have to put input or output desired values in different parameters. Probably I have to encode on a way then "resample" using swresample lib. But for now, I'm pretty sure that I don't encode properly. Any advise please? Thanks!


Solution

  • G.711 requires that your input be 8kHz mono (e.g. sample_rate of 8000). So, before passing your raw pcm audio samples to libavcodec you have to convert them to 8kHz with swresample or any other lib that can do that. If you capture your raw pcm yourself usually you can request 8kHz sampling rate from the os sound api.

    I'm pretty sure on android devices you can request 8kHz audio. G.711 is such a simple codec, you don't need libavcodec for that. You can use any available g711.c and simply call linear2alaw or linear2ulaw for each sample. Basically linear2alaw or linear2ulaw convert each 16-bit audio sample into a byte of g711 bitstream.

    You should also ensure that you init your AVCodecContext properly:

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