AAC的ADTS头文件信息介绍

遵循:BY-SA

署名-相同方式共享 4.0协议

 

 

作者:谭东

时间:2016年10月28日

环境:Windows 7

 

 

ADTS是Audio Data Transport Stream的简称。

 

是AAC音频文件常见的传输格式。

有的时候当你编码AAC裸流的时候,会遇到写出来的AAC文件并不能在PC和手机上播放,很大的可能就是AAC文件的每一帧里缺少了ADTS头信息文件的包装拼接。只需要加入头文件ADTS即可。一个AAC原始数据块长度是可变的,对原始帧加上ADTS头进行ADTS的封装,就形成了ADTS帧。

 

下面分析下ADTS头文件结构和信息:

AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成。

 

 

大家可以用AAC Audio ES Viewer工具来查看AAC的ADTS Header。

 

每一帧的ADTS的头文件都包含了音频的采样率,声道,帧长度等信息,这样解码器才能解析读取。

一般情况下ADTS的头信息都是7个字节,分为2部分:

adts_fixed_header();

adts_variable_header();

先来看:adts_fixed_header();


 

  • syncword :总是0xFFF, 代表一个ADTS帧的开始, 用于同步.
    解码器可通过0xFFF确定每个ADTS的开始位置.
    因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码。
  • ID:MPEG Version: 0 for MPEG-4,1 for MPEG-2
  • Layer:always: '00'
  • protection_absent:Warning, set to 1 if there is no CRC and 0 if there is CRC
  • profile:表示使用哪个级别的AAC,如01 Low Complexity(LC) -- AAC LC
    profile的值等于 Audio Object Type的值减1.
    profile = MPEG-4 Audio Object Type - 1
  • sampling_frequency_index:采样率的下标
  • channel_configuration:声道数,比如2表示立体声双声道

接下来看下adts_variable_header();


  • aac_frame_length:一个ADTS帧的长度包括ADTS头和AAC原始流。frame length, this value must include 7 or 9 bytes of header length:
    aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)

    protection_absent=0时, header length=9bytes
    protection_absent=1时, header length=7bytes

  • adts_buffer_fullness:0x7FF 说明是码率可变的码流。
  • number_of_raw_data_blocks_in_frame:表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。
    所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块。
    (一个AAC原始帧包含一段时间内1024个采样及相关数据)

 

两个头文件就讲到这里。

这里给出JAVA和Android里的给AAC添加ADTS头文件的部分方法代码,针对ByteBuffer。

 

[java] view plain copy

 

  1. /** 
  2.   * 添加ADTS头 
  3.   * 
  4.   * @param packet 
  5.   * @param packetLen 
  6.   */  
  7.  private void addADTStoPacket(byte[] packet, int packetLen) {  
  8.      int profile = 2; // AAC LC  
  9.      int freqIdx = 4; // 44.1KHz  
  10.      int chanCfg = 2; // CPE  
  11.   
  12.      // fill in ADTS data  
  13.      packet[0] = (byte) 0xFF;  
  14.      packet[1] = (byte) 0xF9;  
  15.      packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));  
  16.      packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));  
  17.      packet[4] = (byte) ((packetLen & 0x7FF) >> 3);  
  18.      packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);  
  19.      packet[6] = (byte) 0xFC;  
  20.  }  

这里是调用:(可根据自己需求,这里的AudioBufFrame是我们自己项目里的类,其实就是个ByteBuffer封装的类)

[java] view plain copy

 

  1. AudioBufFrame audioBufFrame = (AudioBufFrame) o;  
  2.         int outBufferSize = audioBufFrame.buf.limit() + 7;  
  3.         byte[] aacBytes = new byte[outBufferSize];  
  4.         try {  
  5.             if (!write) {  
  6.                 fout = new FileOutputStream(MyConfiguration.VIDEO_PATH + "/audio.aac");  
  7.                 write = true;  
  8.             }  
  9.             addADTStoPacket(aacBytes, outBufferSize);  
  10.             audioBufFrame.buf.get(aacBytes, 7, audioBufFrame.buf.limit());  
  11.             fout.write(aacBytes);  
  12.         } catch (IOException e) {  
  13.             e.printStackTrace();  
  14.         }  

 

下面是FFMPEG参考的C的添加ADTS头文件代码,供大家参考。

[java] view plain copy

 

  1. int ff_adts_write_frame_header(ADTSContext *ctx,    
  2.                                uint8_t *buf, int size, int pce_size)    
  3. {    
  4.     PutBitContext pb;    
  5.     
  6.     init_put_bits(&pb, buf, ADTS_HEADER_SIZE);    
  7.     
  8.     /* adts_fixed_header */    
  9.     put_bits(&pb, 12, 0xfff);   /* syncword */    
  10.     put_bits(&pb, 1, 0);        /* ID */    
  11.     put_bits(&pb, 2, 0);        /* layer */    
  12.     put_bits(&pb, 1, 1);        /* protection_absent */    
  13.     put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */    
  14.     put_bits(&pb, 4, ctx->sample_rate_index);    
  15.     put_bits(&pb, 1, 0);        /* private_bit */    
  16.     put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */    
  17.     put_bits(&pb, 1, 0);        /* original_copy */    
  18.     put_bits(&pb, 1, 0);        /* home */    
  19.     
  20.     /* adts_variable_header */    
  21.     put_bits(&pb, 1, 0);        /* copyright_identification_bit */    
  22.     put_bits(&pb, 1, 0);        /* copyright_identification_start */    
  23.     put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */    
  24.     put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */    
  25.     put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */    
  26.     
  27.     flush_put_bits(&pb);    
  28.     
  29.     return 0;    
  30. }    

时间: 2024-08-05 03:11:11

AAC的ADTS头文件信息介绍的相关文章

c语言-C语言结构体数组在头文件里赋值的问题

问题描述 C语言结构体数组在头文件里赋值的问题 上面的赋值是写在一个头文件里的,用VS2008,或者VC++6.0调都会出现上面的错误,VS2013和DEV就不会报错. 完整代码是: //头文件"信息.h" struct students { long code; char *name; float score[3]; float sum; }; void default_initiate(struct students stu[ ]) { stu[0] = { 20140001, &

关于windows h-请教大神有什么书详细介绍像windows.h这类头文件包含的函数的具体用法的?

问题描述 请教大神有什么书详细介绍像windows.h这类头文件包含的函数的具体用法的? 请教大神有什么书详细介绍像windows.h这类头文件包含的函数的具体用法的? 我想系统的学一学这个头文件下的函数的具体用法,苦于找不到相关的书籍,求大神推荐啊 解决方案 WINDOWS核心编程 http://download.csdn.net/detail/huangxy10/5783907 Win32 API 参考手册 http://www.pudn.com/downloads118/ebook/det

NSIS文字及字符串函数与头文件介绍

原文 NSIS文字及字符串函数与头文件介绍 文字函数,顾名思义就是处理字符串的函数.使用这些字符串函数前,必须先包含头文件WordFunc.nsh.该头文件目前包含如下一些函数:WordFind.WordFind2X.WordFind3X.WordReplace.WordAdd.WordInsert.StrFilter.VersionCompare.VersionConvert等.这些函数的主要作用都是查找字符串.下面我们就常用函数用法做以简单介绍.   WordFind 用于在给定字符串中查找

C++中头文件和源文件详细介绍

C++中的头文件和源文件详解 一.C++编译模式 通常,在一个C++程序中,只包含两类文件--.cpp文件和.h文件.其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码:而.h文件则被称作C++头文件,里面放的也是C++的源代码. C+ +语言支持"分别编译"(separate compilation).也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里..cpp文件里的东西都是相对独立的,在编 译(compile)时不需要与其他文件互通,只需要

C/C++ 头文件作用

最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的思考过.概念上还是比较模糊的,只是之前的使用大多比较简单,并没有牵涉到太复杂的工程,所以定义和声明还是比较简单而明了了的.但是最近的大工程让我在这方面吃到了一点点苦头,虽然看了别人的代码能够很快的改正,但是这些改正背后的原因却不知道.我想大多数喜欢C语言的程序员应该是和我一样的,总喜欢去追究程序问题背后的底层原因,而这

C++头文件的包含顺序研究

一.<Google C++ 编程风格指南>里的观点        公司在推行编码规范,领导提议基本上使用<Google C++ 编程风格指南>.其中<Google C++ 编程风格指南>对于头文件的包含顺序是这样的:   Names and Order of Includes link ▽Use standard order for readability and to avoid hidden dependencies:C library, C++ library,

应用PHP文件函数获取文件信息实例教程

上一篇PHP目录函数教程中主要介绍了目录(文件夹)读取,遍历的方法,但最基本的文件管理系统同时涉及到文件信息.文件大小读取以便检查磁盘使用情况,也需要获取文件修改或访问时间,删除或移动整理文件的功能,这些都需要通过PHP文件函数同文件系统交互. 基本PHP文件函数介绍 PHP文件函数dirname()和basename()的区别 dirname()获得文件目录路径的目录部分,而basename()获得不带目录的文件名 如何通过PHP文件函数获得文件基本信息? 之前介绍了PHP目录读取实例,我们只

电子商务网站及类目头文件的定义

现在的公司是从事电子商务网站.年前公司的网站需要重新定义头文件,所以花了两天时间去收集.归类和整理相关title,keywords和description.这里把操作过程中的一些经验写出来和大家分享下. 对头文件内容部分结构的定义 公司网站是主营高端化妆品的电子商务网站,在关键字上竞争是相当激烈.因为目前主要是做百度搜索权重推广,所以选取了主推关键字百度自然排名前几名的网站进行了相关信息的归类和分析   从上面的结构分析后,对自己网站头文件的定义有了较为清晰的定位.当然排名好并不意味着是头文件写

通过预编译头文件来提高CB的编译速度

C++ Builder是最快的C++编译器之一,从编译速度来说也可以说是最快的win32C++编译器了.除了速度之外,C++builder的性能也在其它C++编译器的之上,但许多delphi程序员仍受不了C++builder工程的编译速度.的确,delphi的速度要比任和c++的编译器都要快好多.Delphi在编译一个小工程的时候可能不到一秒,大的工程一般也在5秒钟这内编译完成了. 为什么delphi会比c++builder快这么多?是否有方法来c++builder的编译速度?本文就讲解了为什么