AAC的ADTS头信息介绍

2024-04-12 20:58
文章标签 介绍 信息 aac adts

本文主要是介绍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的开始位置.
    因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码
  • IDMPEG Version: 0 for MPEG-4,1 for MPEG-2
  • Layeralways: '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。

[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] = (byte0xFF;  
  14.      packet[1] = (byte0xF9;  
  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] = (byte0xFC;  
  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, 120xfff);   /* syncword */    
  10.     put_bits(&pb, 10);        /* ID */    
  11.     put_bits(&pb, 20);        /* layer */    
  12.     put_bits(&pb, 11);        /* protection_absent */    
  13.     put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */    
  14.     put_bits(&pb, 4, ctx->sample_rate_index);    
  15.     put_bits(&pb, 10);        /* private_bit */    
  16.     put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */    
  17.     put_bits(&pb, 10);        /* original_copy */    
  18.     put_bits(&pb, 10);        /* home */    
  19.     
  20.     /* adts_variable_header */    
  21.     put_bits(&pb, 10);        /* copyright_identification_bit */    
  22.     put_bits(&pb, 10);        /* copyright_identification_start */    
  23.     put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */    
  24.     put_bits(&pb, 110x7ff);   /* adts_buffer_fullness */    
  25.     put_bits(&pb, 20);        /* number_of_raw_data_blocks_in_frame */    
  26.     
  27.     flush_put_bits(&pb);    
  28.     
  29.     return 0;    
  30. }    

这篇关于AAC的ADTS头信息介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/898220

相关文章

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

Python实现NLP的完整流程介绍

《Python实现NLP的完整流程介绍》这篇文章主要为大家详细介绍了Python实现NLP的完整流程,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 编程安装和导入必要的库2. 文本数据准备3. 文本预处理3.1 小写化3.2 分词(Tokenizatio