avformat_alloc_output_context2(); //初始化输出码流
avio_open(); //打开输出文件
av_new_stream(); //创建输出码流
avcodec_find_encoder(); //寻找解码器
avcodec_alloc_context3(); //打开解码器上下文
avcodec_open2(); //打开解码器
avformat_write_header(); //写文件头
avcodec_send_frame();
avcodec_receive_packet(); //两步为编码
av_interleaved_write_frame(); //将编码后压缩包写入文件
av_write_trailer(); //写文件尾
主要流程图可以去雷神那看看,对于像我这样的初学者很有帮助。
AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (avcodec == NULL)
{
//创建失败
return -1;
}
AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
avcodec_context->bit_rate = 64000;
avcodec_context->sample_rate = 44100;
avcodec_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
avcodec_context->channel_layout = AV_CH_LAYOUT_STEREO;
avcodec_context->channels = 2;
avcodec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
//打开编码器
int ret = avcodec_open2(avcodec_context,avcodec,NULL);
if (ret < 0)
{
//打开失败
return -1;
}
需要注意两点:
1.由于PCM格式为S16,AAC格式为FLTP,所以在编码前需要重采样音频,将其格式转换为所需格式。
2.PCM大小为1152,但是AAC的只有1024,所以也需要注意nb_samples的设置。
len = swr_convert(actx, frame->data, frame->nb_samples,
data, frame->nb_samples);
AVPacket pkt;
av_init_packet(&pkt);
// 音频编码
ret = avcodec_send_frame(avcodec_context,frame);
if (ret != 0) continue;
ret = avcodec_receive_packet(avcodec_context,&pkt);
if (ret != 0) continue;
// 音频封装成aac文件
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(oc,&pkt);
cout << "[" << len << "]";
av_packet_unref(&pkt);
int main(int argc, char *argv[])
{
char infile[] = "out.pcm";
char outfile[] = "out.aac";
av_register_all();
avcodec_register_all();
AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec)
{
cout << "avcodec_find_encoder error" << endl;
return -1;
}
AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
if (!avcodec_context)
{
cout << "avcodec_alloc_context3 error" << endl;
return -1;
}
avcodec_context->bit_rate = 64000;
avcodec_context->sample_rate = 44100;
avcodec_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
avcodec_context->channel_layout = AV_CH_LAYOUT_STEREO;
avcodec_context->channels = 2;
avcodec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
//打开编码器
int ret = avcodec_open2(avcodec_context,avcodec,NULL);
if (ret < 0)
{
cout << "avcodec_open2 error" << endl;
return -1;
}
cout << "avcodec_open2 success!" << endl;
AVFormatContext *oc = NULL;
avformat_alloc_output_context2(&oc,NULL,NULL,outfile);
if (!oc)
{
cout << "avformat_alloc_output_context2 error" << endl;
return -1;
}
AVStream *st = avformat_new_stream(oc,NULL);
st->codecpar->codec_tag = 0;
avcodec_parameters_from_context(st->codecpar,c);
ret = avio_open(&oc->pb,outfile,AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << "avio_open error" << endl;
return -1;
}
ret = avformat_write_header(oc,NULL);
SwrContext *actx = NULL;
actx = swr_alloc_set_opts(actx, avcodec_context->channel_layout,
avcodec_context->sample_fmt,avcodec_context->sample_rate,
AV_CH_LAYOUT_STEREO,AV_SAMPLE_FMT_S16,44100, 0,0);
if (!actx)
{
cout << "swr_alloc_set_opts error" << endl;
return -1;
}
ret = swr_init(actx);
if (ret < 0)
{
cout << "swr_init error" << endl;
return -1;
}
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;
ret = av_frame_get_buffer(frame,0);
if (ret < 0)
{
cout << "av_frame_get_buffer error" << endl;
return -1;
}
int readSize = frame->nb_samples * 2 * 2;
char *pcm = new char[readSize];
FILE *fp = fopen(infile,"rb");
for (;;)
{
int len = fread(pcm,1,readSize,fp);
if (len<=0)
{
break;
}
const uint8_t *data[1];
data[0] = (uint8_t*)pcm;
len = swr_convert(actx, frame->data, frame->nb_samples,
data, frame->nb_samples );
if (len <= 0)
{
break;
}
AVPacket pkt;
av_init_packet(&pkt);
//音频编码
ret = avcodec_send_frame(avcodec_context,frame);
if (ret != 0) continue;
ret = avcodec_receive_packet(avcodec_context,&pkt);
if (ret != 0) continue;
// 音频封装成aac文件
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(oc,&pkt);
cout << "[" << len << "]";
av_packet_unref(&pkt);
}
AVPacket pkt;
av_init_packet(&pkt);
ret = avcodec_send_frame(avcodec_context, NULL);
cout << "ret1 = " << ret << endl;
ret = avcodec_receive_packet(avcodec_context, &pkt);
cout << "ret2 = " << ret << endl;
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(oc,&pkt);
av_packet_unref(&pkt);
delete pcm;
pcm = NULL;
av_write_trailer(oc);
avio_close(oc->pb);
avformat_free_context(oc);
avcodec_close(c);
avcodec_free_context(&c);
fclose(fp);
}