加载中…
个人资料
南冠彤
南冠彤
  • 博客等级:
  • 博客积分:0
  • 博客访问:441,646
  • 关注人气:59
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

(转) 通过ffmpeg将aac格式转换成wav格式

(2013-02-06 10:25:34)
分类: 音视频

http://blog.csdn.net/ajaxhe/article/details/6761678

这是一个很简单的小程序,但也让我这个初学者折腾了好几天,走算是入门了,总结下学习的过程,希望能够初学者能有所帮助。

看源代码,首先得让让它跑起来。看了ffmpeg提供源码api-example.c,很好的入门程序,虽然对视频编解码十分顺利,但是源码提供的音频解码是有问题的,mp2文件不能正常的解码,这是很让人沮丧,特别是对一个初学者来说。

在对源程序进行单步调试的过程中,问题定位在了这个语句上:

  1. avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet);  
再看前面看看,有这样两行语句。
  1.   
  2.     avpkt.data inbuf;  
  3.     avpkt.size fread(inbuf, 1, AUDIO_INBUF_SIZE, f);  
这两行代码的意思很明确,就是将待解码数据数据放入avpkt.data这个缓冲区中,通过avcodec_decode_audio3对其进行解码。这些看起来都很合理,但问题出在哪里呢?

且看video_decode_example函数中这段话:

  1.   
  2.   
  3.           
  4.   
  5.           
这 句话看起来与我们的音频解码没有任何关系,但”codecs are stream based“和“frame based”,却给我们很好的提示,很显然,ffmpeg提供的AAC decoder是基于帧解码的,我们在给avpkt.data缓冲区的填充的数据应该是一个完整的音频帧,不多也不少,而不是简单的一次从文件中 fread AUDIO_INBUF_SIZE大小的数据。

问题已经很明朗了,通过在填充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文件中的源码

  1. #include   
  2.   
  3. #include "libavformat/avformat.h"  
  4. #include "libavcodec/avcodec.h"  
  5. #include "audio.h"  
  6. #include "neaacdec.h"  
  7.   
  8. int main(int argc, char **argv)  
  9.  
  10.     AVFormatContext *in_fctx;  
  11.     AVCodecContext *in_ast_cctx;  
  12.     AVCodec *in_ast_codec;  
  13.     AVPacket packet;  
  14.     audio_file *aufile;  
  15.     char *outbuf (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);  
  16.     int out_size;  
  17.     int samples;  
  18.   
  19.     //char *filename "C:\\Users\\ajaxhe\\Desktop\\AudioCodec\\ffmpeg\\MyProject\\output_example2\\Debug\\higher1.aac";  
  20.     char *filename;  
  21.     char *wavfile "debug_test.wav" 
  22.     //char *wavfile;  
  23.     int ret 0;  
  24.     int ast_idx -1;  
  25.     int i, first_time 1;  
  26.   
  27.     if (argc == 3){  
  28.         filename argv[1];  
  29.         wavfile argv[2];  
  30.      
  31.     else 
  32.         printf("usage: output_example.exe infile.aac outfile.aac\n");  
  33.         return -1;  
  34.      
  35.   
  36.     av_register_all();  
  37.     in_fctx av_alloc_format_context();  
  38.   
  39.     ret av_open_input_file(&in_fctx, filename, NULL, 0, NULL);  
  40.     if ret != ){  
  41.         printf("open input audio file[%s] fail"filename);  
  42.         return -1;  
  43.      
  44.   
  45.     ret av_find_stream_info(in_fctx);  
  46.     if ret ){  
  47.         printf("find stream in audio file[%s] fail"filename);  
  48.         return -1;  
  49.      
  50.   
  51.     //dump_format(in_fctx, 0, filename, 0);  
  52.     //这里我们假设,如果一个文件包含多个音频流,  
  53.     //只对第一个音频流做转码,而对于视频流则忽略  
  54.     for (i=0; i<(int)in_fctx->nb_streams; ++i){  
  55.         if (in_fctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO){  
  56.             ast_idx=i;  
  57.             break 
  58.          
  59.      
  60.     if (ast_idx == -1){  
  61.         printf("there is not any audio stream in [%s]"filename);  
  62.         return 0;  
  63.      
  64.     else 
  65.         printf("find audio stream in [%s]\n"filename);  
  66.      
  67.   
  68.     in_ast_cctx in_fctx->streams[ast_idx]->codec;  
  69.     in_ast_codec avcodec_find_decoder(in_ast_cctx->codec_id);  
  70.     if (!in_ast_codec){  
  71.         printf("find decoder for codec_id[%d] fail, file[%s]"in_ast_cctx->codec_id, filename);  
  72.         return -1;  
  73.      
  74.   
  75.     ret avcodec_open(in_ast_cctx, in_ast_codec);  
  76.     if (ret >= 0){  
  77.         printf("open codec[name:%s] for stream[idx:%d] of file[%s]\n"in_ast_codec->name, ast_idx, filename);  
  78.      
  79.   
  80.     av_init_packet(&packet);  
  81.     while (av_read_frame(in_fctx, &packet) >= 0){  
  82.         out_size AVCODEC_MAX_AUDIO_FRAME_SIZE;  
  83.         ret avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet);  
  84.         if (first_time){  
  85.             aufile open_audio_file(wavfile, in_ast_cctx->sample_rate, in_ast_cctx->channels, FAAD_FMT_16BIT, OUTPUT_WAV, 0);  
  86.             first_time 0;  
  87.          
  88.         samples in_ast_cctx->frame_size in_ast_cctx->channels;  
  89.         write_audio_file(aufile, outbuf, samples, 0);  
  90.      
  91.   
  92.     if (!first_time)  
  93.         close_audio_file(aufile);  
  94.       
  95.     avcodec_close(in_ast_cctx);  
  96.     av_free(in_ast_cctx);  
  97.   
  98.     return 0;  
  99.  
由于仅仅是一个简单的小程序,只写了个main函数,还请见谅。

#include "audio.h"
#include "neaacdec.h"

这两个头文件是我从faad2源代码中弄过来,时间仓促,没有来得及自己整理下,需要的整个工程朋友就直接从下面这个链接下载吧

http://download.csdn.net/detail/ajaxhe/3585763

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有