• FFMpeg音频混合,背景音(二):pcm压缩为aac整体流程


    FFmpeg版本:3.3.1

    一、整体流程代码

    1、基本流程

    #include<iostream>
    using namespace std;
    //用到的C的头文件
    extern "C"
    {
    #include<libavcodec/avcodec.h>
    #include<libavformat/avformat.h>
    #include<libavutil/avutil.h>
    #include<libswresample/swresample.h>
    }
    //对用到的预编译
    #pragma comment(lib, "avformat.lib")
    #pragma comment(lib, "avcodec.lib")
    #pragma comment(lib, "avutil.lib")
    #pragma comment(lib, "swresample.lib")
    int main() 
    {
        //注册
        av_register_all();
        avcodec_register_all();
        //定义文件
        char inputFile[] = "audio.pcm";
        char outputFile[] = "audio.aac";
        int ret = 0;
        //找到aac编码器
        AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
        if (!codec)
        {
            cout << "avcodec_find_encoder faild" << endl;
            return -1;
        }
        //配置编码器上下文
        AVCodecContext* ac = avcodec_alloc_context3(codec);
        if (!ac)
        {
            cout << "avcodec_alloc_context3 faild" << endl;
            return -1;
        }
        //给编码器设置参数
        ac->sample_rate = 44100; //采样率
        ac->channels = 2; //声道数
        ac->channel_layout = AV_CH_LAYOUT_STEREO; //立体声
        ac->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样格式为32位float即样本类型fltp
        ac->bit_rate = 64000; //比特率,采样率。
        //给音频的帧设置同一个头部
        ac->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    
        //打开音频编码器
        ret = avcodec_open2(ac, codec, NULL);
        if (ret < 0) 
        {
            cout << "avcodec_open2 faild" << endl;
            return -1;
        }
        //创建一个输出的上下文, 初始化oc
        AVFormatContext *oc = NULL;
        avformat_alloc_output_context2(&oc, NULL, NULL, outputFile);
        if (!oc)
        {
            cout << " avformat_alloc_output_context2 faild" << endl;
            return -1;
        }
        //设置音频流
        AVStream* st = avformat_new_stream(oc, NULL);
        st->codecpar->codec_tag = 0;
        avcodec_parameters_from_context(st->codecpar,ac); //把ac参数拷贝过来
        //类似于print,打印视频或者音频信息,参数分别为输出上下文,音视频(0,1),输出文件名,是否输出
        av_dump_format(oc, 0,outputFile, 1);
        //打开文件流
        ret = avio_open(&oc->pb, outputFile, AVIO_FLAG_WRITE);
        if (ret < 0)
        {
            cout << "avio_open faild" << endl;
            return -1;
        }
        //打开文件IO流
        avio_close(oc->pb);
        //关闭编码器
        avcodec_close(ac);
        avcodec_free_context(&ac);
        avformat_free_context(oc);
        return 0;
    }

     2、整体代码如下,右击项目属性,需要把预处理器加入_CRT_SECURE_NO_WARNINGS

    #include<iostream>
    using namespace std;
    //用到的C的头文件
    extern "C"
    {
    #include<libavcodec/avcodec.h>
    #include<libavformat/avformat.h>
    #include<libavutil/avutil.h>
    #include<libswresample/swresample.h>
    }
    //对用到的预编译
    #pragma comment(lib, "avformat.lib")
    #pragma comment(lib, "avcodec.lib")
    #pragma comment(lib, "avutil.lib")
    #pragma comment(lib, "swresample.lib")
    int main() 
    {
        //注册
        av_register_all();
        avcodec_register_all();
        //定义文件
        char inputFile[] = "audio.pcm";
        char outputFile[] = "audio.aac";
        int ret = 0;
        //找到aac编码器
        AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
        if (!codec)
        {
            cout << "avcodec_find_encoder faild" << endl;
            return -1;
        }
        //配置编码器上下文
        AVCodecContext* ac = avcodec_alloc_context3(codec);
        if (!ac)
        {
            cout << "avcodec_alloc_context3 faild" << endl;
            return -1;
        }
        //给编码器设置参数
        ac->sample_rate = 44100; //采样率
        ac->channels = 2; //声道数
        ac->channel_layout = AV_CH_LAYOUT_STEREO; //立体声
        ac->sample_fmt = AV_SAMPLE_FMT_FLTP; //采样格式为32位float即样本类型fltp
        ac->bit_rate = 64000; //比特率,采样率。
        //给音频的帧设置同一个头部
        ac->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    
        //打开音频编码器
        ret = avcodec_open2(ac, codec, NULL);
        if (ret < 0) 
        {
            cout << "avcodec_open2 faild" << endl;
            return -1;
        }
        //创建一个输出的上下文, 初始化oc
        AVFormatContext *oc = NULL;
        avformat_alloc_output_context2(&oc, NULL, NULL, outputFile);
        if (!oc)
        {
            cout << " avformat_alloc_output_context2 faild" << endl;
            return -1;
        }
        //设置音频流
        AVStream* st = avformat_new_stream(oc, NULL);
        st->codecpar->codec_tag = 0;
        avcodec_parameters_from_context(st->codecpar,ac); //把ac参数拷贝过来
        //类似于print,打印视频或者音频信息,参数分别为输出上下文,音视频(0,1),输出文件名,是否输出
        av_dump_format(oc, 0,outputFile, 1);
        //打开文件流
        ret = avio_open(&oc->pb, outputFile, AVIO_FLAG_WRITE);
        if (ret < 0)
        {
            cout << "avio_open faild" << endl;
            return -1;
        }
        //向输出写入头部信息
        avformat_write_header(oc, NULL);
        //重采样,并写入输出文件
        SwrContext *ctx = NULL;
        //给重采样上下文配置参数:重采样上下文,输出文件省道布局,输出的
        ctx = swr_alloc_set_opts(ctx, ac->channel_layout, ac->sample_fmt, ac->sample_rate,//需要输出的参数
            AV_CH_LAYOUT_STEREO,AV_SAMPLE_FMT_S16, 44100, //输入的参数
            0,0  //不需要偏移和记录日志
            );
        if (!ctx)
        {
            cout << "swr_alloc_set_opts faild" << endl;
            return -1;
        }
        //重采样初始化
        ret = swr_init(ctx);
        if (ret < 0)
        {
            cout << "swr_init faild" << endl;
            return -1;
        }
        //用frame一帧一帧的从源文件读取
        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; //一帧音频的样本数量
        //创建frame的缓存空间
        ret = av_frame_get_buffer(frame, 0);
        if (ret < 0)
        {
            cout << " av_frame_get_buffer faild" << endl;
            return -1;
        }
        //准备缓存空间专门存放从pcm读取的数据。
        int readSize = frame->nb_samples * 2 * 2;//pcm一帧的大小。双通道。32位
        char* pcms = new char[readSize];
    
        //打开输入文件
        FILE* fp = fopen(inputFile, "rb");
        for (;;)
        {
            //存储到哪,多大,多少,读取哪个文件
            int len = fread(pcms, 1, readSize, fp);
            if (len <= 0)
            {
                break;
            }
            const uint8_t* data[1];
            data[0] = (uint8_t*)pcms;
            //对一帧的数据重采样,
            len = swr_convert(ctx, frame->data, frame->nb_samples, //重采样后的数据
                    data, frame->nb_samples
                );
            if (len <= 0)
            {
                break;
            }
            //AVpacket存放编码后的数据,AVframe存放原始数据
            AVPacket pkt;
            av_init_packet(&pkt);
            //将重采样之后的数据放到编码线程
            ret = avcodec_send_frame(ac, frame);
            if (ret != 0)
            {
                continue;
            }
            //接受编码后的数据
            ret = avcodec_receive_packet(ac, &pkt);
            if (ret != 0)
            {
                continue;
            }
            //对编码后的数据做参数设定,01分别表示音频和视频
            pkt.stream_index = 0; 
            pkt.dts = 0;
            pkt.pts = 0;
            //数据写入输出上下文
            av_interleaved_write_frame(oc, &pkt);
            cout << len << ",";
            //
    
    
    
        }
        delete pcms;
        pcms = NULL;
        //写入音频的索引
        av_write_trailer(oc);
    
    
    
        //关闭打开文件IO流
        avio_close(oc->pb);
        //关闭编码器
        avcodec_close(ac);
        avcodec_free_context(&ac);
        avformat_free_context(oc);
        return 0;
        /*
        严重性    代码    说明    项目    文件    行    禁止显示状态
    错误    C4996    'fopen': This function or variable may be unsafe. Consider using fopen_s instead. 
    To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. pcm_aac D:FFMpegprojectpcm_aacpcm_aacmain.cpp 115
    */ }
  • 相关阅读:
    莎士比亚的对白
    拟人、比喻及修辞 —— 生动的英语
    拟人、比喻及修辞 —— 生动的英语
    32位与64位、单精度(single-precision)与双精度(double-precision)
    32位与64位、单精度(single-precision)与双精度(double-precision)
    OpenGL(十七) 绘制折线图、柱状图、饼图
    计算机的组成 —— PCI(PCIE)、PCB
    计算机的组成 —— PCI(PCIE)、PCB
    ios 打电话结束返回到应用中
    paip.输入法编程----删除双字词简拼
  • 原文地址:https://www.cnblogs.com/zhangxianrong/p/13815003.html
Copyright © 2020-2023  润新知