使用FAAD库解码AAC实例


使用FAAD解码AAC音频为PCM数据流程可以参考下面的文章

http://blog.csdn.net/gavinr/article/details/6959198#reply

[cpp]  view plain  copy
 print ?
  1. /** 
  2.  * faaddec.c 
  3.  * use faad library to decode AAC, only can decode frame with ADTS head  
  4.  */  
  5. #include   
  6. #include   
  7. #include "faad.h"  
  8.   
  9. #define FRAME_MAX_LEN 1024*5   
  10. #define BUFFER_MAX_LEN 1024*1024  
  11.   
  12. void show_usage()  
  13. {  
  14.     printf("usage\nfaaddec src_file dst_file");  
  15. }  
  16.   
  17. /** 
  18.  * fetch one ADTS frame 
  19.  */  
  20. int get_one_ADTS_frame(unsigned char* buffer, size_t buf_size, unsigned char* data ,size_t* data_size)  
  21. {  
  22.     size_t size = 0;  
  23.   
  24.     if(!buffer || !data || !data_size )  
  25.     {  
  26.         return -1;  
  27.     }  
  28.   
  29.     while(1)  
  30.     {  
  31.         if(buf_size  < 7 )  
  32.         {  
  33.             return -1;  
  34.         }  
  35.   
  36.         if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) )  
  37.         {  
  38.             size |= ((buffer[3] & 0x03) <<11);     //high 2 bit  
  39.             size |= buffer[4]<<3;                //middle 8 bit  
  40.             size |= ((buffer[5] & 0xe0)>>5);        //low 3bit  
  41.             break;  
  42.         }  
  43.         --buf_size;  
  44.         ++buffer;  
  45.     }  
  46.   
  47.     if(buf_size < size)  
  48.     {  
  49.         return -1;  
  50.     }  
  51.   
  52.     memcpy(data, buffer, size);  
  53.     *data_size = size;  
  54.       
  55.     return 0;  
  56. }  
  57.   
  58. int main(int argc, char* argv[])  
  59. {  
  60.     static unsigned char frame[FRAME_MAX_LEN];  
  61.     static unsigned char buffer[BUFFER_MAX_LEN] = {0};  
  62.   
  63.     char src_file[128] = {0};  
  64.     char dst_file[128] = {0};  
  65.     FILE* ifile = NULL;  
  66.     FILE* ofile = NULL;  
  67.   
  68.     unsigned long samplerate;  
  69.     unsigned char channels;  
  70.     NeAACDecHandle decoder = 0;  
  71.   
  72.     size_t data_size = 0;  
  73.     size_t size = 0;  
  74.   
  75.     NeAACDecFrameInfo frame_info;  
  76.     unsigned char* input_data = buffer;  
  77.     unsigned char* pcm_data = NULL;  
  78.   
  79.     //analyse parameter  
  80.     if(argc < 3)  
  81.     {  
  82.         show_usage();  
  83.         return -1;  
  84.     }  
  85.     sscanf(argv[1], "%s", src_file);  
  86.     sscanf(argv[2], "%s", dst_file);  
  87.   
  88.   
  89.     ifile = fopen(src_file, "rb");  
  90.     ofile = fopen(dst_file, "wb");  
  91.     if(!ifile || !ofile)  
  92.     {  
  93.         printf("source or destination file");  
  94.         return -1;  
  95.     }  
  96.   
  97.      data_size = fread(buffer, 1, BUFFER_MAX_LEN, ifile);  
  98.   
  99.      //open decoder  
  100.     decoder = NeAACDecOpen();      
  101.     if(get_one_ADTS_frame(buffer, data_size, frame, &size) < 0)  
  102.     {  
  103.         return -1;  
  104.     }  
  105.   
  106.     //initialize decoder  
  107.     NeAACDecInit(decoder, frame, size, &samplerate, &channels);  
  108.     printf("samplerate %d, channels %d\n", samplerate, channels);  
  109.       
  110.     while(get_one_ADTS_frame(input_data, data_size, frame, &size) == 0)  
  111.     {  
  112.        // printf("frame size %d\n", size);  
  113.   
  114.         //decode ADTS frame  
  115.         pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, frame, size);   
  116.           
  117.         if(frame_info.error > 0)  
  118.         {  
  119.             printf("%s\n",NeAACDecGetErrorMessage(frame_info.error));              
  120.   
  121.         }  
  122.         else if(pcm_data && frame_info.samples > 0)  
  123.         {  
  124.             printf("frame info: bytesconsumed %d, channels %d, header_type %d\  
  125.                 object_type %d, samples %d, samplerate %d\n",   
  126.                 frame_info.bytesconsumed,   
  127.                 frame_info.channels, frame_info.header_type,   
  128.                 frame_info.object_type, frame_info.samples,   
  129.                 frame_info.samplerate);  
  130.   
  131.             fwrite(pcm_data, 1, frame_info.samples * frame_info.channels, ofile);      //2个通道  
  132.             fflush(ofile);  
  133.         }          
  134.         data_size -= size;  
  135.         input_data += size;  
  136.     }      
  137.   
  138.     NeAACDecClose(decoder);  
  139.   
  140.     fclose(ifile);  
  141.     fclose(ofile);  
  142.   
  143.     return 0;  
  144. }  


     之前用FAAC编码了一段PCM数据(源数据是16000采样率,单通道,16位取样),编码时设置的参数也是16000采样率,单通道,16位取样。。。然后用FAAD解码时,在NeAACDecInit的时候,是先在之前编码好的aac数据(ADTS头封装的)上往buffer中写入一帧的含ADTS头的数据,然后传入到NeAACDecInit()中初始化解码器,但不知道为什么,返回的采样率总是32000,通道数总是2,我已经查看过编码后的数据,其中与采样率、通道数相应的位,表示的就是16000采样率和1通道。。 


后来跟踪源码才发现 FAAD的NeAACDecInit() 源代码,问题出现在这里

[cpp]  view plain  copy
 print ?
  1. long NEAACDECAPI NeAACDecInit(NeAACDecHandle hpDecoder,  
  2.                               unsignedchar *buffer,  
  3.                               unsignedlong buffer_size,  
  4.                               unsignedlong *samplerate,  
  5.                               unsignedchar *channels)  
  6. {  
  7.   
  8. #if (defined(PS_DEC) || defined(DRM_PS))  
  9. /* check if we have a mono file */  
  10. if (*channels == 1)  
  11. {  
  12.      /* upMatrix to 2 channels for implicit signalling of PS */  
  13.      *channels = 2;  // 这里channels改变为2,why?  
  14. }  
  15. #endif  
  16.   
  17. hDecoder->channelConfiguration = *channels;  
  18.   
  19. #ifdef SBR_DEC  
  20. /* implicit signalling */  
  21. if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0))  
  22. {  
  23.     *samplerate *= 2;    // samplerate 变为32000  
  24.     hDecoder->forceUpSampling = 1;  
  25. }   
[cpp]  view plain  copy
 print ?
  1. else if (*samplerate > 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) {  
  2.      hDecoder->downSampledSBR = 1;  
  3. }  
  4. #endif  
  5. }  

  上面那些宏,在源代码中貌似已经定死了,不是通过条件编译生成的,

也就是 PS_DEC 和 SBR_DEC是define过的...也不是通过./configure 的时候生成的...


再仔细看上面代码的if语句 

if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0))


只要让 hDecoder->config.dontUpSampleImplicitSBR 不为0 不就OK吗?



我们看看在neaacdec.h 文件中该结构体NeAACDecConfiguration 的定义

使用FAAD库解码AAC实例_第1张图片


现在解决这个问题就简单了,初始化前把参数dontUpSampleImplicitSBR设置为1即可。

NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);

 conf->defObjectType = LC;

 conf->defSampleRate = 8000; //real samplerate/2

 conf->outputFormat = FAAD_FMT_16BIT ; //

 conf->dontUpSampleImplicitSBR = 1;

 NeAACDecSetConfiguration(decoder, conf);


最后吐槽一下。在从官网下载的faad 说明文档 NeAACDecConfiguration 这个结构体说明,

居然没有dontUpSampleImplicitSBR这个成员,太坑爹了

使用FAAD库解码AAC实例_第2张图片


你可能感兴趣的:(流媒体,媒体格式)