转自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、程序
- <span style="color: rgb(85, 85, 85);">#include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- </span><span style="color:#3333ff;">获得ADTSframe的函数</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;">第一个参数是指向我们申请的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;}
- <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>
- <span style="color: rgb(85, 85, 85);">int simplest_aac_parser(char *url)
- {
- int data_size = 0;
- int size = 0;
- int cnt=0;
- int offset=0;
-
-
- FILE *myout=stdout;
-
- unsigned char *aacframe=(unsigned char *)malloc(1024*5);
- unsigned char *aacbuffer=(unsigned char *)malloc(1024*1024);
-
- FILE *ifile = fopen(url, "rb");</span><span style="color:#3333ff;">
- if(!ifile){ </span><span style="color:#3333ff;">
- printf("Open file error");
- return -1;
- }
- </span><span style="color:#3333ff;">如果打开文件成功,首先输出一下内容</span><span style="color:#555555;">
- printf("-----+- ADTS Frame Table -+------+\n");
- printf(" NUM | Profile | Frequency| Size |\n");
- printf("-----+---------+----------+------+\n");
- </span>
- <span style="color:#3333ff;">循环操作,直到操作到文件的末尾</span>
- <span style="color:#555555;"> while(!feof(ifile)){</span>
- <span style="color:#3333ff;"><span style="font-size: 15px; font-family: 'microsoft yahei';">
- <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>
data_size = fread(aacbuffer+offset, 1, 1024*1024-offset, ifile);unsigned char* input_data = aacbuffer;while(1){
第一个参数是指向我们申请的1024*1024大小的buffer的指针,第二个参数是buffer里面数据的大小,第三个参数是指向分配的大小为1024*5的buffer的指针,第四个参数是
- <span style="color:#555555;"> int ret=</span><span style="color:#3333ff;">getADTSframe</span><span style="color:#555555;">(input_data, data_size, aacframe, &size);
- if(ret==-1){
- break;
- }else if(ret==1){
- memcpy(aacbuffer,input_data,data_size);
- offset=data_size;
- break;
- }
-
- char profile_str[10]={0};
- char frequence_str[10]={0};
-
- unsigned char profile=aacframe[2]&0xC0;
- profile=profile>>6;
- switch(profile){
- case 0: sprintf(profile_str,"Main");break;
- case 1: sprintf(profile_str,"LC");break;
- case 2: sprintf(profile_str,"SSR");break;
- default:sprintf(profile_str,"unknown");break;
- }
-
- unsigned char sampling_frequency_index=aacframe[2]&0x3C;
- sampling_frequency_index=sampling_frequency_index>>2;
- switch(sampling_frequency_index){
- case 0: sprintf(frequence_str,"96000Hz");break;
- case 1: sprintf(frequence_str,"88200Hz");break;
- case 2: sprintf(frequence_str,"64000Hz");break;
- case 3: sprintf(frequence_str,"48000Hz");break;
- case 4: sprintf(frequence_str,"44100Hz");break;
- case 5: sprintf(frequence_str,"32000Hz");break;
- case 6: sprintf(frequence_str,"24000Hz");break;
- case 7: sprintf(frequence_str,"22050Hz");break;
- case 8: sprintf(frequence_str,"16000Hz");break;
- case 9: sprintf(frequence_str,"12000Hz");break;
- case 10: sprintf(frequence_str,"11025Hz");break;
- case 11: sprintf(frequence_str,"8000Hz");break;
- default:sprintf(frequence_str,"unknown");break;
- }
-
-
- fprintf(myout,"%5d| %8s| %8s| %5d|\n",cnt,profile_str ,frequence_str,size);
- data_size -= size;
- input_data += size;
- cnt++;
- }
-
- }
- fclose(ifile);
- free(aacbuffer);
- free(aacframe);
-
- return 0;
- }</span>