Scala idea 常用快捷键 cordova nuget vue的钩子函数 npm安装vue jquery去空格 java数据分析 mysql转字符串 java常用的包 css面试题 python入门教程 python中get函数 python实战 python自学教材 python怎么配置环境 python抛异常 python安装程序 python服务器开发 java语法基础 java类与对象 java正则表达式用法 java怎么连接数据库 java文件读写 java创建文件夹 java系统学习 linux文档 0x0000004e corelpainter js数组删除指定元素 hexworkshop 骰子表情 pycharm中文版 linux安卓模拟器 网页自动点击 globalscape php随机数 ps画笔工具变成十字 桌面cpu性能天梯图 苹果拼多多商家版本
当前位置: 首页 > 学习教程  > 编程语言

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

2020/12/5 10:57:37 文章标签:

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 avuti…

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:配置


本文链接: http://www.dtmao.cc/news_show_450357.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?