H264原始码流格式分析

1.H264码流结构组成

H.264裸码流(Raw Bitstream)数据主要由一系列的NALU(网络抽象层单元)组成。每个NALU包含一个NAL头和一个RBSP(原始字节序列载荷)。

1.1 H.264码流层次

H.264码流的结构可以分为两个层次:VCL(视频编码层)和NAL(网络抽象层)。下图为H.264码流中的层次图:

VCL层:负责对视频的原始数据进行压缩。VCL数据编码器直接输出的原始数据比特串(SODB),表示图像被压缩后的编码比特流。

  • SODB:生成压缩原始的图像编码数据比特串。
  • 编码图像:宏块进行的帧内编码/帧间编码/熵编码等处理。

NAL层:负责将VCL数据封装成NAL单元(NALU),并在网络上传输或存储到磁盘上。每个NAL单元之前需要添加StartCodePrefix,形成H.264码流。NAL层还处理拆包和组包的工作,以适应网络传输的最大传输单元(通常为1500字节)。

1.2 NALU网络层组成

一个NALU由两个主要部分组成:

  • 头部(Header):

    NALU的头部包含了关于该单元的一些元数据信息,例如NAL单元类型(如序列参数集、图像参数集、帧数据单元等),NALU的优先级、参考帧标识、重要性指示等。头部的信息有助于解码器正确解析和处理每个NAL单元。

  • 载荷(Payload):

    NALU的载荷部分包含了实际的编码数据。这些数据可以是帧的视频数据、补充增强信息或其他特定于编码标准的数据。在视频解码过程中,解码器通过解析头部信息来识别NALU的类型,并且根据类型和载荷数据进行相应的解码和处理。

在H.264/AVC中,定义了多种NALU的类型,以适应不同的应用场景。常见的类型包括:

帧内预测(I)片:仅使用当前帧的信息进行编码。

预测(P)片:使用前一帧的信息进行编码。

双向预测(B)片:使用前一帧和后一帧的信息进行编码。

1.3 序列参数集SPS

序列参数集(Sequence Parameter Set,SPS)包含了描述视频序列全局参数的信息,这些参数对于解码器正确解码视频流至关重要。以下是SPS的一些主要内容和结构:

  1. profile_idc:标识H.264码流的profile,例如Baseline、Main、High等。
  2. level_idc:标识码流的Level,定义了最大分辨率、最大帧率等参数。
  3. seq_parameter_set_id:序列参数集的ID,用于标识不同的SPS。
  4. log2_max_frame_num_minus4:用于计算frame_num的最大值,frame_num标识图像的解码顺序。
  5. pic_order_cnt_type:指明图像播放顺序的编码方法。
  6. log2_max_pic_order_cnt_lsb_minus4:用于计算POC(Picture Order Count)的最大值。
  7. max_num_ref_frames:指定参考帧队列的最大长度。
  8. gaps_in_frame_num_value_allowed_flag:指示是否允许frame_num不连续。
  9. pic_width_in_mbs_minus1:图像宽度,以宏块为单位。
  10. pic_height_in_map_units_minus1:图像高度,以宏块为单位。

SPS中的信息对于解码器初始化和正确解码视频流至关重要。如果SPS数据丢失或损坏,解码器可能无法正确解码视频。

1.4 图像参数集PPS

图像参数集(Picture Parameter Set,PPS)包含了与单个图像编码相关的参数,这些参数用于控制图像的编码方式。以下是PPS的一些主要内容和结构:

  1. pic_parameter_set_id:当前PPS的唯一ID,取值范围为0-255。
  2. seq_parameter_set_id:指明该PPS对应的SPS(序列参数集)ID。
  3. entropy_coding_mode_flag:表示使用的熵编码类型,0为CAVLC,1为CABAC。
  4. num_slice_groups_minus1:表示slice group的数量,通常为0。
  5. num_ref_idx_l0_default_active_minus1num_ref_idx_l1_default_active_minus1:表示P/B slice的前向和后向参考帧的最大个数减1。
  6. weighted_pred_flag:表示P slice的预测权重方式,0为默认预测权重,1为显式方式。
  7. weighted_bipred_flag:表示B slice的预测权重方式,0为默认预测权重,1为显式方式,2为隐式方式。
  8. pic_init_qp_minus26:用于计算Y分量的初始QP值。
  9. chroma_qp_index_offset:表示Cb分量QP相对于slice QP的偏移量。
  10. deblocking_filter_control_present_flag:表示是否存在去块效应滤波器的控制语法元素。
  11. constrained_intra_pred_flag:表示帧内预测方式是否存在限制条件。
  12. transform_8x8_mode_flag:表示是否使用8x8大小的DCT变换方式。
  13. pic_scaling_matrix_present_flag:表示量化参数矩阵是否存在。
  14. second_chroma_qp_index_offset:表示Cr分量QP相对于slice QP的偏移量。

PPS中的信息对于解码器正确解码视频流至关重要。PPS通常紧跟在SPS之后,并且可以有多个,因为不同的slice group可能有不同的参数设置。

2.常用的两种NALU格式

2.1 AnnexB

AnnexB是一种常见的NALU(网络抽象层单元)封装格式,主要用于H.264和H.265视频编码标准。AnnexB格式的基本结构如下:

[开始代码] [NALU单元] [开始代码] [NALU单元] ...

每个NALU单元由一个开始代码和随后的原始字节数据组成,通过分隔符0x00 00 00 01或者0x00 00 01区分不同的NALU单元。如果在RBSP(原始字节流载荷)中出现了0x000000、0x000001、0x000002或0x000003这样的序列,就需要插入一个0x03字节来避免这些序列被误识别。例如,将0x000001变成0x00000301,这样在解码时可以去除0x03字节,恢复原始数据。这种方法确保了数据的完整性和正确解码。例如:

  • 原始数据:0x000001 插入“模拟预防”字节后:0x00000301 解码时去除0x03字节,恢复为:0x000001

  • 原始数据:0x000000 插入“模拟预防”字节后:0x00000300 解码时去除0x03字节,恢复为:0x000000

  • 原始数据:0x000002 插入“模拟预防”字节后:0x00000302 解码时去除0x03字节,恢复为:0x000002

  • 原始数据:0x000003 插入“模拟预防”字节后:0x00000303 解码时去除0x03字节,恢复为:0x000003

如果插入的数据本身包含了“模拟预防”字节(例如0x00000301),编码器会将其转义为0x0000030301。

2.2 AVCC

AVCC(AVC Configuration)格式是一种用于存储和传输H.264视频流的格式,通常用于MP4、MKV等容器中。与Annex B格式不同,AVCC格式不使用起始码(start code)来分隔NALU(网络抽象层单元),而是使用NALU长度前缀。

AVCC格式结构:

  1. 头部信息(extradata):
    • 包含SPS(序列参数集)和PPS(图像参数集)等参数信息。
    • 头部信息的格式如下:
      • 第1字节:版本号(通常为0x01)
      • 第2字节:AVC Profile(与第一个SPS的第2字节相同)
      • 第3字节:AVC Compatibility(与第一个SPS的第3字节相同)
      • 第4字节:AVC Level(与第一个SPS的第4字节相同)
      • 第5字节:保留位(前6位全1),后2位表示NALU长度字段的字节数减1(通常为3,即4字节)
      • 第6字节:保留位(前3位全1),后5位表示SPS的个数(通常为1)
      • 后续字节:SPS数据(包括16位SPS长度和SPS NALU数据)
      • PPS数据(包括16位PPS长度和PPS NALU数据)
  2. NALU数据:
    • 每个NALU前面都有一个长度前缀(通常为4字节),表示该NALU的长度。
    • NALU数据不包含起始码。

假设有一个NALU数据为0x65 88 84 21,其长度为4字节。在AVCC格式中,这个NALU会被存储为:

0x00 00 00 04 65 88 84 21

其中,0x00 00 00 04表示NALU的长度为4字节,后面的65 88 84 21是实际的NALU数据。

在解析AVCC格式时,需要先读取头部信息(extradata),然后根据NALU长度前缀来提取每个NALU的数据。

2.3 AnnexB和AVCC的优缺点

Annex B和AVCC是H.264视频编码中常见的两种NALU(网络抽象层单元)封装格式。它们各有优缺点,适用于不同的应用场景。以下是它们的优劣之处:

Annex B
优点简单直接:使用起始码(start code)0x0000010x00000001来分隔NALU,便于解析和同步。
广泛支持:许多硬件解码器和流媒体协议(如RTSP、RTP)默认支持Annex B格式。
实时流媒体:适合实时流媒体传输,因为起始码可以快速定位NALU的边界。
缺点额外开销:起始码会增加一些额外的字节,导致数据冗余。
不适合文件存储:在文件存储中,起始码的存在可能会增加文件大小,不如AVCC格式高效。
AVCC
优点高效存储:使用NALU长度前缀(通常为4字节)来标识NALU的长度,减少了数据冗余,适合文件存储。
灵活性高:适用于多种容器格式(如MP4、MKV),便于在不同平台和设备之间传输和存储。
标准化:AVCC格式在许多多媒体框架和库(如FFmpeg、GStreamer)中得到广泛支持。
缺点解析复杂:需要解析NALU长度前缀,增加了解码器的复杂性。
实时性较差:不如Annex B格式适合实时流媒体传输,因为需要额外的步骤来解析NALU长度。

选择建议

  • 实时流媒体传输:推荐使用Annex B格式,因其简单直接,便于实时解析和同步。
  • 文件存储和传输:推荐使用AVCC格式,因其高效存储和灵活性,适合在不同平台和设备之间传输和存储。

3.码流中的重要参数

3.1 量化参数(QP值)

QP(Quantization Parameter,量化参数)是H.264视频编码中用于控制视频压缩的质量和比特率。QP值直接影响视频的量化步长(Qstep),从而影响视频的压缩程度和图像质量。QP值的作用:

  1. 控制压缩质量:QP值越小,量化越精细,保留的图像细节越多,视频质量越高,但比特率也越高。相反,QP值越大,量化越粗糙,丢失的细节越多,视频质量下降,但比特率降低。
  2. 调节比特率:通过调整QP值,可以在视频质量和比特率之间找到一个平衡点,以满足不同的应用需求。

QP值的范围,在H.264标准中,QP值的取值范围为0到51:

  • QP = 0:量化最精细,视频质量最高,比特率最大。
  • QP = 51:量化最粗糙,视频质量最低,比特率最小。

假设你有一个视频片段,使用不同的QP值进行编码:

  • QP = 20:视频质量较高,细节保留较多,但比特率较高。
  • QP = 40:视频质量较低,细节丢失较多,但比特率较低。

QP值与量化步长(Qstep)之间存在一个对数关系。具体来说,QP每增加6,Qstep大约增加一倍。这个关系使得编码器可以在不同的QP值下灵活调整视频的压缩程度。

  • 低QP值:适用于需要高质量视频的场景,如高清电影、专业视频制作。
  • 高QP值:适用于对比特率要求较高的场景,如实时视频传输、低带宽环境。

3.2 码率

码率(Bitrate)是指单位时间内传输的数据量,通常以kbps(千比特每秒)或Mbps(兆比特每秒)为单位。码率在视频和音频编码中起着至关重要的作用,直接影响到文件的质量和大小。

  1. 视频质量:码率越高,视频质量越好,因为更多的数据可以用来表示图像细节。反之,码率越低,视频质量越差。
  2. 文件大小:码率越高,文件大小越大。对于同一段视频,较高的码率会导致更大的文件。
  3. 传输效率:在流媒体传输中,码率决定了视频流的带宽需求。较高的码率需要更高的网络带宽。

码率的基本计算公式为:

码率 (kbps)=\frac{文件大小 (KB)×8}{时间 (秒)}

码率控制模式:

  1. 恒定码率(CBR):码率在整个视频中保持恒定,适用于带宽稳定的环境。
  2. 可变码率(VBR):码率根据视频内容的复杂度动态调整,通常在保证质量的同时节省带宽。
  3. 平均码率(ABR):在指定的文件大小内,动态调整码率以平衡质量和文件大小。

假设一个视频文件大小为500MB,时长为10分钟(600秒),其码率计算如下:

码率 (kbps)=\frac{500×1024×8}{600}≈6826.67 kbps

如何选择合适的码率?

  • 高质量需求:如高清电影、专业视频制作,建议使用较高的码率。
  • 实时传输:如视频会议、直播,建议使用适中的码率以平衡质量和带宽需求。
  • 低带宽环境:如移动网络,建议使用较低的码率以减少缓冲和卡顿。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt中QVariant的使用

1.使用QVariant实现不同类型数据的相加 方法:通过type函数返回数值的类型,然后通过setValue来构造一个QVariant类型的返回值。 函数: QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…

C++,STL 简介:历史、组成、优势

文章目录 引言一、STL 的历史STL 的核心组成三、STL 的核心优势四、结语进一步学习资源: 引言 C 是一门强大且灵活的编程语言,但其真正的魅力之一在于其标准库——尤其是标准模板库(Standard Template Library, STL)。STL 提供了…

每日一题——序列化二叉树

序列化二叉树 BM39 序列化二叉树题目描述序列化反序列化 示例示例1示例2 解题思路序列化过程反序列化过程 代码实现代码说明复杂度分析总结 BM39 序列化二叉树 题目描述 请实现两个函数,分别用来序列化和反序列化二叉树。二叉树的序列化是将二叉树按照某种遍历方式…

关于安卓greendao打包时报错问题修复

背景 项目在使用greendao的时候,debug安装没有问题,一到打包签名就报了。 环境 win10 jdk17 gradle8 项目依赖情况 博主的greendao是一个独立的module项目,项目目前只适配了java,不支持Kotlin。然后被外部集成。greendao版本…

Java实现.env文件读取敏感数据

文章目录 1.common-env-starter模块1.目录结构2.DotenvEnvironmentPostProcessor.java 在${xxx}解析之前执行,提前读取配置3.EnvProperties.java 这里的path只是为了代码提示4.EnvAutoConfiguration.java Env模块自动配置类5.spring.factories 自动配置和注册Enviro…

【AutoSar】汽车诊断标准协议UDS详解

目录 一、基本概念二、UDS诊断协议2.1 诊断服务的概念2.2常用的诊断服务2.2.1 诊断会话控制服务(10服务)2.2.2 会话访问0x27服务2.2.3 用于读写的DID的0x22/0x2E服务 一、基本概念 车辆的诊断需要有Tester端和ECU段通过应答的方式进行通信,他…

Java线程认识和Object的一些方法

本文目标: 要对Java线程有整体了解,深入认识到里面的一些方法和Object对象方法的区别。认识到Java对象的ObjectMonitor,这有助于后面的Synchronized和锁的认识。利用Synchronized wait/notify 完成一道经典的多线程题目:实现ABC…

【漫话机器学习系列】067.希腊字母(greek letters)-写法、名称、读法和常见用途

希腊字母(Greek Letters) 希腊字母在数学、科学、工程学和编程中广泛使用,常用于表示变量、常量、参数、角度等。以下是希腊字母的完整列表及其常见用途。 大写与小写希腊字母表 大写小写名称(英文)名称(…

【Block总结】OutlookAttention注意力,捕捉细节和局部特征|即插即用

论文信息 标题: VOLO: Vision Outlooker for Visual Recognition作者: Li Yuan, Qibin Hou, Zihang Jiang, Jiashi Feng, Shuicheng Yan代码链接: https://github.com/sail-sg/volo论文链接: https://arxiv.org/pdf/2106.13112 创新点 前景注意力机制: VOLO引入了一种称为“…

Linux Samba 低版本漏洞(远程控制)复现与剖析

目录 前言 漏洞介绍 漏洞原理 产生条件 漏洞影响 防御措施 复现过程 结语 前言 在网络安全的复杂生态中,系统漏洞的探索与防范始终是保障数字世界安全稳定运行的关键所在。Linux Samba 作为一款在网络共享服务领域应用极为广泛的软件,其低版本中…

hive:基本数据类型,关于表和列语法

基本数据类型 Hive 的数据类型分为基本数据类型和复杂数据类型 加粗的是常用数据类型 BOOLEAN出现ture和false外的其他值会变成NULL值 没有number,decimal类似number 如果输入的数据不符合数据类型, 映射时会变成NULL, 但是数据本身并没有被修改 创建表 创建表的本质其实就是在…

Elasticsearch的开发工具(Dev Tools)

目录 说明1. **Console**2. **Search Profiler**3. **Grok Debugger**4. **Painless Lab**总结 说明 Elasticsearch的开发工具(Dev Tools)在Kibana中提供了多种功能强大的工具,用于调试、优化和测试Elasticsearch查询和脚本。以下是关于Cons…

Qt中Widget及其子类的相对位置移动

Qt中Widget及其子类的相对位置移动 最后更新日期:2025.01.25 下面让我们开始今天的主题… 一、开启篇 提出问题:请看上图,我们想要实现的效果是控件黄色的Widge(m_infobarWidget)t随着可视化窗口(m_glWidge…

【Unity3D】实现横版2D游戏——攀爬绳索(简易版)

目录 GeneRope.cs 场景绳索生成类 HeroColliderController.cs 控制角色与单向平台是否忽略碰撞 HeroClampController.cs 控制角色攀爬 OnTriggerEnter2D方法 OnTriggerStay2D方法 OnTriggerExit2D方法 Update方法 开始攀爬 结束攀爬 Sensor_HeroKnight.cs 角色触发器…

docker搭建redis集群(三主三从)

本篇文章不包含理论解释,直接开始集群(三主三从)搭建 环境 centos7 docker 26.1.4 redis latest (7.4.2) 服务器搭建以及环境配置 请查看本系列前几篇博客 默认已搭建好三个虚拟机并安装配置好docker 相关博客&#xf…

物联网智能项目之——智能家居项目的实现!

成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于物联网智能项目之——智能家居项目…

Deep Seek R1本地化部署

目录 说明 一、下载ollama 二、在ollama官网下载模型 三、使用 后记 说明 操作系统:win10 使用工具:ollama 一、下载ollama 从官网下载ollama: ollama默认安装在C盘,具体位置为C:\Users\用户名\AppData\Local\Programs\O…

跟李沐学AI:视频生成类论文精读(Movie Gen、HunyuanVideo)

Movie Gen:A Cast of Media Foundation Models 简介 Movie Gen是Meta公司提出的一系列内容生成模型,包含了 3.2.1 预训练数据 Movie Gen采用大约 100M 的视频-文本对和 1B 的图片-文本对进行预训练。 图片-文本对的预训练流程与Meta提出的 Emu: Enh…

Java---入门基础篇(上)

前言 本片文章主要讲了刚学Java的一些基础内容,例如注释,标识符,数据类型和变量,运算符,还有逻辑控制等,记录的很详细,带你从简单的知识点再到练习题.如果学习了c语言的小伙伴会发现,这篇文章的内容和c语言大致相同. 而在下一篇文章里,我会讲解方法和数组的使用,也是Java中基础…

3、C#基于.net framework的应用开发实战编程 - 实现(三、三) - 编程手把手系列文章...

三、 实现; 三.三、编写应用程序; 此文主要是实现应用的主要编码工作。 1、 分层; 此例子主要分为UI、Helper、DAL等层。UI负责便签的界面显示;Helper主要是链接UI和数据库操作的中间层;DAL为对数据库的操…