【FFmpeg】FLV 格式分析 ③ ( Tag Body 数据块体结构 - Vedio Data 视频数据 )
文章目录
- 一、Tag Body 数据块体结构 - Video Data 视频数据
- 1、Vedio Data 视频数据 类型标识
- 2、Vedio Data 视频数据 结构分析
- 3、Composition Time Offset 字段涉及的时间计算
- 4、AVC Packet Type 字段说明
- ① AVC Sequence Header 类型
- ② AVC NALU 类型
- ③ AVC End of Sequence 类型
- 5、AVC 数据类型 说明
- 6、AVC 格式视频 Tag 解析流程
- 二、AVC Sequence Header 类型 的 结构分析
- 1、AVC Sequence Header 类型结构
- 2、H.264 的主要 Profile
- 3、H.264 的 Level
- 4、AVC Sequence Header 类型数据 案例
- 三、AVC NALU 类型 的 结构分析
- 1、AVC NALU 类型结构
- ① NALU Length 字段解析
- ② NALU Header 字段解析
- ③ NALU Payload 字段解析
- 2、AVC NALU 类型 数据案例
- 四、AVC End of Sequence 类型 的 结构分析
- 1、AVC End of Sequence 类型结构
- 2、AVC End of Sequence 类型数据值
FLV 文件 的总体结构 由 File Header 文件头、File Body 文件体 组成 ;
- File Header 文件头 固定为 9 字节 ,
- File Body 文件体 由 若干 " Previous Tag Size 前一个标签大小 + Tag 数据块 " 组成 ;
- Tag 数据块 由 Tag Header 数据块头、Tag Body 数据块体 组成 ;
- Tag Header 数据块头 由 固定 11 字节组成 ;
- Tag Body 需要根据 三种不同的 Tag 类型 各自有不同的结构 , 如 :
- 音频数据 Audio Data、
- 视频数据 Video Data、
- 元数据 Script Data ;
在博客 【FFmpeg】FLV 格式分析 ① ( File Header 文件头 | File Body 文件体 | Tag Header 数据块头结构 | Script Data 元数据结构 ) 中 , 讲解了 Script Data 元数据 的 Tag Body 结构 ;
在博客 【FFmpeg】FLV 格式分析 ② ( Tag Body 数据块体结构 - Audio Data 音频数据 | AAC 序列头 AudioSpecificConfig 结构分析 ) 中 介绍了 音频数据 Audio Data 的 Tag Body 结构 ;
在本篇博客 中开始 介绍 <视频数据 Video Data 的 Tag Body 结构 ;
一、Tag Body 数据块体结构 - Video Data 视频数据
1、Vedio Data 视频数据 类型标识
在 Tag Header 数据块头 中 , Tag Type 字段值为 0x09 , 说明该 Tag 数据块 是 视频数据 ;
之后的 Tag Body 数据块体 就是 视频数据 Video Data 的格式 , 其数据的 字节结构 与 音频数据 Audio Data 和 元数据 Script Data 完全不同 , 下面开始讲解 Video Data 视频数据 的 结构 ;
2、Vedio Data 视频数据 结构分析
Tag Body 数据块体 的 Vedio Data 视频数据 类型 , 包含两个部分 :
-
第一字节 : 视频参数信息 , Frame Type 和 Codec ID (1 字节)
- Frame Type (高 4 位): 表示帧类型。
- 1: Keyframe(关键帧)
- 2: Interframe(非关键帧)
- 3: Disposable interframe(仅限 H.263 格式的非关键帧)
- 4: Generated keyframe(保留)
- 5: Video info/command frame(视频信息或命令帧)
- Codec ID (低 4 位): 表示视频编码格式。
- 1: JPEG(仅限序列图像)
- 2: Sorenson H.263
- 3: Screen video
- 4: On2 VP6
- 5: On2 VP6 with alpha channel
- 6: Screen video version 2
- 7: AVC(H.264)
- Frame Type (高 4 位): 表示帧类型。
-
第二字节 :
- AVC 格式 : 如果是 AVC 格式 , 则 第 2 字节是 AVC Packet Type 字段 , 第 3 ~ 5 字节是 Composition Time Offset 字段 , 从第 6 字节开始就是真实的视频数据 ;
- 非 AVC 格式 : 如果不是 AVC 格式 , 则 从第 2 字节开始都是 真实视频数据 ;
字段名称 | 长度 | 描述 |
---|---|---|
Frame Type 和 Codec ID | 1 字节 | 高 4 位表示帧类型,低 4 位表示编码格式。 |
- Frame Type | 第 1 字节 高 4 位 | 帧类型: 1 - Keyframe(关键帧) 2 - Interframe(非关键帧) 3 - Disposable interframe(H.263 特有) 5 - Video info/command frame (视频信息或命令帧) |
- Codec ID | 第 1 字节 低 4 位 | 编码格式: 1 - JPEG 2 - Sorenson H.263 3 - Screen video 4 - On2 VP6 5 - On2 VP6 with alpha 6 - Screen video v2 7 - AVC |
AVC Packet Type | 1 字节 | 仅适用于 AVC 格式: 0 - AVC sequence header 1 - AVC NALU 2 - AVC end of sequence |
Composition Time Offset | 3 字节 | 仅适用于 AVC 格式: 表示 显示时间戳 (PTS) 与 解码时间戳 (DTS) 的偏移量,单位 毫秒 ms。 |
Video Data | 可变长度 | 实际的视频数据内容,格式 和 长度取决于 Codec ID。 |
之前的博客
- 【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | 文件头 Header 分析 | 标签 Tag 分析 | 视频标签 Tag 数据分析 )
- 【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | AVC 序列头格式解析 )
对 FLV 视频格式进行了简单分析 , 可参考上述两篇博客进行理解 ;
3、Composition Time Offset 字段涉及的时间计算
在 【FFmpeg】FLV 格式分析 ① ( File Header 文件头 | File Body 文件体 | Tag Header 数据块头结构 | Script Data 元数据结构 ) – 解码时间 DTS 与 显示时间 PTS 博客章节 中 , 介绍了
在 FLV 的 Tag 数据块的 Tag Header 中 , 存在 如下两个字段 ;
- Timestamp 字段 : 数据块的 解码时间 dts 的 低 24 位 ;
- Timestamp Extended 字段 : 数据块的 解码时间 dts 的 高 8 位 ;
上述计算出来的时间是 DTS 解码时间 , 单位是 毫秒 ;
在上述 Tag Body 的 视频数据 Vedio Data 中的 Composition Time Offset 字段 , 就是 显示时间戳 PTS 与 解码时间戳 DTS 的偏移量 , 单位为 毫秒 ms ;
PTS 计算公式如下 :
PTS = DTS + CompositionTime
4、AVC Packet Type 字段说明
AVC 格式 全称 " Advanced Video Coding " , 高级视频编码 , 又称为 " H.264 " 或 " MPEG-4 AVC " 格式 ;
Vedio Data 视频数据 中 , 如果 第一字节的后 4 位表示的 Codec ID ( 编码格式 ) 字段 值为 7 , 说明这是 AVC 格式 ;
AVC 格式的视频数据 , 分为三种类型 , 具体类型由 AVC Packet Type 字段 设置 ;
AVC Packet Type 字段的取值及其含义如下 :
值 | 类型 | 描述 |
---|---|---|
0 | AVC Sequence Header | 包含 解码器 初始化信息 AVCDecoderConfigurationRecord , 如 : SPS 序列参数集 和 PPS 图像参数集 |
1 | AVC NALU | 存储实际的视频帧数据,基于 H.264 的 NALU(网络抽象层单元)。 |
2 | AVC End Of Sequence | 表示视频流的结束标志(可选,通常用于流式传输场景)。 |
① AVC Sequence Header 类型
包含 AVCDecoderConfigurationRecord 数据 , 通常在视频流的起始位置出现 ;
该类型数据 提供 解码器初始化所需的元信息 , 如 : SPS(序列参数集)和 PPS(图像参数集) ;
解码器 只有 解析该数据 后 , 才能 正确解码后续的 NALU 数据 ;
② AVC NALU 类型
AVC NALU 类型 数据 就是 实际的视频帧数据 , 以 NALU(Network Abstraction Layer Unit)为单位 ;
NALU 是 H.264 数据的核心单元 , 可以是 I 帧、P 帧、B 帧 或 其他类型的编码数据 ;
NALU 数据 的 解析和解码是 H.264 视频播放的核心过程 ;
③ AVC End of Sequence 类型
表示 视频流的结束标志 , 该类型的数据是可选的 , 主要用于明确视频流的终止位置 ;
该类型的数据 在实际的流媒体场景中较少使用 , 但可能出现在 文件流结束 场景中 ;
5、AVC 数据类型 说明
FLV 文件中的 Tag Body 数据块体 中的 Video Data 在使用 AVC 格式(H.264)时 , 视频数据(Video Data) 部分只能是以下三种之一 :
- AVC Sequence Header 用于初始化 H.264 解码器 , 包含 AVCDecoderConfigurationRecord 数据 , 如 : SPS 和 PPS 等信息 ;
- AVC NALU 包含实际的视频帧数据 , 包括 I 帧、P 帧、B 帧等类型的编码数据 ;
- AVC End of Sequence 表示视频流的结束标志 ;
这三种类型由 AVC Packet Type 字段 明确标识 :
- 0 表示 AVC Sequence Header 类型 ;
- 1 表示 AVC NALU 类型 ;
- 2 表示 AVC End of Sequence 类型 ;
每个 FLV 视频 中的 AVC 视频格式 的 Tag 数据块体 的 Video Data 中只能包含 一种类型 , 不可能同时包含 AVC Sequence Header 和 AVC NALU 两种数据 , 解码器根据 AVC Packet Type 来判断如何处理数据 ;
6、AVC 格式视频 Tag 解析流程
AVC 格式视频 Tag 解析流程 :
- 视频开始时 : 首先解析 AVC Sequence Header , 用于初始化解码器 , 如果没有解析该数据 , 则后面的 NALU 数据无法正确解码 ;
- 播放过程中 : 不断接收 AVC NALU 数据 , 解码并显示视频帧 ;
- 视频结束时 ( 可选 ) : 接收到 AVC End of Sequence 类型数据 , 标志视频流结束 ;
二、AVC Sequence Header 类型 的 结构分析
1、AVC Sequence Header 类型结构
在 FLV 视频标签 Video Tag 中 , 如果 AVC Packet Type 的值为 0 , 表示这是 AVC Sequence Header 类型数据 , 该数据结构包含 AVCDecoderConfigurationRecord , 用于初始化解码器并提供必要的解码参数 ;
AVC Sequence Header 类型数据 用于初始化 H.264 解码器 , 使其可以正确解码后续的 AVC NALU 数据 , 其中 SPS 和 PPS 数据是解码 H.264 视频的关键部分 ;
以下是 AVC Sequence Header 的具体结构 :
字段名称 | 长度 | 描述 |
---|---|---|
configurationVersion | 1 字节 | 配置版本号,固定为 1 。 |
AVCProfileIndication | 1 字节 | H.264 的 Profile , 例如: - 66: Baseline Profile - 77: Main Profile - 100: High Profile。 |
profileCompatibility | 1 字节 | 与 Profile 的兼容性相关,通常与 SPS 中的 constraint_set_flags 一致。 |
AVCLevelIndication | 1 字节 | H.264 的 Level ,例如: - 30: Level 3.0 - 31: Level 3.1 - 40: Level 4.0。 |
lengthSizeMinusOne | 1 字节 | 表示 NALU 长度字段的字节数减 1: - 值为 0:NALU 长度字段为 1 字节 - 值为 3:NALU 长度字段为 4 字节(常见)。 |
numOfSequenceParameterSets | 1 字节 | SPS(序列参数集)的数量,通常为 1 。 |
sequenceParameterSetLength | 2 字节 | SPS 数据的长度(以字节为单位)。 |
sequenceParameterSetNALUnit | 可变长度 | 实际的 SPS 数据内容。 |
numOfPictureParameterSets | 1 字节 | PPS(图片参数集)的数量,通常为 1 。 |
pictureParameterSetLength | 2 字节 | PPS 数据的长度(以字节为单位)。 |
pictureParameterSetNALUnit | 可变长度 | 实际的 PPS 数据内容。 |
2、H.264 的主要 Profile
H.264 的 Profile 是视频编码标准中的一种配置 , 用于定义支持的功能集 , 以便在不同场景中优化编码效率和解码复杂性 ;
不同 Profile 支持的功能不同 , 针对性也不同 , 主要用来平衡视频质量、复杂性和解码器的要求 ;
Profile 名称 | 用途 | 特点 |
---|---|---|
Baseline | 视频会议、移动设备等低复杂度场景 | - 不支持 B 帧(双向预测帧)。 - 支持 I 帧、P 帧。 - 支持基本的熵编码(CAVLC)。 |
Main | 标清电视、DVD、流媒体 | - 支持 B 帧和帧间预测。 - 支持 CAVLC 和 CABAC(更高效的熵编码)。 |
High | 高清电视、蓝光光盘 | - 增加支持 8×8 的帧内预测模式。 - 支持更高的色彩精度(8x8 的变换和量化)。 |
Extended | 流媒体传输(已经很少使用) | - 支持数据丢失恢复。 - 支持 B 帧、SP 帧(切换帧)和 SI 帧(恢复帧)。 |
High 10 | 10 位深度的高质量场景 | - 支持更高的色彩深度(10 位),适用于专业视频制作。 |
High 4:2:2 | 广播电视和视频编辑场景 | - 支持 4:2:2 色彩子采样,适合广播和后期制作应用。 |
High 4:4:4 | 高质量的专业视频场景 | - 支持 4:4:4 色彩子采样,保留全色彩精度,适用于高级视频编辑和特效制作。 |
3、H.264 的 Level
在 H.264 标准 的 Level 级别 用来描述 视频的分辨率、帧率和比特率限制的一组参数 , 旨在平衡编解码复杂度和设备性能 , Profile 决定了支持的编码功能 , 而 Level 决定了这些功能的具体性能限制 ;
- 最大分辨率 : 定义视频的水平和垂直像素数上限 ;
- 最大帧率 : 限制视频每秒显示的最大帧数 ;
- 最大码率 : 定义了视频流允许的最大比特率,单位为 Mbps ;
Level | 最大分辨率 (像素) | 最大帧率 (fps) | 最大码率 (Mbps) | 用途 |
---|---|---|---|---|
1.0 | 176×144 | 15 | 0.064 | 视频会议、低分辨率移动设备。 |
1.1 | 176×144 | 30 | 0.192 | 移动设备的视频应用。 |
1.2 | 320×240 | 30 | 0.384 | 更高分辨率的移动设备应用。 |
1.3 | 352×288 | 30 | 0.768 | 低分辨率流媒体应用。 |
2.0 | 352×288 | 30 | 2.0 | 标清视频。 |
3.0 | 720×576 | 30 | 10.0 | 标清流媒体和存储视频。 |
3.1 | 1280×720 | 30 | 14.0 | 高清 (720p) 视频传输。 |
3.2 | 1280×720 | 60 | 20.0 | 高帧率 720p 视频传输。 |
4.0 | 1920×1080 | 30 | 25.0 | 高清 (1080p) 蓝光和流媒体。 |
4.1 | 1920×1080 | 60 | 50.0 | 高帧率 1080p 视频。 |
5.0 | 3840×2160 | 30 | 135.0 | 超高清视频 (4K)。 |
5.1 | 3840×2160 | 60 | 240.0 | 高帧率超高清视频 (4K)。 |
6.0 | 8192×4320 | 30 | 600.0 | 超高清视频 (8K)。 |
6.1 | 8192×4320 | 60 | 960.0 | 高帧率超高清视频 (8K)。 |
4、AVC Sequence Header 类型数据 案例
下面的十六进制数据 就是 AVC Sequence Header 类型数据 :
01 64 00 1F 03 01 00 17 67 64 00 1F AC D9 40 78 02 27 E5 C0 44 00 00 03 00 04 00 00 03 00 80 3C 60 CB 20 01 00 04 68 EE 3C B0
解析每个字段 :
- configurationVersion :
01
, 版本号 , 固定值 ; - AVCProfileIndication :
64
, 设置 H.264 Profile 级别是 High Profile ; - profileCompatibility :
00
, 设置 与 H.264 的兼容性 ; - AVCLevelIndication :
1F
, 设置 H.264 的 Level 3.1 ; - lengthSizeMinusOne :
03
, 4 字节 NALU 长度字段 ; - numOfSequenceParameterSets :
01
, SPS 数量 有 1 个 ; - sequenceParameterSetLength :
00 17
, SPS 数据的长度 是 23 字节 ; - sequenceParameterSetNALUnit :
67 64 00 1F AC D9 40 78 02 27 E5 C0 44 00 00 03 00 04 00 00 03 00 80 3C 60 CB 20
, 是 实际的 SPS 序列参数集 的 数据内容 ; - numOfPictureParameterSets :
01
, PPS 数量 是 1 个 ; - pictureParameterSetLength :
00 04
, PPS 数据的长度 4 字节 ; - pictureParameterSetNALUnit :
68 EE 3C B0
, 实际的 PPS 图片参数集 的 数据内容 ;
注释后的数据字段 :
01 # 版本号 , 固定值 1
64 # 设置 H.264 Profile 级别是 High Profile
00 # 设置 与 H.264 的兼容性
1F # 设置 H.264 的 Level 3.1
03 # 4 字节 NALU 长度字段
01 # SPS 数量 有 1 个
00 17 # SPS 数据的长度 是 23 字节
67 64 00 1F AC D9 40 78 02 27 E5 C0 44 00 00 03 00 04 00 00 03 00 80 3C 60 CB 20 # 实际的 SPS 序列参数集 的 数据内容
01 # PPS 数量 是 1 个
00 04 # PPS 数据的长度 4 字节
68 EE 3C B0 # 实际的 PPS 图片参数集 的 数据内容
三、AVC NALU 类型 的 结构分析
1、AVC NALU 类型结构
在 FLV 文件中,如果 AVC Packet Type 为 1,表示当前数据块是 AVC NALU 类型 ;
AVC NALU 包含实际的视频帧数据 , 基于 H.264 标准的 NALU(Network Abstraction Layer Unit,网络抽象层单元) ;
字段名称 | 长度 | 描述 |
---|---|---|
NALU Length | 1, 2, 或 4 字节 | 表示 NALU 数据(Header + Payload)的长度,通常为大端序 (Big-Endian) 格式。 |
NALU Header | 1 字节 | 包括以下三个部分: |
- 1 bit | forbidden_zero_bit :必须为 0,表示无语法错误。 | |
- 2 bits | nal_ref_idc :NALU 优先级,值越大优先级越高。 | |
- 5 bits | nal_unit_type :NALU 类型(例如:1 = 非 IDR 图像片段,5 = IDR 图像片段,7 = SPS,8 = PPS)。 | |
NALU Payload | 可变长度 | 实际的 NALU 数据部分,包含编码数据(如帧数据或参数集信息)。 |
① NALU Length 字段解析
NALU Length 字段 用于指示紧随其后的 NALU 数据的总长度 , 包括 NALU Header 和 NALU Payload 的长度 , 但不包括 NALU Length 字段本身的大小 ;
NALU Length 字段的长度 的 字节数 , 由 AVC Sequence Header 中的 lengthSizeMinusOne 字段 决定(1、2 或 4 字节);
- 如果 lengthSizeMinusOne = 0 , NALU Length 是 1 字节 ;
- 如果 lengthSizeMinusOne = 1 , NALU Length 是 2 字节 ;
- 如果 lengthSizeMinusOne = 3 , NALU Length 是 4 字节 , 最常见 ;
② NALU Header 字段解析
字段名称 | 长度 | 描述 |
---|---|---|
forbidden_zero_bit | 1 bit | 保留位,必须为 0 ,表示无语法错误。 |
nal_ref_idc | 2 bits | 表示该 NALU 的优先级,值越大优先级越高。 |
nal_unit_type | 5 bits | 表示 NALU 的类型(例如: - 1:非 IDR 图像的片段 - 5:IDR 图像的片段)。 |
RBSP data | 可变长度 | 实际的原始比特流数据(RBSP, Raw Byte Sequence Payload)。 |
- forbidden_zero_bit 字段 : 始终为 0 , 如果不是 0 , 说明数据有错误 ;
- nal_ref_idc 字段 : 决定了 NALU 的优先级 , 常用于帧的丢弃策略 ;
- 00 为最低优先级
- 11 为最高优先级
- nal_unit_type 字段 : 决定 NALU 的具体类型 , 如 :
- 1 : 非 IDR 图像片段(普通帧)
- 5 : IDR 图像片段(关键帧)
- 7 : 序列参数集(SPS)
- 8 : 图像参数集(PPS)
- RBSP data 字段 : 包含实际的编码数据 , 如帧的宏块信息或参数集数据 ;
③ NALU Payload 字段解析
NALU Payload 字段 包含实际的 H.264 编码数据 , 如 : 帧的宏块信息、编码后的视频数据、SPS / PPS 参数 ;
根据 nal_unit_type 的不同 , 数据的意义和内容也不同 ; 如 :
- 1(Coded slice of a non-IDR picture) : P 帧 ;
- 5(Coded slice of an IDR picture) : 关键帧(I 帧) ;
- 7(Sequence Parameter Set, SPS) : 序列参数集 ;
- 8(Picture Parameter Set, PPS) : 图片参数集 ;
2、AVC NALU 类型 数据案例
AVC NALU 类型 数据案例如下 :
00 00 00 1B 65 88 84 00 0A 11 B0 45 67 00 12 34 56 78 9A BC DE F0
解析上述数据 :
00 00 00 1B # 27 , 表示 NALU 的长度为 27 字节
65 # 二进制形式 : 01100101
# forbidden_zero_bit = 0
# nal_ref_idc = 11 (3, 表示最高优先级)
# nal_unit_type = 5 (IDR 帧,关键帧)
88 84 00 0A 11 B0 45 67 00 12 34 56 78 9A BC DE F0 # 实际的视频帧数据
四、AVC End of Sequence 类型 的 结构分析
1、AVC End of Sequence 类型结构
在 FLV 视频标签 Video Tag 中 , 如果 AVC Packet Type 的值为 2 , 表示这是 AVC End of Sequence 类型数据 ;
该类型 数据 用于标记 H.264 视频流的结束位置 , 通知解码器不再有后续的 NALU 数据 ;
该字段是可选字段 , 通常在流媒体传输中很少见 ;
AVC End of Sequence 类型结构 :
字段名称 | 数据类型 | 长度 (字节) | 描述 |
---|---|---|---|
AVC Packet Type | uint8 | 1 | 指定AVC数据包的类型。0表示Sequence Header;1表示NALU;2表示End of Sequence。 |
Composition Time | int24 | 3 | 表示帧的PTS和DTS之间的时间差,以毫秒为单位。仅在AVC Packet Type为1时有意义。 |
- 值固定为 2 , 明确标识数据为 AVC End of Sequence 类型 ;
- 长度为 3 字节 , 通常为
00 00 00
固定值 , 表示解码时间与显示时间的偏移为零 . 因为 End of Sequence 不涉及实际视频帧解码或显示 , Composition Time 通常固定为零 ;
AVC End of Sequence 类型 数据 无其他负载数据 , 不包含实际的 H.264 NALU 数据,仅用于标记视频流的终止 ;
2、AVC End of Sequence 类型数据值
AVC End of Sequence 类型数据值 : 下面的值是固定的 ;
02 00 00 00
02
: AVC Packet Type 字段 , 表示 End of Sequence 类型数据 ;00 00 00
: 表示 Composition Time 字段 , 解码时间与显示时间无偏移 ;