FFmpeg-out1.aac文件解码成out1.pcm文件(代码实现)

该代码示例展示了如何使用ffmpeg库解码AAC音频文件,并将其输出为PCM格式。程序首先根据文件后缀确定音频编码类型,然后找到相应的解码器,进行解码上下文初始化,读取文件数据,解析并解码音频帧,最后将解码后的数据写入新的PCM文件。
摘要由CSDN通过智能技术生成
#include <iostream>
using namespace std;
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include <stdio.h>
}
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

static void decode(AVCodecContext *dec_ctx,AVPacket *pkt,AVFrame *frame,FILE *outfile)
{
    int ret=avcodec_send_packet(dec_ctx,pkt);   //发送给解码器
            while(ret>=0)
            {
                ret=avcodec_receive_frame(dec_ctx,frame);   //接收解码后的帧
                if(ret==AVERROR(EAGAIN)||ret==AVERROR_EOF)
                    return;
                int data_size=av_get_bytes_per_sample(dec_ctx->sample_fmt);  //获取单个sample占用的字节
                for(int i=0;i<frame->nb_samples;i++)
                {
                    for(int ch=0;ch<dec_ctx->channels;ch++)   //交错的方式写入,大部分float的格式输出
                        fwrite(frame->data[ch]+data_size*i,1,data_size,outfile);
                }
            } 
}
int main()
{
    const char *outfilename="out1.pcm";
    const char *filename="out1.aac";
    const AVCodec *codec;
    AVCodecContext *codec_ctx=NULL;
    AVCodecParserContext *parser=NULL;
    int len=0;
    int ret=0;
    FILE *infile=NULL;
    FILE *outfile=NULL;
    uint8_t inbuf[AUDIO_INBUF_SIZE+AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t *data=NULL;
    size_t data_size=0;
    AVPacket *pkt=NULL;
    AVFrame *decoded_frame=NULL;

    pkt=av_packet_alloc();
    enum AVCodecID audio_codec_id=AV_CODEC_ID_AAC;
    if(strstr(filename,"aac")!=NULL){               //  根据文件后缀名给audio_codec_id赋值
        audio_codec_id=AV_CODEC_ID_AAC; //char *strstr( const char *str1, const char *str2 ); 
    }                                                                                //  strstr函数是在字符串str1中查找是否含有字符串str2,如果存在,返回str2在str1中第一次出现的地址;否则返回NULL。
    else if(strstr(filename,"mp3")!=NULL){
        audio_codec_id=AV_CODEC_ID_MP3;
    }
    else{
        printf("default codec id:%d\n",audio_codec_id);
    }
    codec=avcodec_find_decoder(audio_codec_id);      //查找解码器
    parser=av_parser_init(codec->id);  //获取裸流的解析器AVCodecParserContext(数据)+AVCodecParser(方法)
    codec_ctx=avcodec_alloc_context3(codec);    //分配codec上下文
    avcodec_open2(codec_ctx,codec,NULL);    //将解码器和解码器上下文进行关联
    infile=fopen(filename,"rb");    //打开输入文件
    outfile=fopen(outfilename,"wb");    //打开输出文件
    data=inbuf;
    data_size=fread(inbuf,1,AUDIO_INBUF_SIZE,infile);   读取文件进行解码
    while(data_size>0)
    {
        decoded_frame=av_frame_alloc();
        ret=av_parser_parse2(parser,codec_ctx,&pkt->data,&pkt->size,
                                                       data,data_size,AV_NOPTS_VALUE,AV_NOPTS_VALUE,0);
        data+=ret;  //跳过已经解析的数据
        data_size-=ret;  //对应的缓存大小也做相应减小

        if(pkt->size)
        {
            decode(codec_ctx,pkt,decoded_frame,outfile);
       }
        if(data_size<AUDIO_REFILL_THRESH)   //如果数据少了则再次读取
        {
            memmove(inbuf,data,data_size);    //把之前剩的数据拷贝到buffer的起始位置
            data=inbuf;
            //读取数据长度:AUDIO_INBUF_SIZE-data_size
           len=fread(data+data_size,1,AUDIO_INBUF_SIZE-data_size,infile);
            if(len>0)
                data_size+=len;
        }
    }

    /*冲刷解码器*/
    pkt->data=NULL;
    pkt->size=0;
    decode(codec_ctx,pkt,decoded_frame,outfile);

    fclose(outfile);
    fclose(infile);

    avcodec_free_context(&codec_ctx);
    av_parser_close(parser);
    av_frame_free(&decoded_frame);
    av_packet_free(&pkt);

    printf("main finish,please enter Enter and exit\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值