FFmpeg开发——AAC音频格式解析

前言

前一篇文章我们分析了MP4文件的文件格式,接下来我们深入文件内,分析它的数据格式,今天我们主要主要分析的是音频格式AAC。AAC全称Advanced Audio Coding,是相比于MP3更优秀的音频编码格式:更多的采样率,更多的声道,更好的压缩算法等。目前它也是MP4文件中音频部分的数据的常见编码格式。

如果我们测试了之前文章的demo,并调用了av_dump_format函数的话,就会打印如下的类似的媒体信息:

yaml 复制代码
  Duration: 00:00:10.00, start: 0.000000, bitrate: 2279 kb/s
  Stream #-1:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1927 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #-1:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 340 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]

我们看到一般至少有两个数据流,其中一个就是音频流,Audio: aac (LC),表明音频就是使用了aac编码格式。

AAC基本格式

AAC标准来源于ISO/IEC 13818-7,所以我们的分析也主要来自于该文档。

AAC编码格式分为两种类型:ADIF(Audio Data Interchange Format)和ADTS(Audio Data Transport Stream),其中后者是互联网上更加常见的类型。

我们一个一个说。

ADIF

ADIF格式在标准文章中的定义如下:

这是一个伪代码(C)的定义,主要把ADIF数据分为一个header+一个data Stream(byte_alignment是为了和header做内存对齐用的)。

header部分的结构如下:

我们可以看到header部分最多一共占有155bit的空间。 我们把字段罗列一下:

字段 占位(bit) 含义
adif_id 32 值固定为0x41444946,即字符串 "ADIF "的 ASCII 表示
copyright_id_present 1 表明copyright_id是否存在
copyright_id 72 版权信息,该字段由 8 位版权标识符和 64 位版权编号组成
original_copy 1
home 1
bitstream_type 1 0,:固定速率比特流,1:可变速录比特流
bitrate 23 比特率(可变速率时表示比特率最大值)
num_program_config_elements 4 配置程序数量(略)
adif_buffer_fullness 20

ADIF的数据只有一个数据头,也即ADIF音频数据只能从头开始进行解码播放。

ADTS(重点)

ADTS则用于ADIF不同,ADTS把音频数据分为不同的帧组成,每个帧中有独立的头部和数据。其数据解析方式定义如下:

从伪代码中我们可以看到,数据被循环读取,每次都读取一个Frame,而在Frame读取内部,则是先读取header(读取两次),然后读取data。

adts_fixed_header

首先读取固定头部数据:adts_fixed_header

固定头部的占位是28bit,我们把固定头部数据罗列一下:

字段 占位(bit) 含义
syncword 12 总是0xfff,标识帧开始的位置
ID 1 表示算法ID,对于ffmpeg音频为固定1
layer 2 表明处于哪个层级:"11" Layer I, "10" Layer II, "01" Layer III,"00" reserved
protection_absent 1 判断error_check() data 是否存在
profile 2 配置选项(3种:Main profile/LC/SSR)
sampling_frequency_index 4 指向采样频率取值的下标
private_bit 1
channel_configuration 3 声道配置
original_copy 1
home 1

sampling_frequency_index

表示采样频率表的下标,可以获取采样频率值。

channel_configuration

声道配置,表示该音频的数据声道数,根据声道数来确定不同的解析方式。

adts_variable_header

然后是可变头部数据:adts_variable_header

可变头部的占位也是28bit,我们把可变头部数据罗列一下:

字段 占位(bit) 含义
copyright_identification_bit 1 版权标识相关
copyright_identification_start 1 版权标识相关
aac_frame_length 13 音频帧的大小(含header)
adts_buffer_fullness 11
number_of_raw_data_blocks_in_frame 2 raw_data_blocks的数量+1

我们可以做一个ADTS基本数据结构的示意图:固定头部+可变头部+data

由于ADTS的的数据结构是分帧结构,每个帧有自己独立的header部分,也意味着ADTS格式的数据可以从任意位置(任意帧)开始解码,播放。这也更加符合目前互联网上对于音频的消费习惯,所以ADTS的音频格式在互联网上更加流行。

数据部分

AAC文件的数据主要是原始数据流部分,且围绕着音频的编码过程进行,这就超出了本文的探讨了。有兴趣的同学可以查看文档ISO/IEC 13818-7

相关推荐
一一Null35 分钟前
Token安全存储的几种方式
android·java·安全·android studio
JarvanMo1 小时前
flutter工程化之动态配置
android·flutter·ios
时光少年4 小时前
Android 副屏录制方案
android·前端
时光少年4 小时前
Android 局域网NIO案例实践
android·前端
alexhilton4 小时前
Jetpack Compose的性能优化建议
android·kotlin·android jetpack
流浪汉kylin4 小时前
Android TextView SpannableString 如何插入自定义View
android
火柴就是我6 小时前
git rebase -i,执行 squash 操作 进行提交合并
android
你说你说你来说6 小时前
安卓广播接收器(Broadcast Receiver)的介绍与使用
android·笔记
你说你说你来说7 小时前
安卓Content Provider介绍及使用
android·笔记
RichardLai887 小时前
[Flutter学习之Dart基础] - 类
android·flutter