H264编码 封装成MP4格式 视频流 RTP封包

        分类:             多媒体编程              2013-02-20 21:31     3067人阅读     评论(0)     收藏     举报    

转自:http://www.cnblogs.com/ghw-NO1/archive/2012/08/28/2660848.html

http://blog.csdn.net/crazyman2010/article/details/8596229

一、概述

本文讲述的是对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格式及在MP4文件中提取H264的SPS、PPS及码流

SkySeraph Apr 1st 2012 

Email:skyseraph00@163.com


一、MP4格式基本概念

MP4格式对应标准MPEG-4标准(ISO/IEC14496)


二、MP4封装格式核心概念

1  MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象编码的第12部分: ISO 基本媒体文件格式/Information technology Coding of audio-visual objects Part 12: ISO base media file format)

 附-- 标准免费下载: Freely Available Standards    http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html

2  MP4封装格式是基于QuickTime容器格式定义,媒体描述与媒体数据分开,目前被广泛应用于封装h.264视频和ACC音频,是高清视频/HDV的代表。

MP4文件中所有数据都封装在box中(对应QuickTime中的atom),即MP4文件是由若干个box组成,每个box有长度和类型,每个box中还可以包含另外的子box(称container box)。

 一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box),它是一种container box,子box包含了媒体的metadata信息;MP4文件的媒体数据包含在“mdat”类型的box(Midia Data Box)中,该类型的box也是container box,可以有多个,也可以没有(当媒体数据全部引用其他文件时),媒体数据的结构由metadata进行描述。

MP4中box存储方式为大端模式。一般,标准的box开头会有四个字节的box size。

5 几个名词

track

表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。

hint track

特殊的track,并不包含媒体数据,包含的是一些将其他数据track打包成流媒体的指示信息。

sample

对于非hint   track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。

对于hint   track,sample定义一个或多个流媒体包的格式。

sample table

指明sampe时序和物理布局的表。

chunk

一个track的几个sample组成的单元。


三、MP4封装格式结构图

1 实例样本

来源于Android MediaRecoder视频录制,平台为华为T8300和TCL968,mp4info查看如下

EsEYE查看如下:

winhex分析如下:

2 box结构图

接下来对h264编码中有用的几个进行阐述,其它不再描述。

3 ftyp(file type box)

如下图所示,开始的四字节00 00 00 00 18表示该box的size为24字节(含头),然后66 74 79 70是ftyp的BOX TYPE,其它是一些格式兼容等相关信息。

4  mdat

如下图所示,BOX YPE为6D 64 61 74 ,紧接着的00 00 09 39表示sliece长度

5 avcC

如下图所示,红色为BOX TYPE


四、MP4文件中h264的 SPS、PPS获取

1  【参考依据】ISO/IEC 14496-15 (下载

2  【综述】在H264中,SPS和PPS存在于NALU header中,而在MP4文件中,SPS和PPS存在于AVCDecoderConfigurationRecord, 首先要定位avcC.

3  【定义】

①参数集:一组很少改变的,为大量VCL NALU 提供解码信息的数据。

序列参数集SPS作用于一系列连续的编码图像,而图像参数集PPS作用于编码视频序列中一个或多个独立的图像。

如果解码器没能正确接收到这两个参数集,那么其他NALU 也是无法解码的。因此它们一般在发送其它 NALU 之前发送,并且使用不同的信道或者更加可靠的传输协议(如TCP)进行传输,也可以重复传输。

②关于AVCDecoderConfigurationRecord结构定义为  

4  【实例分析】 数据如上avcC图所示,现在对数据进行详细分析

所以,提取的SPS和PPS分别为67 42 00 1E A6 81 41 F9和68 CE 38 80


五、MP4文件中的H264 data /NALU slice

1  【参考】H264官方文档(下载) + 毕书—新一代视频压缩编码标准(下载

2  【综述】

① 在MP4格式文件中,H264 slice并不是以00 00 00 01来作分割,而是存储在mdat box中。

②  H264基本码流由一些列的NALU组成。原始的NALU单元组成:[start code] + [NALU header] + [NALU payload]

start   code

1字节

00 00 01 或 00 00 00 01

需要添加的

NALU header

1字节

如下3

通过mdat定位

③  H264基本码流结构分两层:视频编码层VCL和网络适配层NAL,这样使信号处理和网路传输分离

VCL

负责高效视频内容表示

NAL

以网络所要求的恰当方式对数据进行打包和发送

3  【定义】 NALU header

+---------------+

|0|1|2|3|4|5|6|7|

+-+-+-+-+-+-+-+-+

|F|NRI| Type |

+---------------+

特别的,当值为7和8分别为SPS和PPS。

毕书(下载)(P191)上的定义为:

4  【实例分析】数据分析,数据如上图mdat所示

6D 64 61 74

mdat   BOX TYPE

00 00   09 39

silce长度,2361

接下来的65就是NALU header,可以由65&0x1F来求的后五个bit,从而得知此slice为I frame

注意,mdat与silce之间有可能存在若干占位符,我在TCL手机测试时就出现了连续的00的占位符,这样后面用H264硬编码时会比较麻烦一点。


Ref/Related

1 相关资料和工具在文中链接下载

2 http://www.52rd.com/Blog/wqyuwss/559/4/

3 http://blog.csdn.net/szu030606/article/details/5943279

4 http://blog.csdn.net/k1988/article/details/5654631

5 http://www.cppblog.com/czanyou/archive/2008/11/26/67940.html

6 http://krdai.info/blog/sps-pps-in-mp4-format.html

7 http://www.cnitblog.com/zouzheng/archive/2007/04/04/25155.html

8 http://bbs.chinavideo.org/viewthread.php?tid=10273

H264编码 封装成MP4格式 视频流 RTP封包的更多相关文章

  1. 【转】qlv文件如何转换成mp4 怎样把下载好的qlv格式视频转换成MP4格式

    狸窝  复制  收藏  保存到桌面  快速找教程方案  反馈需求  社会主义核心价值观  客服QQ41442901   马上注册 升级VIP   对于视频文件之间的转换问题,我也已经是无力吐槽了,每个 ...

  2. 【iOS】控件截图、MP4格式视频流和m3u8格式视频流截取某一帧功能的实现

    最近开发遇到一个点击按钮实现直播视频流截屏的功能,去网上查了一下资料,总结了一下iOS中截屏相关的知识,然后自己做了个demo. demo主要实现了3种截屏方法,分别对应三种不同的应用场景. 1.im ...

  3. Flv视频格式如何转换成MP4格式

    如何将flv视频格式转换成MP4格式呢?随着现在视频格式的不断多样化,视频格式转换的问题也成了现在生活中常见的问题,那么我们应该怎样将flv视频格式转换成MP4格式呢?下面我们就一起来看一下吧. 操作 ...

  4. javascript将form表单中的元素值封装成json格式

    把form表单中的元素值封装成json function toJSON(form)//form是要进行封装的form表单对象,dom对象,可以通过document.mainForm获得,mainFor ...

  5. 视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧,可拖动

    作者测试是在windows下使用,所以下载的页面地址是: http://ffmpeg.zeranoe.com/builds/点击页面上的Download FFmpeg git-738ebb4 64-b ...

  6. 用ffmpeg命令将264裸码流封装成mp4(转载)

    转自:http://bbs.csdn.net/topics/370256130 ffmpeg -f h264 -i source.264 -vcodec copy out.mp4

  7. qlv格式转换成MP4格式

    腾讯视频下载:1.先下载腾讯的客户端--->播放视频在客户端 2.播放视频一段后停止 3.点击腾讯客户端的右上角的设置 4.复制缓存地址(注意:在此之前需要设置"显示隐藏的文件夹&qu ...

  8. python合并大量ts文件成mp4格式(ps:上限是450,亲测)

    import os #exec_str = r'copy /b ts/c9645620628078.ts+ts/c9645620628079.ts ts/1.ts' #os.system(exec_s ...

  9. H264视频编码成MP4文件

    firehood的专栏 Wince嵌入式开发       目录视图 摘要视图 订阅 赠书 | AI专栏(AI圣经!<深度学习>中文版)      每周荐书:Kotlin.分布式.Keras ...

随机推荐

  1. Ubuntu 系统学习

    apt 命令 apt-get remove [app] # 删除已安装的软件包(保留配置文件),不会删除依赖软件包,且保留配置文件 apt-get remove --pure [app] # 删除已安 ...

  2. Python 必备好库 - 好工具收藏

    apscheduler collections collections.OrderDict collections.defaultdict Python 标准库提供了 collections 模块.这 ...

  3. linux内核中的两个标记GFP_KERNEL和GFP_ATOMIC是用来干什么的?

    1. 作用 用来标记分配内核空间内存时的方式 2. 两个标记使用在什么场合? 如果内存不够时,会等待内核释放内存,直到可以分配相应大小的内存,也就意味着会发生阻塞,因此不能使用在中断处理函数中,而GF ...

  4. 【Dalston】【第二章】客户端负载均衡(Ribbon)

    对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题.在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如 ...

  5. How to know the directory size in CENTOS 查看文件夹大小

    Under any linux system, you want to use the command du. (Disk Usage) Common usage is : du -sh file(s ...

  6. 深度学习课程笔记(四)Gradient Descent 梯度下降算法

    深度学习课程笔记(四)Gradient Descent 梯度下降算法 2017.10.06 材料来自:http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLDS1 ...

  7. 论文笔记:Parallel Tracking and Verifying: A Framework for Real-Time and High Accuracy Visual Tracking

    Parallel Tracking and Verifying: A Framework for Real-Time and High Accuracy Visual Tracking  本文目标在于 ...

  8. Async、Await

    Async.Await:net4.x新增的异步编程方式: 目的:为了简化异步程序编写 Async方式, 使用Async标记Async1为异步方法, 用Await标记GetRequestStreamAs ...

  9. UI、JS框架----Bootstrap、Metro

    Bootstrap Datagrid EasyUI Metro bootstrap Datepicker Editable for Bootstrap:bootstrap-editable.js X- ...

  10. C语言调用Python 混合编程

    导语 Python有很多库,Qt用来编写界面,自然产生C++调用Python的需求.一路摸索,充满艰辛 添加头文件搜索路径,导入静态库 我的python头文件搜索路径:C:\Python27amd64 ...