zoukankan      html  css  js  c++  java
  • AAC的ADTS格式分析(转)

    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. }    
    AAC的规格一览:

    因为AAC是一个庞大家族,他们共分为9种规格,以适应不同场合的需要,也正是由于AAC的规格(Profile)繁多,导致普通电脑用户感觉十分困扰:

    1. MPEG-2 AAC LC低复杂度规格(Low Complexity)
    2. MPEG-2 AAC Main主规格
    3. MPEG-2 AAC SSR可变采样率规格(Scaleable Sample Rate)
    4. MPEG-4 AAC LC低复杂度规格(Low Complexity),现在的手机比较常见的MP4文件中的音频部分就包括了该规格音频档案
    5. MPEG-4 AAC Main主规格
    6. MPEG-4 AAC SSR可变采样率规格(Scaleable Sample Rate)
    7. MPEG-4 AAC LTP长时期预测规格(Long Term Predicition)
    8. MPEG-4 AAC LD低延迟规格(Low Delay)
    9. MPEG-4 AAC HE高效率规格(High Efficiency)
    上述的规格中,主规格(Main)包含了除增益控制之外的全部功能,其音质最好,而低复杂度规格(LC)则是比较简单,没有了增益控制,但提高了编码效率,至“SSR”对“LC”规格大体是相同,但是多了增益的控制功能,另外,MPEG-4 AAC/LTP/LD/HE,都是用在低比特率下编码,特别是“HE”是有Nero AAC编码器支持,是近来常用的一种编码器,不过通常来说,Main规格和LC规格的音质相差不大,因此目前使用最多的AAC规格多数是“LC”规格,因为要考虑手机目前的存储器能力未达合理水准。

    MPEG-4 AAC LC(Low Complexity)是最常用的规格,我们叫“低复杂度规格”,我们简称“LC-AAC”,这种规格在中等码率的编码效率以及音质方面,都能找到平衡点。所谓中等码率,就是指:96kbps-192kbps之间的码率。因此,如果要使用LC-AAC规格,请尽可能把码率控制在之前说的那个区间内。

  • 相关阅读:
    TCP/UDP模型
    分时技术
    Linux文件浏览命令
    Maven下载私服上的jar包(全局)
    Maven下载私服上的jar包
    Maven将中央仓库修改为阿里云的仓库地址
    数据结构之算法初涉(2)
    数据结构之概念初涉(1)
    JAVA中GridBagLayout布局管理器应用详解
    C++数据结构中的基本算法排序
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/13141832.html
Copyright © 2011-2022 走看看