zoukankan      html  css  js  c++  java
  • 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
    */ }
  • 相关阅读:
    CQUOJ 10819 MUH and House of Cards
    CQUOJ 9920 Ladder
    CQUOJ 9906 Little Girl and Maximum XOR
    CQUOJ 10672 Kolya and Tandem Repeat
    CQUOJ 9711 Primes on Interval
    指针试水
    Another test
    Test
    二分图匹配的重要概念以及匈牙利算法
    二分图最大匹配
  • 原文地址:https://www.cnblogs.com/zhangxianrong/p/13815003.html
Copyright © 2011-2022 走看看