参考雷神的博客,我使用的是VS2010,加载AAC文件,读取数据解析,如果没有AAC文件的,可以网上下载一个格式工厂,转换出一个AAC文件出来,注意文件尽量小一点
工程:
效果:
代码是使用雷神的代码,然后我加了一些注释,让刚入门的能降低理解难度:
// my1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//C++中malloc、free的头文件
#include <stdlib.h>
//解析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 |