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);
- /* decode until eof */
- avpkt.data = inbuf;
- avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
且看video_decode_example函数中这段话:
- /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
- and this is the only method to use them because you cannot
- know the compressed data size before analysing it.
- BUT some other codecs (msmpeg4, mpeg4) are inherently frame
- based, so you must call them with all the data for one
- frame exactly. You must also initialize 'width' and
- 'height' before initializing them. */
- /* NOTE2: some codecs allow the raw parameters (frame size,
- sample rate) to be changed at any frame. We handle this, so
- you should also take care of it */
- /* here, we use a stream based decoder (mpeg1video), so we
- feed decoder and see if it could decode a frame */
问题已经很明朗了,通过在填充avpkt.data之前,需要进行一个预处理,即通过AAC帧中的同步字(帧头的12bit--0xFFF)来找出完整的一帧。
那就写预处理程序吧,转念一想,ffmpeg这么多行代码,不提供AAC帧解析的API也没有天理了,继续google,找到了下面一篇文章:
http://hi.baidu.com/wg_wang/blog/item/8e7e321796063a0c4b90a770.html
http://hi.baidu.com/wg_wang/blog/item/f78216f35465655d342acc16.html
http://hi.baidu.com/wg_wang/blog/item/4d55bd23eb3e2d49ac34de17.html
文章的标题是:利用libavcodec和libavformat对音频转码。附上了很详细的代码解析,我写的源程序大部分基于该文章。
下面就是test.c文件中的源码
- #include <stdio.h>
- #include "libavformat/avformat.h"
- #include "libavcodec/avcodec.h"
- #include "audio.h"
- #include "neaacdec.h"
- int main(int argc, 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);
- int out_size;
- int samples;
- //char *filename = "C:\\Users\\ajaxhe\\Desktop\\AudioCodec\\ffmpeg\\MyProject\\output_example2\\Debug\\higher1.aac";
- char *filename;
- char *wavfile = "debug_test.wav";
- //char *wavfile;
- int ret = 0;
- int ast_idx = -1;
- int i, 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 < 0 ){
- printf("find stream in audio file[%s] fail", filename);
- return -1;
- }
- //dump_format(in_fctx, 0, filename, 0);
- //这里我们假设,如果一个文件包含多个音频流,
- //只对第一个音频流做转码,而对于视频流则忽略
- for (i=0; i<(int)in_fctx->nb_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);
- return 0;
- }
- 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);
- return 0;
- }
#include "audio.h"
#include "neaacdec.h"
这两个头文件是我从faad2源代码中弄过来,时间仓促,没有来得及自己整理下,需要的整个工程朋友就直接从下面这个链接下载吧