本文共 3520 字,大约阅读时间需要 11 分钟。
本篇FFMEPG实现对AAC解码,解码结果保存wav格式。对AAC编码文件来说,编码根据音频参数编码,解码根据音频参数重新构建声波,
FFMPEG构建的音频存储方式不一定支持播放, 所以需要重采样样本,例如新版ffmpeg解码AAC解码后得到AV_SAMPLE_FMT_FLTP,该格式SDKL播放不支持该格式
ffmpeg所支持的音频格式中:有的仅内部使用,有的可以外部作为音频文件格式
AVFormatContext * pFormatCtx = avformat_alloc_context();avformat_open_input(&pFormatCtx,INPUT_FILE_NAME,NULL,NULL)‘avformat_find_stream_info(pFormatCtx,NULL);// Dump valid information onto standard errorav_dump_format(pFormatCtx, 0, INPUT_FILE_NAME, false); // Find the first audio stream👉👉int audioStreamp_codec_par = p_fmt_ctx->streams[a_idx]->codecpar;AVCodec *pCodec=avcodec_find_decoder(pCodecCtx->codec_id);AVCodecContext *p_codec_ctx = avcodec_alloc_context3(p_codec);avcodec_parameters_to_context(p_codec_ctx, p_codec_par);// Open codecavcodec_open2(pCodecCtx, pCodec,NULL);uint64_t iInputLayout = av_get_default_channel_layout(pCodecCtx->channels);//使用默认声道分布int iInputChans = pCodecCtx->channels;AVSampleFormat eInputSampleFormat = pCodecCtx->sample_fmt;int iInputSampleRate = pCodecCtx->sample_rate;uint64_t iOutputLayout = av_get_default_channel_layout(pCodecCtx->channels);int iOutputChans = pCodecCtx->channels;AVSampleFormat eOutputSampleFormat = AV_SAMPLE_FMT_S16;int iOutputSampleRate = pCodecCtx->sample_rate;SwrContext *pSwrCtx = swr_alloc_set_opts(NULL,iOutputLayout, eOutputSampleFormat, iOutputSampleRate, iInputLayout,eInputSampleFormat , iInputSampleRate,0, NULL);swr_init(pSwrCtx);//AVPacket读取原始解码前的数据AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));av_init_packet(packet);//1帧数据样本数int iFrameSamples = pCodecCtx->frame_size;// 存储原始数据 int iRawLineSize = 0;int iRawBuffSize = av_samples_get_buffer_size(&iRawLineSize, iInputChans, iFrameSamples, eInputSampleFormat, 0);uint8_t *pRawBuff = (uint8_t *)av_malloc(iRawBuffSize);//原始数据保存在AVFrame结构体中AVFrame* pRawframe = av_frame_alloc(); pRawframe->nb_samples = iFrameSamples; //number of audio samples (per channel) described by this frame pRawframe->format = eInputSampleFormat; pRawframe->channels = iInputChans;avcodec_fill_audio_frame(pRawframe, iInputChans, eInputSampleFormat, (const uint8_t*)pRawBuff, iRawBuffSize, 0);/* swr的接收帧pConvertframe*/// 存储转换后数据 int iConvertLineSize = 0;int iConvertBuffSize = av_samples_get_buffer_size(&iConvertLineSize, iOutputChans, iFrameSamples, eOutputSampleFormat, 0);uint8_t *pConvertBuff = (uint8_t *)av_malloc(iConvertBuffSize);//转换后数据保存在AVFrame结构体中AVFrame* pConvertframe = av_frame_alloc(); pConvertframe->nb_samples = iFrameSamples; pConvertframe->format = eOutputSampleFormat; pConvertframe->channels = iOutputChans;avcodec_fill_audio_frame(pConvertframe, iOutputChans, eOutputSampleFormat, (const uint8_t*)pConvertBuff, iConvertBuffSize, 0);int iGetPicture;int iDecodeRet;int iFrameNo = 0;write_wav_header(16,iOutputChans,eOutputSampleFormat,iOutputSampleRate,0,pOutFile);//自定义,按照wav格式while(av_read_frame(pFormatCtx, packet)>=0){ if(packet->stream_index==audioStream) { avcodec_decode_audio4( pCodecCtx, pRawframe,&iGetPicture, packet);//要解码成功&&拿到pkt if ( iGetPicture > 0 ) { printf("FrameNo:%5d\n",iFrameNo); swr_convert(pSwrCtx, (uint8_t**)pConvertframe->data, iFrameSamples ,(const uint8_t**)pRawframe->data, iFrameSamples ); fwrite(pConvertframe->data[0],pConvertframe->linesize[0],1,pOutFile); iFrameNo++; } } av_free_packet(packet);}av_free(pRawBuff);av_free(pConvertBuff);swr_free(&pSwrCtx);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);fclose(pOutFile);printf("Aac encode Success!!\n");getchar();return 0;
转载地址:http://fbhrn.baihongyu.com/