H.264编码格式简单分析
本文记录一下H.264的编码格式。H.264官方文档:https://github.com/jiayayao/DataSheet/tree/master/encode-decode/h264。
一、H.264编码格式
H.264从层次来看分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL,Network Abstraction Layer)。VCL输出的是原始数据比特流(SODB,String of data bits),表示H.264的语法元素编码完成后的实际的原始二进制码流。SODB通常不能保证字节对齐,故需要补齐为原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。H.264引入了片(slice)的概念,每个片只携带该片自身独有的句法元素,一个片的丢失不会影响其他片的解码,还可以通过该片前后的片来恢复该片的解码。
NAL层实际上就是最终输出的H.264码流,它是由一个个NALU组成的,每个NALU包括一组对应于视频编码数据的NAL头信息和一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。以上名词之间的关系如下:
RBSP = SODB + RBSP trailing bits
NALU = NAL header( byte) + RBSP
H. = Start Code Prefix( bytes) + NALU + Start Code Prefix( bytes) + NALU +…
所以H.264码流的结构如下:

每个NALU之间由起始码(Start Code Prefix)分隔,起始码分为两种:0x000001(3 bytes) or 0x00000001(4 bytes). 如果NALU 对应的Slice 为一帧的开始,则用4 字节表示,即0x00000001;否则用3 字节表示,0x000001.NALU针对起始码设计了防止冲突机制,如果出现连续的0x000000,0x000001,0x000002,0x000003时,会在两个0之间插入03,如下:
0x00 -> 0x00
0x00 -> 0x00
0x00 -> 0x00
0x00 -> 0x00
一个NALU就是编码后的一帧数据。NAL header是一个字节:
forbidden_zero_bit(1 bit) 禁止位,等于0;
nal_ref_idc(2 bit)指示当前NAL的优先级,取值范围为0~3,值越高,表示当前NAL越重要。H.264规定,如果当前NAL是序列参数集,或是图像参数等,该值必须大于0.比如nal_unit_type等于5时,nal_ref_idc大于0;nal_unit_type等于6,9,10,11或12时,nal_ref_idc等于0;
nal_unit_type表示当前NALU的类型,表格如下:
|
nal_unit_type |
NAL类型 |
C |
|
0 |
未使用 |
|
|
1 |
不分区、非IDR图像的片 |
2,3,4 |
|
2 |
片分区A |
2 |
|
3 |
片分区B |
3 |
|
4 |
片分区C |
4 |
|
5 |
IDR图像中的片 |
2,3 |
|
6 |
补充增强信息单元(SEI) |
5 |
|
7 |
序列参数集(SPS) |
0 |
|
8 |
图像参数集(PPS) |
1 |
|
9 |
分界符 |
6 |
|
10 |
序列结束 |
7 |
| 11 | 码流结束 | 8 |
| 12 | 填充 | 9 |
| 13~23 | 保留 | |
| 24~31 | 未使用 |
nal_unit_type=5时,表示当前NAL是IDR图像的一个片,此时,IDR图像中的每个片的nal_unit_type都应该等于5.
一般H.264原始码流是以SPS->PPS->SEI->IDR->SCLICE->SCLICE…开头的。
GOP即Group of picture(图像组),指两个I帧之间的距离。即几秒有一个关键帧。一般在2、3秒之间。
二、H.264 Tips
H.264有两种封装格式:
(1)annexb模式:传统模式,使用start code来分隔NAL, SPS和PPS是在ES流的头部;
Annex-B: startCode Nalu1, startCode Nalu2......startCode NaluN
(2)mp4模式:没有start code,使用NALU长度(固定字节,通常为4个字节)来分隔NAL。AVCodecContext的extradata内部保存着分隔的字节数,SPS和PPS;
mp4(AVCC): NaluLength Nalu1, LaluLength Lalu2, ......NaluLength NaluN
SPS的头部是0x67,PPS的头部是0x68,要保持对数据的敏感性。
IDR帧:IDR帧都是I帧,H.264引入IDR图像是为了解码的重同步,当解码器解码到IDR帧时,会立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数及,开始一个新的序列。IDR帧之后的图像永远不会引用IDR帧之前图像的数据来解码。IDR帧一定是I帧,I帧不一定是IDR帧。
当解码器性能不足需要丢帧时,nal_ref_idc可以作为判断能否丢帧的依据。如果nal_ref_idc为0,则可以丢弃。当该帧nal_unit_type等于6,9,10,11或12时,nal_ref_idc为0。部分非IDR帧的nal_ref_idc也为0,也可以丢弃。丢弃的同时也能保证不会花屏。
H.264编码格式简单分析的更多相关文章
- 【视频编解码·学习笔记】6. H.264码流分析工程创建
一.准备工作: 新建一个VS工程SimpleH264Analyzer, 修改工程属性参数-> 输出目录:$(SolutionDir)bin\$(Configuration)\,工作目录:$(So ...
- 视音频数据处理入门:H.264视频码流解析
===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...
- 新手学习FFmpeg - 调用API完成录屏并进行H.264编码
Screen Record H.264 目前在网络传输视频/音频流都一般会采用H.264进行编码,所以尝试调用FFMPEG API完成Mac录屏功能,同时编码为H.264格式. 在上一篇文章中,通过调 ...
- H.264视频压缩标准
H.264 这部分一直在讲,但是却没有系统的来说.接下来要详细. 参看:H.264视频压缩标准 一.简介 H.264是最新的视频压缩标准,它也称为MPEG-4 Part 10或AVC(高级视频编码). ...
- H.264码流结构解析
from:http://wenku.baidu.com/link?url=hYQHJcAWUIS-8C7nSBbf-8lGagYGXKb5msVwQKWyXFAcPLU5gR4BKOVLrFOw4bX ...
- FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- FFmpeg的H.264解码器源代码简单分析:熵解码(Entropy Decoding)部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- FFmpeg的H.264解码器源代码简单分析:解码器主干部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
随机推荐
- MySql基本学习知识点:
1.Mysql的简介: (1):常识: MySQL是一种关系数据库管理系统,是一种开源软件 由瑞典MySQL AB公司开发,2008年1月16号被Sun公司收购.2009年,SUN又被Oracle收购 ...
- react组件更新swiper
如果swiper渲染出来的数据不是写死的,那么就会涉及到swiper的更新, 那么我们在new 出 swiper 实例的时候,就需要把这个实例添加到组件里面去,在更新的或卸载的时候就可以直接使用 sw ...
- JQuery 简单表格验证
<form action="{% url 'register' %}" method="post"> 用户名:<input id=" ...
- git常用命令简集
基础操作: 初始化git仓库: git init 提交到暂存区: git add “filename” 提交到分支: git commit -m "注释" 工作区状态: git s ...
- 软工读书笔记 week 6 ——《疯狂的程序员》Part 1
这本小说以主人公绝影上大学后初次接触编程开始讲起,这周主要看的就是绝影还在大学的那段经历,虽然故事背景很多年前,但很多地方仍然会引发我的共鸣. 第一个梦想 在“第一个梦想”一节讲了作业布置做一个通讯录 ...
- 从零开始——MySql01
注:如有侵权,请速联系,会速度删除!(都是同学分享的内容) 安装详解: 链接:http://pan.baidu.com/s/1skMQVgx 密码:z0xh Navicat安装包: 链接:http:/ ...
- fastdfs搭建和使用
目录 前言 安装 安装插件 tracker storage 用自带的 client 进行测试 想要查看结果必须安装nginx 使用示例 引用 配置 使用 前言 参考网址 错误处理 安装 安装插件 yu ...
- Linux 系统的用户和组详解_【all】
1.Linux 用户和用户组详解 2.Linux 文件特殊权限详解 3.Linux 文件的读写执行权限的说明 4.Linux 架构之简述企业网站 5.Linux 环境变量设置详解 6.企业生产环境用户 ...
- handsontable 和 echarts都定义了require方法,初始化时冲突了,怎么办?
echarts初始化时报这个错误. require.config is not a function 方案一: 让其中一方的初始化不依赖于 require即可 1.去掉 var testDrowEc ...
- Bootstrap后台管理框架
B-JUI http://www.xknaan.com/ B-JUI 前端框架,基于Bootstrap的Jquery UI框架,核心思想脱胎于DWZ(j-ui). BJUI_SSM_DEMO 基于 ...