FFmpeg解码内存G711A

背景

最近从FFmpeg中学习了音频解码相关的知识,刚好做了音频G711A解码的工作,特此记录分享。

功能描述

我的需求是解码一帧帧的音频G711A的数据,所以我是从内存中取一帧完整的G711A音频数据去做解码动作,解码后的PCM数据我再另做处理(存成PCM文件或者重采样再编码)。

源码构成

源码主要的构成,主要是初始化解码器和解码两个接口。

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

接口介绍

解码初始化:
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;
}

注意:解码G711A的话AVCodecID 是 AV_CODEC_ID_PCM_ALAW !

解码初始化的流程很简单,主要是:查找解码器、创建解码上下文、打开解码器等。

解码上下文需要设置的参数:
sample_fmt:采样格式
sample_rate:采样频率
channels:采样通道数

解码:

解码接口输入是一帧完整的音频编码数据:

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

解码主要内容:
av_packet_from_data:产生要解码的AVPacket数据;
avcodec_send_packet:输入待解码码流;
avcodec_receive_frame:输出解码数据。

解码出来的audioframe->data[0]就是一帧原始的pcm音频数据,可以直接存成文件,数据长度为audioframe->linesize[0]。

接口调用

DecodeAudio *pdecodeaudio = NULL;
pdecodeaudio = new DecodeAudio;
pdecodeaudio->audioInit(AV_CODEC_ID_PCM_ALAW, AV_SAMPLE_FMT_S16, 8000, 1) < 0);
//g711data为一帧的G711A音频数据
AVFrame *audioframe = pdecodeaudio->decode(g711data, g711len);
//解码出来的audioframe->data[0]就是一帧原始的pcm音频数据,可以直接存成文件,数据长度为audioframe->linesize[0]
delete pdecodeaudio;

下载

源码下载:https://download.csdn.net/download/qq_22633333/11584405

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值