ffmpeg C代码音频解码

生成原始PCM数据

#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
int main(){
    char* fileName = "./jichi.mp4";
    char* outFile = "./jichi.pcm";
    AVFormatContext* avf_cxt = NULL;
    //设置日志打印级别
    // av_log_set_level(AV_LOG_INFO);

    //1. 注册组件
    av_register_all();
  

    //2. 打开输入的文件
    int ret = avformat_open_input(&avf_cxt,fileName,NULL,NULL);
    if(ret < 0){
        printf("文件地址错误 %s  \n",fileName);
        return -1;
    }
    //3. 读取文件信息失败
    ret = avformat_find_stream_info(avf_cxt,NULL);
    if(ret < 0){
        printf("不能获取到文件多媒体信息  %s  \n",fileName);
        goto _end;
    }
    //打印文件信息
    av_dump_format(avf_cxt,0,fileName,0);
    int audio_index = -1;
    //找到文件中的视频流索引
    for(int i = 0; i < avf_cxt->nb_streams;i++){
       if( avf_cxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){
           audio_index = i;
           break;
       }
    }
    if(audio_index == -1){
        printf("没有找到文件中的音频流 \n");
        goto _end;
    }

    //4. 在avformatContext中得到avcodecContext
    AVCodecContext *avc_cxt = avf_cxt->streams[audio_index]->codec;
    ///再根据上下文拿到编解码id,通过该id拿到解码器
    AVCodec *avcodec = avcodec_find_decoder(avc_cxt->codec_id);
    if(avcodec == NULL){
        printf("不能得到音频的解码器 \n");
        goto _end;
    }
    //5. 打开解码器
    ret = avcodec_open2(avc_cxt,avcodec,NULL);
    if(ret < 0){
        printf("不能打开解码器");
        goto _end;
    }
    AVPacket *avp = av_packet_alloc();
    AVFrame *avf = av_frame_alloc();

    //frame->16bit 44100 PCM 统一音频采样格式与采样率
    SwrContext* swr_cxt = swr_alloc();
    //重采样设置选项-----------------------------------------------------------start
    //输入的采样格式
    enum AVSampleFormat in_sample_fmt = avc_cxt->sample_fmt;
    //输出的采样格式
    enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
    //输入的采样率
    int in_sample_rate = avc_cxt->sample_rate;
    //输出的采样率
    int out_sample_rate = 44100;
    //输入的声道布局
    uint64_t in_ch_layout = avc_cxt->channel_layout;
    //输出的声道布局
    uint64_t out_ch_layout = AV_CH_LAYOUT_MONO;
    //SwrContext 设置参数
    swr_alloc_set_opts(swr_cxt,out_ch_layout,out_sample_fmt,out_sample_rate,in_ch_layout,in_sample_fmt,in_sample_rate,0,NULL);
    //初始化SwrContext
    swr_init(swr_cxt);
    //重采样设置选项-----------------------------------------------------------end
    //获取输出的声道个数
    int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout);

    //存储pcm数据
    uint8_t *out_buf = (uint8_t*)av_malloc(2*44100);
    FILE *fb_out = fopen(outFile,"wb+");
    int got_frame, frame_count = 0;
    //6.一帧一帧读取压缩的音频数据AVPacket
    while(av_read_frame(avf_cxt,avp) >= 0){
        if(avp->stream_index == audio_index){
            //解码从avpacket到avframe
            ret = avcodec_decode_audio4(avc_cxt,avf,&got_frame,avp);
            // =0 表示解码完成
            if(ret < 0){
                av_log(NULL,AV_LOG_INFO,"解码完成  \n");
            }
            //表示正在解码
            if(got_frame != 0){
                // printf("正在解码第%d帧  \n",++frame_count);
                swr_convert(swr_cxt , &out_buf , 2 * 44100 , avf->data , avf->nb_samples);
                //获取sample的size
                int out_buf_size = av_samples_get_buffer_size(NULL,out_channel_nb,avf->nb_samples,out_sample_fmt,1);
                fwrite(out_buf,1,out_buf_size,fb_out);
            }
        }
        av_free_packet(avp);
    }

    _end:
    fclose(fb_out);
    av_frame_free(&avf);
    av_free(out_buf);
    swr_free(&swr_cxt);
    avcodec_close(avc_cxt);
    avformat_free_context(avf_cxt);
    return 0;
}
以下是使用FFmpeg新版本库实现音频解码为wav格式的代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <stdbool.h> #include <unistd.h> #include <libavutil/frame.h> #include <libavutil/mem.h> #include <libavutil/opt.h> #include <libavutil/samplefmt.h> #include <libavutil/channel_layout.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswresample/swresample.h> #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 int main(int argc, char **argv) { AVCodec *codec; AVCodecContext *c = NULL; int len; FILE *f, *outfile; uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; AVPacket avpkt; AVFrame *decoded_frame = NULL; int got_frame; int ret; int16_t *samples; int sample_size; SwrContext *swr_ctx = NULL; int dst_nb_samples; int dst_linesize; uint8_t **dst_data; int dst_bufsize; int i; if (argc <= 2) { fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]); exit(0); } av_register_all(); if (avformat_open_input(&c, argv[1], NULL, NULL) < 0) { fprintf(stderr, "Could not open input file '%s'\n", argv[1]); exit(1); } if (avformat_find_stream_info(c, NULL) < 0) { fprintf(stderr, "Could not find stream information\n"); exit(1); } av_dump_format(c, 0, argv[1], 0); codec = avcodec_find_decoder(c->streams[0]->codecpar->codec_id); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate codec context\n"); exit(1); } if (avcodec_parameters_to_context(c, c->streams[0]->codecpar) < 0) { fprintf(stderr, "Could not copy codec parameters to context\n"); exit(1); } if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(argv[2], "wb"); if (!f) { fprintf(stderr, "Could not open output file '%s'\n", argv[2]); exit(1); } decoded_frame = av_frame_alloc(); if (!decoded_frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } av_init_packet(&avpkt); while (av_read_frame(c, &avpkt) >= 0) { if (avpkt.stream_index == 0) { ret = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); if (ret < 0) { fprintf(stderr, "Error decoding audio frame\n"); exit(1); } if (got_frame) { sample_size = av_get_bytes_per_sample(c->sample_fmt); if (sample_size < 0) { fprintf(stderr, "Failed to calculate sample size\n"); exit(1); } samples = (int16_t *)decoded_frame->data[0]; len = decoded_frame->nb_samples * c->channels * sample_size; if (swr_ctx) { av_freep(&dst_data[0]); swr_free(&swr_ctx); } swr_ctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(c->channels), AV_SAMPLE_FMT_S16, c->sample_rate, av_get_default_channel_layout(c->channels), c->sample_fmt, c->sample_rate, 0, NULL); if (!swr_ctx || swr_init(swr_ctx) < 0) { fprintf(stderr, "Failed to initialize the resampling context\n"); exit(1); } dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + decoded_frame->nb_samples, c->sample_rate, c->sample_rate, AV_ROUND_UP); ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, c->channels, dst_nb_samples, AV_SAMPLE_FMT_S16, 0); if (ret < 0) { fprintf(stderr, "Could not allocate destination samples\n"); exit(1); } dst_bufsize = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples, AV_SAMPLE_FMT_S16, 0); if (dst_bufsize < 0) { fprintf(stderr, "Could not get sample buffer size\n"); exit(1); } ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame->data, decoded_frame->nb_samples); if (ret < 0) { fprintf(stderr, "Error while converting\n"); exit(1); } fwrite(dst_data[0], 1, dst_bufsize, f); } } av_packet_unref(&avpkt); } fclose(f); avcodec_free_context(&c); av_frame_free(&decoded_frame); av_free(samples); if (swr_ctx) { av_freep(&dst_data[0]); swr_free(&swr_ctx); } return 0; } ``` 这段代码使用了FFmpeg库来解码音频文件,并将其转换为WAV格式。它可以处理多种音频格式,包括MP3、AAC、FLAC等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值