FFmpeg读取PCM音频数据编码为AAC格式

本文所给的是一个简单的FFmpeg音频编码示例:

输入的PCM文件格式信息:采样率为48000、双通道、32位

输出的AAC文件格式信息:采样率为44100、双通道、16位

受项目的限制,FFmpeg的版本为2.4.6

如果是需要在新版本上开发,可以用做参考,整体的思路不会有太大的变化。

整体思路是先进行重采样,然后再进行编码。

extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libavutil/opt.h"
};

#define INBUF_SIZE 1024
#define IN_SAMPLE_RATE 48000
#define OUT_SAMPLE_RATE 44100

#define CHANNEL 2				//通道数
#define BITPERSAMPLE 4			//每个样本点的字节数,例如S16为2,FLT为4

int main()
{
	SwrContext *swr;
	swr = swr_alloc();
	swr = swr_alloc_set_opts(swr, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, OUT_SAMPLE_RATE,    //输出的音频参数
		AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, IN_SAMPLE_RATE,    //输入的音频参数
		0, 0);
	if (!swr) {
		fprintf(stderr, "Could not allocate resample context\n");
		return 0;
	}
	if (swr_init(swr) < 0) {
		fprintf(stderr, "Could not open resample context\n");
		swr_free(&swr);
		return 0;
	}

	uint8_t *samples = (uint8_t *)av_malloc(INBUF_SIZE * CHANNEL * BITPERSAMPLE);
	FILE *in_file = fopen("test.pcm", "rb");
	FILE *out_file = fopen("Convert_test.aac", "wb");

	const int out_num_samples = av_rescale_rnd(
		swr_get_delay(swr, IN_SAMPLE_RATE) + INBUF_SIZE, OUT_SAMPLE_RATE,
		IN_SAMPLE_RATE, AV_ROUND_UP);
	uint8_t* outputBuffer = (uint8_t *)av_malloc(out_num_samples * CHANNEL * BITPERSAMPLE);

	avcodec_register_all();
	AVCodec* pCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);

	AVCodecContext* pCodecCtx = avcodec_alloc_context3(pCodec);
	pCodecCtx->sample_rate = OUT_SAMPLE_RATE;
	pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
	pCodecCtx->channels = 2;
	pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;			    //声道类型
	pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;		//输入音频的channel layout
	pCodecCtx->bit_rate = 64000;							// 音频码率 Bit(码率)
	int ret = avcodec_open2(pCodecCtx, pCodec, nullptr);
	if (ret < 0) {
		char errbuf[128] = { 0 };
		const char *errbuf_ptr = errbuf;
		if (av_strerror(ret, errbuf, sizeof(errbuf)) < 0)
			strerror_s(errbuf, AVUNERROR(ret));
		return false;
	}
	AVFrame* pFrame = av_frame_alloc();
	pFrame->format = pCodecCtx->sample_fmt;
	pFrame->channels = pCodecCtx->channels;
	pFrame->channel_layout = pCodecCtx->channel_layout;
	pFrame->sample_rate = pCodecCtx->sample_rate;
	pFrame->nb_samples = pCodecCtx->frame_size;
	ret = avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,
		(const uint8_t*)outputBuffer, out_num_samples * CHANNEL * BITPERSAMPLE, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not setup audio frame\n");
		exit(1);
	}
	AVPacket pkt;
	int got_pkt = 0;

	while(1) {
		if (fread(samples, 1, INBUF_SIZE * CHANNEL * BITPERSAMPLE, in_file) <= 0) {
			printf("Failed to read raw data! \n");
			return 0;
		}
		else if (feof(in_file)) {
			break;
		}
		
		swr_convert(swr, &outputBuffer, out_num_samples, (const uint8_t**)(&samples), INBUF_SIZE);
	
		av_init_packet(&pkt);
		pkt.data = NULL;
		pkt.size = 0;
		ret = avcodec_encode_audio2(pCodecCtx, &pkt, pFrame, &got_pkt);
		if (ret < 0 || got_pkt != 1) {
			av_packet_unref(&pkt);
			return false;
		}

		fwrite(pkt.data, 1, pkt.size, out_file);
	}

    av_packet_unref(&pkt);
	av_freep(&outputBuffer[0]);
	av_freep(&samples[0]);
	swr_free(&swr);
	fclose(in_file);
	fclose(out_file);

    printf("Successful encoding of PCM format to AAC format! \n");
	system("pause");
	return 0;
}

参考文档:

https://blog.csdn.net/leixiaohua1020/article/details/25430449

https://blog.csdn.net/vnanyesheshou/article/details/54560684

https://github.com/FFmpeg/FFmpeg/blob/n2.4.6/doc/examples/decoding_encoding.c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值