FFmpeg API进行AAC编码

Posted 顾文繁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFmpeg API进行AAC编码相关的知识,希望对你有一定的参考价值。

FFmpeg API进行AAC编码步骤

1 注册设备

avdevice_register_all();

 2 查找格式并打开输入

av_find_input_format("avfoundation");
avformat_open_input(&fmt_ctx, devicename, iformat, &options))

 3 编码器

     //avcodec_find_encoder(AV_CODEC_ID_AAC);
    AVCodec *codec = avcodec_find_encoder_by_name("libfdk_aac");
    //创建 codec 上下文
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);

    codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;          //输入音频的采样大小
    codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;    //输入音频的channel layout
    codec_ctx->channels = 2;                            //输入音频 channel 个数
    codec_ctx->sample_rate = 44100;                     //输入音频的采样率
    codec_ctx->bit_rate = 0; //AAC_LC: 128K, AAC HE: 64K, AAC HE V2: 32K
    codec_ctx->profile = FF_PROFILE_AAC_HE_V2; //阅读 ffmpeg 代码
    //打开编码器
    avcodec_open2(codec_ctx, codec, NULL)

 4 初始化重采样上下文

     //channel, number/
    swr_ctx = swr_alloc_set_opts(NULL,                //ctx
                              AV_CH_LAYOUT_STEREO, //输出channel布局
                              AV_SAMPLE_FMT_S16,   //输出的采样格式
                              44100,               //采样率
                              AV_CH_LAYOUT_STEREO, //输入channel布局
                              AV_SAMPLE_FMT_FLT,   //输入的采样格式
                              44100,               //输入的采样率
                              0, NULL);

5 创建frame

 //音频输入数据
 frame = av_frame_alloc();
 if(!frame){
     printf("Error, No Memory!\\n");
     goto __ERROR;
 }

 6 给frame设置参数

    frame->nb_samples     = 512;                //单通道一个音频帧的采样数
    frame->format         = AV_SAMPLE_FMT_S16;  //每个采样的大小
    frame->channel_layout = AV_CH_LAYOUT_STEREO; //channel layout

 7 给frame分配真实缓冲

    av_frame_get_buffer(frame, 0); // 512 * 2 * = 2048
     if(!frame->data[0]){
         printf("Error, Failed to alloc buf in frame!\\n");
         //内存泄漏
         goto __ERROR;
     }

 8 分配编码后的数据空间AVPacket

packet = av_packet_alloc()

9 创建输入输出缓冲区

    av_samples_alloc_array_and_samples(src_data,         //输输入缓冲区地址
                                    src_linesize,     //缓冲区的大小
                                    2,                 //通道个数
                                    512,               //单通道采样个数
                                    AV_SAMPLE_FMT_FLT, //采样格式
                                    0);



    av_samples_alloc_array_and_samples(dst_data,         //输出缓冲区地址
                                    dst_linesize,     //缓冲区的大小
                                    2,                 //通道个数
                                    512,               //单通道采样个数
                                    AV_SAMPLE_FMT_S16, //采样格式
                                    0);

10 不断接受数据进行重采样然后进行编码,然后写入文件中    

while((ret = av_read_frame(fmt_ctx, &pkt)) == 0 && rec_status) {
         //进行内存拷贝,按字节拷贝的
         memcpy((void*)src_data[0], (void*)pkt.data, pkt.size);
         
         //重采样
         swr_convert(swr_ctx,                    //重采样的上下文
                     dst_data,                   //输出结果缓冲区
                     512,                        //每个通道的采样数
                     (const uint8_t **)src_data, //输入缓冲区
                     512);                       //输入单个通道的采样数

         

         //将重采样的数据拷贝到 frame 中
         memcpy((void *)frame->data[0], dst_data[0], dst_linesize);

         //进行编码
         //将数据送编码器
         ret = avcodec_send_frame(ctx, frame);
         //如果ret>=0说明数据设置成功
         while(ret >= 0){
             //获取编码后的音频数据,如果成功,需要重复获取,直到失败为止
             ret = avcodec_receive_packet(ctx, pkt);

             //write file
             fwrite(pkt->data, 1, pkt->size, output);
             fflush(output);

         }

         //release pkt
         av_packet_unref(&pkt);

     }

    这里需要注意,由于有缓冲的存在,当停止时,应将缓冲区的数据刷出。

    //强制将编码器缓冲区中的音频进行编码输出
     while(ret >= 0){
         //获取编码后的音频数据,如果成功,需要重复获取,直到失败为止
         ret = avcodec_receive_packet(ctx, pkt);

         //write file
         fwrite(pkt->data, 1, pkt->size, output);

         fflush(output);

     }

 11 释放空间

以上是关于FFmpeg API进行AAC编码的主要内容,如果未能解决你的问题,请参考以下文章

最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

编码aac音轨时FFmpeg媒体信息不正确

ffmpeg创建AAC编码器

AAC_LC用LATM封装header信息解析

FFmpeg音频的编码流程详解及demo

Java mp4parser 片段序列不连续