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

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. /* decode until eof */  
  2.     avpkt.data = inbuf;  
  3.     avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);  
这两行代码的意思很明确,就是将待解码数据数据放入avpkt.data这个缓冲区中,通过avcodec_decode_audio3对其进行解码。这些看起来都很合理,但问题出在哪里呢?

且看video_decode_example函数中这段话:

  1. /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)  
  2.            and this is the only method to use them because you cannot  
  3.            know the compressed data size before analysing it.  
  4.   
  5.            BUT some other codecs (msmpeg4, mpeg4) are inherently frame  
  6.            based, so you must call them with all the data for one  
  7.            frame exactly. You must also initialize 'width' and  
  8.            'height' before initializing them. */  
  9.   
  10.         /* NOTE2: some codecs allow the raw parameters (frame size,  
  11.            sample rate) to be changed at any frame. We handle this, so  
  12.            you should also take care of it */  
  13.   
  14.         /* here, we use a stream based decoder (mpeg1video), so we  
  15.            feed decoder and see if it could decode a frame */  
这句话看起来与我们的音频解码没有任何关系,但”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 <stdio.h>  
  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 != 0 ){  
  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 < 0 ){  
  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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用R19CNDK编译完整的FFMPE4.2.2库,用于集到Android平台使用,完音视频开发。 压缩包里包含了完整源码,配置文件、编译功的动态库。如何需要重新编译,可以自己看配置文件。 配置文件包含了arm-v7、arm64-v8两种,根据自己平台可以选择编译。 ffmpeg里编译时包含了X264解码库。 支持的解码库如下; "当前APP的工作路径:/home/wbyq/qt_code/build-ffmpeg_code-Desktop_Qt_5_12_6_GCC_64bit-Release\n" "FFMPEG的版本号:4.2.2\n" "[Encode][Video]a64multi ID=142" "[Encode][Video]a64multi5 ID=143" "[Encode][Video]alias_pix ID=175" "[Encode][Video]amv ID=107" "[Encode][Video]apng ID=32782" "[Encode][Video]asv1 ID=31" "[Encode][Video]asv2 ID=32" "[Encode][Video]avrp ID=32769" "[Encode][Video]avui ID=32771" "[Encode][Video]ayuv ID=32772" "[Encode][Video]bmp ID=78" "[Encode][Video]cinepak ID=43" "[Encode][Video]cljr ID=36" "[Encode][Audeo]comfortnoise ID=86077" "[Encode][Video]dnxhd ID=99" "[Encode][Video]dpx ID=128" "[Encode][Video]dvvideo ID=24" "[Encode][Video]ffv1 ID=33" "[Encode][Video]ffvhuff ID=67" "[Encode][Video]fits ID=32803" "[Encode][Video]flashsv ID=86" "[Encode][Video]flashsv2 ID=131" "[Encode][Video]flv ID=21" "[Encode][Video]gif ID=97" "[Encode][Video]h261 ID=3" "[Encode][Video]h263 ID=4" "[Encode][Video]h263p ID=19" "[Encode][Video]huffyuv ID=25" "[Encode][Video]jpeg2000 ID=88" "[Encode][Video]jpegls ID=11" "[Encode][Video]ljpeg ID=9" "[Encode][Video]magicyuv ID=32787" "[Encode][Video]mjpeg ID=7" "[Encode][Video]mpeg1video ID=1" "[Encode][Video]mpeg2video ID=2" "[Encode][Video]mpeg4 ID=12" "[Encode][Video]msmpeg4v2 ID=15" "[Encode][Video]msmpeg4 ID=16" "[Encode][Video]msvideo1 ID=46" "[Encode][Video]pam ID=66" "[Encode][Video]pbm ID=63" "[Encode][Video]pcx ID=109" "[Encode][Video]pgm ID=64" "[Encode][Video]pgmyuv ID=65" "[Encode][Video]png ID=61" "[Encode][Video]ppm ID=62" "[Encode][Video]prores ID=147" "[Encode][Video]prores_aw ID=147" "[Encode][Video]prores_ks ID=147" "[Encode][Video]qtrle ID=55" "[Encode][Video]r10k ID=144" "[Encode][Video]r210 ID=133" "[Encode][Video]rawvideo ID=13" "[Encode][Video]roqvideo ID=38" "[Encode][Video]rv10 ID=5" "[Encode][Video]rv20 ID=6" "[Encode][Audeo]s302m ID=65562" "[Encode][Video]sgi ID=101" "[Encode][Video]snow ID=32780" "[Encode][Video]sunrast ID=110" "[Encode][Video]svq1 ID=22" "[Encode][Video]targa ID=93" "[Encode][Video]tiff ID=96" "[Encode][Video]utvideo ID=152" "[Encode][Video]v210 ID=127" "[Encode][Video]v308 ID=32774" "[Encode][Video]v408 ID=32775" "[Encode][Video]v410 ID=156" "[Encode][Video]vc2 ID=116" "[Encode][Video]wrapped_avframe ID=135169" "[Encode][Video]wmv1 ID=17" "[Encode][Video]wmv2 ID=18" "[Encode][Video]xbm ID=159" "[Encode][Video]xface ID=32779" "[Encode][Video]xwd ID=157" "[Encode][Video]y41p ID=32768" "[Encode][Video]yuv4 ID=32776" "[Encode][Video]zlib ID=54" "[Encode][Video]zmbv ID=81" "[Encode][Audeo]aac ID=86018" "[Encode][Audeo]ac3 ID=86019" "[Encode][Audeo]ac3_fixed ID=86019" "[Encode][Audeo]alac ID=86032" "[Encode][Audeo]aptx ID=88081" "[Encode][Audeo]aptx_hd ID=88082" "[Encode][Audeo]dca ID=86020" "[Encode][Audeo]eac3 ID=86056" "[Encode][Audeo]flac ID=86028" "[Encode][Audeo]g723_1 ID=86068" "[Encode][Audeo]mlp ID=86045" "[Encode][Audeo]mp2 ID=86016" "[Encode][Audeo]mp2fixed ID=86016" "[Encode][Audeo]nellymoser ID=86049" "[Encode][Audeo]opus ID=86076" "[Encode][Audeo]real_144 ID=77824" "[Encode][Audeo]sbc ID=88083" "[Encode][Audeo]sonic ID=88065" "[Encode][Audeo]sonicls ID=88066" "[Encode][Audeo]truehd ID=86060" "[Encode][Audeo]tta ID=86038" "[Encode][Audeo]vorbis ID=86021" "[Encode][Audeo]wavpack ID=86041" "[Encode][Audeo]wmav1 ID=86023" "[Encode][Audeo]wmav2 ID=86024" "[Encode][Audeo]pcm_alaw ID=65543" "[Encode][Audeo]pcm_dvd ID=65555" "[Encode][Audeo]pcm_f32be ID=65556" "[Encode][Audeo]pcm_f32le ID=65557" "[Encode][Audeo]pcm_f64be ID=65558" "[Encode][Audeo]pcm_f64le ID=65559" "[Encode][Audeo]pcm_mulaw ID=65542" "[Encode][Audeo]pcm_s8 ID=65540" "[Encode][Audeo]pcm_s8_planar ID=65563" "[Encode][Audeo]pcm_s16be ID=65537" "[Encode][Audeo]pcm_s16be_planar ID=65566" "[Encode][Audeo]pcm_s16le ID=65536" "[Encode][Audeo]pcm_s16le_planar ID=65554" "[Encode][Audeo]pcm_s24be ID=65549" "[Encode][Audeo]pcm_s24daud ID=65552" "[Encode][Audeo]pcm_s24le ID=65548" "[Encode][Audeo]pcm_s24le_planar ID=65564" "[Encode][Audeo]pcm_s32be ID=65545" "[Encode][Audeo]pcm_s32le ID=65544" "[Encode][Audeo]pcm_s32le_planar ID=65565" "[Encode][Audeo]pcm_s64be ID=67585" "[Encode][Audeo]pcm_s64le ID=67584" "[Encode][Audeo]pcm_u8 ID=65541" "[Encode][Audeo]pcm_u16be ID=65539" "[Encode][Audeo]pcm_u16le ID=65538" "[Encode][Audeo]pcm_u24be ID=65551" "[Encode][Audeo]pcm_u24le ID=65550" "[Encode][Audeo]pcm_u32be ID=65547" "[Encode][Audeo]pcm_u32le ID=65546" "[Encode][Audeo]pcm_vidc ID=67588" "[Encode][Audeo]roq_dpcm ID=81920" "[Encode][Audeo]adpcm_adx ID=69641" "[Encode][Audeo]g722 ID=69660" "[Encode][Audeo]g726 ID=69643" "[Encode][Audeo]g726le ID=71684" "[Encode][Audeo]adpcm_ima_qt ID=69632" "[Encode][Audeo]adpcm_ima_wav ID=69633" "[Encode][Audeo]adpcm_ms ID=69638" "[Encode][Audeo]adpcm_swf ID=69645" "[Encode][Audeo]adpcm_yamaha ID=69646" "[Encode][Other]ssa ID=96269" "[Encode][Other]ass ID=96269" "[Encode][Other]dvbs

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值