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

如何选择合适的码率?

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型(二)基于Deepseek搭建本地可视化交互UI

AI大模型(二)基于Deepseek搭建本地可视化交互UI DeepSeek开源大模型在榜单上以黑马之姿横扫多项评测,其社区热度指数暴涨、一跃成为近期内影响力最高的话题,这个来自中国团队的模型向世界证明:让每个普通人都能拥有媲…

图的基本术语——非八股文

我之前只看到了数据结构与算法的冰山一角,感觉这些术语只会让知识越来越难理解,现在来看,他们完美抽象一些概念和知识,非常重要。 本篇概念肯定总结不全,只有遇到的会写上,持续更新,之前文章已经…

oracle: 表分区>>范围分区,列表分区,散列分区/哈希分区,间隔分区,参考分区,组合分区,子分区/复合分区/组合分区

分区表 是将一个逻辑上的大表按照特定的规则划分为多个物理上的子表,这些子表称为分区。 分区可以基于不同的维度,如时间、数值范围、字符串值等,将数据分散存储在不同的分区 中,以提高数据管理的效率和查询性能,同时…

本地快速部署DeepSeek-R1模型——2025新年贺岁

一晃年初六了,春节长假余额马上归零了。今天下午在我的电脑上成功部署了DeepSeek-R1模型,抽个时间和大家简单分享一下过程: 概述 DeepSeek模型 是一家由中国知名量化私募巨头幻方量化创立的人工智能公司,致力于开发高效、高性能…

C++11详解(一) -- 列表初始化,右值引用和移动语义

文章目录 1.列表初始化1.1 C98传统的{}1.2 C11中的{}1.3 C11中的std::initializer_list 2.右值引用和移动语义2.1左值和右值2.2左值引用和右值引用2.3 引用延长生命周期2.4左值和右值的参数匹配问题2.5右值引用和移动语义的使用场景2.5.1左值引用主要使用场景2.5.2移动构造和移…

手写MVVM框架-构建虚拟dom树

MVVM的核心之一就是虚拟dom树,我们这一章节就先构建一个虚拟dom树 首先我们需要创建一个VNode的类 // 当前类的位置是src/vnode/index.js export default class VNode{constructor(tag, // 标签名称(英文大写)ele, // 对应真实节点children,…

【大数据技术】教程03:本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …

pytorch实现门控循环单元 (GRU)

人工智能例子汇总:AI常见的算法和例子-CSDN博客 特性GRULSTM计算效率更快,参数更少相对较慢,参数更多结构复杂度只有两个门(更新门和重置门)三个门(输入门、遗忘门、输出门)处理长时依赖一般适…

PAT甲级1032、sharing

题目 To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For example, loading and being are stored as showed in Figure …

最小生成树kruskal算法

文章目录 kruskal算法的思想模板 kruskal算法的思想 模板 #include <bits/stdc.h> #define lowbit(x) ((x)&(-x)) #define int long long #define endl \n #define PII pair<int,int> #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); using na…

为何在Kubernetes容器中以root身份运行存在风险?

作者&#xff1a;马辛瓦西奥内克&#xff08;Marcin Wasiucionek&#xff09; 引言 在Kubernetes安全领域&#xff0c;一个常见的建议是让容器以非root用户身份运行。但是&#xff0c;在容器中以root身份运行&#xff0c;实际会带来哪些安全隐患呢&#xff1f;在Docker镜像和…

ConcurrentHashMap线程安全:分段锁 到 synchronized + CAS

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 理解ConcurrentHashMap为什么线程安全&#xff1b;ConcurrentHashMap的具体细节还需要进一步研究 目录 ConcurrentHashMap介绍JDK7的分段锁实现JDK8的synchr…

[ESP32:Vscode+PlatformIO]新建工程 常用配置与设置

2025-1-29 一、新建工程 选择一个要创建工程文件夹的地方&#xff0c;在空白处鼠标右键选择通过Code打开 打开Vscode&#xff0c;点击platformIO图标&#xff0c;选择PIO Home下的open&#xff0c;最后点击new project 按照下图进行设置 第一个是工程文件夹的名称 第二个是…

述评:如果抗拒特朗普的“普征关税”

题 记 美国总统特朗普宣布对美国三大贸易夥伴——中国、墨西哥和加拿大&#xff0c;分别征收10%、25%的关税。 他威胁说&#xff0c;如果这三个国家不解决他对非法移民和毒品走私的担忧&#xff0c;他就要征收进口税。 去年&#xff0c;中国、墨西哥和加拿大这三个国家&#…

九. Redis 持久化-AOF(详细讲解说明,一个配置一个说明分析,步步讲解到位 2)

九. Redis 持久化-AOF(详细讲解说明&#xff0c;一个配置一个说明分析&#xff0c;步步讲解到位 2) 文章目录 九. Redis 持久化-AOF(详细讲解说明&#xff0c;一个配置一个说明分析&#xff0c;步步讲解到位 2)1. Redis 持久化 AOF 概述2. AOF 持久化流程3. AOF 的配置4. AOF 启…

基于Springboot框架的学术期刊遴选服务-项目演示

项目介绍 本课程演示的是一款 基于Javaweb的水果超市管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附…

新版231普通阿里滑块 自动化和逆向实现 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向过程 补环境逆向 部分补环境 …

java-(Oracle)-Oracle,plsqldev,Sql语法,Oracle函数

卸载好注册表,然后安装11g 每次在执行orderby的时候相当于是做了全排序,思考全排序的效率 会比较耗费系统的资源,因此选择在业务不太繁忙的时候进行 --给表添加注释 comment on table emp is 雇员表 --给列添加注释; comment on column emp.empno is 雇员工号;select empno,en…

泰山派Linux环境下自动烧录脚本(EMMC 2+16G)

脚本名字&#xff1a; download.sh 输入./download -h获取帮助信息 &#xff0c;其中各个IMG/TXT烧录的地址和路径都在前几行修改即可 #!/bin/bash# # DownLoad.sh 多镜像烧录脚本 # 版本&#xff1a;1.1 # 作者&#xff1a;zhangqi # 功能&#xff1a;通过参数选择烧录指定镜…

正大杯攻略|分层抽样+不等概率三阶段抽样

首先&#xff0c;先进行分层抽样&#xff0c;确定主城区和郊区的比例 然后对主城区分别进行不等概率三阶段抽样 第一阶段&#xff0c;使用PPS抽样&#xff0c;确定行政区&#xff08;根据分层抽样比例合理确定主城区和郊区行政区数量&#xff09; 第二阶段&#xff0c;使用分…