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

  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/standardzero/p/12553127.html
Copyright © 2011-2022 走看看