• 【AAC文件数据解析和ADTS frame】


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

    工程:

    效果:

    代码是使用雷神的代码,然后我加了一些注释,让刚入门的能降低理解难度:

    1. // my1.cpp : 定义控制台应用程序的入口点。
    2. //
    3. #include "stdafx.h"
    4. //C++中malloc、free的头文件
    5. #include
    6. //解析ADTS frame结构
    7. int getADTSframe(unsigned char* buffer, int buf_size, unsigned char* data ,int* data_size)
    8. {
    9. int size = 0;
    10. if(!buffer || !data || !data_size )
    11. {
    12. return -1;
    13. }
    14. while(1)
    15. {
    16. //ADTS header占用的大小为7字节或者9字节,区别在于结尾是否有CRC效验
    17. //adts_fixed_header部分中的protection_absent为1时没有效验,为0时有效验,大小小于7字节就没有意义了
    18. if(buf_size < 7 )
    19. {
    20. return -1;
    21. }
    22. //syncword占用12位,所以判断前12位,是否为0xFFF,用来分离AAC码流中每个ADTS frame
    23. if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) )
    24. {
    25. //frame_length是ADTS frame长度,按位存放,(第四个字节最后两位,第五个字节,第六个字节前3位)
    26. size |= ((buffer[3] & 0x03) <<11); //high 2 bit
    27. size |= buffer[4]<<3; //middle 8 bit
    28. size |= ((buffer[5] & 0xe0)>>5); //low 3bit
    29. break;
    30. }
    31. --buf_size;
    32. ++buffer;
    33. }
    34. if(buf_size < size)
    35. {
    36. return 1;
    37. }
    38. //每次获取一个ADTS frame
    39. memcpy(data, buffer, size);
    40. *data_size = size;
    41. return 0;
    42. }
    43. int simplest_aac_parser(char *url)
    44. {
    45. int data_size = 0;
    46. int size = 0;
    47. int cnt=0;
    48. int offset=0;
    49. FILE *myout=stdout;
    50. unsigned char *aacframe=(unsigned char *)malloc(1024*5);
    51. unsigned char *aacbuffer=(unsigned char *)malloc(1024*1024);
    52. FILE *ifile = fopen(url, "rb");
    53. if(!ifile)
    54. {
    55. printf("Open file error");
    56. return -1;
    57. }
    58. printf("-----+- ADTS Frame Table -+------+\n");
    59. printf(" NUM | Profile | Frequency| Size |\n");
    60. printf("-----+---------+----------+------+\n");
    61. while(!feof(ifile))
    62. {
    63. //返回读取对象个数,ifile中读取1024*1024-offset,到aacbuffer+offset
    64. data_size = fread(aacbuffer+offset, 1, 1024*1024-offset, ifile);
    65. unsigned char* input_data = aacbuffer;
    66. while(1)
    67. {
    68. int ret=getADTSframe(input_data, data_size, aacframe, &size);
    69. if(ret==-1)
    70. {
    71. break;
    72. }
    73. else if(ret==1)
    74. {
    75. memcpy(aacbuffer,input_data,data_size);
    76. offset=data_size;
    77. break;
    78. }
    79. char profile_str[10]={0};
    80. char frequence_str[10]={0};
    81. //使用的AAC级别,2位,0为AAC Main,1为 AAC LC (Low Complexity),2为 AAC SSR (Scalable Sampling Rate)
    82. unsigned char profile=aacframe[2]&0xC0;
    83. profile=profile>>6;
    84. switch(profile)
    85. {
    86. case 0: sprintf(profile_str,"Main");break;
    87. case 1: sprintf(profile_str,"LC");break;
    88. case 2: sprintf(profile_str,"SSR");break;
    89. default:sprintf(profile_str,"unknown");break;
    90. }
    91. //采样率sampling_frequency_index,Sampling Frequencies[ ]数组查询对于采样率
    92. unsigned char sampling_frequency_index=aacframe[2]&0x3C;
    93. sampling_frequency_index=sampling_frequency_index>>2;
    94. switch(sampling_frequency_index)
    95. {
    96. case 0: sprintf(frequence_str,"96000Hz");break;
    97. case 1: sprintf(frequence_str,"88200Hz");break;
    98. case 2: sprintf(frequence_str,"64000Hz");break;
    99. case 3: sprintf(frequence_str,"48000Hz");break;
    100. case 4: sprintf(frequence_str,"44100Hz");break;
    101. case 5: sprintf(frequence_str,"32000Hz");break;
    102. case 6: sprintf(frequence_str,"24000Hz");break;
    103. case 7: sprintf(frequence_str,"22050Hz");break;
    104. case 8: sprintf(frequence_str,"16000Hz");break;
    105. case 9: sprintf(frequence_str,"12000Hz");break;
    106. case 10: sprintf(frequence_str,"11025Hz");break;
    107. case 11: sprintf(frequence_str,"8000Hz");break;
    108. default:sprintf(frequence_str,"unknown");break;
    109. }
    110. fprintf(myout,"%5d| %8s| %8s| %5d|\n",cnt,profile_str ,frequence_str,size);
    111. data_size -= size;
    112. input_data += size;
    113. cnt++;
    114. }
    115. }
    116. fclose(ifile);
    117. free(aacbuffer);
    118. free(aacframe);
    119. return 0;
    120. }
    121. int _tmain(int argc, _TCHAR* argv[])
    122. {
    123. simplest_aac_parser("F:/123.aac");//acc文件路径
    124. return 0;
    125. }

    注意:

    1、自己准备一个AAC的文件放在自己觉得方便的路径

    2、使用调试模式打断点查看结果,在_tmain函数的return 0,打上断点,不要一下跑完了,

    ADTS frame结构和信息:

    参数长度 (bits)描述
    syncword12同步字,占12bit,值固定,都是0xFFF,转成二进制就是111111111111,
    ID1MPEG的版本,0表示MPEG-4,1表示MPEG-2
    layer2固定值都是00
    protection_absent1是否同步CRC效验,0说有,1说没有,长度差两个字节
    profile2使用的AAC级别,0为AAC Main,1为 AAC LC (Low Complexity),2为 AAC SSR (Scalable Sampling Rate)
    sampling_frequency_index4对应采样率
    private_bit1私有流,编码时设置为0,解码时忽略
    channel_configuration3

    声道数,LF RF表示左右声道

    original_copy1原创性,编码时设置为0,解码时忽略
    home1编码时设置为0,解码时忽略
    copyright_identification_bit 1受版权保护的流,编码时设置为0,解码时忽略
    copyright_identification_start1版权开始,编码时设置为0,解码时忽略
    frame_length13一个ADTS帧的长度包括ADTS头和AAC原始流
    adts_buffer_fullness11缓冲区充满度,0x7FF 说明是码率可变的码流。
    number_of_raw_data_blocks_in_frame2

    表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。
    所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块。
    (一个AAC原始帧包含一段时间内1024个采样及相关数据)

    ADTS帧中的AAC帧(RDB)数减去1,为实现最大兼容性,每个ADTS帧始终使用1个AAC帧

    CRC效验位16如果没有保护,这位为0

  • 相关阅读:
    翻译: 网页排名PageRank算法的来龙去脉 以及 Python实现
    Linux基本指令(下)
    React报错之react component changing uncontrolled input
    .net8 Syncfusion生成pdf/doc/xls/ppt最新版本
    SpringBoot 使用与介绍
    PAT 1065 A+B and C (64bit)
    Nginx入门到精通1-nginx基础及环境搭建
    impala常用时间函数,date->string->timestamp互转
    【Linux私房菜】第四期——管理
    前端秘法基础式终章----欢迎来到JS的世界
  • 原文地址:https://blog.csdn.net/bigtree_mfc/article/details/126488375