本文记录一下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编码格式简单分析的更多相关文章

  1. 【视频编解码·学习笔记】6. H.264码流分析工程创建

    一.准备工作: 新建一个VS工程SimpleH264Analyzer, 修改工程属性参数-> 输出目录:$(SolutionDir)bin\$(Configuration)\,工作目录:$(So ...

  2. 视音频数据处理入门:H.264视频码流解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  3. 新手学习FFmpeg - 调用API完成录屏并进行H.264编码

    Screen Record H.264 目前在网络传输视频/音频流都一般会采用H.264进行编码,所以尝试调用FFMPEG API完成Mac录屏功能,同时编码为H.264格式. 在上一篇文章中,通过调 ...

  4. H.264视频压缩标准

    H.264 这部分一直在讲,但是却没有系统的来说.接下来要详细. 参看:H.264视频压缩标准 一.简介 H.264是最新的视频压缩标准,它也称为MPEG-4 Part 10或AVC(高级视频编码). ...

  5. H.264码流结构解析

    from:http://wenku.baidu.com/link?url=hYQHJcAWUIS-8C7nSBbf-8lGagYGXKb5msVwQKWyXFAcPLU5gR4BKOVLrFOw4bX ...

  6. FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  7. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  8. FFmpeg的H.264解码器源代码简单分析:熵解码(Entropy Decoding)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  9. FFmpeg的H.264解码器源代码简单分析:解码器主干部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

随机推荐

  1. package.json中devDependencies与dependencies的区别

    前言:之前一直不懂既然都是项目的依赖,为什么要分成两个部分,devDependencies和dependencies,有什么区别? 安装方式 我们在通过npm安装插件或库时,有三种方式: npm in ...

  2. js-权威指南学习笔记18

    1.除mouseenter和mouseleave外的所有鼠标事件都能冒泡. 2.传递给鼠标事件处理程序的事件对象有clientX和clientY属性,它们制订了鼠标指针相对于包含窗口的坐标. 3.一个 ...

  3. 【代码笔记】iOS-gif图片播放

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...

  4. 计算mysql中某个字段某字符出现的次数,case when 和 截取字符的用法

    select LENGTH(type) - LENGTH(replace(type,'_','')) as counts from sa_log_olap where type like 'XX_XX ...

  5. cocos2d-x学习网站

    非常好的学习cocos2d-x网站 强烈推荐!---游戏蛮牛

  6. 解决 login.live.com onedrive.live.com 等微软国外网站打不开问题

    下面就分享一下通过更改HOSTS文件的方式打开onedrive网页版的方法. C:\Windows\System32\drivers\etc目录下的hosts文件把它复制到D盘,再复制一份放到桌面上. ...

  7. Spring Boot—18Redis

    pom.xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-ja ...

  8. 如何选择分布式事务形态(TCC,SAGA,2PC,基于消息最终一致性等等)

    各种形态的分布式事务 分布式事务有多种主流形态,包括: 基于消息实现的分布式事务 基于补偿实现的分布式事务 基于TCC实现的分布式事务 基于SAGA实现的分布式事务 基于2PC实现的分布式事务 这些形 ...

  9. SwipeRefreshLayout的高度测量

    感谢此作者的分享 http://www.cnblogs.com/linjzong/p/5221604.html 若SwipeRefreshLayout的子布局为一个线性布局LinearLayout, ...

  10. python中的字符串编码问题——3.各操作系统下的不同编码方式

    各操作系统下的不同编码方式  先看一下 linux,python2.7 >>> B = b'\xc3\x84\xc3\xa8' >>> B.decode('utf- ...