参考雷神的博客,我使用的是VS2010,加载AAC文件,读取数据解析,如果没有AAC文件的,可以网上下载一个格式工厂,转换出一个AAC文件出来,注意文件尽量小一点
工程:

效果:

代码是使用雷神的代码,然后我加了一些注释,让刚入门的能降低理解难度:
- // my1.cpp : 定义控制台应用程序的入口点。
- //
-
- #include "stdafx.h"
- //C++中malloc、free的头文件
- #include
-
-
- //解析ADTS frame结构
- int getADTSframe(unsigned char* buffer, int buf_size, unsigned char* data ,int* data_size)
- {
- int size = 0;
-
- if(!buffer || !data || !data_size )
- {
- return -1;
- }
-
- while(1)
- {
- //ADTS header占用的大小为7字节或者9字节,区别在于结尾是否有CRC效验
- //adts_fixed_header部分中的protection_absent为1时没有效验,为0时有效验,大小小于7字节就没有意义了
- if(buf_size < 7 )
- {
- return -1;
- }
- //syncword占用12位,所以判断前12位,是否为0xFFF,用来分离AAC码流中每个ADTS frame
- if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) )
- {
- //frame_length是ADTS frame长度,按位存放,(第四个字节最后两位,第五个字节,第六个字节前3位)
- size |= ((buffer[3] & 0x03) <<11); //high 2 bit
- size |= buffer[4]<<3; //middle 8 bit
- size |= ((buffer[5] & 0xe0)>>5); //low 3bit
- break;
- }
- --buf_size;
- ++buffer;
- }
-
- if(buf_size < size)
- {
- return 1;
- }
-
- //每次获取一个ADTS frame
- memcpy(data, buffer, size);
- *data_size = size;
-
- return 0;
- }
-
- 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");
- if(!ifile)
- {
- printf("Open file error");
- return -1;
- }
-
- printf("-----+- ADTS Frame Table -+------+\n");
- printf(" NUM | Profile | Frequency| Size |\n");
- printf("-----+---------+----------+------+\n");
-
- while(!feof(ifile))
- {
- //返回读取对象个数,ifile中读取1024*1024-offset,到aacbuffer+offset
- data_size = fread(aacbuffer+offset, 1, 1024*1024-offset, ifile);
- unsigned char* input_data = aacbuffer;
-
- while(1)
- {
- int ret=getADTSframe(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};
-
- //使用的AAC级别,2位,0为AAC Main,1为 AAC LC (Low Complexity),2为 AAC SSR (Scalable Sampling Rate)
- 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;
- }
-
- //采样率sampling_frequency_index,Sampling Frequencies[ ]数组查询对于采样率
- 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;
- }
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- simplest_aac_parser("F:/123.aac");//acc文件路径
-
- return 0;
- }
注意:
1、自己准备一个AAC的文件放在自己觉得方便的路径
2、使用调试模式打断点查看结果,在_tmain函数的return 0,打上断点,不要一下跑完了,
ADTS frame结构和信息:

| 参数 | 长度 (bits) | 描述 |
|---|---|---|
| syncword | 12 | 同步字,占12bit,值固定,都是0xFFF,转成二进制就是111111111111, |
| ID | 1 | MPEG的版本,0表示MPEG-4,1表示MPEG-2 |
| layer | 2 | 固定值都是00 |
| protection_absent | 1 | 是否同步CRC效验,0说有,1说没有,长度差两个字节 |
| profile | 2 | 使用的AAC级别,0为AAC Main,1为 AAC LC (Low Complexity),2为 AAC SSR (Scalable Sampling Rate) |
| sampling_frequency_index | 4 | 对应采样率![]() |
| private_bit | 1 | 私有流,编码时设置为0,解码时忽略 |
| channel_configuration | 3 | 声道数,LF RF表示左右声道
|
| original_copy | 1 | 原创性,编码时设置为0,解码时忽略 |
| home | 1 | 编码时设置为0,解码时忽略 |
| copyright_identification_bit | 1 | 受版权保护的流,编码时设置为0,解码时忽略 |
| copyright_identification_start | 1 | 版权开始,编码时设置为0,解码时忽略 |
| frame_length | 13 | 一个ADTS帧的长度包括ADTS头和AAC原始流 |
| adts_buffer_fullness | 11 | 缓冲区充满度,0x7FF 说明是码率可变的码流。 |
| number_of_raw_data_blocks_in_frame | 2 | 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。 ADTS帧中的AAC帧(RDB)数减去1,为实现最大兼容性,每个ADTS帧始终使用1个AAC帧 |
| CRC效验位 | 16 | 如果没有保护,这位为0 |