这段时间一直在进行编写H264文件的解析类,因此对于H264文件的格式有了初步的了解,官方文档也看了个大概。这篇文章主要是总结了一些为解码H264文件而需要的一些前期知识,话不多说,下面是干货,有些是自己在wiki上翻译过来的,有些是看官方文档后发现的一些关键部分。
首先了解一下视频文件中的一些知识:


Video compression picture types(视频压缩图像类型)

1. 视频帧的压缩使用了不同的算法,这些应用于视频帧的不同算法被称为图像类型或者帧类型。a. I - 该帧可压缩程度最低,也不需要通过其他视频帧解码。b. P  - 该帧可以引用前面的帧的数据来解压缩并且相对于I帧来说,该帧可以压缩程度更高。c. B - 该帧可以引用前面的帧和后面的帧的数据,从而压缩程度最高。


(图为一段视频帧,由2个关键帧(I-frame),1个向前预测帧(P-frame)和1个双向预测帧(B-frame)构成)

这里共有三种类型的帧被用在视频压缩技术中:I-帧,P-帧 和 B-帧。
I-帧是一种“内编码图片”,实际上是一种信息十分详细的图片,跟传统的静态图片文件相似。P-帧 和 B-帧 只存储了部分的图片信息,因此相比于I-帧来说,他们需要更少的存储空间,也因此而提高了压缩速率。
P-帧(“预测图片”)只保存图片中与前一帧的不同的地方。比如,在一个场景中,汽车行驶在静止的背景中,只有汽车的运动需要被编码。编码器无需存储未改变的背景像素信息到P-帧中,因此而节省了空间,P-帧 也同样被称为 delta-帧。
B-帧(“双向预测图片”)通过比较现在的帧和前后的帧的不同来指定具体存储的内容,从而节省了更多的空间。


Slices(条带)

一个条带是一个帧中比较独特的区域,不同于该帧中的其他区域。在最新的国际标准中,这里已经存在 I-slices(I-条带),P-slices(P-条带)和 B-slices(B-条带)。


Macroblocks(宏块)

普遍来说,图片(帧)被分割成许多宏块和个体预测类型能够在宏块层被挑选出来,并且整个图片(帧)中的宏块与宏块并不相同,如下:
1. I-帧 只能包含内部宏块
2. P-帧 既能包含内部宏块,也能包含预测宏块
3. B-帧 能包含内部宏块,预测宏块和双向预测宏块
进一步说,在视频编解码H.264中,帧能够被分割成宏块序列,该宏块序列被称为条带(slices)。编解码过程不是使用I,B和P 帧类型作为选集,而是通过每个条带明确无误的选择出预测类型。在H.264文件中也能找到几个额外的 帧/条带 类型:
1. SI-帧/条带(Switching I);使编码流之间的转换变得更加容易;包含了 SI-宏块(一种内部编码宏块的特殊类型)
2. SP-帧/条带(Switching P);使编码流之间的转换变得更加容易;包含了 P-宏块 和/或 I-宏块。
3. muti-帧 动态预测(包括16个引用帧,或32个引用域)


Intra coded frames/slices(I-frames/slices or Key frames)(内编码帧/条带(I帧/条带 或者 关键帧))

1. I-帧 编码不依赖于其他帧
2. 可能被编码器生成并创建于一个随机访问点(来允许解码器在图片的该位置开始解码)
3. 当区分图片细节时也可能为了避免产生有效的 P-帧 或 B-帧 而生成
4. 普遍来说比其他类型的帧需要更多的位数来编码

通常,I-帧 被用来随机访问和作为其他图片(帧)解码时的引用。内部刷新周期通常为半秒(在数字电视广播和DVD存储介质中很常见)。在一些环境下,也可能需要更长的时间周期。比如,在视频会议系统中,通常会间歇的发送I-帧(不频繁的发送)。


Predicted frames/slices(P-frames/slices)(预测帧/条带(P-帧/条带))

1. 为了解码的需要,要优先解码一些其他图片(帧)
2. 可能包含图像数据或运动向量偏移量或者两者的组合
3. 能够按照解码顺序引用前面的图片
4. 旧的设计标准在解码时只使用一张前面的解码图片作为引用,并且需要该图片也要在P-帧图片之前显示。
5. 在H.264文件中,在解码过程中能够使用多个先前解码的图片作为引用,并且相对于被用来做预测的图片帧,该帧能够以任意顺序显示。
6. 通常,相对于编码I-帧来说,编码预测帧需要更少的比特位数。

Bi-directional predicted frames/slices(B-frames/slices)(双向预测帧/条带(B-帧/条带))

1. 为了解码的需要,要优先解码一些其他图片(帧)
2. 可能包含图像数据或运动向量偏移量或者两者的组合a. 旧的标准有一个关于整个帧的全局运动补偿向量b. 一些标准关于每个宏块都有一个运动补偿向量
3. 一些标准允许每个宏块使用两个运动补偿向量(双向预测)
4. 在旧的设计标准中(比如MPEG-2),B-帧从不用来作为其他图片(帧)的预测引用。因此,B-帧可以用一个稍低质量的编码(编码量少的)来完成,因为一些细节的丢失不会对预测后续图片(帧)的质量带来影响。
5. 在H.264文件中,有可能被作为解码其他图片(帧)的引用(由编码器决定)
6. 在旧的设计标准中(比如MPEG-2),在解码过程中会使用前面的2帧解码图片作为引用,并且需要其中一帧在B-帧之前显示,另外一帧在B-帧之后显示。
7. 在H.264文件中,能够使用1,2或者更多先前解码的图片(帧)作为解码过程中的引用,并且相对于被用来做预测的图片帧,该帧能够以任意顺序显示。
8. 通常,相对于编码I-帧 和 P-帧来说,编码该帧需要更少的比特位数。

有了已上的基本知识以后,我们已经了解到I-帧是关键帧,并且是占空间最多的帧,因为很多数据都是内编码的,而P-帧是预测帧,需要借助前面的帧来作为引用,从而得到完整的数据,而B-帧是双向预测帧,需要借助前面和后面的帧来作为引用。因此一般来说占用空间排序:I-帧 > P-帧 > B-帧 (I-帧占用空间最多)。

对于如何解析帧类型(I,P还是B帧等等),需要用到nal_unit_type这一字段,在Nalu中它占据第一个字节的3~8位,Nalu的第一个字节(忽略起始码startcode:0x000001 or 0x00000001)如下:
forbidden_zero_bit: 1 bit
nal_ref_idc: 2 bit
nal_unit_type: 5 bit
官方文档也给出了语义解析,以伪代码的形式给出的:

后面的f(1),u(2),u(5)是代表要使用的解析方法,前面加深的粗体forbidden_zero_bit,nal_ref_idc,nal_unit_type称为syntax_element,语法元素,即:解析这些语法元素要用到后面的f(1),u(2),u(5)方法,下面是官方文档中给出的解析方法:


这里面的解析方法,个人感觉只有Exp-Golomb-coded的解析有些麻烦(解析具体是什么帧需要用到该方法),其他的用简单的几个位操作就能轻松应对了吧,下面讲讲指数哥伦布编码的相关信息:


Exponential-Golomb(universal code):指数哥伦布编码

以下是wiki上给出的解释(给翻译过来的,英文水平不好,请轻喷,thanks)1. (默认k=0的形式)a. 将原数加1写成二进制形式b. 将1中的二进制的位数减一并记下,添加这么多个0到1中二进制位数的前面例子:0 ⇒ 1 ⇒ 11 ⇒ 10 ⇒ 0102 ⇒ 11 ⇒ 0113 ⇒ 100 ⇒ 001004 ⇒ 101 ⇒ 001015 ⇒ 110 ⇒ 001106 ⇒ 111 ⇒ 001117 ⇒ 1000 ⇒ 00010008 ⇒ 1001 ⇒ 0001001将其推广到负数范围表示,方法如下:(1) 非负整数x≤0映射到偶数-2x上(2) 正整数x>0映射到奇数2x - 1上例子:0 ⇒ 0 ⇒ 1 ⇒ 11 ⇒ 1 ⇒ 10 ⇒ 010−1 ⇒ 2 ⇒ 11 ⇒ 0112 ⇒ 3 ⇒ 100 ⇒ 00100−2 ⇒ 4 ⇒ 101 ⇒ 001013 ⇒ 5 ⇒ 110 ⇒ 00110−3 ⇒ 6 ⇒ 111 ⇒ 001114 ⇒ 7 ⇒ 1000 ⇒ 0001000−4 ⇒ 8 ⇒ 1001 ⇒ 00010012. 衍生到k阶(k≥0)形式a. 用于编码更大的数,编码后形成更少的二进制位(编码比较小的数需要使用更多的二进制位数)b. 要以k阶形式编码一个非负整数x,方法如下:i. 以0阶方式编码⌊x/2^k ⌋ii. 将x取模2^k等价方式:i. 使用0阶exp-Golomb编码方式编码x+2k−1ii. 从编码结构中删除前面的k个0位


官方文档有关于解析哥伦布指数编码的方法,of course,仍然是以伪代码的形式给出: )


再继续说解析帧类型的方法…
依然是官方文档….
发现了这么一个东东

这应该就是我们要分析该Nalu是什么帧类型的关键吧!于是找找它在哪里出现过

很明显,第3行出现了,再找找slice_header出现的地方


然后再继续逆向查找它们分别出现在哪里,结果最后都在一张表中找到了

于是开始分析:

  1. 对于slice_layer_without_partitioning_rbsp:

    1. nal_unit_type = 1,5,19
  2. 对于slice_data_partition_a_layer_rbsp:
    1. nal_unit_type = 2
  3. 对于slice_layer_extension_rbsp:
    1. nal_unit_type = 20
      于是下面就是具体分析nal_unit_type的值来进行相应处理的过程:
      首先,在代码中枚举如下NAL单元类型(参考了下ffmpeg)

      相应的,枚举如下Slice类型,根据Slice类型即能得出帧类型

      (具体为什么要都定义2种,因为根据官方文档来写的,其实每个第二种类型数值-5即为第一种类型,没有仔细研究)
      具体的解析代码在我的GitHub上,欢迎参观:yijiazhen的GitHub
      刚刚接触H264文件解析不久,如有分析错误或是不到位的地方,恳请各路好汉批评指正,希望可以互相交流,共同提高。

解码H264文件的一些基础知识相关推荐

  1. 【文件上传漏洞11】中间件文件解析漏洞基础知识及实验——Nginx

    目录 1 文件解析漏洞概述 1.1 概述 1.2 Nginx 解析漏洞 1.2.1 空字节解析漏洞 1.2.2 文件名逻辑漏洞 CVE-2013-4547 1.2.3 CGI-PHP 解析漏洞 2 实 ...

  2. 计算机基础文件与文件夹,计算机基础知识 第03部分 操作系统 文件与文件夹管理.ppt...

    文档介绍: 文件(夹)和程序的管理怕鄙扰蛆甩行陀渴侍往拽监扇散抑人蓟毒融莽斜撼熙掺拧茫炕惶甭喜妥超计算机基础知识第03部分操作系统文件与文件夹管理计算机基础知识第03部分操作系统文件与文件夹管理第3章 ...

  3. linux 筛选文件,「Linux基础知识」grep文件内容筛选命令的使用

    原标题:「Linux基础知识」grep文件内容筛选命令的使用 grep命令用于从文档中抓取显示包含指定字符的行,grep命令的使用格式如下: grep [选项] 匹配模式 文件1 文件2 ...... ...

  4. java反射头文件_编程基础知识——C++能不能支持Java和ObjC的反射?

    C++能不能支持Java和ObjC的反射? 要回答这个问题.首先我们要清楚什么是反射.什么是反射? 教科书的解释我就不说了,(^o^)事实上我也记不得.实际开发应用的反射就是在没有某个类型的头文件或者 ...

  5. 计算机基础知识学习第七课,7、新建文件夹--电脑基础知识

    在电脑中一般建一个自己的文件夹,这样自己的文件都放在里头,不容易弄乱,找起来也方便 (电脑入门到精通网 www.58116.cn) (电脑入门到精通网 www.58116.cn) C:盘一般是系统盘, ...

  6. 运行python程序的两种方式交互式和文件式_Python基础知识2

    运行Python程序的两种方式 小白学习,如有错误欢迎指点 一.每位小白写的第一个Python程序 1.运行Python程序的两种方式 1.1 交互式模式(即时对话) 打开cmd,打开Python解释 ...

  7. 文件的读写基础知识总结

    文章目录 文件打开 关闭文件 读取文件 较大文件的读取 文件的写入 二进制文件写入 删除目录 json 把文件以json格式储存 打开json格式的文件 文件打开 读 - r: 以只读模式打开文件,文 ...

  8. 文件(QTextStream基础知识)

    QTextStream类提供了一个方便的接口来读/写文本,可以在QIODevice.QByteArray.QStrirng上进行操作. 使用QTextStream的流操作符(<<),可以方 ...

  9. 大作业-点灯机器人-记录心得(1)-----基础铺垫-文件基础知识

    我在此次大作业的任务中负责的是绘制模块,任务是根据玩家输入的参数绘制生成对应的地图,以及每走一步生成一张新的状态图保存下来. 由于我的二位队友很早就写完了他们的部分,而我由于各方面繁多事务与学业压力迟 ...

  10. 计算机自学知识,计算机基础知识自学

    计算机基础知识自学 计算机基础知识自学 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能.是能够按照程序运行,自动.高速处 ...

最新文章

  1. 图像几何变换C++实现--镜像,平移,旋转,错切,缩放
  2. Hibernate学习(九)———— 二级缓存和事务级别详讲
  3. 利用SMS OSD实现win2008操作系统的部署
  4. Docker框架的使用系列教程(二)
  5. devices-list
  6. 机器学习入门系列(1)--机器学习概览
  7. php e error,E_ERROR定义与用法汇总
  8. 计算机视觉论文-2021-06-21
  9. 先查询后修改并发的时候sql_如何解决并发场景下扣款的数据一致性问题?
  10. Windows Phone 7 文件下载进度和速度显示
  11. [读后感]Java 控制台执行 Jar 传參的编码问题
  12. 数据结构-----栈+中缀表达式(计算器)
  13. FR cpt报表的自动滚屏/滚动编辑
  14. Python常用的19个工具包汇总
  15. 一体机扫描文档FTP搭建全程
  16. Python菜鸟起飞day2--数据类型(元组,字典,字符串)
  17. 模拟实现内存动态分区分配与回收
  18. Java --- 线程同步和异步的区别
  19. 人的天性是贪嗔痴和戒定慧的等量叠加态
  20. oracle收购了什么意思,BEA为何会被Oracle收购?

热门文章

  1. 对话 “智能+”平台大师,看IBM如何重塑企业数字化
  2. scratch3.0 整体页面介绍
  3. java调用hownet--jni
  4. 基于vue和springboot的物流仓储管理系统
  5. 你还在使用xshell绿色破解版?
  6. hdfs及yarn的ha和failover
  7. Mintec.MineSight.3D.v7.0.3
  8. 新建网站的长尾词应该如何去做优化
  9. idea抽取重复方法快捷键_idea 常用快捷键
  10. 《安富莱嵌入式周报》第259期:2022.03.28--2022.04.03