FFMpeg音频混合,背景音(二):pcm压缩为aac整体流程
FFmpeg版本:3.3.1
一、整体流程代码
1、基本流程
#include<iostream> using namespace std; //用到的C的头文件 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(); //定义文件 char inputFile[] = "audio.pcm"; char outputFile[] = "audio.aac"; int ret = 0; //找到aac编码器 AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { cout << "avcodec_find_encoder faild" << endl; return -1; } //配置编码器上下文 AVCodecContext* ac = avcodec_alloc_context3(codec); if (!ac) { cout << "avcodec_alloc_context3 faild" << endl; return -1; } //给编码器设置参数 ac->sample_rate = 44100; //采样率 ac->channels = 2; //声道数 ac->channel_layout = AV_CH_LAYOUT_STEREO; //立体声 ac->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样格式为32位float即样本类型fltp ac->bit_rate = 64000; //比特率,采样率。 //给音频的帧设置同一个头部 ac->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //打开音频编码器 ret = avcodec_open2(ac, codec, NULL); if (ret < 0) { cout << "avcodec_open2 faild" << endl; return -1; } //创建一个输出的上下文, 初始化oc AVFormatContext *oc = NULL; avformat_alloc_output_context2(&oc, NULL, NULL, outputFile); if (!oc) { cout << " avformat_alloc_output_context2 faild" << endl; return -1; } //设置音频流 AVStream* st = avformat_new_stream(oc, NULL); st->codecpar->codec_tag = 0; avcodec_parameters_from_context(st->codecpar,ac); //把ac参数拷贝过来 //类似于print,打印视频或者音频信息,参数分别为输出上下文,音视频(0,1),输出文件名,是否输出 av_dump_format(oc, 0,outputFile, 1); //打开文件流 ret = avio_open(&oc->pb, outputFile, AVIO_FLAG_WRITE); if (ret < 0) { cout << "avio_open faild" << endl; return -1; } //打开文件IO流 avio_close(oc->pb); //关闭编码器 avcodec_close(ac); avcodec_free_context(&ac); avformat_free_context(oc); return 0; }
2、整体代码如下,右击项目属性,需要把预处理器加入_CRT_SECURE_NO_WARNINGS
#include<iostream> using namespace std; //用到的C的头文件 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(); //定义文件 char inputFile[] = "audio.pcm"; char outputFile[] = "audio.aac"; int ret = 0; //找到aac编码器 AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { cout << "avcodec_find_encoder faild" << endl; return -1; } //配置编码器上下文 AVCodecContext* ac = avcodec_alloc_context3(codec); if (!ac) { cout << "avcodec_alloc_context3 faild" << endl; return -1; } //给编码器设置参数 ac->sample_rate = 44100; //采样率 ac->channels = 2; //声道数 ac->channel_layout = AV_CH_LAYOUT_STEREO; //立体声 ac->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样格式为32位float即样本类型fltp ac->bit_rate = 64000; //比特率,采样率。 //给音频的帧设置同一个头部 ac->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //打开音频编码器 ret = avcodec_open2(ac, codec, NULL); if (ret < 0) { cout << "avcodec_open2 faild" << endl; return -1; } //创建一个输出的上下文, 初始化oc AVFormatContext *oc = NULL; avformat_alloc_output_context2(&oc, NULL, NULL, outputFile); if (!oc) { cout << " avformat_alloc_output_context2 faild" << endl; return -1; } //设置音频流 AVStream* st = avformat_new_stream(oc, NULL); st->codecpar->codec_tag = 0; avcodec_parameters_from_context(st->codecpar,ac); //把ac参数拷贝过来 //类似于print,打印视频或者音频信息,参数分别为输出上下文,音视频(0,1),输出文件名,是否输出 av_dump_format(oc, 0,outputFile, 1); //打开文件流 ret = avio_open(&oc->pb, outputFile, AVIO_FLAG_WRITE); if (ret < 0) { cout << "avio_open faild" << 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, //输入的参数 0,0 //不需要偏移和记录日志 ); if (!ctx) { cout << "swr_alloc_set_opts faild" << endl; return -1; } //重采样初始化 ret = swr_init(ctx); if (ret < 0) { cout << "swr_init faild" << endl; return -1; } //用frame一帧一帧的从源文件读取 AVFrame* frame = av_frame_alloc(); frame->format = AV_SAMPLE_FMT_FLTP; frame->channels = 2; frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = 1024; //一帧音频的样本数量 //创建frame的缓存空间 ret = av_frame_get_buffer(frame, 0); if (ret < 0) { cout << " av_frame_get_buffer faild" << endl; return -1; } //准备缓存空间专门存放从pcm读取的数据。 int readSize = frame->nb_samples * 2 * 2;//pcm一帧的大小。双通道。32位 char* pcms = new char[readSize]; //打开输入文件 FILE* fp = fopen(inputFile, "rb"); 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; } //AVpacket存放编码后的数据,AVframe存放原始数据 AVPacket pkt; av_init_packet(&pkt); //将重采样之后的数据放到编码线程 ret = avcodec_send_frame(ac, frame); if (ret != 0) { continue; } //接受编码后的数据 ret = avcodec_receive_packet(ac, &pkt); if (ret != 0) { continue; } //对编码后的数据做参数设定,01分别表示音频和视频 pkt.stream_index = 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; /* 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. pcm_aac D:\FFMpeg\project\pcm_aac\pcm_aac\main.cpp 115 */ }