zoukankan      html  css  js  c++  java
  • 将 PCM 数据编码为AAC格式

    TOC

    1.将mp3文件转换为pcm文件

    ffmpeg -i test.mp3 -f s16le test.pcm

    2.贴上代码

    aac.c

    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    #include <libswresample/swresample.h>
    #include <stdio.h>
    #include <stdbool.h>
    
    
    SwrContext *g_swr_ctx = NULL;
    
    
    static int audio_resampling_2(AVFrame *dst, const AVFrame *src)
    {
        int ret = 0;
    
    
        if (!dst || !src)
        {
            av_log(NULL, AV_LOG_ERROR, "frame pointer is null
    ");
            return -1;
        }
    
    
        //创建swr对象
        if (!g_swr_ctx)
        {
            g_swr_ctx = swr_alloc();
            if (!g_swr_ctx)
            {
                av_log(NULL, AV_LOG_ERROR, "swr contex alloc failed
    ");
                return -1;
            }
    
    
            printf("in_channel_layout = %d
    ", src->channel_layout);
            printf("in_sample_rate = %d
    ", src->sample_rate);
            printf("in_format = %d
    ", src->format);
    
    
            printf("out_channel_layout = %d
    ", dst->channel_layout);
            printf("out_sample_rate = %d
    ", dst->sample_rate);
            printf("out_format = %d
    ", dst->format);
            //设置转换参数
            av_opt_set_int(g_swr_ctx, "in_channel_layout", src->channel_layout, 0);
            av_opt_set_int(g_swr_ctx, "in_sample_rate", src->sample_rate, 0);
            av_opt_set_sample_fmt(g_swr_ctx, "in_sample_fmt", src->format, 0);
    
    
            av_opt_set_int(g_swr_ctx, "out_channel_layout", dst->channel_layout, 0);
            av_opt_set_int(g_swr_ctx, "out_sample_rate", dst->sample_rate, 0);
            av_opt_set_sample_fmt(g_swr_ctx, "out_sample_fmt", dst->format, 0);
    
    
            //初始化swr对象
            if ((ret = swr_init(g_swr_ctx)) < 0)
            {
                av_log(NULL, AV_LOG_ERROR, "init swr contex failed
    ");
                swr_free(&g_swr_ctx);
                return -1;
            }
        }
    
    
        //估算输出的采样数
        dst->nb_samples = FFMAX(av_rescale_rnd(swr_get_delay(g_swr_ctx, src->sample_rate) + src->nb_samples,
                                        dst->sample_rate, src->sample_rate, AV_ROUND_UP), 
                                av_rescale_rnd(src->nb_samples, dst->sample_rate, src->sample_rate, AV_ROUND_UP));
    
    
        //分配样本空间
        ret = av_samples_alloc(dst->data, &dst->linesize[0], dst->channels,
                              dst->nb_samples, dst->format, 0);
        if (ret < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "samples alloc failed
    ");
            swr_free(&g_swr_ctx);
            return -1;
        }
    
    
        //进行重采样,并且把缓存的样本flush掉
        ret = swr_convert(g_swr_ctx, dst->data, dst->nb_samples, (const uint8_t **)src->data, src->nb_samples) 
              + swr_convert(g_swr_ctx, dst->data, dst->nb_samples, 0, 0);
        if (ret < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "resample failed
    ");
            swr_free(&g_swr_ctx);
            return -1;
        }
    
    
        //重新设置输出采样数
        dst->nb_samples = ret;
    
    
        return 0;
    }
    
    
    
    
    int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)
    {
        int ret = 0;
        int got_frame = 0;
        AVPacket enc_pkt;
        if(!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
                    CODEC_CAP_DELAY))
        {
            return 0;
        }
    
    
        while(1)
        {
            enc_pkt.data = NULL;
            enc_pkt.size = 0;
            av_init_packet(&enc_pkt);
            ret = avcodec_encode_audio2(fmt_ctx->streams[stream_index]->codec, &enc_pkt, NULL, &got_frame);
            if(ret < 0)
            {
                break;
            }
            if(!got_frame)
            {
                ret = 0;
                break;
            }
    
    
            ret = av_write_frame(fmt_ctx, &enc_pkt);
            if(ret < 0)
            {
                break;
            }
        }
    
    
        return ret;
    }
    
    
    void usage(void)
    {
        printf("./aac input_file output_file.aac
    ");
    }
    
    
    int main(int argc, char *argv[])
    {
    
    
        if(argc != 3)
        {
            usage();
            return -1;
        }
    
    
        char *input_file = argv[1];
        char *output_file = argv[2];
    
    
        AVFormatContext *pFormatCtx = NULL;
        AVOutputFormat *ofmt = NULL;
        AVStream *audio_stream = NULL;
        AVCodecContext *pCodecCtx = NULL;
        AVCodec *pCodec = NULL;
    
    
        uint8_t *frame_buf = NULL;
        AVFrame *pFrame = NULL;
        AVPacket pkt;
    
    
        int got_frame = 0;
        int ret = 0;
        int size = 0;
    
    
        int i = 0;
    
    
        FILE *fp = fopen(input_file, "rb");
    
    
        av_register_all();
        avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, output_file);
        ofmt = pFormatCtx->oformat;
    
    
        if(avio_open(&pFormatCtx->pb, output_file, AVIO_FLAG_READ_WRITE) < 0)
        {
            printf("Error: call avio_open failed!
    ");
            return -1;
        }
    
    
        audio_stream = avformat_new_stream(pFormatCtx, 0);
        if(!audio_stream)
        {
            return -1;
        }
    
    
        //初始化编码器
        pCodecCtx = audio_stream->codec;
        pCodecCtx->codec_id = ofmt->audio_codec;
        pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
        pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
        pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
        pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
        pCodecCtx->sample_rate = 44100;
        pCodecCtx->bit_rate = 192000;
        pCodecCtx->frame_size = 1024;
    
    
        AVFrame *src_frame = NULL;
        AVFrame *dst_frame = NULL;
    
    
        src_frame = av_frame_alloc();
        src_frame->nb_samples = 1024;
        src_frame->sample_rate = 44100;
        src_frame->format= AV_SAMPLE_FMT_S16;
        src_frame->channel_layout = AV_CH_LAYOUT_STEREO;
        src_frame->channels = av_get_channel_layout_nb_channels(src_frame->channel_layout);
    
    
        //重采样
        dst_frame = av_frame_alloc();
        dst_frame->sample_rate = 44100;
        dst_frame->format = AV_SAMPLE_FMT_FLTP;
        dst_frame->channel_layout = AV_CH_LAYOUT_STEREO;
        dst_frame->channels = av_get_channel_layout_nb_channels(dst_frame->channel_layout);
    
    
    
    
        pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
        //pCodec = avcodec_find_encoder_by_name("aac");
        if(!pCodec)
        {
            printf("Error: call avcodec_find_encoder failed!
    ");
            return -1;
        }
    
    
        if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        {
            printf("Error: call avcodec_open2 failed!
    ");
            return -1;
        }
    
    
        int sr_size = 0;
        sr_size = av_samples_get_buffer_size(NULL, src_frame->channels, src_frame->nb_samples, src_frame->format, 1);
        frame_buf = (uint8_t *)av_malloc(sr_size);
        if(!frame_buf)
        {
            printf("Error: call av_malloc failed, sr_size = %d
    ", sr_size);
            return -1;
        }
    
    
        if(av_sample_fmt_is_planar(src_frame->format))
        {
            avcodec_fill_audio_frame(src_frame, src_frame->channels, src_frame->format, (const uint8_t *)frame_buf, sr_size * src_frame->channels, 1 );
        }
        else
        {
            avcodec_fill_audio_frame(src_frame, src_frame->channels, src_frame->format, (const uint8_t *)frame_buf, sr_size, 0 );
        }
    
    
    
    
        //Write Header
        if(avformat_write_header(pFormatCtx,NULL) < 0)
        {
            printf("Error: call avformat_write_header..
    ");
            return -1;
        }
    
    
        AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
        av_init_packet(packet);
    
    
        dst_frame->pts = 0;
        while(fread(frame_buf, 1, sr_size, fp) > 0)
        {
            //printf("Read a frame..
    ");
            got_frame = 0;
            if(audio_resampling_2(dst_frame, src_frame) < 0)
            {
                printf("Error: call audio_resampling_2
    ");
                return -1;
            }
    
    
            ret = avcodec_encode_audio2(pCodecCtx, packet, dst_frame, &got_frame);
            if(ret < 0)
            {
                printf("Error: call avcodec_encode_audio2
    ");
                return -1;
            }
            i++;
    
    
            dst_frame->pts = i * 100;
    
    
            if(1 == got_frame)
            {
                packet->stream_index = audio_stream->index;
                ret = av_write_frame(pFormatCtx, packet);
                if(ret < 0)
                {
                    printf("Error: call av_write_frame..
    ");
                }
                av_free_packet(packet);
            }
    
    
            if(dst_frame->data[0])
            {
                av_free(dst_frame->data[0]);
            }
        }
    
    
        //flush encoder
        ret = flush_encoder(pFormatCtx, 0);
        if(ret < 0)
        {
            printf("Error: call flush_encoder failed!
    ");
            return -1;
        }
    
    
        if(av_write_trailer(pFormatCtx) < 0)
        {
            printf("Error: call av_write_trailer..
    ");
            return -1;
        }
    
    
        if(audio_stream)
        {
            avcodec_close(audio_stream->codec);
            av_frame_free(&dst_frame);
            av_frame_free(&src_frame);
            av_free(frame_buf);
        }
    
    
        av_free(packet);
        avio_close(pFormatCtx->pb);
        avformat_free_context(pFormatCtx);
    
    
        fclose(fp);
    
    
        printf("Encode Audio End...
    ");
    
    
        return 0;
    }

    3.编译

    gcc -g mp2.c -o mp2 -lavformat -lavcodec -lavutil -lswresample

    4.执行

    ./mp2 test.pcm test.aac

  • 相关阅读:
    chromedriver与chrome各版本及下载地址
    chromedriver和firefox driver的安装过程
    ubuntu python及python IDLE 的安装
    Ubuntu14.04安装及配置mysql5.7.19
    容器集群管理平台的比较
    Android调试神器stetho使用详解和改造
    Vue CLI 3搭建vue+vuex 最全分析
    不会PPT配色没关系,有这些配色网站,也能让你的PPT配色美到极致
    15个超赞的配色网站,建议收藏
    10个超好用的配色网站
  • 原文地址:https://www.cnblogs.com/standardzero/p/12553127.html
Copyright © 2011-2022 走看看