FFmpeg Decoded Memory G711A

Posted by explorer on Sun, 06 Oct 2019 12:18:18 +0200

background

Recently, I learned the knowledge of audio decoding from FFmpeg. I just did the work of audio G711A decoding, so I want to record and share it.

Function description

My requirement is to decode the data of the audio G711A of a frame, so I take a complete G711A audio data from memory to do the decoding action, and the decoded PCM data will be processed separately (saved into PCM files or resampling and re encoding).

Source structure

The main components of source code are initialization decoder and decoding interface.

class DecodeAudio
{
public:
	DecodeAudio();
	~DecodeAudio();

	int audioInit(AVCodecID codec_id, AVSampleFormat sample_fmt, int sample_rate, int channels);
	AVFrame* decode(char *data, int datalen);
	void audioUnit(void);

private:
	AVCodec         *pCodecAudioDec;
	AVCodecContext  *pCodecCtxAudio;
	AVFrame         *pFrameAudio;
	AVPacket        *pPacketAudio;
};

Interface introduction

Decoding initialization:

int DecodeAudio::audioInit(AVCodecID codec_id, AVSampleFormat sample_fmt, int sample_rate, int channels)
{
	pCodecAudioDec = avcodec_find_decoder(codec_id);
	if (!pCodecAudioDec) {
		printf("Codec not found audio codec id\n");
		return -1;
	}

	pCodecCtxAudio = avcodec_alloc_context3(pCodecAudioDec);
	if (!pCodecCtxAudio) {
		printf("Could not allocate audio codec context\n");
		return -1;
	}
	pCodecCtxAudio->sample_fmt = sample_fmt;
	pCodecCtxAudio->sample_rate = sample_rate;
	pCodecCtxAudio->channels = channels;

	if (avcodec_open2(pCodecCtxAudio, pCodecAudioDec, NULL) < 0) {
		printf("Could not open codec\n");
		return -1;
	}

	pPacketAudio = av_packet_alloc();
	if (NULL == pPacketAudio)
		return -1;

	pFrameAudio = av_frame_alloc();
	if (NULL == pFrameAudio)
		return -1;

	return 0;
}

Note: When decoding G711A, AVCodecID is AV_CODEC_ID_PCM_ALAW!

The process of decoding initialization is very simple, mainly: find the decoder, create the decoding context, open the decoder and so on.

The parameters that need to be set for decoding context:
sample_fmt: Sampling format
sample_rate: Sampling frequency
Channels: number of sampling channels

Decode:

The decoding interface input is a complete set of audio coding data:

AVFrame* DecodeAudio::decode(char *data, int datalen)
{
	int ret = 0;

	pPacketAudio->size = datalen;
	pPacketAudio->data = (uint8_t *)av_malloc(pPacketAudio->size);
	memcpy(pPacketAudio->data, data, datalen);

	ret = av_packet_from_data(pPacketAudio, pPacketAudio->data, pPacketAudio->size);
	if (ret <0)
	{
		printf("av_packet_from_data error \n");
		av_free(pPacketAudio->data);
		return NULL;
	}

	ret = avcodec_send_packet(pCodecCtxAudio, pPacketAudio);
	av_packet_unref(pPacketAudio);
	if (ret < 0) {
		printf("avcodec_send_packet error \n");
		return NULL;
	}

	ret = avcodec_receive_frame(pCodecCtxAudio, pFrameAudio);
	if (ret < 0) {
		printf("avcodec_receive_frame error \n");
		return NULL;
	}

	return pFrameAudio;
}

The main contents of decoding are as follows:
av_packet_from_data: Generates AVPacket data to be decoded;
avcodec_send_packet: Enter the stream to be decoded;
avcodec_receive_frame: Output decoded data.

The decoded audioframe - > data [0] is a frame of original pcm audio data, which can be directly stored in a file with the length of audioframe - > linesize [0].

Interface call

DecodeAudio *pdecodeaudio = NULL;
pdecodeaudio = new DecodeAudio;
pdecodeaudio->audioInit(AV_CODEC_ID_PCM_ALAW, AV_SAMPLE_FMT_S16, 8000, 1) < 0);
//g711data as a frame of G711A audio data
AVFrame *audioframe = pdecodeaudio->decode(g711data, g711len);
//The decoded audioframe - > data [0] is a frame of original pcm audio data, which can be directly stored in a file with the length of audioframe - > linesize [0]
delete pdecodeaudio;

download

Source download: https://download.csdn.net/download/qq_22633333/11584405

Topics: codec encoding