H264宏块包含的各种语法信息详解

news2024/10/5 16:28:53

H264宏块包含的各种语法信息详解

本文将以CABAC编码需要编码的语法元素的程序为例,分析H264宏块中所包含的各种语法元素的含义。


以上三种变量的其他情况分支,本文进行了省略处理,完整的,全分支的CABAC编码见参考资料【1】


1、 slice_data

slice_data( ) {
	if( entropy_coding_mode_flag )
		while( !byte_aligned( ) )
			cabac_alignment_one_bit
	CurrMbAddr = first_mb_in_slice * ( 1 + MbaffFrameFlag )
	moreDataFlag = 1
	prevMbSkipped = 0
	do {
		if( slice_type != I && slice_type != SI )
			if( !entropy_coding_mode_flag ) {
				mb_skip_run
				prevMbSkipped = ( mb_skip_run > 0 )
				for( i=0; i<mb_skip_run; i++ )
					CurrMbAddr = NextMbAddress( CurrMbAddr )
					if( mb_skip_run > 0 )
					moreDataFlag = more_rbsp_data( )
			} else {
			mb_skip_flag
			moreDataFlag = !mb_skip_flag
			}
		if( moreDataFlag ) {
			if( MbaffFrameFlag && ( CurrMbAddr % 2 = = 0 | |
			( CurrMbAddr % 2 = = 1 && prevMbSkipped ) ) )
				mb_field_decoding_flag
			macroblock_layer( )
		}
		if( !entropy_coding_mode_flag )
			moreDataFlag = more_rbsp_data( )
		else {
			if( slice_type != I && slice_type != SI )
				prevMbSkipped = mb_skip_flag
			if( MbaffFrameFlag && CurrMbAddr % 2 = = 0 )
				moreDataFlag = 1
			else {
				end_of_slice_flag
				moreDataFlag = !end_of_slice_flag
				}
		}
		CurrMbAddr = NextMbAddress( CurrMbAddr )
	} while( moreDataFlag )
}

首先需要明确的是,H264将一张图像分为很多个slice,而以一个slice被划分为很多16x16的块,这个16x16的块成为宏块(MB),H264一般以宏块为单位进行压缩编码。

 ✐  entropy_coding_mode_flag: 是否采用熵编码,该标志为1时,采用CABAC编码;
 ✐  MbaffFrameFlag : 帧编码时,该标志位为0,(目前场编码用的少了);
 ✐ ChromaArrayType: chroma的类型,当该值为0时,图像格式为YUV400;该值为1时图像格式为YUV420;
 ✐  byte_aligned( ) 0 : 字节未对齐; 1: 字节对齐;
 ✐  mb_skip_flag: 0:非skip, 1:skip(可跳过不编码);
 ✐  macroblock_layer( ) : 宏块包含的信息;
 ✐  end_of_slice_flag: 1:该MB为当前slice的最后一个MB;

一个Slice由很多个宏块组成,部分宏块可以由其他宏块的内容推断出来,这种宏块完全可以由附近的宏块信息猜出来,没必要单独编码;

这种可以通过前后图像直接推断出来,都是可以不用编码的;我们给每个宏块一个标志位mb_skip_flag来表示是否可以不编码这个宏块(slice_type为I时,他里面包含的宏块只有I宏块肯定不能跳过,因此这两个类型的mb_skip_flag不需要单独编码);

slice type该类型slice中允许出现的宏块类型
II
PP , I
BB, I

宏块类型:
 ✑ I宏块: 编码解码时只和当前图像有关(帧内预测);
 ✑ P宏块:编码解码时需要参考前面的图像信息(帧间预测);
 ✑ B宏块:编码解码时需要参考前面和后面的图像信息(帧间预测);

2、macroblock_layer( )

macroblock_layer( ) {
	mb_type
	if( mb_type = = I_PCM ) {
		while( !byte_aligned( ) )  //字节对齐
			pcm_alignment_zero_bit
	for( i = 0; i < 256; i++ )
		pcm_sample_luma[ i ]
	for( i = 0; i < 2 * MbWidthC * MbHeightC; i++ )
		pcm_sample_chroma[ i ]
	} else {
		noSubMbPartSizeLessThan8x8Flag = 1
		if( mb_type != I_NxN &&
		MbPartPredMode( mb_type, 0 ) != Intra_16x16 &&
		NumMbPart( mb_type ) = = 4 ) {
		sub_mb_pred( mb_type )
		for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ )
			if( sub_mb_type[ mbPartIdx ] != B_Direct_8x8 ) {
				if( NumSubMbPart( sub_mb_type[ mbPartIdx ] ) > 1 )
					noSubMbPartSizeLessThan8x8Flag = 0
				} else if( !direct_8x8_inference_flag )
				noSubMbPartSizeLessThan8x8Flag = 0
		} else {
			if( transform_8x8_mode_flag && mb_type = = I_NxN )
				transform_size_8x8_flag
			mb_pred( mb_type )
		}
	if( MbPartPredMode( mb_type, 0 ) != Intra_16x16 ) {
		coded_block_pattern
		if( CodedBlockPatternLuma > 0 &&
			transform_8x8_mode_flag && mb_type != I_NxN &&
			noSubMbPartSizeLessThan8x8Flag &&
			( mb_type != B_Direct_16x16 | | direct_8x8_inference_flag ) )
		transform_size_8x8_flag
		}
	if( CodedBlockPatternLuma > 0 | | CodedBlockPatternChroma > 0 | |
		MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) {
		mb_qp_delta
		residual( 0, 15 )
		}
	}
}

每个宏块都有mb_type表明该宏块的类型,若该宏块为I_PCM,则直接输出原始图像,即256(16*16)个luma(Y)分量pcm_sample_luma和512个chroma分量(U+V)pcm_sample_chroma;

mb_type所代表的含义如下所示:

  •  ➸ I slice :

请添加图片描述

H264一般以16X16的宏块为单位进行划分,其中I_16X16_a_b_c代表,该宏块的大小是1个16x16,_a代表帧内预测的方式;_b和_c 分别表示chroma和luma的 CBP;

H264一般是帧间预测信息或者帧内预测信息,再加上一些预测值和真实值的差值(残差块),CBP主要用于表示残差块的哪些信息为0,后面将再详细介绍;

  •  ➸ P Slice: Pslice中包含I宏块和P宏块,P宏块的mb_type如下所示,I宏块的mb_type – 5后和I slice中的I宏块含义相同,例如:Pslice的mb_type为6,则其为I宏块I_16X16_1_0_0
    请添加图片描述
    P宏块是前向参考,即根据前面的图像来恢复当前图像;16x16为单位,或者8x8,或者16*8等方式进行划分,参考前面的不同的图像;

  •  ➸ B Slice: Bslice中包含I宏块和B宏块,B宏块的mb_type如下所示,I宏块的mb_type – 23后和I slice中的I宏块含义相同,例如:B slice的某个宏块的mb_type为24,则其为I宏块I_16X16_1_0_0; P_L0_L0_16X8表示该16X16的宏块被划分为2个16*8的块,两个块都参考L0系列里的图像进行帧间编码(帧间预测时的参考图像分L0和L1两个系列)

请添加图片描述

B_Bi_L0_16X8表示该16X16的宏块被划分为2个16X8的块,两个块分别参考L0,L1系列里的图像(Bi),和L0系列的某个图像进行帧间编码

H264对于P_8X8,P_8X8ref0和B_8X8,如图所示我们可以将其进一步细分,最小可以再划分成4个4X4的块,因此我们在编码时,将这三种和比较特殊的B_direct_16X16单独写一种编码函数sub_mb_pred()进行编码。对其他类型的宏块用mb_pred()进行编码;

此外,H264中宏块的信息是经过DCT变换处理的,这个DCT变换可以是4X4为单位的,也可以是8X8为单位的,因此还需要对transform_size_8x8_flag这个信息进行编码,这个信息表示该宏块是采用8X8的单位编码(1),还是4X4的单位编码(0)。部分类型的宏块不支持8*8变换,因此这里是有个选择语句,;看起来有点复杂,总的来说就是这些情况:

  •  ❂ 1. 首先,transform_8X8_mode_flag相当于一个总开关,若该标志为0,则一定是DCT一定是4X4为单位,此时不对transform_size_8x8_flag进行编码(默认是0);
  •  ❂ 2. I_N*N 对transform_size_8x8_flag进行编码;
  •  ❂ 3. I_16*16不对transform_size_8x8_flag进行编码;
  •  ❂ 4. P和B的宏块除了被划分为8X8的(sub_mb_pred处理),其他的若宏块的luma的CBP大于0,则均需要对transform_size_8x8_flag进行编码;mb_type 为B_Direct_16x16且direct_8x8_inference_flag为0,则不编码transform_size_8x8_flag;
  •  ❂ 5. 对于sub_mb_pred处理的这几种宏块,若不含比8X8小的子宏块,且若子宏块含B_direct_8*8(此时direct_8x8_inference_flag为1),则编码transform_size_8x8_flag,否则不编码该元素;

由上表可知,宏块类型为I (Intra16*16)时,我们直接从mb_type就能看出来CBP(coded_block_pattern),而宏块类型就P,B时,我们无法直接看出CBP,因此我们还需要对P,B的CBP进行编码;

CodedBlockPatternLuma 和CodedBlockPatternChroma 分别代表亮度和色度的残差块信息是否为0,若为0就不编码了;因为Intra16X16的CBP可以直接从mb_type中获取,因此对残差块信息的编码程序有那三个条件;其中mb_qp_delta是残差块的量化系数,residual()则是对残差块信息的编码;

3、sub_mb_pred()和mb_pred()

由上述内容可知,只有B和P的部分宏块用sub_mb_pred()
因此sub_mb_pred()包含如下系数:
 ✠ 4个子宏块的类型
 ✠ 4组 ref_idx_l0(L0参考图像的坐标),mvd_l0(参考图像的运动信息)
 ✠ 4组 ref_idx_l1(L1参考图像的坐标),mvd_l1(参考图像的运动信息)
 ✠ P_8x8ref0不编码ref_idx_l0, B_Direct_8X8只编码sub_mb_type;

mb_pred()需要编码I宏块,因此可能含有帧内编码的信息,包含如下系数:
 ✸ Intra4X4 则编码16组prev_intra4x4_pred_mode_flag(是否直接采用临近块的帧内编码模式)rem_intra4x4_pred_mode(帧内编码的模式);
 ✸ Intra8X8 则编码4组prev_intra8x8_pred_mode_flag(是否直接采用临近块的帧内编码模式)rem_intra8x8_pred_mode(帧内编码的模式);
 ✸ Intra 16 X16的可以通过mb_type看出来,这里不做编码;
 ✸ 若含有chroma分量,还需要编码Intra_chroma_pred_mode(chroma帧内编码的模式)
 ✸ 若是B,P宏块,则为帧间预测,和sub_mb_pred()一样,编码每个宏块的ref_idx_l0,mvd_l0,ref_idx_l1和mvd_l1;

4、残差块residual()

残差块就是16X16的大小的,帧内或者帧间预测后,和原始图像的误差信息。以4X4或8X8为单位进行DCT变换和量化,变换单位的左上角的数值记为DC系数,其余位置的数值记为AC系数;

 ❂ significant_coeff_flag:该位置的残差系数是否为0,是为0,否为1;
 ❂ last_significant_coeff_flag:该位置是否为最后一个不为0的系数,是为1,不是为0
 ❂ coeff_abs_level_minus1:该位置i上残差系数的绝对值减1
 ❂ coeff_sign_flag[i]:该位置残差系数的正负号,1为正,0为负

5、总结

H264编码可以看成是,先根据一些其他信息进行预测,预测后的图像和原始图像有差异;H264就将预测方式和与原始图像的差异值保留。解码端可以通过预测方式恢复图像,再将差异值相加,从而达到较好的恢复压缩效果;

一个宏块里包含的信息,

 ✸  1. 是否skip? 宏块类型是什么,即采用哪种方式压缩;

 ✸  帧内编码:采用哪种模式根据上方和左侧数据恢复图像

 ✸  帧间编码:采用根据前面的哪张图像,或者后面的哪张图像的哪个位置来恢复当前图像,以及选取这个图像的具体哪个位置的16*16块来恢复当前图像;

 ✸ 4. DCT变化后的量化参数

 ✸ 5. 残差:通过预测恢复后的图像与原始图像的差异

6、参考资料

  1. 博客园的一个大佬,写的很全,对理解H264帮助很大
  2. CSDN : H.265/HEVC编码原理及其处理流程的分析
  3. H264官方标准协议下载链接(英)
  4. 新一代高效视频编码H.265/HEVC:原理、标准与实现,作者:万帅、杨付正

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

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

相关文章

vscode使用插件remote-ssh远程连接服务器

vscode使用插件remote-ssh远程连接服务器 0.引言1.配置密钥对1.1.本地端1.2.服务器端 2.服务器端配置3.vscode连接4.调试 0.引言 用上了公司百万级的服务器 &#x1f606; &#x1f606; &#x1f606; &#x1f606; 参考1参考2 1.配置密钥对 生成密钥对&#xff0c;是为了…

[离散数学]谓词逻辑与推理演算

文章目录 谓词逻辑辖域变元的约束---换自由变元 不容易出错枚举前束范式量词例子练习题特殊例子如果明天下雨&#xff0c;则某些人将被淋湿如果人都爱美,则漂亮的衣服有销路 谓词推理量词相关规则 (去量词 加量词) 谓词逻辑 辖域 变元的约束—换自由变元 不容易出错 枚举 前束范…

博客系统后端设计(五) - 实现登录页面功能

文章目录 约定前后端交互接口修改前段代码修改后端代码登录测试 约定前后端交互接口 这里约定请求是一个 POST 请求&#xff0c;路径是 /login&#xff0c;使用的是以下的格式&#xff1a; usernamzhangsan&password123 响应是 HTTP/1.1 302&#xff0c;因为在成功登录之…

SpringCloud(26.分布式服务框架Dubbo面试题简析)

上一篇&#xff1a;25. 简述 Seata 的原理 下一篇&#xff1a;27. Redis 和 ZK 分布式锁 文章目录 1. 为什么要将系统进行拆分&#xff1f;2. 如何进行系统拆分&#xff1f;3. 拆分后不用 dubbo 可以吗&#xff1f;4. dubbo 工作原理5. 注册中心挂了可以继续通信吗&#xff1…

【Drone】ubuntu 20.x 版本下 通过docker-compose方式部署drone的全流程 整合gitee

一、前期准备 1、ubuntu环境 确定是否具有 ssh&#xff1a; service ssh start&#xff0c;如果没有&#xff0c;使用&#xff1a;apt install openssh-server 进行安装查看 Linux 的 IP 地址&#xff1a; ifconfig&#xff0c;命令不可用时&#xff0c;通过&#xff1a;apt …

pdf太大,怎么压缩的小一点,这几个方法高效便捷

pdf太大&#xff0c;怎么压缩的小一点呢&#xff1f;我们在日常办公中&#xff0c;使用到pdf文件的情况很多。因为pdf文件可以在几乎所有操作系统和设备上打开&#xff0c;这使得它们非常方便。而且PDF 文件的内容和格式在不同设备之间始终保持一致&#xff0c;这意味着无论在哪…

PowerShell install 一键部署virtualbox

VirtualBox 前言 VirtualBox 是一款开源虚拟机软件。VirtualBox 是由德国 Innotek 公司开发&#xff0c;由Sun Microsystems公司出品的软件&#xff0c;使用Qt编写&#xff0c;在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。Innotek 以 GNU General Public Licens…

优思学院|什么是8D报告?

企业中的问题&#xff0c;就像生活中的麻烦事&#xff0c;总是层出不穷&#xff0c;让人头疼不已。有时候&#xff0c;我们可能会遇到一些棘手的问题&#xff0c;简单的方法已经无法解决了&#xff0c;这时候&#xff0c;8D问题解决法就是一把利器。 所以&#xff0c;我们不应…

档案室库房十防要求及措施

档案室“十防”措施 根据档案保护技术的要求&#xff0c;结合本公司档案实际&#xff0c;现制定“十防”措施如下&#xff1a; 一、 防火 1、 指定专人负责防火安全工作。 2、 定期检查手动灭火器&#xff0c;发现灭火器表压低于绿色区域时&#xff0c;必须及重新充装。 3、…

Consule系列:Consul实现详解

Consul 的实现 Consul 使用 Consensus 协议提供一致性(Consistency)—— CAP 定义的一致性。Consensus 协议是基于 “Raft: In search of an Understandable Consensus Algorithm” 实现的。 Consul Protocol Raft 算法 Raft 是基于 Paxos 的一致性算法。 与 Paxos 相比&#x…

Java每日一练(20230518) 移除元素、跳跃游戏II、复原IP地址

目录 1. 移除链表元素 &#x1f31f; 2. 跳跃游戏 II &#x1f31f;&#x1f31f; 3. 复原 IP 地址 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 移…

在 Mac M2 (arm64架构)上编译安装 GmSSL 工具

GmSSL是一个开源密码工具包&#xff0c;为GM/T系列标准中规定的中国国家密码算法和协议提供一级支持。作为OpenSSL项目的一个分支&#xff0c;GmSSL提供了与OpenSSL的API级兼容性&#xff0c;并维护了所有功能。现有的项目&#xff0c;如ApacheWeb服务器&#xff0c;只需稍加修…

前端面试题整理3

目录 1.不使用promise怎么实现一个异步编程? 2.this的指向有哪些&#xff1f; 3.Ref和reactive响应式的区别&#xff1f; 4.首屏加载优化。如何处理&#xff1f; 5.axios封装&#xff1f; 6.css为什么使用预处理&#xff1f; 7.从1000-9999里面取出AAAA这种数字&#xf…

从价格战中突围,仅10个月开发出一款车,安全性能靠谱吗?

经历了2023年初的价格战&#xff0c;一场关于智能汽车的淘汰赛似乎正式开始了。 尽管“降价热潮”还在继续&#xff0c;但简单的价格竞争毕竟非长久良策。 一方面&#xff0c;为了维持收益&#xff0c;部分车企通过减配、降低服务成本&#xff0c;甚至将降本压力给到上游供应…

【这个命令的 7 种用法!你确定不会用?】

可以很肯定地说&#xff0c;find 命令是 Linux 后台开发人员必须熟知的操作之一&#xff0c;除非您使用的是 Windows Server。 对于技术面试&#xff0c;它也是一个热门话题。让我们看一道真题&#xff1a; 如果你的 Linux 服务器上有一个名为 logs 的目录&#xff0c;如何删…

Spring 事务和事务传播机制

1.什么是事务&#xff08;为什么要有事务&#xff09; 事务就是将一组操作封装成一个执行单元&#xff08;封装到一起&#xff09;&#xff0c;要么一起成功&#xff0c;要么一起失败。 在打账的情景上&#xff0c;A向B转账200 元&#xff0c;A的账户-200.B的账号200&#xff…

基于直流微电网的光伏并网功率转换装置设计与运行仿真

摘要 微电网是目前国内外应用较为广泛的一种绿色可再生能源&#xff0c;近几年我国微电网产业的发展十分迅速。然后&#xff0c;越来越多的微电网系统建立并网&#xff0c;微电网产生的电能受外界因素影响较大&#xff0c;具有一定的随机性和波动性&#xff0c;给并网后的电力系…

SaaS 产品如何选择设计协作工具?

文章内容转载腾讯 CoDesign 随着互联网及其衍生技术的发展&#xff0c;企业比以往更依赖内容去吸引、去培养自己的用户&#xff0c;寻求转化。小鹅通就是在微信生态中帮助企业通过知识服务去实现内容分发和流量聚合&#xff0c;帮助企业沉淀用户&#xff0c;提供深度私域运营服…

回收站清空了怎么找回文件?3种办法恢复彻底删除文件!

电脑回收站大家都有一定的了解&#xff0c;只要在回收站的文件没有被删除的时候是可以还原的&#xff0c;但是回收站删除了&#xff0c;文件就无法直接恢复。回收站清空了怎么找回文件? 别着急&#xff0c;今天小编就分析几种恢复回收站删除数据的办法&#xff1a; 方法一&am…

(转载)从0开始学matlab(第8天)—matlab画图入门

1.基本画图方式 MATLAB 的扩展性和机制独立的画图功能是一个极其重要的功能.这个功能使数据画图变得十分简单 . 画一个数据图 , 首先要创建两个向量&#xff0c;由 x, y 构成 , 然后使用 plot 函数. 例如 , 假设我们要画出函数 yx -10x10 的图象 , 定义域为&#xff3b; …