H264编码 封装成MP4格式 视频流 RTP封包
From:http://www.cnblogs.com/ghw-NO1/archive/2012/08/28/2660848.html
一、概述
本文讲述的是对H264编码且封装成MP4格式的视频流进行RTP打包过程时需要了解的一些基本知识。
二、H264的基础知识
1.H264的编码格式
H.263 定义的码流结构是分级结构,共四层。自上而下分别为:图像层(picturelayer)、块组层(GOB layer)、宏块层(macroblock layer)和块层(block layer)。而与H.263 相比,H.264的码流结构和H.263 的有很大的区别,它采用的不再是严格的分级结构。H.264 支持4:2:0 的连续或隔行视频的编码和解码。H.264 压缩与H.263、MPEG-4 相比,视频压缩比提高了一倍。
H.264 的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL,Network Abstraction Layer)。VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL 数据传输或存储之前,这些编码的VCL 数据,先被映射或封装进NAL 单元中。每个NAL 单元包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组对应于视频编码的NAL 头信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾比特。一个bit“1”若干比特“0”,以便字节对齐。
2.H264的传输
H.264 的编码视频序列包括一系列的NAL 单元,每个NAL 单元包含一个RBSP,见表1。编码片(包括数据分割片IDR 片)和序列RBSP 结束符被定义为VCL NAL 单元,其余
为NAL 单元。典型的RBSP 单元序列如图2 所示。每个单元都按独立的NAL 单元传送。单元的信息头(一个字节)定义了RBSP 单元的类型,NAL 单元的其余部分为RBSP 数据。
3.H264的码流结构
起始码:如果NALU 对应的Slice 为一帧的开始,则用4 字节表示,即0x00000001;否则用3 字节表示,0x000001。
一个frame是可以分割成多个Slice来编码的,而一个Slice编码之后被打包进一个NAL单元,不过NAL单元除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。
三、MP4封装的H264数据
MP4文件中所有数据都封装在box中,它是由若干个子box组成,每个box还可以包含另外的子box,且每个box都有长度和类型。“ftyp”(66 74 79 70)box:作为MP4格式的标志并包含关于文件的一些信息,有且仅有一个;“moov”(6D 6F 6F 76)box:包含了媒体的metadata信息(特别是avcC中的sps和pps),有且仅有一个;“mdat”(6D 64 61 74)box:包含了MP4的媒体数据,可以有多个,也可以没有。但是媒体数据的结构由metadata进行描述。MP4中box存储方式为大端模式。一般,标准的box开头会有四个字节的box size。
在MP4格式文件中,H264 slice并不是以00 00 00 01来作分割,而是存储在mdat box中。H264基本码流由一些列的NALU组成。原始的NALU单元组成:[start code] + [NALU header] + [NALU payload].
MP4数据格式:|"ftyp"box|"moov"box(及其子box)|"mdat"box|....|。
"mdat"box的格式:|box的length(4字节)|box类型(4字节)mdat-6D 64 61 74|NALU的length(4字节)|NALU的header(1字节)|payload|;
MP4封装结构图:
box结构图:
用MP4info分析的实例分析图:
四、H264视频流的RTP封包
1.RTP打包原则
RTP的包长度必须要小于MTU(最大传输单元),IP协议中MTU的最大长度为1500字节。除去IP报头(20字节)、UDP报头(8字节)、RTP头(12字节),所有RTP有效载荷(即NALU内容)的长度不得超过1460字节。
2.RTP协议的报文结构
开始12个八进制出现在每个RTP包中,而CSRC标识列表仅出现在混合器插入时。各段含义如下:
①版本(V)
version (V): 2 bits 2位,标识RTP版本,协议初始版本为0,RFC3550中规定的版本号为2。。
②填充标识(P)
padding (P): 1 bit 1位,如设置填充位,在包末尾包含了额外的附加信息,它不属于有效载荷。附加信息的最后一个字节表示额外附加信息的长度(包含该字节本身)。该字段之所以 存在是因为某些加密算法需要固定大小的填充字,或为在底层协议数据单元中携带几个RTP包。
③扩展(X)
extension (X): 1 bit 1位,如果该位被设置,则在固定的头部后存在一个扩展头部,格式定义在RFC3550 5.3.1节。
④CSRC计数(CC)
CSRC count (CC): 4 bits 4位,CSRC计数包括紧接在固定头后标识CSRC个数。
⑤标记(M)
marker (M): 1 bit 1位,标记解释由设置定义,目的在于允许重要事件在包流中标记出来。设置可定义其他标示位,或通过改变位数量来指定没有标记位,该位的功能依赖于 profile的定义。profile可以改变该位的长度,但是要保持marker和payload type总长度不变(一共是8 bit)。。
或M:标示位,1 位。如果当前 NALU为一个接入单元最后的那个NALU,那么将M位置 1;或者当前RTP 数据包为一个NALU 的最后的那个分片时(NALU 的分片在后面讲述),M位置 1。其余情况下M 位保持为 0。
⑥载荷类型(PT)
payload type (PT): 7 bits 7位,记录后面资料使用哪种 Codec , receiver 端找出相应的 decoder 解碼出來,该位标记着RTP packet所携带信息的类型,标准类型列出在RFC3551中。如果接收方不能识别该类型,必须忽略该packet。
⑦系列号
sequence number:16 bits 16位,系列号随每个RTP数据包发送后而增加1,接收方可以根据该序列号重新排列数据包顺序,或者探测包损失。系列号初值是随机的,使对加密的文本攻击更加困难。
⑧时间戳
timestamp: 32 bits 32位,时标反映RTP数据包中第一个八进制数的采样时刻,采样时刻必须从单调、线性增加的时钟导出,以允许同步与抖动计算。时标可以让receiver端知道在正确的时间将资料播放出来。实际中当采用”分片封包模式“打包RTP时,当一个NALU打包完毕时,时间戳更一次。
由上图可知,如果只有系列号,并不能完整按照顺序的将data播放出来,因为如果data中间有一段是没有资料的,只有系列号的话会造成错误,需搭配上让它知道在哪个时间将data正确播放出来,如此我们才能播放出正确无误的信息。
⑨SSRC
SSRC: 32 bits 32位,SSRC段标识同步源。此标识不是随机选择的,目的在于使同一RTP包连接中没有两个同步源有相同的SSRC标识,也就是在一个RTP Session其间每个数据流都应该有一个不同的SSRC。尽管多个源选择同一个标识的概率很低,所有RTP实现都必须探测并解决冲突。如源改变源传输地 址,也必须选择一个新SSRC标识以避免插入成环行源。
⑩CSRC列表
CSRC list: 0 to 15 items bits0到15项,每项32位。CSRC列表表示包内的对载荷起作用的源。标识数量由CC段给出。如超出15个作用源,也仅标识15个。CSRC标识由 混合器插入,采用作用源的SSRC标识。只有存在Mixer的时候才有效。如一个将多声道的语音流合并成一个单声道的语音流,在这里就列出原来每个声道的 SSRC。
3.NALU header结构图
NALU header由一个字节组成, 它的语法如下:
F: 1 个比特.forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2 个比特.nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如00的NALU解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心这个属性.
Type: 5 个比特.nal_unit_type. 这个 NALU 单元的类型. 但是在h264中只有 1~23 是有效的值.而其他的24~29在RTP封包采用”组合封包模式“和”分片封包模式“时所用的type类型,而非“单一NAL单元模式”时。
简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义
4.RTP打包模式
主要分为三种模式:单一NALU模式、分片模式、组合模式,实际中前两种用的比较多。
(1)单一NALU模式
一个RTP包仅由一个完整的NALU组成。这种情况下RTP NAL头类型字段和原始的H.264的NALU头类型字段是一样的。适合条件是当NALU的长度小于RTP包长减去12时。
特别NALU type 值为 7 和 8 的NALU分别为序列参数集(sps)和图像参数集(pps)。
(2)组合封包模式
即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.那么这里的类型值分别是 24, 25, 26 以及 27.适合条件当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.
(3)分片封包模式Fragmentation Units (FUs)
用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29。适合条件当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包.
FU indicator 结构
F:当网络识别此单元存在比特错误时,可将其设为 1,以便接收方丢掉该单元。
NRI:必须根据分片NAL单元的NRI域的值设置,用来指示该NALU的重要性等级。值越大,表示当前NALU越重要。
TYPE:28表示FU-A和29表示FU-B
FU Header 结构:
S:当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。
E:当设置成1,结束位指示分片NAL单元的结束。即荷载的最后字节是分片NAL单元的最后一个字节。当跟随的FU荷载不是分片NAL单元的最后分片,结束位设置为0。
R:保留位必须设置为0,接收者必须忽略该位。
Type:与NALU的header中的Type类型一致。
H264编码 封装成MP4格式 视频流 RTP封包相关推荐
- FFMPEG音视频同步-音频实时采集编码封装成MP4
https://blog.csdn.net/quange_style/article/details/90083173
- ts无损剪辑合并_将你的视频无损封装成MP4,非转码哦!
想每天收到这么好的文章? 分享一个批处理文件,可以无损地将FLV.MKV视频格式重新封装成MP4格式.与转码不同,转码是对视频文件再次压缩编码,是有损的,而封装只是将格式换掉而已,并没有对视频编码 ...
- 如何快速且不失真剪切与合并视频?如何将视频快速转成MP4格式?无需渲染!视频秒转MP4,剪辑合并!
视频剪切或合并后变模糊(变不清晰)怎么办?视频剪切或合并速度很慢怎么办?如何快速且不失真剪切与合并视频?如何将视频快速转成MP4格式? 工具下载: 小丸工具箱下载及如何压制视频:https://blo ...
- 把h264文件快速包装成mp4格式
mkv里封装的.h264文件提取出来后,不能直接导入到premiere等视频编辑软件里,需要转换成mp4文件. 这里介绍如何把封装在 mkv 里面的 .h264 视频文件转换为 mp4 格式.(只有视 ...
- 使用ffmpeg开源库将h264封装为mp4格式
最近一直在做使用ffmpeg关于读取标准h264格式内存如何封装为mp4格式文件,在经过一周的持续奋战之后在网上找了一些代码,特别的雷神的博客让我获益匪浅,开始不知道如何持续读取发送来的内存块,如何边 ...
- 使用mp4v2将aac音频h264视频数据封装成mp4开发心得
这阵子在捣鼓一个将游戏视频打包成本地可播放文件的模块.开始使用avi作为容器,弄了半天无奈avi对aac的支持实在有限,在播放时音视频时无法完美同步. 关于这点avi文档中有提到: For AAC, ...
- 怎么把mkv文件转成mp4格式,3招立马处理
怎么把mkv文件转成mp4格式的方法你知道吗?我想很多朋友会遇到这样的情况,下载视频后发现无法打开.原来我们下载的视频格式是mkv,也许这个格式大家不是很熟悉的.那么今天就来认识一下,mkv是Matr ...
- QSV格式转换器如何将爱奇艺视频转换成MP4格式
爱奇艺视频网站中拥有大量影视剧的版权,其官方为了保护视频的版权信息,就将已下载或已缓存视频的格式从MP4格式改成QSV格式.QSV格式文件是爱奇艺视频缓存的视频文件格式,QSV格式只能使用爱奇艺系列的 ...
- 如何将m4v转换成mp4格式?这些方法极速无损
如何将m4v转换成mp4格式?众所周知,M4V文件格式是一个由苹果公司开发的视频文件格式,它通常用于iTunes Store中售卖和租赁的电影.电视节目等内容.但是,在某些情况下,我们可能无法在其他设 ...
最新文章
- 高性能ASP.NET站点构建之简单的优化措施
- (*p)++和*(p++)和*p++的区别
- 查找数组中未出现的和出现2次的数值 Set Mismatch
- 【IOS】自定义UIAlertView样式,实现可替换背景和按钮
- myeclipse中如何修改Servlet模板
- IP通信基础 4月1日
- 关于deepin系统安装design compiler的问题解答
- web前端基础(01html基本标签)
- Leetcode打卡 | No.24 两两交换链表中的节点
- 洛谷1196 银河英雄传说(并查集)
- 关于今日头条小程序(字节跳动小程序)相关问题
- java webserver demo_Java 实现 web服务器的简单实例
- C++ const与static
- 我的爬虫(一)之抓取优美图库图片
- Collection、List、泛型、数据结构
- 尤雨溪:Vue3 将在2022年2月7日成为新的默认版本(你准备好了吗?)
- Unity 编辑器下运行没有声音
- 2021年全球及中国三元前驱体行业现状及竞争格局分析,基于海外新能源汽车发展,我国是最大出口国「图」
- 基于Python的Excel读写操作--内容超详细,值得排排坐
- 跨域图片资源权限(CORS enabled image)
热门文章
- Android ANR
- AGPM(高级组策略管理)3.0之二操作
- hibernate h2变mysql_struts2-hibernate-mysql开发案例 -解道Jdon
- 什么事数据科学_如果您想进入数据科学,则必须知道的7件事
- SpringCloud入门(一)
- leetcode 49. 字母异位词分组(排序+hash)
- leetcode513. 找树左下角的值(dfs)
- 基本SQL命令-您应该知道的数据库查询和语句列表
- rxjs 怎么使用_使用RxJS Observables进行SUPER SAIYAN
- doom 源码_Cartpole和Doom的策略梯度简介