前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android音视频H264码流结构

Android音视频H264码流结构

原创
作者头像
花落花相惜
修改于 2021-11-24 05:47:25
修改于 2021-11-24 05:47:25
6550
举报

H.264码流格式

h264的有两种码流格式:字节流格式和RTP包格式。

字节流格式

`Annex-B Byte stream

format,这个是官方h264协议文档中规定的格式,所以它是大多数编码器默认的编码后的输出格式。它的基本数据单位为NAL单元,简称NALU`(Network

Abstraction Layer

Unit)。每个NALU的前面加上起始码:0x000001(3个字节)或0x00000001(4个字节)用于分割,后面会介绍。

RTP包格式

这种格式没有在h264中规定,这种格式不需要起始码分割NALU,而是在NALU开始的几个字节代表NALU的长度。这个我没有过多研究,应该是不常用的。

所以我们这里主要介绍的就是字节流格式的h264裸流。所谓的裸流就是经编码器编码后输出的数据,而没有经过传输协议(比如flv)封装的数据,这样的数据就叫做裸流。

H.264结构

码流分层

如上所说h264码流是由一个接一个的 NALU组成的,但是它按照功能分为

视频编码层:VCL(Video Coding Layer),编码器压缩处理后的压缩视频数据序列。

网络抽象层:NAL(Network Abstraction

Layer),负责以网络要求的格式对数据进行打包和传送,是传输层。不管是本地保存还是在网络上传送,都需要通过这一层来传输。

也就是视频编码数据(VCL)在传输或存储(保存到文件)之前,会先被封装进NAL(也就是NALU)单元才可以。

NALU(NAL单元)

h264码流是一系列的NALU组成,用起始码分割每个。所以整体看码流的格式就是:

H264码流 = …Start_Code_Prefix + NALU + Start_Code_Prefix + NALU + …

Start_Code_Prefix

标示的就是起始码,起始码为:0x000001(3个字节)或0x00000001(4个字节),起始码中间的部分就是NALU的部分。

我们看下我们从抖音/快手提取的h264文件的开始部分(因为h264格式开始有SPS,PPS,SEI 分割较多,你可以搜索一下文件后后面的数据流也有):

起始码.png

NALU的主体是:NALU=NALU Header + EBSP

NALU的主体有细分:分别为EBSP、RBSP和SODB。其中EBSP完全等价于NALU主体,而且它们三个的结构关系为:

EBSP包含RBSP,RBSP包含SODB。

EBSP名字叫:扩展字节序列载荷(Encapsulated Byte Sequence Payload)

RBSP名字叫:原始字节序列载荷(Raw Byte Sequence Payload)

SODB(String Of Data Bits)就是最原始的编码数据。

后续介绍,先有个大概的概念区分,真的是概念非常多。

NALU Header

NALU Header 在每个的NALU中,占据一个字节也就是8位。分三部分,如下:

名称

占据位数bit

代表的意义

forbidden_zero_bit

1bit

h264文档规定,这个值应该为0,当它不为0时,表示网络传输过程中,当前NALU中可能存在错误,解码器可以考虑不对这个NALU进行解码

nal_ref_idc | 2bit | 取值0~3,代表当前这个NALU的重要性,取值越大,代表当前NALU越重要

nal_unit_type | 5bit | NALU的数据类型,比如是sps,pps,sei,idr等

我们主要看一下nal_unit_type在h264协议中定义如下:

nal_unit_type.png

nal_unit_type =1-5是VCL(视频编码层)单元。

6-代表当前NALU为辅助增强信息(SEI)。一般会埋入视频版权等信息。

7-代表当前NALU为序列参数集SPS,包括一个图像序列的所有信息,即两个 IDR 图像间的所有图像信息,如图像尺寸、视频格式等

8-代表当前NALU为图像参数集PPS,包括一个图像的所有分片的所有相关信息, 包括图像类型、序列号等

一般h264的码流最开始都是SEI,SPS,PPS,IDR(I帧)...,SPS,PPS,IDR(I帧).

一般在IDR(I帧)前有SPS,PPS,也就是每一组图像(GOP序列,图片组)都给予了图像参数集(PPS)和这个序列参数集SPS(SPS)。我们看下最开始提取的抖音的h264文件(也就是上面启始码的后一字节)。

代码语言:txt
AI代码解释
复制
// 这里只贴了关键字节,省略其它的
代码语言:txt
AI代码解释
复制
// 16进制打开,每2位数是一个字节byte=8位(bit)
代码语言:txt
AI代码解释
复制
// 1F的二进制位的后五位为:11111
代码语言:txt
AI代码解释
复制
0000 0001 0605 ffff e1dc 45e9 bde6 d948  SEI  06&1F取该字节的后五位=6
代码语言:txt
AI代码解释
复制
3d31 3a31 2e30 3000 8000 0000 0167 6400  SPS  67&1F取该字节的后五位=7
代码语言:txt
AI代码解释
复制
0303 c0f1 8319 a000 0000 0168 e978 b2c8  PPS  68&1F取该字节的后五位=8
代码语言:txt
AI代码解释
复制
b000 0001 6588 8400 4ffe 841f c0a5 9f35  IDR  65&1F取该字节的后五位=5
代码语言:txt
AI代码解释
复制
71b9 4cd3 13c1 0000 0001 419a 246c 47ff  slice(片)  41&1F取该字节的后五位=1

视频的宽高就是在SPS中取出来的。

EBSP和RBSP

NALU的起始码为0x0000010x00000001,但是有一种在NALU的内部也有0x0000010x00000001的数据怎么办?H264采用了一种方法如果NALU内部出现了编码器就在最后一个字节前,插入一个新的字节:0x03。做了如下4种情况的处理:

代码语言:txt
AI代码解释
复制
0x000000  插入x03  0x00000300
代码语言:txt
AI代码解释
复制
0x000001  插入x03  0x00000301
代码语言:txt
AI代码解释
复制
0x000002  插入x03  0x00000302
代码语言:txt
AI代码解释
复制
0x000003  插入x03  0x00000303

0x000003是为了防止NALU内部本来就有0x000003这样的数据。

所以说EBSP相较于RBSP,多了防止冲突的一个字节:0x03。当使用EBSP时,就需要检测EBSP内是否有序列:0x000003,如果有,则去掉其中的0x03。这样一来,我们就能得到原始字节序列载荷:RBSP。

我们用提取的抖音的h264文件找下:

代码语言:txt
AI代码解释
复制
3d31 3a31 2e30 3000 8000 0000 0167 6400
代码语言:txt
AI代码解释
复制
1fac d980 b40a 1b01 1000 0003 0010 0000
代码语言:txt
AI代码解释
复制
// 比如67=SPS 的NALU就有一个0303
代码语言:txt
AI代码解释
复制
0303 c0f1 8319 a000 0000 0168 e978 b2c8
代码语言:txt
AI代码解释
复制
b000 0001 6588 8400 4ffe 841f c0a5 9f35
代码语言:txt
AI代码解释
复制
11fe 06cb d3bf 26e6 9d1f ff2c e1b1 aaf2

RBSP和SODB

原始编码数据SODB(String Of Data Bits)他们2个的关系是:

RBSP = SODB + RBSP尾部

RBSP尾部

H264协议文档中有两种尾部表示,如下:

RBSP尾部.png

尾部特RBSP语法

RBSP最后一个字节的最后一个比特为rbsp_stop_one_bit,其值为1,并且当rbsp_stop_one_bit不是最后一个比特时,用一个或多个rbsp_alignment_zero_bit,其值为0,补齐以形成一个字节对齐。

条带RBSP尾部

nal_unit_type等于1~5时采用这种尾部。在尾部特RBSP语法的基础上,如果当entropy_coding_mode_flag值为1,也即当前采用的熵编码为CABAC,而且more_rbsp_trailing_data返回为true,也即RBSP中有更多数据时,添加一个或多个0x0000

H264的码流结构

所以整体H.264的Annex-B码流格式从概念上来看就是,SODB里就是原始的编码数据。

H.264 Annex-B 码流格式.png

如有描述不准确欢迎指正。

H.264的协议文档

http://www.itu.int/rec/T-REC-H.264(https://links.jianshu.com/go?to=http%3A%2F%2Fwww.itu.int%2Frec%2FT-

REC-H.264-200503-S%2Fen)

http://www.itu.int/rec/T-REC-H.264-200503-S/en(https://links.jianshu.com/go?to=http%3A%2F%2Fwww.itu.int%2Frec%2FT-

REC-H.264-200503-S%2Fen)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
暂无评论
推荐阅读
Git ssh 配置及使用
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/53573399
程序员徐公
2018/09/18
2.4K0
Git ssh 配置及使用
Git ssh 配置及使用
前言:前几天在写博客 手把手教你用Hexo + github 搭建自己博客的时候,经常需要用到一些git操作,截了好多图,于是就想干脆整理成一系列的git 教程,总结如下
Dream城堡
2018/09/10
7380
Git ssh 配置及使用
Git入门学习到进阶3
但是在GitHub上,利用Git极其强大的克隆和分支功能,广大人民群众真正可以第一次自由参与各种开源项目了。
全栈工程师修炼指南
2022/09/28
5580
Git入门学习到进阶3
mac下使用github
      提起github相信大家都不会陌生,在这里就不再赘述了。作为开源代码库以及版本控制系统,使用好了确实会非常受益,再说的势利点,你找工作时给面试官说你经常维护自己的技术博客和github,相信你给他的印象会好很多。      windows底下如何使用github,很多好心人都已经给了非常详细的解决方案,你只需问下度娘,她会帮你解决,这里对于windows底下的使用我也就不再赘述了。这里主要讲讲如何在mac底下使用github,我刚开始使用时,还是费了一点功夫的,因为网上的资料比较杂,有些不是太准
猿人谷
2018/01/17
9540
mac下使用github
【踩坑实录】Github提交时出现错误:remote:Permission to xxx/test.git denied to xxx
第一个账号进行了提交之后,这个账号的凭据信息就被保存了下来,然后切换到第二个账号进行提交时,系统依然会使用第一个账号的凭据信息进行提交,因此便会报错。
知识分子没文化
2023/07/01
1.1K0
【踩坑实录】Github提交时出现错误:remote:Permission to xxx/test.git denied to xxx
使用 SSH 连接到 GitHub(多帐号)
◎ 通过 SSH 克隆仓库 我们克隆 GitHub 上的仓库时,一般是通过默认的 HTTPS 的方式,而非上面这种 SSH 的方式。对于克隆仓库的话,我们使用起来是感受不到这两种方式的差别的。但是,当
莲花海
2020/01/21
1.5K0
多个git账号之间的切换
做过很多遍了,却总是记不住,这回从头来描述一下。 介绍 所谓多个git账号,可能有两种情况: 我有多个github的账号,不同的账号对应不同的repo,需要push的时候自动区分账号 我有多个git的账号,有的是github的,有的是bitbucket的,有的是单位的gitlab的,不同账号对应不同的repo,需要push的时候自动区分账号 这两种情况的处理方法是一样的,分下面几步走: 处理 先假设我有两个账号,一个是github上的,一个是公司gitlab上面的。先为不同的账号生成不同的ssh-key
happy123.me
2018/06/04
2.2K0
github网站介绍、并使用git命令管理github(详细描述)
  比如:别人通过fork你的项目后,并改进了项目,向你发送了new pull request请求,
诺谦
2019/05/24
1.1K0
GitHub不再支持密码验证解决方案:SSH免密与Token登录配置
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
周陆军
2021/08/14
118.8K0
解决github提交代码Support for password authentication was removed 问题
一大早发现周末的代码commit之后没有push。按照之前的常规操作,采用用户名+密码的方式,通过https的方式push代码。结果出现如下错误:
冬天里的懒猫
2021/08/20
2.9K0
解决github提交代码Support for password authentication was removed 问题
Git的常用命令
git clone 命令默认的只会建立master分支,如果你想clone指定的某一远程分支(如:dev)的话,可以如下:
新人小试
2018/09/19
1K0
Git的常用命令
如何上传项目到GitHub
github作为开源的分布式版本管理系统,上面有众多的优秀开源项目,也有丰富的学习资料,熟练使用github也是程序员的一项必备技能。下面简单介绍下如何提交代码到github。
吾非同
2020/10/23
9110
如何上传项目到GitHub
windows git 使用的一些问题和解决方案
没这个习惯都把私钥叫id_rsa这个名字, 通常也不会放在 ~/.ssh目录下 , 但是他默认就在那儿=>C盘,我非要放D盘怎么弄?
chuchur
2022/10/25
8890
git push上传代码到gitlab上,报错401/403(或需要输入用户名和密码)
之前部署的gitlab,采用ssh方式连接gitlab,在客户机上产生公钥上传到gitlab的SSH-Keys里,git clone下载和git push上传都没问题,这种方式很安全。 后来应开发同事要求采用http方式连接gitlab,那么首先将project工程的“Visibility Level”改为“Public”公开模式,要保证gitlab的http端口已对客户机开放。 后面发现了一个问题: http方式连接gitlab后,git clone下载没有问题,但是git push上传有报错: erro
洗尽了浮华
2018/01/23
3.8K0
git push上传代码到gitlab上,报错401/403(或需要输入用户名和密码)
关于VSCode推送GitHub团队项目403的问题
推测 403(Permission Denied)是由于 VSCode 自带的扩展 "GitHub" 登录 GitHub 账号时请求的权限不足导致。
TagBug
2023/03/17
1.5K0
GitHub 系列之「向GitHub 提交代码」1.SSH2.生成SSH key3.GitHub 上添加 SSH key4.Push & Pull5.提交代码
你拥有了一个 GitHub 账号之后,就可以自由的 clone 或者下载其他项目,也可以创建自己的项目,但是你没法提交代码。仔细想想也知道,肯定不可能随意就能提交代码的,如果随意可以提交代码,那么 GitHub 上的项目岂不乱了套了,所以提交代码之前一定是需要某种授权的,而 GitHub 上一般都是基于 SSH 授权的。
Python攻城狮
2018/08/23
5000
GitHub 系列之「向GitHub 提交代码」1.SSH2.生成SSH key3.GitHub 上添加 SSH key4.Push & Pull5.提交代码
git 把项目托管到 码云出现的错误集合
https://blog.csdn.net/weixin_49931650/article/details/132416285?spm=1001.2014.3001.5501
打不着的大喇叭
2024/03/11
2660
git 把项目托管到 码云出现的错误集合
git配置远程仓库,同时配置github、gitee、gitlab,完美解决方案
新安装 git 跳过。 若之前对 git 设置过全局的 user.name 和 user.email。(用 git config --global --list 进行查看你是否设置) 必须删除该设置 git config --global --unset user.name "你的名字" git config --global --unset user.email "你的邮箱"
鳄鱼儿
2024/05/21
5500
git ssh 配置多个账户
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/53573426
程序员徐公
2018/09/18
1.8K0
git ssh 配置多个账户
github多账户切换
由于工作需要,有两个github的账号,需要经常切换账户,下面展示具体操作步骤。
猫叔Rex
2020/06/30
3.1K0
相关推荐
Git ssh 配置及使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档