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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值