H264 NALU分析

H264简介

H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫AdvancedVideo Codec,因此常常称为MPEG-4 AVC或直接叫AVC。

本文福利, 免费领取C++音视频学习资料包+学习路线大纲、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

H264编码原理

在⾳视频传输过程中,视频⽂件的传输是⼀个极⼤的问题;⼀段分辨率为1920*1080,每个像素点为RGB占⽤3个字节,帧率是25的视频,对于传输带宽的要求是:1920*1080*3*25/1024/1024=148.315MB/s,换成bps则意味着视频每秒带宽为1186.523Mbps,这样的速率对于⽹络存储是不可接受的。因此视频压缩和编码技术应运⽽⽣。

对于视频⽂件来说,视频由单张图⽚帧所组成,⽐如每秒25帧,但是图⽚帧的像素块之间存在相似性,因此视频帧图像可以进⾏图像压缩;H264采⽤了16*16的分块⼤⼩对,视频帧图像进⾏相似⽐较和压缩编码。如下图所示:

H264中的I帧、P帧和B帧

H26使⽤帧内压缩和帧间压缩的⽅式提⾼编码压缩率;H264采⽤了独特的I帧、P帧和B帧策略来实现,连续帧之间的压缩;

如上图所示:

帧的分类

中文

意义

I帧

帧内编码帧intra picture

I 帧通常是每个 GOP(MPEG 所使⽤的⼀种视频压缩技术)的第⼀个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是⼀个图像经过压缩后的产物。⾃身可以通过视频解压算法解压成⼀张单独的完整的图⽚。

P帧

前向预测编码帧predictive-frame

通过充分将低于图像序列中前⾯已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧。需要参考其前⾯的⼀个I frame 或者P frame来⽣成⼀张完整的图⽚。

B帧

双向预测帧bi-directional interpolatedprediction frame

既考虑与源图像序列前⾯已编码帧,也顾及源图像序列后⾯已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧。则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。

压缩率 B > P > I

H264编码结构解析

H264除了实现了对视频的压缩处理之外,为了⽅便⽹络传输,提供了对应的视频编码和分⽚策略;类似于⽹络数据封装成IP帧,在H264中将其称为组(GOP, group of pictures)、⽚(slice)、宏块(Macroblock)这些⼀起组成了H264的码流分层结构;H264将其组织成为序列(GOP)、图⽚(pictrue)、⽚(Slice)、宏块(Macroblock)、⼦块(subblock)五个层次。

GOP (图像组)主要⽤作形容⼀个IDR帧 到下⼀个IDR帧之间的间隔了多少个帧。

H264将视频分为连续的帧进⾏传输,在连续的帧之间使⽤I帧、P帧和B帧。同时对于帧内⽽⾔,将图像分块为⽚、宏块和字块进⾏分⽚传输;通过这个过程实现对视频⽂件的压缩包装。

IDR(Instantaneous Decoding Refresh,即时解码刷新)

⼀个序列的第⼀个图像叫做 IDR 图像(⽴即刷新图像),IDR 图像都是 I 帧图像。I和IDR帧都使⽤帧内预测。I帧不⽤参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。⽐如(解码的顺序):

  • IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15 这⾥的B8可以跨过I10去参考P7

  原始图像: IDR1 B2 B3 P4 B5 B6 P7 B8 B9 I10

  • IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12 这⾥的B9就只能参照IDR8和P11,不可以参考IDR8前⾯的帧

其核⼼作⽤是,是为了解码的重同步,当解码器解码到 IDR 图像时,⽴即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始⼀个新的序列。这样,如果前⼀个序列出现重⼤错误,在这⾥可以获得重新同步的机会。IDR图像之后的图像永远不会使⽤IDR之前的图像的数据来解码。

下⾯是⼀个H264码流的举例(从码流的帧分析可以看出来B帧不能被当做参考帧)

I0 B40 B80 B120 P160
I0 B160

GOP group of pictures

GOP 指的就是两个I帧之间的间隔. ⽐较说GOP为120,如果是720 p60 的话,那就是2s⼀次I帧.在视频编码序列中,主要有三种编码帧:I帧、P帧、B帧,如下所示:

  1. I帧即Intra-coded picture(帧内编码图像帧),不参考其他图像帧,只利⽤本帧的信息进⾏编码。
  2. P帧即Predictive-codedPicture(预测编码图像帧),利⽤之前的I帧或P帧,采⽤运动预测的⽅式进⾏帧间预测编码。
  3. B帧即Bidirectionallypredicted picture(双向预测编码图像帧),提供最⾼的压缩⽐,它既需要之前的图像帧(I帧或P帧),也需要后来的图像帧(P帧),采⽤运动预测的⽅式进⾏帧间双向预测编码。

在视频编码序列中,GOP即Group of picture(图像组),指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离。⼀个I帧所占⽤的字节数⼤于⼀个P帧,⼀个P帧所占⽤的字节数⼤于⼀个B帧。

所以在码率不变的前提下,GOP值越⼤,P、B帧的数量会越多,平均每个I、P、B帧所占⽤的字节数就越多,也就更容易获取较好的图像质量;Reference越⼤,B帧的数量越多,同理也更容易获得较好的图像质量。

需要说明的是,通过提⾼GOP值来提⾼图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会⾃动强制插⼊⼀个I帧,此时实际的GOP值被缩短了。另⼀⽅⾯,在⼀个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量⽐较差时,会影响到⼀个GOP中后续P、B帧的图像质量,直到下⼀个GOP开始才有可能得以恢复,所以GOP值也不宜设置过⼤。同时,由于P、B帧的复杂度⼤于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过⻓的GOP还会影响Seek操作的响应速度,由于P、B帧是由前⾯的I或P帧预测得到的,所以Seek操作需要直接定位,解码某⼀个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越⻓,需要解码的预测帧就越多,seek响应的时间也越⻓。

NALU

SPS:序列参数集,SPS中保存了⼀组编码视频序列(Coded video sequence)的全局参数。
PPS:图像参数集,对应的是⼀个序列中某⼀幅图像或者某⼏幅图像的参数。
I帧:帧内编码帧,可独⽴解码⽣成完整的图⽚。
P帧: 前向预测编码帧,需要参考其前⾯的⼀个I 或者B 来⽣成⼀张完整的图⽚。
B帧: 双向预测内插编码帧,则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。

发I帧之前,⾄少要发⼀次SPS和PPS。

NALU结构

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

  • VCL:包括核⼼压缩引擎和块,宏块和⽚的语法级别定义,设计⽬标是尽可能地独⽴于⽹络进⾏⾼效的编码;
  • NAL:负责将VCL产⽣的⽐特字符串适配到各种各样的⽹络和多元环境中,覆盖了所有⽚级以上的语法级别

在VCL进⾏数据传输或存储之前,这些编码的VCL数据,被映射或封装进NAL单元。(NALU)

⼀个NALU = ⼀组对应于视频编码的NALU头部信息 + ⼀个原始字节序列负荷(RBSP,Raw Byte Sequence Payload).

NALU结构单元的主体结构如下所示;⼀个原始的H.264 NALU单元通常由[StartCode] [NALU Header] [NALU Payload]三部分组成,其中 Start Code ⽤于标示这是⼀个NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP;

(对于FFmpeg解复⽤后,MP4⽂件读取出来的packet是不带startcode,但TS⽂件读取出来的packet带了startcode)

解析NALU

每个NAL单元是⼀个⼀定语法元素的可变⻓字节字符串,包括包含⼀个字节的头信息(⽤来表示数据类型),以及若⼲整数字节的负荷数据。

NALU头信息(⼀个字节):

其中:

  • T为负荷数据类型,占5bit

  nal_unit_type:这个NALU单元的类型,1~12由H.264使⽤,24~31由H.264以外的应⽤使⽤

  • R为重要性指示位,占2个bit

  nal_ref_idc.:取00~11,似乎指示这个NALU的重要性,如00的NALU解码器可以丢弃它⽽不影响图像的回放,0~3,取值越⼤,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的⽚,或是序列参数集,或是图像参数集这些重要的单位时,本句法元
素必需⼤于0。

  • 最后的F为禁⽌位,占1bit

  forbidden_zero_bit: 在 H.264 规范中规定了这⼀位必须为 0.

H.264标准指出,当数据流是储存在介质上时,在每个NALU 前添加起始码:0x000001 或0x00000001,⽤来指示⼀个NALU 的起始和终⽌位置:

  • 在这样的机制下,在码流中检测起始码,作为⼀个NALU得起始标识,当检测到下⼀个起始码时,当前NALU结束。
  • 3字节的0x000001只有⼀种场合下使⽤,就是⼀个完整的帧被编为多个slice(⽚)的时候,包含这些slice的NALU 使⽤3字节起始码。其余场合都是4字节0x00000001的。

例⼦:
0x00 00 00 01 67 …
0x00 00 00 01 68 …
0x00 00 00 01 65 …
67:
⼆进制:0110 0111
00111 = 7(⼗进制)

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

未指定

H264 annexb模式

H264有两种封装
⼀种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中
⼀种是mp4模式,⼀般mp4 mkv都是mp4模式,没有startcode,SPS和PPS以及其它信息被封装在container中,每⼀个frame前⾯4个字节是这个frame的⻓度
很多解码器只⽀持annexb这种模式,因此需要将mp4做转换:在ffmpeg中⽤h264_mp4toannexb_filter可以做转换

实现:

const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
AVBSFContext *bsf_ctx = NULL;
// 2 初始化过滤器上下⽂
 av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;
// 3 添加解码器属性
avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->cod
ecpar);
av_bsf_init(bsf_ctx);

本文福利, 免费领取C++音视频学习资料包+学习路线大纲、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

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

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

相关文章

雷达波形之一——LFM线性调频波形

文章目录 前言一、线性调频信号的形式1、原理2、时域表达式3、频域表达式 二、MATLAB 仿真1、涅菲尔积分①、MATLAB 源码②、仿真结果 2、LFM①、MATLAB 源码②、仿真结果1) 典型 LFM 波形,实部2) 典型 LFM 波形,虚部3) LFM 波形的典型谱 前言 线性调频…

追寻Moonbeam身影,泰国区块链周正在火热进行中!

继Moonbeam参与HK Web3月之后,下一站便是由Cryptomind Group举办的泰国2023年区块链周。本次位于泰国的区块链周以“熊市中建设,牛市中崛起”为理念,旨在为对区块链技术感兴趣的个人和投资者提供机会接触行业中的团队和专家,并邀请…

【学习笔记】MySQL死锁及热点行问题

目录 案例优化思路死锁的一些记录笔记热点行问题 本文记录下关于MySQL优化的学习和一点点思考。 案例 一个并发比较大的下单接口; 包括 step1 扣减商品库存step2 生成订单数据step3 记录操作记录 伪代码如下,底层使用的是MySQL数据库,单体服务…

家政系统、家政小程序

家政系统、家政小程序。提供线上下单,订单微信提醒,手机端一键派单,保姆月嫂人员展示,预约。拼团、秒杀、分销等营销功能。系统管理订单,人员,财务。

微头条项目实战:新增RequestHeader注解

1、RequestHeader package com.csdn.mymvc.annotation; import java.lang.annotation.*; Target(ElementType.PARAMETER) Retention(RetentionPolicy.RUNTIME) Inherited public interface RequestHeader { }2、DispatcherServlet package com.csdn.mymvc.core; import com.csd…

外贸SEO外链类型有哪些?外链建设如何做?

外贸SEO外链资源怎么找?海洋建站SEO外链优化方法? 外贸SEO外链在提高网站排名、吸引流量、增加品牌曝光方面发挥着重要作用。海洋建站将探讨外贸SEO外链的不同类型,帮助外贸企业更好地理解如何优化他们的在线营销策略。 外贸SEO外链&#x…

centos配置docker环境

CentOS系统更换软件安装源 yum默认链接的还是国外的镜像,速度相对不理想,配置成国内的镜像会快很多,这里以阿里镜像为例进行配置: 首先进行更新: yum updatebase源 第一步:备份你的原镜像文件,以免出错后…

工厂设备报修的流程是怎样的?维修流程要如何优化?

在当今高度自动化的生产环境中,工厂设备的正常运行无疑对于企业的生产效率和经济效益具有至关重要的影响。然而,设备故障是生产过程中不可避免的现象。当设备发生故障时,如何快速、有效地进行报修、维修,以恢复设备的正常运转&…

Activiti

序言 activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN进行定义(所以我们也需要了解BPMN相关信息),业务流程按照预先定义的流程进行执行。实现了系统的流程由activiti进行管理,减少业务系…

Linux--信号

一.引号的产生 1.什么是信号 在生活中,信号的产生是多种多样的,比如红绿灯,闹钟等等,Linux中的信号是什么呢? 1.在Linux中,信号的本质是一种通信方式,由用户或操作系统发送信号,通知…

性格软弱怎么办?如何改变性格软弱?

软弱指的是身体衰弱无力气,而这里要说的是性格软弱,性格软弱的人,大多是不自信的,无主见,容易妥协,害怕产生矛盾,遇到问题就想逃避,自我否定,担心自己这也不行那也不行。…

vue+css动画 实现文字的上下轮播切换

突然间碰到一个比较丝滑的特效,就研究了一下想把它实现出来。 效果:渐隐消失,底部往上走覆盖出现 以下是完整代码,复制粘贴即可运行 <template><div class="aaa"><divclass="page1":class="{ private-fade-out: prevIndex === 1…

代码随想录算法训练营第四十七天丨 动态规划part10

121. 买卖股票的最佳时机 思路 动态规划 动规五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][0] 表示第i天持有股票所得最多现金 &#xff0c;这里可能有疑惑&#xff0c;本题中只能买卖一次&#xff0c;持有股票之后哪还有…

Python大语言模型实战-利用ChatDev框架自动开发一个游戏软件(附完整教程)

实现功能 ChatDev一个由多智能体协作框架&#xff0c;是一个虚拟软件公司&#xff0c;在人类 “用户” 指定一个具体的任务需求后&#xff0c;不同角色的智能体将进行交互式协同&#xff0c;以生产一个完整软件&#xff08;包括源代码、环境依赖说明书、用户手册等&#xff09…

利用IP风险画像强化金融行业网络安全防御

在数字化时代&#xff0c;金融行业日益依赖互联网和技术创新&#xff0c;但这也使得金融机构成为网络攻击的主要目标。为了应对日益复杂的网络威胁&#xff0c;金融机构迫切需要采用先进的安全技术和工具。其中&#xff0c;IP风险画像技术成为提升网络安全的一项重要策略。 1.…

若依分离版——使用Knife4j 自动生成接口文档

背景&#xff1a; 前后端分离程序&#xff0c;如果需要前端开发人员和后端开发人员配合开发&#xff0c;则需要将接口文档并显性给前端人员 解决办法&#xff1a; 使用knife4j替代若依自带的swagger&#xff0c;因为knife4j是在swagger基础上包装的&#xff0c;Knife4j不仅具…

Django生鲜蔬菜采购系统-计算机毕设 附源码 24033

Django生鲜蔬菜采购系统 目 录 摘要 1 绪论 1.1 研究背景 1.2国内外研究现状 1.3论文结构与章节安排 2 生鲜蔬菜采购系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流…

react类式组件的生命周期和useEffect实现函数组件生命周期

概念 生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的. ....多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更…

【三维重建】摄像机几何

针孔相机模型 为了方便我们对针孔相机模型进行数学建模&#xff0c;我们往往对虚拟像平面进行研究&#xff0c;因为虚拟像平面的方向与我们实际物体的方向一致。 通过相似三角形法可以得到三维坐标到二维坐标映射 将像平面原点坐标移动到左下角&#xff1a; 加上现实世界单位&a…

Excel表列序号

题意&#xff1a; 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1: 输入: columnTitle “A” 输出: 1 示例 2: 输…