音视频入门
- 音视频入门
- 参考
该文记录音视频入门学习。
音视频入门
1. 学习框架
2. 基础知识篇1
2.1. 音视频播放原理
音视频播放主要分为两大类:在线播放和本地播放。在线播放即通过互联网,在线播放音视频;本地播放及播放本地存放的音视频文件。
音视频播放的原理主要分为:解协议->解封装->解码->音视频同步->播放。当然,如果是本地播放,没有解协议这一步骤。
2.2. 录播、点播、直播
- 录播:录播更侧重于“录”,比如录播系统,主要集成了音视频的采集、后期剪辑、工具软件的系统。通俗的讲录播就是生产音视频。
- 点播:点播从字面意义上讲是播放选择的视频,比如观看爱奇艺、腾讯等视频网站的电影和综艺,可以随意拖动视频进度,这些音视频共性特点是提前录制好的。通俗的讲点播就是播放录制好的视频,点播是消费音视频。
- 直播:直播相对好理解,虎牙、斗鱼等直播平台上的游戏、才艺直播,这些音视频共性特点是实时的,观看者不能拖动音视频进度。通俗的讲直播就是播放实时直播视频,直播既生产又消费音视频。
2.3. 图像篇(YUV和RGB)
音视频中编码前的图像格式,即 YUV
和 RGB
。YUV
,RGB
,包括 YcbCr
是色彩空间的模型,而平常所说的 BMP
、PNG
、JPEG
是文件的存储形式。而 YUV
是音视频(编解码)最常用的格式。
YUV
是编译 true-color
颜色空间(color space)的种类,Y'UV
, YUV
, YCbCr
, YPbPr
等专有名词都可以称为 YUV
,彼此有重叠。Y
表示明亮度(Luminance、Luma),U
和 V
则是色度、浓度(Chrominance、Chroma)。
2.3.1. YUV空间-间的数据划分
YUV
按照“空间-间”的划分方式,分为 YUV444
、YUV422
、YUV420
。
2.3.2. YUV空间-内的数据划分
半平面格式有时被归入平面系列。
- 紧缩格式(packed formats):
Y、U、V
是交错出现的。例如: $Y_{1}U_{1}Y_{2}V_{1}Y_{3}U_{2}Y_{4}V_{2}…Y_{n-1}U_{n/2}Y_{n}V_{n/2}$。 - 平面格式(planar formats, p):
Y、U、V
每个单独的。例如:$Y_{1}Y_{2}…Y_{n}U_{1}U_{2}…U_{n/2}V_{1}V_{2}…V_{n/2}$。 - 半平面格式( Semi-planar formats, sp):
Y
单独,U、V
是组合在一起的。例如:$Y_{1}Y_{2}…Y_{n}U_{1}V_{1}U_{2}V_{2}…U_{n/2}V_{n/2}$。
下图描述了以下格式2:
YV12
I420
=IYUV
=YUV420p
(有时YUV420p
可以指YV12
)NV21
NV12
=YUV420sp
(有时YUV420sp
可以指NV21
)
2.3.3. RGB
RGB
:即 red
,green
,blue
三色存储空间。
2.4. 图像篇(H.264)
2.4.1. 什么是H.264
H.264
是由 ITU-T
视频编码专家组(VCEG)和 ISO/IEC
动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。
H264编码的输入数据需要是 YUV420P。
2.4.2. H.264的数据格式
H.264
的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL,Network Abstraction Layer)。
VCL
:H264 编码/压缩的核心,主要负责将视频数据编码/压缩,再切分。NAL
:因为H264
最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是1500
字节,一个H264
的帧往往是大于1500
字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在NAL
层去处理。
2.4.3. H.264码流结构
码流名称 | 中文 | 意义 |
---|---|---|
SODB | String Of Data Bits 原始数据比特流 | 因为它是流的形式,所以长度不一定是8倍数,它是由 VLC 层产生的。由于我们计算机是以 8 倍数去处理数据所以计算机在处理 H264 时,就需要 RBSP。 |
RBSP | SODB + tailing bits (原始字节序列载荷) | 由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在 SODB 最后一位补一个 1,没有按字节对齐的则补 0。 |
EBSP | EBSP (扩展字节序列载荷) | 在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。所以在 h264 码流中规定每有两个连续的 00 00,就增加一个 0x03。 |
H.264 = start_code + NALU
(start_code:00000001 or 000001)每个
NAL
前有一个起始码0x000001
(或者0x00000001),解码器检测每个起始码,作为一个NAL
的起始标识,当检测到下一个起始码时,当前NAL
结束。同时
H.264
规定,当检测到0x000000
时,也可以表征当前NAL
的结束。那么NAL
中数据出现0x000001
或0x000000
时怎么办?H.264
引入了防止竞争机制,如果编码器检测到NAL
数据存在0x000001
或0x000000
时,编码器会在最后个字节前插入一个新的字节0x03
,这样:1 2 3 4
0x000000 --> 0x00000300 0x000001 --> 0x00000301 0x000002 --> 0x00000302 0x000003 --> 0x00000303
2.4.4. NALU
NALU = NALU header + NALU payload
,下图显示的是 NALU header
F
(forbidden_zero_bit):1 位,初始为 0。当网络识别此单元存在比特错误时,可将其设为 1,以便接收方丢掉该单元NRI
(nal_ref_idc):2 位,用来指示该NALU
的重要性等级。值越大,表示当前NALU
越重要。具体大于 0 时取何值,没有明确规定Type
(nal_unit_type):5 位,指出NALU
的类型,如下所示:
nal_unit_type | NAL 单元和 RBSP 语法结构的内容 |
---|---|
0 | 未指定 |
1 | 非 IDR 图像的编码条带 slice_layer_without_partitioning_rbsp ( ) |
2 | 编码条带数据分割块 A slice_data_partition_a_layer_rbsp ( ) |
3 | 编码条带数据分割块 B slice_data_partition_b_layer_rbsp ( ) |
4 | 编码条带数据分割块 C slice_data_partition_c_layer_rbsp ( ) |
5 | IDR 图像的编码条带 slice_layer_without_partitioning_rbsp ( ) |
6 | 辅助增强信息 (SEI) sei_rbsp ( ) |
7 | 序列参数集 seq_parameter_set_rbsp ( ) |
8 | 图像参数集 pic_parameter_set_rbsp ( ) |
9 | 访问单元分隔符 access_unit_delimiter_rbsp ( ) |
10 | 序列结尾 end_of_seq_rbsp ( ) |
11 | 流结尾 end_of_stream_rbsp ( ) |
12 | 填充数据 filler_data_rbsp ( ) |
13 | 序列参数集扩展 seq_parameter_set_extension_rbsp ( ) |
14…18 | 保留 |
19 | 未分割的辅助编码图像的编码条带 slice_layer_without_partitioning_rbsp ( ) |
20…23 | 保留 |
24…31 | 未指定 |
常见 NALU Type
1
2
3
4
5
6
7
8
9
0x06(0 00 00110) SEI type = 6
0x67(0 11 00111) SPS type = 7
0x68(0 11 01000) PPS type = 8
0x65(0 11 00101) IDR type = 5
0x61(0 11 00001) I帧 type = 1
0x41(0 10 00001) P帧 type = 1
0x01(0 00 00001) B帧 type = 1
2.4.5. I帧、P帧和B帧
帧的分类 | 中文 | 意义 |
---|---|---|
I帧(Intra-coded picture) | 帧内编码图像帧 | I 帧通常是每个 GOP(MPEG 所使⽤的⼀种视频压缩技术)的第⼀个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I 帧可以看成是⼀个图像经过压缩后的产物。⾃身可以通过视频解压算法解压成⼀张单独的完整的图⽚。 |
P帧(Predictive-coded picture) | 前向预测编码图像帧 | 通过充分将低于图像序列中前⾯已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧。需要参考其前⾯的⼀个 I frame 或者 P frame 来⽣成⼀张完整的图⽚。 |
B帧(Bidirectionally predicted picture) | 双向预测编码图像帧 | 既考虑与源图像序列前⾯已编码帧,也顾及源图像序列后⾯已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧。则要参考其前⼀个 I 或者 P 帧及其后⾯的⼀个 P 帧来⽣成⼀张完整的图片。 |
IDR帧(Instantaneous Decoding Refresh) | 即时解码刷新 | 首个I帧,是立刻刷新,使错误不致传播,IDR导致DPB(DecodedPictureBuffer参考帧列表——这是关键所在)清空;在IDR帧之后的所有帧都不能引用任何IDR帧之前的帧的内容;IDR具有随机访问的能力,播放器可以从一个IDR帧播放。 |
GOP(Group Of Picture) | 图像序列 | 两个I帧之间是一个图像序列,一个GOP包含一个I帧 |
2.4.6. 解码时间戳和显示时间戳
H.264
中还有两个重要的概念:DTS
和 PTS
。
- DTS(Decoding Time Stamp,解码时间戳解):读入内存中的比特流在什么时候开始送入解码器中进行解码
- PTS(Presentation Time Stamp,显示时间戳):解码后的视频帧什么时候被显示出来
2.4.7. H.264码流分层结构3
宏块分类 | 意义 |
---|---|
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(残差数据) | 预测后对应于残差图象取样的编码变换系数 |
H.264
编码后视频的每一组图像(GOP,图像组)都给予了传输中的序列(PPS)和本身这个帧的图像参数(SPS),所以,我们的整体结构,应该如此:
2.5. 音频篇(PCM)
2.5.1. 什么是PCM
PCM
(Pulse Code Modulation,脉冲编码调制)音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准数字音频数据。
2.5.2. 如何理解PCM
PCM
是一种用数字表示采样模拟信号方法。主要包括采样,量化,编码三个主要过程。
- 采样:模拟信号转数字信号。模拟信号转换至
4-bit PCM
的取样和量化。
采样率:每秒钟采样的样本数。比如我们常说的
44.1kHz
,即每秒钟采样44100
次。量化:将采样信号数据四舍五入到一个可用整数表示的过程。(位深)4
位深度 | 信噪比 | 整数取值总数(单个采样点) | 有符十进制取值范围(单个采样点) |
---|---|---|---|
4 | 24.08 dB | 16 | −8至+7 |
8 | 48.16 dB | 256 | −128至+127 |
11 | 66.22 dB | 2,048 | −1,024至+1,023 |
12 | 72.24 dB | 4,096 | −2,048至+2,047 |
16 | 96.33 dB | 65,536 | −32,768至+32,767 |
18 | 108.37 dB | 262,144 | −131,072至+131,071 |
20 | 120.41 dB | 1,048,576 | −524,288至+524,287 |
24 | 144.49 dB | 16,777,216 | −8,388,608至+8,388,607 |
32 | 192.66 dB | 4,294,967,296 | −2,147,483,648至+2,147,483,647 |
48 | 288.99 dB | 281,474,976,710,656 | −140,737,488,355,328至+140,737,488,355,327 |
64 | 385.32 dB | 18,446,744,073,709,551,616 | −9,223,372,036,854,775,808至+9,223,372,036,854,775,807 |
- 编码:将量化后的信号转换成二进制数据。
2.5.3. 描述PCM数据的6个参数
参数 | 中文 | 举例 |
---|---|---|
Sample Rate | 采样频率 | 8kHz(电话)、44.1kHz(CD)、48kHz(DVD)。 |
Sample Size | 量化位数 | 常见值为8-bit、16-bit |
Number of Channels | 通道个数 | 常见的音频有立体声(stereo)和单声道(mono)两种类型,立体声包含左声道和右声道。另外还有环绕立体声等其它不太常用的类型。 |
Sign | 表示样本数据是否是有符号位 | 比如用一字节表示的样本数据,有符号的话表示范围为-128 ~ 127,无符号是0 ~ 255。 |
Byte Ordering | 字节序 | 字节序是little-endian还是big-endian。通常均为little-endian |
Integer Or Floating Point | 整形或浮点型 | 大多数格式的PCM样本数据使用整形表示,而在一些对精度要求高的应用方面,使用浮点类型表示PCM样本数据。 |
2.6. 音频篇(AAC)
2.6.1. 什么是AAC
AAC
(Advanced Audio Coding,高级音频编码)是一种声音数据的文件压缩格式。AAC
分为 ADIF
和 ADTS
两种文件格式。
2.6.2. 什么是ADIF和ADTS
ADIF
:Audio Data Interchange Format
音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。ADTS
:Audio Data Transport Stream
音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。
2.6.3. ADTS的数据结构
ADTS
帧首部结构5
字母 | 长度(位) | 描述 |
---|---|---|
A | 12 | 同步字(所有位必须设置为1) |
B | 1 | MPEG版本,设置为0表示MPEG-4,设置为1表示MPEG-2 |
C | 2 | Layer,始终设置为0 |
D | 1 | CRC校验位,如果没有CRC,则设置为1,如果有CRC,则设置为0 |
E | 2 | Profile,MPEG-4音频对象类型减去1 |
F | 4 | MPEG-4采样频率索引(禁止使用15) |
G | 1 | 私有位,MPEG保证不使用,编码时设置为0,解码时忽略 |
H | 3 | MPEG-4声道配置(如果为0,则通过内部的PCE(程序配置元素)发送声道配置) |
I | 1 | 原始性,设置为1表示音频为原始内容,设置为0表示非原始内容 |
J | 1 | 家庭使用,设置为1表示音频为家庭使用,设置为0表示非家庭使用 |
K | 1 | 版权标识位,用于传输中心注册的版权标识符的下一位,以LSB优先顺序滑动位字符串,将当前位值放在该字段中,如果到达末尾,则回到开头(循环缓冲区) |
L | 1 | 版权标识起始位,设置为1表示该帧的版权标识位为第一个,否则设置为0 |
M | 13 | 帧长度,包括ADTS头部和CRC校验的长度 |
O | 11 | 缓冲区满度,表示每帧的位保留池状态 |
P | 2 | AAC帧数减1(RDBs(原始数据块)在ADTS帧中),为确保最大兼容性,请始终每个ADTS帧使用一个AAC帧 |
Q | 16 | CRC校验(根据ISO/IEC 11172-3,条款2.4.3.1),如果Protection absent为0,则存在CRC校验位 |
2.7. 字幕篇(SSA&&ASS)
2.7.1. 什么是SSA
SSA
(SubStation Alpha),是由CS Low
(亦称Kotus)创建,比传统字幕格式(如SRT)功能更加先进的字幕文件格式。- 该格式字幕的外挂文件以
*.ssa
作为后缀。
2.7.2. 什么是ASS
ASS
(Advanced SubStation Alpha),是一种比SSA
更为高级的字幕格式, 其实质版本是SSA v4.00+
,它是基于SSA 4.00+
编码构建的。ASS
的主要变化就是在SSA
编写风格的基础上增添更多的特效和指令。- 该格式字幕的外挂文件以
*.ass
作为后缀。
2.7.3. SSA&ASS的基本结构
SSA/ASS
字幕是一种类 ini
风格纯文本文件;包含五个 section:[Script Info]、[v4+ Styles]、[Events]、[Fonts]、[Graphics]。
- [Script Info]:包含了脚本的头部和总体信息。[Script Info] 必须是 v4 版本脚本的第一行。
- [v4 Styles]:包含了所有样式的定义。每一个被脚本使用的样式都应该在这里定义。ASS 使用 [v4+ Styles]。
- [Events]:包含了所有脚本的事件,有字幕、注释、图片、声音、影像和命令。基本上,所有在屏幕上看到的内容都在这一部分。
- [Fonts]:包含了脚本中内嵌字体的信息。
- [Graphics]:包含了脚本中内嵌图片的信息。
2.7.4. SSA字幕示例6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[Script Info]
; This is a Sub Station Alpha v4 script.
; For Sub Station Alpha info and downloads,
; go to http://www.eswat.demon.co.uk/
; or email kotus@eswat.demon.co.uk
Title: Spirited Away
Original Script: Ian Roberts
Original Translation: Eisuke Ishibashi
ScriptType: v4.00
Collisions: Normal
PlayResY: 480
PlayDepth: 0
Wav: 0, 28688,H:\3.wav
LastWav: 1
Timer: 100.0000
[V4 Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
Style: ICredit,Gill Sans Condensed,36,16777215,65535,65535,-2147483640,-1,0,1,3,0,2,70,70,40,0,0
Style: IDefault,Gill Sans Condensed,30,65535,65535,65535,-2147483640,-1,0,1,3,0,2,70,70,40,0,0
Style: IScreenText,Gill Sans Condensed,30,16744576,65535,65535,-2147483640,-1,0,1,3,5,2,70,70,40,0,0
[Events]
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: Marked=0,0:00:06.60,0:00:08.90,IScreenText,,0000,0000,0000,,{\a10}See you again... Best wishes
Dialogue: Marked=0,0:00:11.84,0:00:14.74,ICredit,,0000,0000,0100,,{\a2}Story, Script & Direction - MIYAZAKI Hayao
3. 视频
将图像、音频、字幕封装在一起,就形成了我们常见的视频。
3.1. 视频封装格式篇(FLV)
3.1.1. FLV的封装格式
FLV
(Flash Video),Adobe公司设计开发的一种流行的流媒体格式,由于其视频文件体积轻巧、封装简单等特点,使其很适合在互联网上进行应用。除了播放视频,在直播时也可以使用。采用FLV格式封装的文件后缀为 .flv
,格式如下(FLV = FLV Header + Body):
在实际讲解 FLV
协议前,首先对单位进行约定:
类型 | 定义 |
---|---|
0x | 16进制数据 |
SI8 | 有符号8位整数 |
SI16 | 有符号16位整数 |
SI24 | 有符号24位整数 |
SI32 | 有符号32位整数 |
STRING | Unicode 8位字符序列(UTF-8) ,以0x00结束(除非另有说明) |
UI8 | 无符号8位整数 |
UI16 | 无符号16位整数 |
UI24 | 无符号24位整数 |
UI32 | 无符号32位整数 |
xxx [ ] | 类型为xxx的数组 |
xxx [n] | 类型为xxx的数组,数组长度为n |
3.1.2. FLV Header7
FLV header
由如下字段组成,其中:
- 前三个字节内容固定是FLV
- 最后4个字节内容固定是9(对FLV版本1来说)
字段 | 字段类型 | 字段含义 |
---|---|---|
Signature | UI8 | 签名,固定为’F’ (0x46) |
Signature | UI8 | 签名,固定为’L’ (0x4c) |
Signature | UI8 | 签名,固定为’V’ (0x56) |
Version | UI8 | 版本,比如 0x01 表示 FLV 版本 1 |
TypeFlagsReserved | UB[5] | 保留字段,全为0 |
TypeFlagsAudio | UB[1] | 1表示有音频标志,0表示没有 |
TypeFlagsReserved | UB[1] | 保留字段,全为0 |
TypeFlagsVideo | UB[1] | 1表示有视频标志,0表示没有 |
DataOffset | UI32 | 版本为 0x01 时,一般是9,大于9表示下面还有扩展信息 |
3.1.3. FLV Body
Body
是由一个个 Tag
组成的,每个 Tag
下面有一块4个字节的空间,用来记录这个 Tag
的长度。这个后置的 PreviousTagSize
用于逆向读取处理,表示的是前面的 Tag
的大小。
3.1.4. FLV Tag
FLV tag
由 tag header + tag body
组成。
3.1.4.1. Tag Header
tag header
如下,总共占据11个字节:
字段 | 字段类型 | 字段含义 |
---|---|---|
Reserved | UB[2] | 为 FMS 保留,应该为0 |
Filter | UB[1] | 通常为0 |
TagType | UB[5] | tag类型:0x08表示audio;0x09表示video;0x12表示script data |
DataSize | UI24 | tag body的大小 |
Timestamp | UI24 | 相对于第一个tag的时间戳(单位是毫秒) 第一个tag的Timestamp为0 |
TimestampExtended | UI8 | 时间戳的扩展字段,当 Timestamp 3个字节不够时,会启用这个字段,代表高8位 |
StreamID | UI24 | 总是0 |
Data | 取决于根据TagType | TagType=8,则为AUDIODATA;TagType=9,则为VIDEODATA;TagType=18,则为SCRIPTDATAOBJECT |
3.1.4.2. Tag Data
Tag Data
分成 Audio
,Video
,Script
三种。
3.1.4.2.1. Audio Tag Data
字段 | 字段类型 | 字段含义 |
---|---|---|
SoundFormat | UB[4] | 音频格式,重点关注10=AAC 0 = Linear PCM, platform endian 1 = ADPCM 2 = MP3 3 = Linear PCM, little endian 4 = Nellymoser 16-kHz mono 5 = Nellymoser 8-kHz mono 6 = Nellymoser 7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved 10 = AAC 11 = Speex 14 = MP3 8-Khz 15 = Device-specific sound |
SoundRate | UB[2] | 采样率,对AAC来说,永远等于3 0 = 5.5-kHz 1 = 11-kHz 2 = 22-kHz 3 = 44-kHz |
SoundSize | UB[1] | 采样精度,对于压缩过的音频,永远是16位 0 = snd8Bit 1 = snd16Bit |
SoundType | UB[1] | 声道类型,对Nellymoser来说,永远是单声道;对AAC来说,永远是双声道; 0 = sndMono 单声道 1 = sndStereo 双声道 |
AACPacketType | UI8 | SoundFormat等于10才存在,0表示AAC序列头,1表示AAC裸数据 |
SoundData | UI8[size of sound data] | 如果是AAC,则为 AACAUDIODATA; 其他请参考规范; |
3.1.4.2.2. Video Tag Data
字段 | 字段类型 | 字段含义 |
---|---|---|
FrameType | UB[4] | 重点关注1、2: 1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧; 2: inter frame (for AVC, a non- seekable frame) —— H.264的普通I帧; 3: disposable inter frame (H.263 only) 4: generated keyframe (reserved for server use only) 5: video info/command frame |
CodecID | UB[4] | 编解码器,主要关注 7(AVC) 1: JPEG (currently unused) 2: Sorenson H.263 3: Screen video 4: On2 VP6 5: On2 VP6 with alpha channel 6: Screen video version 2 7: AVC |
VideoData | 取决于CodecID | 实际的媒体类型,主要关注 7:AVCVIDEOPACKE 2: H263VIDEOPACKET 3: SCREENVIDEOPACKET 4: VP6FLVVIDEOPACKET 5: VP6FLVALPHAVIDEOPACKET 6: SCREENV2VIDEOPACKET 7: AVCVIDEOPACKE |
3.1.4.2.3. Script Tag Data
字段 | 字段类型 | 字段含义 |
---|---|---|
Type | UI8 | 变量类型: 0 = Number type 1 = Boolean type 2 = String type 3 = Object type 4 = MovieClip type 5 = Null type 6 = Undefined type 7 = Reference type 8 = ECMA array type 10 = Strict array type 11 = Date type 12 = Long string type |
ECMAArrayLength | 如果Type为8(数组),则为UI32 | 数组长度 |
ScriptDataValue | 根据Type的值来决定 If Type == 0 DOUBLE If Type == 1 UI8 If Type == 2 SCRIPTDATASTRING | 变量的值 |
ScriptDataValueTerminator | Type==3,则为SCRIPTDATAOBJECTEND Type==8,则为SCRIPTDATAVARIABLEEND | Object、Array的结束符 |
3.2. 视频封装格式篇(TS)
3.2.1. 什么是TS8
TS
(Transport Stream,传输流),一种常见的视频封装格式,是基于 MPEG-2
的封装格式(所以也叫MPEG-TS),后缀为 .ts
。
3.2.2. TS的分层结构
TS
文件分为三层,如下所示(可以倒序看更好理解):
TS
(Transport Stream):在PES层基础上加入了数据流识别信息和传输信息。PES
(Packet Elemental Stream):在ES层基础上加入时间戳(PTS/DTS)等信息。ES
(Elementary Stream):压缩编码后的音视频数据。
3.2.3. TS层
- ts包大小固定为188字节,ts层分为三个部分:
ts header
、adaptation field
、payload
。 ts header
固定4个字节;adaptation field
可能存在也可能不存在,主要作用是给不足 188 字节的数据做填充。payload
是 PES 数据,或者PAT
,PMT
等。ts Header + adaptation field
格式如下:
3.2.3.1. TS Header
字段 | 字段类型 | 字段含义 |
---|---|---|
sync_byte | UB[8] | 同步字节,为固定的 8 比特字段,其值为 0100 0111 (0x47) 。 |
transport_error_indicator | UB[1] | 传输错误指示位,1 比特,发送时(调制前)值为 0。接收方的解调器在无法成功解调(即使有前向纠错机制)TS 分组内容时,将该位设置为 1,表示该 TS 分组损坏。 |
payload_unit_start_indicator | UB[1] | 载荷单元开始指示位,1 比特,负载单元起始标示符,一个完整的数据包开始时标记为 1, 表示携带的是 PES 或 PSI 第一个包。PSI(Program Specific Information)由对于传输流的多路分解以及节目成功再现所必要的标准数据组成。 |
transport_priority | UB[1] | 传输优先级,1 比特,值为 1 时,在相同 PID 的分组中具有更高的优先权。传输机制可以使用该字段优先考虑基本流内的该包数据。 |
PID | UB[13] | 用于识别 TS 分组的 ID,13 比特。一个 PID 对应一个特定的 PES。 |
transport_scrambling_control | UB[2] | 传输加扰控制,2 比特。值为 00 时表示载荷未加扰。其余值由具体系统定义。 |
adaptation_field_control | UB[2] | 适配域存在标志,2 比特。值的含义如下:00 ,供未来使用,由 ISO/IEC 所保留。解码器应丢弃设置为 00 值的传输流包。 01 ,无 adaptation_field,仅有效载荷。在空包的情况中,值应为 01 。 10 ,仅有 Adaptation_field,无有效载荷。 11 ,Adaptation Field 后跟着有效载荷。 |
continuity_counter | UB[4] | 连续性计数器,4 比特。取值为 0x00 到 0x0F ,循环使用。用于检查同一个 PID 的 TS 分组的连续性。每当一个 TS 分组中包含载荷时,该计数器加 1。 |
- pid 决定了负载内容的类型,主要包括:PAT表,PMT表,视频流,音频流。常用的PID值:
表 | PAT | CAT | TSDT | EIT,ST | RST,ST | TDT,TOT,ST |
---|---|---|---|---|---|---|
PID | 0x0000 | 0x0001 | 0x0002 | 0x0012 | 0x0013 | 0x0014 |
3.2.3.2. Adaptation Field
适配域(Adaptation Field)中的数据主要用于携带一些额外信息以及做数据填充以确保 TS
的一个包大小固定在 188
字节。
当 TS Header
中的 adaptation_field_control
字段值为 10
或 11
时,这就表明存在适配域(Adaptation Field)部分。
3.2.3.3. PAT表结构(指明PMT表的PID值)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct TS_PAT{
unsigned table_id :8 //固定位0x00,表示该表是PAT
unsigned section_syntax_indicator :1 //段语法标志,固定为1
unsigned zero :1 //固定为0
unsigned reserved_1 :2 //第一个保留位
unsigned section_length :12 //表示这个字节之后有用的字节数,包括CRC_32
unsigned transport_stream_id :16 //传输流的ID,区别于一个网络中其他多路复用的流
unsigned reserved_2 :2 //第二个保留位
unsigned version_number :5 //表示PAT的版本号
unsigned current_next_indicator :1 //表示发送的PAT是当前有效还是下一个有效,为1时代表当前有效
unsigned section_number :8 //如果PAT分段传输,那么此值每次递增1
unsigned last_section_number :8 //最后一个分段的号码
for(int i=0;i<N;i++){
unsigned Program_number :16 //节目号
unsigned Reversed_3 :3 //保留位
if(Program_number == 0)
Network_id :13 //网络信息表(NIT)的PID
else
Program_MAP_PID :13 //节目映射表的PID,每个节目都有一个
}
unsigned CRC_32 :32 //CRC32校检码
}TS_PAT
3.2.3.4. PMT表(指明音视频流的PID值)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
typedef struct TS_program_map_section{
unsigned Table_id :8 //标志PSI分段的内容,对于PMT,此值为0x02
unsigned Section_syntax_indicator :1 //置为1
unsigned '0' :1
unsigned Reserved :2 //保留位
unsigned Section_length :12 //指明了自此到最后CRC_32的字节数
unsigned Program_number :16 //指出该节目的节目号,与PAT表对应
unsigned Reserved :2 //保留位
unsigned Version_number :5 //取值0-31,代表当前PMT的版本号
unsigned Current_next_indicator :1 //代表当前PMT是否有效
unsigned Section_number :8 //给出了当前所处段的数目
unsigned Last_section_number :8 //给出了最后一个分段,即分段的最大数目
unsigned Reserved :3 //保留位
unsigned PCR_PID :13 //指示TS包的PCR值,该TS包含有PCR字段
unsigned Reserved :4 //保留位
unsigned Program_info_length :12 //该字段描述跟随其后对节目信息描述的字节数
for(int i = 0; i < N; i++)
Descriptr()
for(int i = 0; i < N; i++){
unsigned Stream_type :8 //0x00:保留, 0x01:MPEG1视频,0x02:MPEG2视频,0x03:MPEG1音频,0x04:MPEG2音频,0x05:私有字段,0x06:含有私有数据的PES包 ......
unsigned Reserved :3 //保留
unsigned Elementary_PID :13 //指示TS包的PID,这些TS包含有相同的PID
unsigned Reserved :4 //保留
unsigned ES_info_length :12 //指示跟随其后描述相关节目元素的字节数
for(int j = 0; j < N2; j++)
Descriptr()
}
unsigned CRC_32 :32 //循环校检位
}
3.2.4. PES层
PES
(Packetized Elementary Stream,打包的ES),在 ES
层的基础上加入了时间戳(PTS/TDS)等信息。
ES
数据包比较大,加入PES头时需将ES进行分割,只在第一个分割的ES上加PES头,PES packet length
:指示PES
包中跟随该字段最后字节的字节数。0 值指示PES 包长度既未指示也未限定并且仅在这样的PES 包中才被允许,该PES
包的有效载荷由来自传输流包中所包含的视频基本流的字节组成。
3.2.5. ES层
ES
(Elementary Stream,基本码流),就是音视频编码数据流,比如视频H.264
,音频AAC
。- 一个
ES
流中只包含一种类型的数据(视频,或音频,或字幕)。
3.2.6. 总结
3.2.6.1. TS 流生成流程
- 将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。
- 对ES(基本码流)进行打包形成PES。
- 在PES包中加入时间戳信息(PTS/DTS)。
- 将PES包内容分配到一系列固定长度的传输包(TS Packet)中。
- 在传输包中加入定时信息(PCR)。
- 在传输包中加入节目专用信息(PSI) 。
- 连续输出传输包形成具有恒定比特率的MPEG-TS流。
3.2.6.2. TS 流解析流程
- 复用的MPEG-TS流中解析出TS包;
- 从TS包中获取PAT及对应的PMT;
- 从而获取特定节目的音视频PID;
- 通过PID筛选出特定音视频相关的TS包,并解析出PES;
- 从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
- 将ES交给解码器,获得压缩前的原始音视频数据。
3.3. 视频封装格式篇(MP4)
3.3.1. MP4(MPEG-4)
MP4
是一套用于音频、视频信息的压缩编码标准,由国际标准化组织(ISO)和国际电工委员会(IEC)下属的“动态图像专家组”(Moving Picture Experts Group,即MPEG)制定,第一版在1998年10月通过,第二版在1999年12月通过。MPEG-4格式的主要用途在于网上流、光盘、语音发送(视频电话),以及电视广播。MP4
由许多box组成,每个box包含不同的信息,这些box以树形结构的方式组成,box 当中可以包含 box。
3.3.2. box
mp4
文件由若干个 box
组成。下面是 box
结构的一个示意图:
box
由 header 和 body 组成,header 指明 box 的 size 和 type。size 是包含 box header 的整个 box 的大小。box type
,通常是4个ASCII码的字符如“ftyp”、“moov”等,这些 box type都是已经预定义好的,表示固定的含义。如果是“uuid”,表示该box为用户自定义扩展类型,如果 box type 是未定义的,应该将其忽略。- 如果 header 中的 size 为1,则表示 box 长度需要更多的bits位来描述,在后面会有一个 8自己 位的 largesize 用来描述 box 的长度。如果 size 为0,表示该 box 为文件的最后一个box,文件结尾(同样只存在于“mdat”类型的box中)。
box
分为两种,Box
和Fullbox
。FullBox 是 Box 的扩展,Header 中增加了version
和flags
字段。