http://blog.csdn.net/ajaxhe/article/details/6761678
这是一个很简单的小程序,但也让我这个初学者折腾了好几天,走算是入门了,总结下学习的过程,希望能够初学者能有所帮助。
看源代码,首先得让让它跑起来。看了ffmpeg提供源码api-example.c,很好的入门程序,虽然对视频编解码十分顺利,但是源码提供的音频解码是有问题的,mp2文件不能正常的解码,这是很让人沮丧,特别是对一个初学者来说。
在对源程序进行单步调试的过程中,问题定位在了这个语句上:
avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet);
再看前面看看,有这样两行语句。
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
这两行代码的意思很明确,就是将待解码数据数据放入avpkt.data这个缓冲区中,通过avcodec_decode_audio3对其进行解码。这些看起来都很合理,但问题出在哪里呢?
且看video_decode_example函数中这段话:
问题已经很明朗了,通过在填充avpkt.data之前,需要进行一个预处理,即通过AAC帧中的同步字(帧头的12bit--0xFFF)来找出完整的一帧。
那就写预处理程序吧,转念一想,ffmpeg这么多行代码,不提供AAC帧解析的API也没有天理了,继续google,找到了下面一篇文章:
文章的标题是:利用libavcodec和libavformat对音频转码。附上了很详细的代码解析,我写的源程序大部分基于该文章。
下面就是test.c文件中的源码
#include
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "audio.h"
#include "neaacdec.h"
intmain(intargc,char**argv)
{
AVFormatContext *in_fctx;
AVCodecContext *in_ast_cctx;
AVCodec *in_ast_codec;
AVPacket packet;
audio_file *aufile;
char*outbuf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
intout_size;
intsamples;
//char *filename = "C:\\Users\\ajaxhe\\Desktop\\AudioCodec\\ffmpeg\\MyProject\\output_example2\\Debug\\higher1.aac";
char*filename;
char*wavfile ="debug_test.wav";
//char *wavfile;
intret = 0;
intast_idx = -1;
inti, first_time = 1;
if(argc == 3){
filename = argv[1];
wavfile = argv[2];
}
else{
printf("usage: output_example.exe infile.aac outfile.aac\n");
return-1;
}
av_register_all();
in_fctx = av_alloc_format_context();
ret = av_open_input_file(&in_fctx, filename, NULL, 0, NULL);
if( ret != 0 ){
printf("open input audio file[%s] fail", filename);
return-1;
}
ret = av_find_stream_info(in_fctx);
if( ret
printf("find stream in audio file[%s] fail", filename);
return-1;
}
//dump_format(in_fctx, 0, filename, 0);
//这里我们假设,如果一个文件包含多个音频流,
//只对第一个音频流做转码,而对于视频流则忽略
for(i=0; inb_streams; ++i){
if(in_fctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO){
ast_idx=i;
break;
}
}
if(ast_idx == -1){
printf("there is not any audio stream in [%s]", filename);
return0;
}
else{
printf("find audio stream in [%s]\n", filename);
}
in_ast_cctx = in_fctx->streams[ast_idx]->codec;
in_ast_codec = avcodec_find_decoder(in_ast_cctx->codec_id);
if(!in_ast_codec){
printf("find decoder for codec_id[%d] fail, file[%s]", in_ast_cctx->codec_id, filename);
return-1;
}
ret = avcodec_open(in_ast_cctx, in_ast_codec);
if(ret >= 0){
printf("open codec[name:%s] for stream[idx:%d] of file[%s]\n", in_ast_codec->name, ast_idx, filename);
}
av_init_packet(&packet);
while(av_read_frame(in_fctx, &packet) >= 0){
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
ret = avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet);
if(first_time){
aufile = open_audio_file(wavfile, in_ast_cctx->sample_rate, in_ast_cctx->channels, FAAD_FMT_16BIT, OUTPUT_WAV, 0);
first_time = 0;
}
samples = in_ast_cctx->frame_size * in_ast_cctx->channels;
write_audio_file(aufile, outbuf, samples, 0);
}
if(!first_time)
close_audio_file(aufile);
avcodec_close(in_ast_cctx);
av_free(in_ast_cctx);
return0;
}
由于仅仅是一个简单的小程序,只写了个main函数,还请见谅。
#include "audio.h"
#include "neaacdec.h"
这两个头文件是我从faad2源代码中弄过来,时间仓促,没有来得及自己整理下,需要的整个工程朋友就直接从下面这个链接下载吧