音频参数详解将pcm转aac格式 vs2017 c++ ffmpeg

AV_SAMPLE_FMT_S16 使用16位 两个字节

AV_SAMPLE_FMT_FLTP 使用32位 四字节 fLOAT

播放pcm文件 :

./ffplay.exe -ar 16000 -channels 1 -f s16le -i device_check_voice.pcm     

 

新建工程:

附加依赖项:

avcodec.lib
swresample.lib
avutil.lib
avformat.lib

 

ffmpeg是由C语言写的,在c++中使用,需要extern "C"

#include <iostream>

using namespace std;

extern "C"
{
#include <libavcodec/avcodec.h>   //编解码
#include <libavformat/avformat.h>   //格式
#include <libavutil/avutil.h>
#include <libswresample/swresample.h>  //重采样

}

//添加静态库
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swresample.lib")



int main()
{
//	av_register_all(); 弃用

//	avcodec_register_all();

	int ret = 0;

	char inputfile[] = "audio.pcm";
	char outputfile[] = "audio.aac";

	//注册编码器  acc
	AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
	if (!codec)
	{
		cout << "avcodec_find_encoder failed" << endl;
		return -1;
	}

	//配置编码器上下文 初始化编码器上下文,主要通道数,采样率,采样格式
	AVCodecContext* ac = avcodec_alloc_context3(codec);
	if (!ac) {
		cout << "avcodec_alloc_context3 failed" << endl;
		return -1;
	}

	//设置参数
	ac->sample_rate = 44100;
	ac->channels = 2;
	ac->channel_layout = AV_CH_LAYOUT_STEREO;//立体声

	ac->sample_fmt = AV_SAMPLE_FMT_FLTP;//AAC 支持float类型
	ac->bit_rate = 64000;

	ac->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;//音频帧设置头部

	//打开音频编码器
	ret = avcodec_open2(ac, codec, NULL);
	if (ret < 0)
	{
		cout << "avcodec_open2 failed" << endl;
		return -1;
	}

	//创建输出上下文结构体
	AVFormatContext* oc = NULL;
	avformat_alloc_output_context2(&oc, NULL, NULL, outputfile);//初始化结构体
	if (!oc)
	{
		cout << "avformat_alloc_output_context2 failed" << endl;
		return -1;
	}

	//创建音频流
	AVStream* st = avformat_new_stream(oc, NULL);
	st->codecpar->codec_tag = 0;//在一个文件中,音频流 视频流 字幕流的下标分别为 0 1 2 

	//将配置的编解码器上下文拷贝到st
	avcodec_parameters_from_context(st->codecpar, ac);

	//打印信息    上下文 流下标 输出文件名 是否输出1 输出;
	av_dump_format(oc, 0, outputfile, 1);

	//打开输出文件流
	ret = avio_open(&oc->pb, outputfile, AVIO_FLAG_WRITE);
	if (ret < 0)
	{
		cout << "avio_open failed" << endl;
		return -1;
	}

	avformat_write_header(oc, NULL);//写入头部信息

	//重采样上下文
	SwrContext* ctx = NULL;
	//配置重采样 参数              
	ctx = swr_alloc_set_opts(ctx, ac->channel_layout, ac->sample_fmt, ac->sample_rate,//输出的音频参数
		AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 44100,//输入的pcm的声道布局
		0, 0

	);
	if (!ctx)
	{
		cout << "swr_alloc_set_opts failed" << endl;
		return -1;
	}

	ret = swr_init(ctx);
	if (ret < 0)
	{
		cout << "swr_init failed" << endl;
		return -1;
	}


	//创建AVFrame 结构体  :是一帧样本:1024个
	AVFrame* frame = av_frame_alloc();//分配空间
	frame->format = AV_SAMPLE_FMT_FLTP;//四字节 acc只支持fltp
	frame->channels = 2;
	frame->channel_layout = AV_CH_LAYOUT_STEREO;
	frame->nb_samples = 1024;//一帧音频的样本数量

	ret = av_frame_get_buffer(frame, 0);//设置frame 缓存空间
	if (ret < 0) {
		cout << "av_frame_get_buffer failed" << endl;
		return -1;
	}

	int readSize = frame->nb_samples * 2 * 2;//每一次读取的数据  双声道 * 两字节
	char* pcms = new char[readSize];

	//打开输入的文件
	FILE* fp = fopen(inputfile, "rb");
	if (fp == nullptr)
	{
		std::cout << "open inputfile error" << std::endl;
		return -1;
	}

	for (;;)
	{
		int len = fread(pcms, 1, readSize, fp);
		if (len <= 0)
		{
			break;
		}

		//强制类型转换
		const uint8_t* data[1];
		data[0] = (uint8_t*)pcms;

		//重采样               接收          样本数量
		len = swr_convert(ctx, frame->data, frame->nb_samples, //重采样之后的数据
			data, frame->nb_samples  //重采样之前的数据
		);

		if (len <= 0)
		{
			break;
		}


		//AVFrame 存储原始数据  AVPacket存放编码后的数据 存放到aac文件中
		AVPacket pkt;
		av_init_packet(&pkt);//初始化

		//重采样之后的数据进行编码

		    //重采样之后的数据发送到编码线程  todo
		ret = avcodec_send_frame(ac, frame);
		if (ret != 0) {
			continue;
		}

		   //接收编码之后的数据
		ret = avcodec_receive_packet(ac, &pkt);
		if (ret != 0)
		{
			continue;
		}

		//编码后的数据写入acc文件中
		pkt.stream_index = 0;//音频流 0
		pkt.dts = 0;//
		pkt.pts = 0;

		av_interleaved_write_frame(oc, &pkt);

		cout << len << ",";



	}


	delete pcms;
	pcms = NULL;

	//写入音频的索引
	av_write_trailer(oc);

	//关闭打开的文件io流
	avio_close(oc->pb);

	//关闭编码器
	avcodec_close(ac);

	//清理在编码器设置的参数
	avcodec_free_context(&ac);

	//清理封装的上下文
	avformat_free_context(oc);

	return 0;

}

 

编译:出现关于fopen报错_CRT_SECURE_NO_WARNINGS:配置

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值