iOS音视频(H264&AAC)

1,047 阅读14分钟

前言

在日常开发中,或多或少都会接触到H264和AAC这个两个词,上一篇文章粗略的把大部分的音视频格式做了介绍,这一篇文章来重点解析一下H264的格式和AAC的编码格式。

H264

H264压缩

H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:

  • 帧内预测压缩,解决的是空域数据冗余问题。
  • 帧间预测压缩(运动估计与补偿),解决的是时域数据冗徐问题。
  • 整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
  • CABAC压缩。

I帧,P帧和B帧

经过压缩后的帧分为:I帧,P帧和B帧:

  • I帧:帧内编码帧

I帧通常是每个GOP的第一帧,经过适度压缩,作为随机访问的参考点,可看成一个图片经过压缩后的产物

  • P帧:前向预测编码帧

通过充分低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据编码图像,也叫预测帧

  • B帧:双向预测编码帧

既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧

I,P,B帧的不同:

  • I frame: 自身可以通过视频解压算法解压成一张单独完整的图片
  • P frame: 需要参考其前面的一个I frame 或者B frame来生成一张完整图片
  • B frame: 既要参考其前一个I frame 或者 P frame以及其后一个P frame来生成一张完整的图片。

除了I/P/B帧外,还有图像序列GOP。

  • GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。如下图所示:

H264原始码流

H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层).

  • VCL:包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码。
  • NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。

NALU (Nal Unit) = NALU头 + RBSP

在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中。每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特。一个 bit“1”若干比特“0”,以便字节对齐。

一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成

  • StartCode:Start Code 用于标示这是一个 NALU 单元的开始,必须是 "00 00 00 01" 或 "00 00 01"
  • NALU Header:由三部分组成,forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)

例如:

00 00 00 01 06:  SEI信息   
00 00 00 01 07:  SPS
00 00 00 01 08:  PPS
00 00 00 01 05:  IDR Slice
  • RBSP

RBSP 序列举例

RBSP 描述

SODB与RBSP

  • SODB 数据比特串:是编码后的原始数据.
  • RBSP 原始字节序列载荷:在原始编码数据的后面添加了结尾比特。一个 bit“1”若干比特“0”,以便字节对齐。

一帧图片跟NALU的关联

  • 一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了。片是H.264提出的新概念,通过编码图片后切分通过高效的方式整合出来的概念。一张图片有一个或者多个片,而片由NALU装载并进行网络传输的。但是NALU不一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息.
  • 设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。

刚才在片中提到了宏块.那么什么是宏块呢?

  • 宏块是视频信息的主要承载者,它包含着每一个像素的亮度和色度信息。视频解码的主要工作则是提供高效的方式从码流中获得宏块中的像素阵列。
  • 宏块的组成:一个宏块由一个16*16亮度像素和附加的一个8 * 8Cb和一个8 * 8Cr彩色像素块组成。每个图像中,若干宏块被排列成片的形式。

片有一下五种类型:

  • I片:只包 I宏块,I 宏块利用从当前片中已解码的像素作为参考进行帧内预测(不能取其它片中的已解码像素作为参考进行帧内预测)。
  • P片:可包 P和I宏块,P 宏块利用前面已编码图象作为参考图象进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即 16×16、16×8、8×16 或 8×8 亮度像素块(以及附带的彩色像素);如果选了 8×8 的子宏块,则可再分成各种子宏块的分割,其尺寸为 8×8、8×4、4×8 或 4×4 亮度像素块(以及附带的彩色像素)。
  • B片:可包 B和I宏块,B 宏块则利用双向的参考图象(当前和 来的已编码图象帧)进行帧内预测。
  • SP片(切换P):用于不同编码流之间的切换,包含 P 和/或 I 宏块
  • SI片:扩展档次中必须具有的切换,它包含了一种特殊类型的编码宏块,叫做 SI 宏块,SI 也是扩展档次中的必备功能。

宏块结构如下:

宏块分类

  • mb_type:确定该 MB 是帧内或帧间(P 或 B)编码模式,确定该 MB 分割的尺寸
  • mb_pred:确定帧内预测模式(帧内宏块)确定表 0 或表 1 参考图 像,和每一宏块分割的差分编码的运动矢量(帧间宏块,除 8×8 宏块分割的帧内 MB)
  • sub_mb_pred:(只对 8×8MB 分割的帧内 MB)确定每一子宏块的子宏 块分割,每一宏块分割的表 0 和/或表 1 的参考图象;每一 宏块子分割的差分编码运动矢量。
  • coded_block_pattern:指出哪个 8×8 块(亮度和彩色)包 编码变换系数
  • mb_qp_delta:量化参数的改变值
  • residual:预测后对应于残差图象取样的编码变换系数

结合片(slice)宏块(Macroblock),我们可以整合出它们的关系

再结合之前帧的概念,整合的关系如下:

整体结构:

AAC

声音的物理性质

声音(sound)是由物体振动产生的声波。是通过介质(空气或固体、液体)传播并能被人或动物听觉器官所感知的波动现象。最初发出振动(震动)的物体叫声源。声音以波的形式振动(震动)传播。声音是声波通过任何介质传播形成的运动。
声音作为一种波,频率在20 Hz~20 kHz之间的声音是可以被人耳识别的。

数字音频

从模拟信号到数字化需要经过抽样,量化和编码3个步骤。

  • 抽样(采样)
    数码音频系统是通过将声波波形转换成一连串的二进制数据来再现原始声音的,实现这个步骤使用的设备是模/数转换器(A/D)它以每秒上万次的速率对声波进行采样,每一次采样都记录下了原始模拟声波在某一时刻的状态,称之为样本。将一串的样本连接起来,就可以描述一段声波了,把每一秒钟所采样的数目称为采样频率或采率,单位为HZ(赫兹)。采样频率越高所能描述的声波频率就越高。采样率决定声音频率的范围(相当于音调),可以用数字波形表示。以波形表示的频率范围通常被称为带宽。
  • 量化
    简单地说就是描述声音波形的数据是多少位的二进制数据,通常用bit做单位,如16bit、24bit。16bit量化级记录声音的数据是用16位的二进制数,因此,量化级也是数字声音质量的重要指标。我们形容数字声音的质量,通常就描述为24bit(量化级)、48KHz采样,比如标准CD音乐的质量就是数字音频16bit、44.1KHz采样。
  • 编码
    从信息论的观点来看,描述信源的数据是信息和数据冗余之和,即:数据=信息+数据冗余。音频信号在时域和频域上具有相关性,也即存在数据冗余。将音频作为一个信源,音频编码的实质是减少音频中的冗余。 自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。

其他名词补充

  • 采样率
    简单地说就是通过波形采样的方法记录1秒钟长度的声音,需要多少个数据。44KHz采样率的声音就是要花费44000个数据来描述1秒钟的声音波形。原则上采样率越高,声音的质量越好。
  • 压缩率
    通常指音乐文件压缩前和压缩后大小的比值,用来简单描述数字声音的压缩效率。
  • 比特率
    是另一种数字音乐压缩效率的参考性指标,表示记录音频数据每秒钟所需要的平均比特值(比特是电脑中最小的数据单位,指一个0或者1的数),通常我们使用Kbps(通俗地讲就是每秒钟1024比特)作为单位。CD中的数字音乐比特率为1411.2Kbps(也就是记录1秒钟的CD音乐,需要1411.2×1024比特的数据),近乎于CD音质的MP3数字音乐需要的比特率大约是112Kbps~128Kbps。

音频压缩

压缩编码的原理实际上是压缩掉冗余信号,冗余信号是指不能被人耳感知到的信号,包含人耳听觉范围之外的音频信号以及被掩蔽掉的音频信号等。人耳听觉范围之外的音频上面提到过。被掩蔽掉的音频信号则主要是因为人耳的掩蔽效应,主要表现为频域掩蔽效应与时域掩蔽效应。

  • 频域掩蔽效应

一个强纯音会掩蔽在其附近同时发声的弱纯音,这种特性称为频域掩蔽,也称同时掩蔽(simultaneous masking)。如,一个声强为60dB、频率为1000Hz的纯音,另外还有一个1100Hz的纯音,前者比后者高18dB,在这种情况下我们的耳朵就只能听到那个1000Hz的强音。如果有一个1000Hz的纯音和一个声强比它低18dB的2000Hz的纯音,那么我们的耳朵将会同时听到这两个声音。要想让2000Hz的纯音也听不到,则需要把它降到比1000Hz的纯音低45dB。一般来说,弱纯音离强纯音越近就越容易被掩蔽;低频纯音可以有效地掩蔽高频纯音,但高频纯音对低频纯音的掩蔽作用则不明显。 由于声音频率与掩蔽曲线不是线性关系,为从感知上来统一度量声音频率,引入了“临界频带(criticalband)”的概念。通常认为,在20Hz到16kHz范围内有24个临界频带。

  • 时域掩蔽效应

除了同时发出的声音之间有掩蔽现象之外,在时间上相邻的声音之间也有掩蔽现象,并且称为时域掩蔽。时域掩蔽又分为超前掩蔽(pre-masking)和滞后掩蔽(post-masking),如图12-05所示。产生时域掩蔽的主要原因是人的大脑处理信息需要花费一定的时间。一般来说,超前掩蔽很短,只有大约5~20ms,而滞后掩蔽可以持续50~200ms。这个区别也是很容易理解的。

AAC 编码格式

AAC(Advanced Audio Coding),中文名:高级音频编码,出现于1997年,基于MPEG-2的音频编码技术。由Fraunhofer IIS、杜比实验室、AT&T、Sony等公司共同开发,目的是取代MP3格式。2000年,MPEG-4标准出现后,AAC重新集成了其特性,加入了SBR技术和PS技术,为了区别于传统的MPEG-2 AAC又称为MPEG-4 AAC。

AAC共有9种规格,以适应不同的场合的需要:

  • MPEG-2 AAC LC 低复杂度规格(Low Complexity)

比较简单,没有增益控制,但提高了编码效率,在中等码率的编码效率以及音质方面,都能找到平衡点

  • MPEG-2 AAC Main 主规格
  • MPEG-2 AAC SSR 可变采样率规格(Scaleable Sample Rate)
  • MPEG-4 AAC LC 低复杂度规格(Low Complexity)

现在的手机比较常见的MP4文件中 的音频部份就包括了该规格音频文件

  • MPEG-4 AAC Main 主规格

包含了除增益控制之外的全部功能,其音质最好

  • MPEG-4 AAC SSR 可变采样率规格(Scaleable Sample Rate)
  • MPEG-4 AAC LTP 长时期预测规格(Long Term Predicition)
  • MPEG-4 AAC LD 低延迟规格(Low Delay)
  • MPEG-4 AAC HE 高效率规格(High Efficiency)

这种规格适合用于低码率编码,有Nero ACC 编码器支持

AAC音频文件格式
AAC的音频文件格式有ADIFADTS

  • ADIF:Audio Data Interchange Format

音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。

  • ADTS:Audio Data Transport Stream

音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频流。

ADIF格式:

ADTS格式:
AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成。
而ADTS的 Header部分分成两部分,固定部分和可变部分

固定部分 adts_fixed_header

  • yncword :总是0xFFF, 代表一个ADTS帧的开始, 用于同步.解码器可通过0xFFF确定每个ADTS的开始位置.因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码。
  • ID:MPEG 版本: 0 代表 MPEG-4,1 代表 MPEG-2
  • Layer:总是: '00'
  • protection_absent:设置0,进行crc校验,1不进行crc校验,进行crc校验导致固定部分边长成28+16 = 44bits
  • profile:表示使用哪个级别的AAC.

如01 Low Complexity(LC) -- AAC LC。

  • sampling_frequency_index:采样率的下标

  • channel_configuration:声道数,比如2表示立体声双声道

声道数量这里用3个bits表示

可变部分adts_variable_header

  • aac_frame_length 一个ADTS帧的长度包括ADTS头和AAC原始流。就是该帧的总长度。

aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)

  • 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数据块。


参考文章

H.264码流结构 (H.264 Data Structure)
H264基本原理
AAC音频编码
《音视频开发进阶指南》读书笔记(一) —— 音视频基础概念