音视频开发——(四)编码音频

基于QT FFMPEG的音视频开发(四)——编码音频一、编码一般步骤二、编码2.1创建编码器(本文创建AAC)2.2核心编码三、源码我的大部分学习都来自雷神,没有基础去雷神博客转转,每次都有很多收获。https://blog.csdn.net/leixiaohua1020/article/details/42658139一、编码一般步骤avformat_alloc_output_context2(...


我的大部分学习都来自雷神,没有基础去雷神博客转转,每次都有很多收获。
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);}
源文地址:https://www.guoxiongfei.cn/csdn/4960.html