音视频入门基础:AAC专题(3)——AAC的ADTS格式简介

news2024/11/14 14:52:32

=================================================================

音视频入门基础:AAC专题系列文章:

音视频入门基础:AAC专题(1)——AAC官方文档下载

音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件

音视频入门基础:AAC专题(3)——AAC的ADTS格式简介

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

音视频入门基础:AAC专题(6)——FFmpeg源码中解码ADTS格式的AAC的Header的实现

音视频入门基础:AAC专题(7)——FFmpeg源码中计算AAC裸流每个packet的size值的实现

音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现

音视频入门基础:AAC专题(9)——FFmpeg源码中计算AAC裸流每个packet的duration和duration_time的实现

音视频入门基础:AAC专题(10)——FFmpeg源码中计算AAC裸流每个packet的pts、dts、pts_time、dts_time的实现

=================================================================

一、引言

AAC(Advanced Audio Coding)有两种格式:

1.ADIF(Audio Data Interchange Format,音频数据交换格式):整个流中只包含一个Header(文件头),不能在任意处读取。这种格式基本用不到。

2.ADTS(Audio Data Transport Stream,音频数据传输流):每一帧的音频压缩数据包中都有一个Header,记录音频的采样率、通道数等参数,使得解码可以在流的任何位置开始。所以一般都是用ADTS包装的AAC。

这两种格式的Header不一样,本系列主要针对ADTS格式的AAC进行讲解。首先我们从《音视频入门基础:AAC专题(1)——AAC官方文档下载》下载AAC的标准文档《ISO_IEC_13818-7_2006(E).pdf》和《ISO14496-3-2009.pdf》,以及MP3的标准文档《ISO11172-3.pdf》。现在一般都是用MPEG-4的AAC,所以我们主要阅读《ISO14496-3-2009.pdf》,但是对于从MPEG-2中继承下来的属性,我们需要翻阅《ISO_IEC_13818-7_2006(E).pdf》,对于从MP3中继承下来的属性,我们需要翻阅《ISO11172-3.pdf》。

注:《ISO_IEC_13818-7_2006(E).pdf》总共有202页,《ISO14496-3-2009.pdf》总共有1416页,下面的页数是指在pdf阅读器中显示的页数:

二、ADTS格式的Header

(一)ADTS Header的基本概念

根据《ISO14496-3-2009.pdf》第121页,ADTS序列(ADTS流)由一个个adts音频帧(adts音频压缩数据包)组成。使用syncword分割各个adts音频帧:

根据《ISO14496-3-2009.pdf》第29页,syncword为嵌入在ADTS流中的一种编码,用于标识ADTS音频帧的起始位置:

根据《ISO14496-3-2009.pdf》第122页,adts_variable_header中的number_of_raw_data_blocks_in_frame属性的值为0的情况下,每个adts帧由adts_fixed_header(固定头)、adts_variable_header(可变头)、adts_error_check(错误校验)、raw_data_block(原始数据块)组成:

其中,ADTS Header由adts_fixed_header、adts_variable_header和adts_error_check组成。根据《ISO14496-3-2009.pdf》第123页,adts_fixed_header中的protection_absent属性的值为0时,adts_error_check才会存在CRC校验。所以当protection_absent为0时,adts_error_check占16位(2字节),当protection_absent不为0时,adts_error_check占0位(0字节):

adts_fixed_header固定占28位,adts_variable_header也占28位。所以当protection_absent为0时,ADTS Header占9字节;protection_absent不为0时,ADTS Header占7字节。

(二)adts_fixed_header

根据《ISO14496-3-2009.pdf》第122页,adts_fixed_header包含的属性如下。从下表中可以看到每个属性占的位数,这些属性加起来总共占28位,所以adts_fixed_header固定占28位:

根据《ISO14496-3-2009.pdf》第32页,bslbf(bit string,left bit first)表示比特串,左位在先。

uimsbf(unsigned integer,most significant bit first)表示无符号整数,高位在先。具体可以参考:《uimsbf和 bslbf的含义》:

syncword:占12位。关于syncword属性的值的描述,在《ISO14496-3-2009.pdf》中并没有提到,但是在《ISO_IEC_13818-7_2006(E).pdf》可以找到关于它的说明。从上文我们可以知道,syncword为嵌入在ADTS流中的一种编码,用于标识ADTS帧的起始位置。根据《ISO_IEC_13818-7_2006(E).pdf》第45页,,syncword的每个位都必须被设置为1,也就是0b111111111111:

ID:占1位。根据《ISO14496-3-2009.pdf》第124页,ID为MPEG版本的标识符。如果ADTS流中的音频数据是MPEG-2 AAC,ID被设置为1,如果音频数据是MPEG-4 AAC,其被设置为0:

layer:占2位。根据《ISO_IEC_13818-7_2006(E).pdf》第45页,layer总被设置为00:

protection_absent:占1位。根据《ISO_IEC_13818-7_2006(E).pdf》第45页,protection_absent表示CRC校验是否存在。从上文可以知道,当protection_absent为0时,CRC校验存在,当protection_absent为1时,CRC校验不存在:

profile_ObjectType:占2位。根据《ISO14496-3-2009.pdf》第124页,MPEG版本为MPEG-4时,如果profile_ObjectType为0,AAC的规格为AAC Main;如果profile_ObjectType为1,规格为AAC LC;如果profile_ObjectType为2,规格为AAC SSR;如果profile_ObjectType为3,规格为AAC LTP:

samplingFrequencyIndex:占4位。根据《ISO14496-3-2009.pdf》第59页,samplingFrequencyIndex表示音频的采样频率:

private_bit:占1位。《ISO_IEC_13818-7_2006(E).pdf》和《ISO14496-3-2009.pdf》里面没有对其进行任何说明。在《ISO_IEC_13818-7_2006(E).pdf》第46页,写了想要了解private_bit属性得查阅标准文档《ISO/IEC 11172-3》:

所以我们从https://csclub.uwaterloo.ca/~pbarfuss/ISO11172-3.pdf 下载《ISO11172-3.pdf》,在其第23页终于找到关于private_bit属性的说明了,意思就是private_bit没用:

channel_configuration:占3位。根据《ISO14496-3-2009.pdf》第60页。channel_configuration表示音频声道数。比如channel_configuration值为1表示是单声道(center front speaker);值为2表示是双声道(left, right front speakers);值为3:三声道(center, left, right front speakers);值为4:四声道(center, left, right front speakers, rear surround speakers);值为5:五声道(center, left, right front speakers, left surround, right surround rear speakers);值为6: 5.1声道(center, left, right front speakers, left surround, right surround rear speakers, front low frequency effects speaker);值为7:7.1声道(center, left, right center front speakers, left, right outside front speakers, left surround, right surround rear speakers, front low frequency effects speaker);值为8到15:保留:

original_copy:占1位。该属性继承自mp3里的copyright属性。根据《ISO11172-3.pdf》第24页,如果这个比特位等于0,则表示编码的比特流没有版权,1表示版权受保护:

home:占1位。该属性继承自mp3里的original/home属性。根据《ISO11172-3.pdf》第24页,如果比特流是一个拷贝,home的值为0,如果是原始比特流,则值为1:

(三)adts_variable_header

根据《ISO14496-3-2009.pdf》第122页,adts_variable_header包含的属性如下。从下表中可以看到每个属性占的位数,这些属性加起来总共占28位,所以adts_variable_header固定占28位:

copyright_identification_bit:占1位。根据《ISO_IEC_13818-7_2006(E).pdf》第46页,copyright_identification_bit为72位版权标识字段中的一位:

copyright_identification_start:占1位。根据《ISO_IEC_13818-7_2006(E).pdf》第46页,copyright_identification_start表示copyright_identification_bit音频帧是72位版权标识的第一位。如果没有版权标识传输,此位应保留' 0 ':

aac_frame_length:占13位。根据《ISO_IEC_13818-7_2006(E).pdf》第46页,aac_frame_length为整个ADTS音频帧的长度,包含ADTS Header、错误校验和AAC原始数据块,单位为字节:

adts_buffer_fullness:占11位。根据《ISO_IEC_13818-7_2006(E).pdf》第46页至47页,adts_buffer_fullness为在adt编码过程中,比特储存的状态。如果值为0x7FF,表示比特流是可变速率比特流:

number_of_raw_data_blocks_in_frame:占2位。根据《ISO_IEC_13818-7_2006(E).pdf》第47页,一个ADTS音频帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始数据块。number_of_raw_data_blocks_in_frame的值为0表示该ADTS音频帧中只有一个AAC原始数据块:

三、AAC的samples

根据《ISO14496-3-2009.pdf》第9页,对于标准的MPEG-2/4 AAC,其samples(一帧音频数据中采样的次数)为1024或者960次:

根据《ISO14496-3-2009.pdf》第46页,规格为AAC LC和AAC LTP的AAC,一帧音频数据中采样的次数只允许为1024次:

至于AAC的samples啥时候为960次,我浏览了AAC的标准文档,在里面并没有找到相关说明,AAC的Header中也没有属性用来标识samples是1024还是960次。在微软的官方文章《AAC 解码器》中说明了Microsoft Media Foundation AAC 解码器仅支持1024个样本帧,也就是AAC解码器仅支持的samples为1024不支持960:

我浏览了国外论坛的某些文章《Topic: AAC decoding with a free Windows Library?》、《Support of AAC with 960 samples/frame》,里面写到AAC(AAC Main、AAC LC、AAC SSR、AAC LTP)的samples是1024,而DAB+(AAC+、HE AAC v2)的samples是960。所以可以认为目前约定俗成是:AAC(AAC Main、AAC LC、AAC SSR、AAC LTP)的samples是1024,而DAB+(AAC+、HE AAC v2)的samples是960。

这个samples(一帧音频数据中采样的次数)非常重要,用于计算一个adts音频帧(adts音频压缩数据包)的时长,具体可以参考:《FFmpeg源码:get_audio_frame_duration、av_get_audio_frame_duration2、av_get_audio_frame_duration函数分析》。

四、AAC的Bit depth

Bit depth(又叫位深度、位元深度、采样深度、采样位数、采样格式)是用于编码每个样本的数字信息位数。简单来说,位元深度衡量的是“精度”。Bit depth越高,信号就越能准确地表示实际模拟声源的振幅。使用最低可能的Bit depth,我们只有两种选择来测量声音的精度:0表示完全静音,1表示最高音量。Bit depth越高,对音频编码的精度越高。举个例子:CD质量的音频的Bit depth是标准的16位,有216(或65536)个音量可供选择。

Bit depth对于PCM编码是固定的,但对于有损压缩编解码器(如MP3和AAC),它是在编码期间计算的,并且可以因采样而异。

也就是说Bit depth只对PCM数字信号有意义。非PCM格式,如AAC这种有损压缩格式,Bit depth是没有意义的。所以AAC裸流的Header中没有Bit depth信息,WAV音频文件因为一般存贮的是PCM音频数据,所以WAV Header中才有Bit depth信息,具体可以参考:《音视频入门基础:WAV专题(2)——WAV格式简介》。

五、参考文章

《Audio encoding demystified》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2151031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenSSH从7.4升级到9.8的过程 亲测--图文详解

一、下载软件 下载openssh 下载地址: Downloads | Library 下载openssl Index of /pub/OpenBSD/OpenSSH/ zlib Home Site 安装的 openssl-3.3.1.tar.gz ,安装3.3.2有问题 安装有问题, 二、安装依赖 yum install -y perl-CPAN perl-ExtUtils-CB…

stm32f411ceu6芯片学习

首先找到对应芯片的数据手册,硬件电路设计参考的是Electrical characteristics这一节,芯片的每一个引脚都会有推荐的电路接线。 基本每个芯片,都可以在数据手册中找到厂家提供的参考电路图,这就是绘制芯片的原理图最基本的依据。 …

【小白向】Google Play日区如何支付?Google Play日区怎么转?Google Play日区账号支付教程

1.引言 在移动应用和游戏的世界里,Google Play(谷歌Play商店)日区一直是许多用户的向往之地。日本作为全球第三大应用市场,拥有大量优质且独特的应用和游戏。本教程将为你详细介绍如何在Google Play商店进行日区支付、Google Pla…

mat工具的几个实用地方

背景 使用mat的过程中,有几个值得关注的注意点,可以帮助我们尽快查找到问题的答案 mat实用的注意点 一.打开直方图后排序,直观查看内存占用大小,如下图所示 二.查看某个对象实例的具体值,点击对象,点击List Object…

mysql使用sql函数对json数组的处理

MySQL从5.7版本开始增加了对JSON数据类型的支持。你可以使用->>操作符和JSON_EXTRACT函数来访问JSON数据中的值。 但是,对于JSON数组,如果你想要获取数组中的所有元素,MySQL并没有直接的函数来返回数组中的所有元素作为单独的行。不过…

甲基化组学全流程分析(适用于27k的甲基化数据)

甲基化组学全流程分析(适用于27k的甲基化数据) 前面我已经讲过450k和870k EPIC的甲基化芯片的全流程分析教程,分析功能更为完善和强大,今天讲讲甲基化位点探针较少的27k甲基化芯片的分析流程。 我开发了一款本地电脑无限使用的零代码生信数据分析作软图…

不出海等于出局?

从2023年开始,“出海”已经成了很多企业的主题词。我以前做过一段时间的百度竞价工作,所以有个习惯,会比较关注友商网站上的一些动态信息。2023年开始,以前熟悉的一些公司,网站上都多了一个板块,就是“出海…

HTML常见语法设计

HTML常见语法设计 1.HTML类和ID类id 2.HTML 响应式 Web 设计3.HTML5 语义元素4.HTML 字符实体5.HTML 编码(字符集) 1.HTML类和ID 类 对 HTML 进行分类(设置类),使我们能够为元素的类定义 CSS 样式。为相同的类设置相…

鸿蒙Harmony-Next 徒手撸一个日历控件

本文将介绍如何使用鸿蒙Harmony-Next框架实现一个自定义的日历控件。我们将创建一个名为CalendarView的组件(注意,这里不能叫 Calendar因为系统的日历叫这个),它具有以下功能: 显示当前月份的日历支持选择日期显示农历日期可以切换上一月和下一月 组件…

9月18日国家网络安全通报中心发布的100个高危漏洞(下)

9月18日国家网络安全通报中心发布,公安机关网安部门从危害程度、广泛性、漏洞利用形式、利用难度、检测难度等维度,梳理出了100个突出的高危漏洞,目前这些漏洞是各个网络安全公司检测的重点,广大网络运营者应尽快对照排查自己的网…

火车站高铁站站点时刻查询网站计算机毕设/动车站点时刻查询

创建一个关于火车站高铁站站点时刻查询的毕业设计项目,是一个非常实际且具有挑战性的任务。这样的项目不仅能帮助学生综合运用所学知识,还能够为用户提供便捷的服务。下面将详细说明项目的各个方面: 1. 需求分析 用户需求&am…

代码随想录冲冲冲 Day51 图论Part3

101. 孤岛的总面积 dfs 首先dfs的作用就是在遇到陆地的时候找到所有的周围陆地 对于这道题的dfs 会把所有的链接边缘的陆地变成海洋 这样在全部调整之后 剩下的就是孤岛了 这道题中的dfs的结束条件就是遇到海洋时 遇到每一个陆地就会把面积1,在每一次重新找到…

(2)leetcode 234.回文链表 141.环形链表

234.回文链表 题目链接 234.回文链表 解题思路与代码 获取链表的中间段。 我们将mid这个节点记录下来,然后将这段链表反转,以下是反转的逻辑,最后我们将pre返回就是结果,就是通过中间变量tem记录位置从而实现链表的反转 最后结果…

LLM - 理解 多模态大语言模型(MLLM) 的 对齐微调(Alignment) 与相关技术 (五)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/142354652 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 完备(F…

vue scoped解析

不加scoped 加上scoped 从上面的图可以看出,给style加上scoped之后,会给这个模块的所有元素都加上一个自定义属性data-v-xxxx,这个xxxx就是这个文件的相对路径加上文件名生成的hash值,这样就能保证自定义属性独一无二 给所有元…

windows打开可选功能窗口的方式(呜呜设置里面找不到可选功能只能这样找了)

打开方式 winR打开运行窗口,输入fodhelper,按下回车键 即可快速打开可选功能窗口

手动部署并测试内网穿透

文章目录 手动部署并测试内网穿透1、原理2、下载 frp 文件3、配置对应的配置文件4、启动 frp 服务5、效果 手动部署并测试内网穿透 1、原理 原理就是让你需要访问的内网可以被其他内网访问到。 其实就是让内网经过一个公网服务器的转发,使得能够被访问。 这里我们需…

算法课习题汇总(2)

整数划分问题 将正整数n表示成一系列正整数之和&#xff0c;nn1n2…nk(n1>n2>…>nk,k>1)。正整数n的这种表示称为正整数n的划分。 思路&#xff1a; n表示待划分数&#xff0c;m表示最大减数。 #include<iostream> using namespace std;int q(int n, int…

MySQL:库表的基本操作

库操作 查看 查看存在哪些数据库&#xff1a; show databases;查看自己当前处于哪一个数据库&#xff1a; select database(); 由于我不处于任何一个数据库中&#xff0c;此处值为NULL 查看当前有哪些用户连接到了MySQL&#xff1a; show processlist; 创建 创建一个数据库 语…

【JAVA入门】Day48 - 线程池

【JAVA入门】Day48 - 线程池 文章目录 【JAVA入门】Day48 - 线程池一、线程池的主要核心原理二、自定义线程池三、线程池的大小 我们之前写的代码都是&#xff0c;用到线程的时候再创建&#xff0c;用完之后线程也就消失了&#xff0c;实际上这是不对的&#xff0c;它会浪费计算…