AAC--ffmpeg解码AAC

余生长醉 提交于 2020-03-01 16:26:52

本篇FFMEPG实现对AAC解码,解码结果保存wav格式。对AAC编码文件来说,编码根据音频参数编码,解码根据音频参数重新构建声波,FFMPEG构建的音频存储方式不一定支持播放, 所以需要重采样样本,如AAC解码的样本格式AV_SAMPLE_FMT_FLTP。AAC的解码器如果是外部解码器"aac",解码格式需要AV_SAMPLE_FMT_FLTP,如果是“libvo_aacenc”这个解码器需要格式AV_SAMPLE_FMT_S16。

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 error
av_dump_format(pFormatCtx, 0, INPUT_FILE_NAME, false);
 
// Find the first audio stream👉👉int audioStream


// Get a pointer to the codec context for the audio stream
AVCodecContext	*pCodecCtx=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the audio stream
AVCodec	*pCodec=avcodec_find_decoder(pCodecCtx->codec_id);


// Open codec
avcodec_open2(pCodecCtx, pCodec,NULL);

//对AAC编码文件来说,编码根据音频参数编码,解码根据音频参数重新构建声波,FFMPEG构建的
//音频存储方式不一定支持播放,所以需要重采样样本 如AAC解码的样本格式是AV_SAMPLE_FMT_FLTP

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;
pRawframe->format		= eInputSampleFormat;
pRawframe->channels     = iInputChans;


avcodec_fill_audio_frame(pRawframe, iInputChans, eInputSampleFormat, (const uint8_t*)pRawBuff, iRawBuffSize, 0);



// 存储转换后数据 
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);


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;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!