AAC音频码流解析

转自http://blog.csdn.net/leixiaohua1020/article/details/50535042

1、先了解AAC是什么

AAC(Advanced Audio Coding),中文称为“高级音频编码”,出现于1997年,基于 MPEG-2的音频编码技术。由Fraunhofer IIS、杜比实验室AT&T、Sony(索尼)等公司共同开发,目的是取代MP3格式。2000年,MPEG-4标准出现后,AAC 重新集成了其特性,加入了SBR技术和PS技术,为了区别于传统的 MPEG-2 AAC 又称为 MPEG-4 AAC。 
2、原理

AAC原始码流(又称为“裸流”)是由一个一个的ADTS frame组成的。他们的结构如下图所示。


其中每个ADTS frame之间通过syncword(同步字)进行分隔。同步字为0xFFF(二进制“111111111111”)。AAC码流解析的步骤就是 首先从码流中搜索0x0FFF,分离出ADTS frame ;然后 再分析ADTS frame的首部各个字段 。本文的程序即实现了上述的两个步骤。

ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格

3、程序

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color: rgb(85, 85, 85);">#include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. </span><span style="color:#3333ff;">获得ADTSframe的函数</span>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre code_snippet_id="1570980" snippet_file_name="blog_20160131_1_9511089" name="code" class="cpp" style="white-space: pre-wrap; word-wrap: break-word; font-size: 15px; line-height: 35px; background-color: rgb(255, 255, 255);"><span style="color:#3333ff;">第一个参数是指向我们申请的1024*1024大小的buffer的指针,第二个参数是buffer里面数据的大小,第三个参数是指向分配的大小为<span style="font-family: 'microsoft yahei';">1024*5的buffer的指针,第四个参数是</span></span>  
int getADTSframe(unsigned char* buffer, int buf_size, unsigned char* data ,int* data_size){int size = 0; 如果文件大小为0返回异常值-1 if(!buffer || !data || !data_size ){return -1;} 如果文件的大小少于7字节,返回异常值? while(1){if(buf_size < 7 ){return -1;} //Sync words,同步字为0xFFF(二进制“111111111111”) if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) ){size |= ((buffer[3] & 0x03) <<11); //high 2 bitsize |= buffer[4]<<3; //middle 8 bitsize |= ((buffer[5] & 0xe0)>>5); //low 3bitbreak;}--buf_size;++buffer;}if(buf_size < size){return 1;}memcpy(data, buffer, size);*data_size = size;return 0;}
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:24px;"><span style="font-family: 'microsoft yahei'; font-size: 15px;"><span style="color: rgb(51, 51, 255);">分析ADTS frame的首部各个字段</span></span></span>  

 
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color: rgb(85, 85, 85);">int simplest_aac_parser(char *url)  
  2. {  
  3.     int data_size = 0;  
  4.     int size = 0;  
  5.     int cnt=0;  
  6.     int offset=0;  
  7.   
  8.     //FILE *myout=fopen("output_log.txt","wb+");  
  9.     FILE *myout=stdout;  
  10.   
  11.     unsigned char *aacframe=(unsigned char *)malloc(1024*5);  
  12.     unsigned char *aacbuffer=(unsigned char *)malloc(1024*1024);  
  13.   
  14.     FILE *ifile = fopen(url, "rb");</span><span style="color:#3333ff;"//打开文件</span><span style="color:#555555;">  
  15.     if(!ifile){      </span><span style="color:#3333ff;">//如果文件指针为空,输出提示信息,并返回-1</span><span style="color:#555555;">  
  16.         printf("Open file error");  
  17.         return -1;  
  18.     }  
  19. </span><span style="color:#3333ff;">如果打开文件成功,首先输出一下内容</span><span style="color:#555555;">  
  20.     printf("-----+- ADTS Frame Table -+------+\n");  
  21.     printf(" NUM | Profile | Frequency| Size |\n");  
  22.     printf("-----+---------+----------+------+\n");  
  23. </span>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#3333ff;">循环操作,直到操作到文件的末尾</span>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#555555;"while(!feof(ifile)){</span>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#3333ff;"><span style="font-size: 15px; font-family: 'microsoft yahei';">//把大小为(</span><span style="font-size: 15px; font-family: Arial, Helvetica, sans-serif;">1024*1024-offset)的文件写入</span><span style="font-family:microsoft yahei;font-size:14px;">到</span><span style="font-size: 15px; font-family: Arial, Helvetica, sans-serif;">aacbuffer+offset里面,返回值是文件大小。</span></span>  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#3333ff;"><strong style="font-family: 'microsoft yahei';font-size:24px;"></strong></span><pre code_snippet_id="1570980" snippet_file_name="blog_20160131_1_9511089" name="code" class="cpp" style="white-space: pre-wrap; word-wrap: break-word; font-size: 15px; line-height: 35px; background-color: rgb(255, 255, 255);"><span style="color:#3333ff;"><strong>//aacbuffer指向大小为1024*1024字节大小的空间</strong></span>  
data_size = fread(aacbuffer+offset, 1, 1024*1024-offset, ifile);unsigned char* input_data = aacbuffer;while(1){ 第一个参数是指向我们申请的1024*1024大小的buffer的指针,第二个参数是buffer里面数据的大小,第三个参数是指向分配的大小为1024*5的buffer的指针,第四个参数是
 
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#555555;"int ret=</span><span style="color:#3333ff;">getADTSframe</span><span style="color:#555555;">(input_data, data_size, aacframe, &size);  
  2.             if(ret==-1){  
  3.                 break;  
  4.             }else if(ret==1){  
  5.                 memcpy(aacbuffer,input_data,data_size);  
  6.                 offset=data_size;  
  7.                 break;  
  8.             }  
  9.   
  10.             char profile_str[10]={0};  
  11.             char frequence_str[10]={0};  
  12.   
  13.             unsigned char profile=aacframe[2]&0xC0;  
  14.             profile=profile>>6;  
  15.             switch(profile){  
  16.             case 0: sprintf(profile_str,"Main");break;  
  17.             case 1: sprintf(profile_str,"LC");break;  
  18.             case 2: sprintf(profile_str,"SSR");break;  
  19.             default:sprintf(profile_str,"unknown");break;  
  20.             }  
  21.   
  22.             unsigned char sampling_frequency_index=aacframe[2]&0x3C;  
  23.             sampling_frequency_index=sampling_frequency_index>>2;  
  24.             switch(sampling_frequency_index){  
  25.             case 0: sprintf(frequence_str,"96000Hz");break;  
  26.             case 1: sprintf(frequence_str,"88200Hz");break;  
  27.             case 2: sprintf(frequence_str,"64000Hz");break;  
  28.             case 3: sprintf(frequence_str,"48000Hz");break;  
  29.             case 4: sprintf(frequence_str,"44100Hz");break;  
  30.             case 5: sprintf(frequence_str,"32000Hz");break;  
  31.             case 6: sprintf(frequence_str,"24000Hz");break;  
  32.             case 7: sprintf(frequence_str,"22050Hz");break;  
  33.             case 8: sprintf(frequence_str,"16000Hz");break;  
  34.             case 9: sprintf(frequence_str,"12000Hz");break;  
  35.             case 10: sprintf(frequence_str,"11025Hz");break;  
  36.             case 11: sprintf(frequence_str,"8000Hz");break;  
  37.             default:sprintf(frequence_str,"unknown");break;  
  38.             }  
  39.   
  40.   
  41.             fprintf(myout,"%5d| %8s|  %8s| %5d|\n",cnt,profile_str ,frequence_str,size);  
  42.             data_size -= size;  
  43.             input_data += size;  
  44.             cnt++;  
  45.         }     
  46.   
  47.     }  
  48.     fclose(ifile);  
  49.     free(aacbuffer);  
  50.     free(aacframe);  
  51.   
  52.     return 0;  
  53. }</span>  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值