编码流程:
avformat_alloc_output_context2(); //打开输出音频上下文句柄;
avcodec_find_encoder(); //查找编码器
avcodec_alloc_context3(); //创建编码器上下文
//初始化编码器参数
codecCtx->channels = 2; //通道数量
codecCtx->channel_layout = AV_CH_LAYOUT_STEREO; //通道类型
codecCtx->sample_rate = 8000; //采样率
codecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样数据格式
if (!check_sample_fmt(codec, codecCtx->sample_fmt))
{
fprintf(stderr, "Encoder does not support sample format %s",
av_get_sample_fmt_name(codecCtx->sample_fmt));
exit(1);
}
codecCtx->bit_rate = 64000; //码率
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //公共头部
avcodec_open2(); //打开编码器
avformat_new_stream(); //创建AVstream语音通道
avcodec_parameters_from_context(); //从编码器上下文获取编码参数
avio_open(); //创建并初始化AVIOContext
avformat_write_header(); //写文件头
av_frame_alloc(); //初始化语音帧
fread(); //读pcm语音
swr_convert(); //语音重采样
avcodec_send_frame(); //发送一帧音频给编码器
avcodec_receive_packet(); //接收编码数据
av_interleaved_write_frame(); //写编码数据
av_write_trailer(); //写文件尾
代码
#include <iostream>
#include <string>
extern "C"{
#include "libavutil/samplefmt.h"
#include "libavutil/timestamp.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswresample/swresample.h"
}
using namespace std;
AVFormatContext *fmt_cntx = NULL;
AVCodec *codec = NULL;
AVCodecContext *codecCtx = NULL;
AVStream *astream = NULL;
SwrContext *swrCtx = NULL;
AVFrame *frame = NULL;
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
const enum AVSampleFormat *p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
int main()
{
cout<<"ffmpeg pcm to aac"<<endl;
const char* pcm_file = "test.wav";
const char* aac_file = "out.aac";
FILE *fp = fopen(pcm_file,"rb");
if(!fp)
{
cout<<"open fille "<<pcm_file<<" fail"<<endl;
return -1;
}
//创建输出上下文
int ret = avformat_alloc_output_context2(&fmt_cntx, NULL, NULL, aac_file);
if (ret < 0) {
cout<<"avformat_alloc_output_context2 fail"<<endl;
exit(0);
}
//查找编码器
codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec) {
cout<<"avcodec_find_encoder fail"<<endl;
return -1;
}
codecCtx = avcodec_alloc_context3(codec);
if(!codecCtx)
{
cout<<"avcodec_alloc_context3 fail"<<endl;
return -1;
}
//av_dump_format(fmt_cntx, 0, aac_file, 1);
//初始化编码器参数
codecCtx->channels = 2; //通道数量
codecCtx->channel_layout = AV_CH_LAYOUT_STEREO; //通道类型
codecCtx->sample_rate = 8000; //采样率
codecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样数据格式
if (!check_sample_fmt(codec, codecCtx->sample_fmt))
{
fprintf(stderr, "Encoder does not support sample format %s",
av_get_sample_fmt_name(codecCtx->sample_fmt));
exit(1);
}
codecCtx->bit_rate = 64000; //码率
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //公共头部
//打开编码器
ret = avcodec_open2(codecCtx, codec, NULL);
if (ret != 0) {
cout<<"avcodec_open2 fail"<<endl;
return -1;
}
//创建AVstream
astream = avformat_new_stream(fmt_cntx,NULL);
astream ->codecpar->codec_tag = 0;
avcodec_parameters_from_context(astream->codecpar,codecCtx);
//创建并初始化AVIOContext
ret = avio_open(&fmt_cntx->pb,aac_file,AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << "avio_open error" << endl;
return -1;
}
//写文件头
ret = avformat_write_header(fmt_cntx,NULL);
swrCtx = swr_alloc();
if(!swrCtx)
{
cout<<"swr_alloc fail"<<endl;
}
swrCtx = swr_alloc_set_opts(
swrCtx,
codecCtx->channel_layout, //输出通道类型
codecCtx->sample_fmt, //输出采样格式
codecCtx->sample_rate, //输出采样率
av_get_default_channel_layout(1),//输入通道类型
AV_SAMPLE_FMT_S16, //输入采样格式
8000, //输入采样率
0, 0);
ret = swr_init(swrCtx);
if(ret < 0)
{
cout<<"swr init fail"<<endl;
return -1;
}
frame = av_frame_alloc();
frame->format = AV_SAMPLE_FMT_FLTP;
frame->channels = 2;
frame->channel_layout = AV_CH_LAYOUT_STEREO;
frame->nb_samples = 1024; //一帧音频存放的样本数量
ret = av_frame_get_buffer(frame,0);
if (ret < 0)
{
cout << "av_frame_get_buffer error" << endl;
return -1;
}
//读取pcm数据一帧样本的大小 样本数*通道数*存储格式16位
int readSize = frame->nb_samples * 1* 2;
char *buf = (char*)malloc(readSize);
memset(buf,0,readSize);
int len = 0;
while((len = fread(buf,1,readSize,fp)) > 0)
{
cout<<"read len="<<len<<endl;
const uint8_t *data[1];
data[0] = (uint8_t*)buf;
len = swr_convert(swrCtx,
frame->data,
frame->nb_samples,
data,
frame->nb_samples);
if(len <=0)
break;
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_send_frame(codecCtx,frame);
if (ret != 0) continue;
while(ret >= 0)
{
ret = avcodec_receive_packet(codecCtx,&pkt);
if (ret != 0) continue;
//音频封装成aac文件
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(fmt_cntx,&pkt);
}
}
free(buf);
buf = NULL;
//写文件尾
av_write_trailer(fmt_cntx);
//关闭输出流
avio_close(fmt_cntx->pb);
//清理封装输出上下文
avformat_free_context(fmt_cntx);
//关闭编码器
avcodec_close(codecCtx);
//清理编码器上下文
avcodec_free_context(&codecCtx);
return 0;
}