iOS RTMP 视频直播开发笔记(2)----关于MP4及H.264
2016-06-06 14:23
781 查看
虽然我们不需要了解详细的编码实现细节,但对于文件格式和相关名词的了解,对于开发仍然是非常必要的。
由于之后的 iOS 编码实现中需要首先生成 MP4 视频文件,然后从 MP4 文件中提取 NALU 交给下一步做处理,因此这里首先介绍一下 MP4 和 H.264 的相关知识吧。
MP4 是一种视频容器格式,而 H.264 是一种图像编码标准。
将flv转换为mp4:
在使用 Hex Fiend 分析mp4文件后,会发现
大体文件结构: | ftyp | mdat | moov |
这里的三个是最常见也是最重要的数据。
MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将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进行描述。
track 表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。
hint track 这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。
sample 对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。对于hint track,sample定义一个或多个流媒体包的格式。
sample table 指明sampe时序和物理布局的表。
chunk 一个track的几个sample组成的单元。
track:
stco: chunk offset, partial data-offset information 记录Chunk偏移
stsc: sample-to-chunk, partial data-offset information
stss: sync sample table (random access points) 判断是否关键帧
stsz: sample sizes (framing) 记录每一帧大小
还记得前面提到的 Chunk 和 Sample 的概念吗?一个 Chunk 里有多个 Sample,一个 Sample 代表一帧。
chunk 和 sample 的关系:一个chunk中有一个或多个sample,一个文件有多个chunk,在stco中标记了chunk在文件中的绝对位置。不是相对于某一个box.stsz标记了每一个sample的大小,stsc则是chunk和sample的对应关系。
这里有个问题就是Stsc中有个 参数是first_chunk,这个是什么意思呢?
可以看出chunk1、chunk2、chunk3都有4个sample,chunk4有3个sample,chunk5、chunk6、chunk7有4个sample……就是这个意思。
Github上一位童鞋写的MP4Reader.m,代码中详细展示了MP4文件解析的过程。
是不是关键帧?sample为帧计数,如果帧的计数存在与stss中,则是关键帧
stsz 记录了每一帧的大小,这里的videoSamples来自stsz。
MPEG-4 wiki
关于avcC:第十五部分(ISO/IEC 14496-15):AVC文件格式:定义了基于第十二部分的用于存储第十部分的视频内容的文件格式。
mp4格式(转帖加修改)
将h.264视频流封装成flv格式文件(一.flv格式)
MP4(一)-结构
MP4(二)-解复用器
我之前一直没有搞明白,直到仔细看了
标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。如果size为1,则表示这个box的大小为large size,真正的size值要在largesize域上得到。(实际上只有“mdat”类型的box才有可能用到large size。)如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。(同样只存在于“mdat”类型的box中。)
size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略
而MDAT中的数据,它的结构就是[box size][h264 data],也就是后面的数据的大小+h264裸流了。
重要的是该“14496-12 基础文件格式”协议如果认祖归宗,我们发现这种文件格式最初是由Apple公司的QuickTime媒体格式发展而来的。
即,mov格式发展出了“ISO 14496 – 12协议”,再由该协议衍生出了mp4,f4v,ismv,3gp等我们常见的媒体封装格式。
因此上述标志位的poster位,在14496-12中并没有见到描述,而在Apple的协议中却看到了准确定义。
详见 https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html
由于之后的 iOS 编码实现中需要首先生成 MP4 视频文件,然后从 MP4 文件中提取 NALU 交给下一步做处理,因此这里首先介绍一下 MP4 和 H.264 的相关知识吧。
MP4 是一种视频容器格式,而 H.264 是一种图像编码标准。
2.1 了解 MP4 文件格式
本节内容整理自: MP4(一)-结构 ,原作者不详将flv转换为mp4:
ffmpeg -i test.flv -vcodec libx264 test.mp4
在使用 Hex Fiend 分析mp4文件后,会发现
moov段总是位于文件的末尾,这也是为什么
AVEncoder会专门使用
headerWriter只写编码一帧存入文件的原因——为了尽早获得
moov数据存储下来,作为meta信息发送出去。很难理解为什么这个会在文件末尾。
大体文件结构: | ftyp | mdat | moov |
这里的三个是最常见也是最重要的数据。
ftyp用于标识文件类型,
mdat是真正包含的编码数据,
moov为参数信息。
基本概念
MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将box理解为一个数据对象块。box中可以包含另一个box,这种box称为container box。一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box),它是一种container box,子box包含了媒体的metadata信息;MP4文件的媒体数据包含在“mdat”类型的box(MidiaData Box)中,该类型的box也是container box,可以有多个,也可以没有(当媒体数据全部引用其他文件时),媒体数据的结构由metadata进行描述。
名词解释
track 表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。hint track 这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。
sample 对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。对于hint track,sample定义一个或多个流媒体包的格式。
sample table 指明sampe时序和物理布局的表。
chunk 一个track的几个sample组成的单元。
track:
1 2 3 4 5 6 7 | ? mp4info test.mp4 mp4info version 1.9.1 test.mp4: Track Type Info 1 video H264 High@3, 425.120 secs, 764 kbps, 832x468 @ 25.000000 fps 2 audio MPEG-4 AAC LC, 425.152 secs, 127 kbps, 48000 Hz Encoded with: Lavf55.33.100 |
‘stsc’ 中的 Chunk
stco: chunk offset, partial data-offset information 记录Chunk偏移stsc: sample-to-chunk, partial data-offset information
stss: sync sample table (random access points) 判断是否关键帧
stsz: sample sizes (framing) 记录每一帧大小
还记得前面提到的 Chunk 和 Sample 的概念吗?一个 Chunk 里有多个 Sample,一个 Sample 代表一帧。
chunk 和 sample 的关系:一个chunk中有一个或多个sample,一个文件有多个chunk,在stco中标记了chunk在文件中的绝对位置。不是相对于某一个box.stsz标记了每一个sample的大小,stsc则是chunk和sample的对应关系。
这里有个问题就是Stsc中有个 参数是first_chunk,这个是什么意思呢?
First chunk Samples | per chunk Sample | description ID |
---|---|---|
1 | 4 | 1 |
4 | 3 | 1 |
5 | 4 | 1 |
8 | 3 | 1 |
Github上一位童鞋写的MP4Reader.m,代码中详细展示了MP4文件解析的过程。
是不是关键帧?sample为帧计数,如果帧的计数存在与stss中,则是关键帧
1 | keyframe = [syncSamples containsObject:[NSNumber numberWithInt:sample]]; |
1 2 | // Size of the sample int size = [[videoSamples objectAtIndex:(sample - 1)] integerValue]; |
相关资料
MPEG-4 wiki关于avcC:第十五部分(ISO/IEC 14496-15):AVC文件格式:定义了基于第十二部分的用于存储第十部分的视频内容的文件格式。
mp4格式(转帖加修改)
将h.264视频流封装成flv格式文件(一.flv格式)
MP4(一)-结构
MP4(二)-解复用器
关于MDAT部分:
这里的格式是什么样的?我之前一直没有搞明白,直到仔细看了
AVEncoder.m才恍然大悟,根据MP4的文件结构描述,所有内容都使用Box来存储:[box size][box type][…]
标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。如果size为1,则表示这个box的大小为large size,真正的size值要在largesize域上得到。(实际上只有“mdat”类型的box才有可能用到large size。)如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。(同样只存在于“mdat”类型的box中。)
size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略
而MDAT中的数据,它的结构就是[box size][h264 data],也就是后面的数据的大小+h264裸流了。
MP4 与 QuickTime 之间的关系?
我们知道,MP4文件格式是ISO-14496-12基础文件格式的衍生品,14496-14中对-12协议进行了扩充与进一步定义。重要的是该“14496-12 基础文件格式”协议如果认祖归宗,我们发现这种文件格式最初是由Apple公司的QuickTime媒体格式发展而来的。
即,mov格式发展出了“ISO 14496 – 12协议”,再由该协议衍生出了mp4,f4v,ismv,3gp等我们常见的媒体封装格式。
因此上述标志位的poster位,在14496-12中并没有见到描述,而在Apple的协议中却看到了准确定义。
详见 https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html
相关文章推荐
- 买视频送图书-五月活动
- DVI 视频接口图文解析
- ASP编码必备的8条原则
- C#实现语音视频录制-附demo源码
- XML指南——XML编码
- C#中字符串编码处理
- ExtJS中文乱码之GBK格式编码解决方案及代码
- 程序员趣味读物 谈谈Unicode编码
- 文本文件编码方式区别
- 编写C++程序使DirectShow进行视频捕捉
- C语言安全编码之数值中的sizeof操作符
- C#实现获取文本文件的编码的一个类(区分GB2312和UTF8)
- AnyChat的视频会议程序实例详解
- VC中BASE64编码和解码使用详解
- 计算机中的字符串编码、乱码、BOM等问题详解
- Base64编码解码原理及C#编程实例
- C#编码好习惯小结
- C#调用mmpeg进行各种视频转换的类实例
- javascript编码的几个方法详细介绍
- C#获取视频某一帧的缩略图的方法