基于QT+FFMPEG的音视频开发(四)——编码音频

* 一、编码一般步骤 <https://blog.csdn.net/Mr__Hu/article/details/91795842#_3>
* 二、编码 <https://blog.csdn.net/Mr__Hu/article/details/91795842#_19>
* 2.1 创建编码器(本文创建AAC)
<https://blog.csdn.net/Mr__Hu/article/details/91795842#21__AAC_20>
* 2.2 核心编码 <https://blog.csdn.net/Mr__Hu/article/details/91795842#22___43>
* 三、源码 <https://blog.csdn.net/Mr__Hu/article/details/91795842#_69>
我的大部分学习都来自雷神,没有基础去雷神博客转转,每次都有很多收获。
https://blog.csdn.net/leixiaohua1020/article/details/42658139
<https://blog.csdn.net/leixiaohua1020/article/details/42658139>


<>一、编码一般步骤
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(); //写文件尾
主要流程图可以去雷神那看看,对于像我这样的初学者很有帮助。

<>二、编码

<>2.1 创建编码器(本文创建AAC)
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; }
<>2.2 核心编码

需要注意两点:

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); }

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信