转自/***************************************************************

作者:谭东

https://blog.csdn.net/jay100500/article/details/52955232

//*********************************************************************

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
  • 采样率的下标
  • 声道数,比如
接下来看下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。
 
  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. // fill in ADTS data
  12. packet[0] = (byte) 0xFF;
  13. packet[1] = (byte) 0xF9;
  14. packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
  15. packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
  16. packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
  17. packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
  18. packet[6] = (byte) 0xFC;
  19. }

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

  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头文件代码,供大家参考。

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

AAC-ADTS的更多相关文章

  1. AAC ADTS AAC LATM 格式分析

    http://blog.csdn.net/tx3344/article/details/7414543# 目录(?)[-] ADTS是个啥 ADTS内容及结构 将AAC打包成ADTS格式 1.ADTS ...

  2. (转)AAC ADTS格式分析

    1,ADTS是个啥ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式记得第一做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给 ...

  3. 【转】AAC ADTS格式分析

    1.ADTS是个啥 ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽 ...

  4. AAC ADTS解析

    1.ADTS ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 一般的AAC解码器都需要把AAC的ES流打包成ADTS的格式,一般是在AAC ...

  5. 【多媒体封装格式详解】--- AAC ADTS格式分析

    ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给硬件解码器时 ...

  6. AAC ADTS格式分析

    转自: https://blog.csdn.net/jay100500/article/details/52955232 https://blog.csdn.net/andyhuabing/artic ...

  7. (转)【多媒体封装格式详解】--- AAC ADTS格式分析

     出自:http://blog.csdn.net/tx3344/article/details/7414543 http://www.it6655.com/2012/08/aac-adts-html ...

  8. aac adts & LATM封装码流分析

    本文继续上一篇文章的内容,介绍一个音频码流处理程序.音频码流在视频播放器中的位置如下所示. 本文中的程序是一个AAC码流解析程序.该程序可以从AAC码流中分析得到它的基本单元ADTS frame,并且 ...

  9. AAC 格式分析

    一直在做一个语音项目,到了测试阶段,近来不是很忙,想把之前做的内容整理一下. 关于AAC音频格式基本情况,可参考维基百科http://en.wikipedia.org/wiki/Advanced_Au ...

  10. 音视频编解码技术(二):AAC 音频编码技术

    一.AAC编码概述 AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术,目的是取代MP3格式.2000年,MPEG-4标准 ...

随机推荐

  1. java栈的实现复习

    栈是一种线性表,仅限在一端进行插入和删除操作,特点是先进后出. 由于栈是一种线性结构,首先可以想到用数组来实现,但由于数组初始化后容量就已经确定,如果不添加扩容操作,则会出现栈溢出,同时扩容操作也会降 ...

  2. Getting Visual Studio version of a Solution file

    VS 6.0 -> 6.0 VS 2002 -> 7.0 VS 2003 -> 8.0 VS 2005 -> 9.0 VS 2008 -> 10.0 VS 2010 -& ...

  3. winform中devexpress bindcommand无效的解决方法

    正常绑定,编译运行无报错,但无法执行command fluentAPI.BindCommand(commandButton, (x, p) => x.DoSomething(p), x => ...

  4. python pytz时区设置模块

    如果你的程序要考虑时区,可以使用pytz.pytz官方文档:http://pytz.sourceforge.net/我使用的python版本:3.7.1 datetime模块中有tzinfo相关的东西 ...

  5. Java学习路线思维导图

  6. react-native 获取组件的宽度和高度

    react-native 获取组件的尺寸有两种方式,第一种方式使用元素自身的onLayout属性去获取,但是这种方式有一个局限性,就是只有在初次渲染的时候才会触发这个函数,而且此种方法获取的是组件相对 ...

  7. __slots__用法

    class Test(object): __slots__ = ("name","age") t = Test() t.name = "老王" ...

  8. Spring复习

    第一天 IOC:控制反转,对象的创建权交给Spring DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来. 包括集合的注入 ClassPathXml ...

  9. linux中 bashrc文件的alias添加快捷命令

    alias (为了简化命令操作,节省时间) 进入 /home下的用户,假设为 web 执行命令 ls -alh   找到 .bashrc 隐藏文件,如果没有则新建 通过  vi .bashrc  在里 ...

  10. CentOS7 JDK1.8部署详解

    一.下载 首先需要将本地下载好的jdk包拷贝到Linux中:scp jdk-8u91-linux-x64.tar.gz hadoop@192.168.***.***:~/software/ //星号处 ...