MP4文件格式介绍及解析程序(中)

各Box的作用

在上一博客中,我们简单介绍了一下封装格式的概念和MP4文件结构。下面我们仅针对存储常用编码格式H.264编码和AAC音频编码的MP4文件格式进行解封装。即将视频数据和音频数据从MP4格式中进行分离。我们先实现视频的分离。
MP4 的box结构格式是固定的,每个box的前四个字节描述了box的大小,接下来的四个字节描述了box的类型。经过分析,我们将每个box的作用罗列如下图:
在这里插入图片描述前面我们说过,视音频数据的信息存储在moov box中,顺着moov box往下走,trak的类型可以通过mdia box下的hdlr box来辨别,这里我们解封装得视频,故只需要解析这个trak box。到了stbl box,其子box存储的使我们从MP4问件中分理出视频流所需要的具体信息。stbl box是mp4文件中最复杂的一个box了,也是解开mp4文件格式的主干。

其子box包括:

stsd:sample description box,样本的描述信息。其子box提供了编码格式信息,H.264在其下的box为avc1——avcC,这个box存储了sps 和 pps,sps和pps接下来我们会介绍。上文中的Video信息就存储在这个box中。
stts:time to sample box,sample解码时间的压缩表。
ctts:composition time to sample box,sample的CTS与DTS的时间差的压缩表。
stss:sync sample box,针对视频,关键帧的序号。
stsz/stz2:sample size box,每个sample的字节大小。
stsc:sample to chunk box,sample-chunk映射表。
stco/co64:chunk offset box,chunk在文件中的偏移。

H.264码流结构

视频文件的编码格式是H.264,我们首先要了解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)。NAL层实际上就是最终输出的H.264码流,它是由一个个NALU组成的,每个NALU包括一组对应于视频编码数据的NAL头信息和一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。以上名词之间的关系如下:

RBSP = SODB + RBSP trailing bits
NALU = NAL header(1 byte) + RBSP
H.264 = Start Code Prefix(3 bytes) + NALU + Start Code Prefix(3 bytes) + NALU +…

所以H.264码流的结构如下:
在这里插入图片描述
  每个NALU之间由起始码(Start Code Prefix)分隔,起始码分为两种:0x000001(3 bytes) or 0x00000001(4 bytes). 如果NALU 对应的Slice 为一帧的开始,则用4 字节表示,即0x00000001;否则用3 字节表示,0x000001.
  
下图描述了长度为一个字节的NAL header结构
在这里插入图片描述在解释此表之前先了解一些概念:

I,P,B帧

I frame : 自身可以通过视频解压算法解压成一张单独完整的图片
P frame : 需要参考其前面的一个I frame 或者B frame来生成一张完整图片
B frame : 既要参考其前一个I frame 或者 P frame以及其后一个P frame来生成一张完整的图片。

DTS,PTS

PTS :PTS主要用于度量解码后的视频什么时候被显示
DTS :DTS主要是标识内存中的Bit流什么时候开始送入解码器进行解码

GOP

GOP是画面组,一个GOP是一组连续的画面。
GOP一般有两个数字,如M=3,N=12.M制定I帧与P帧之间的距离,N指定两个I帧之间的距离。那么现在的GOP结构是
I BBP BBP BBP BB I

SPS 、PPS

SPS:图像参数集 PPS:序列参数集
sps和pps包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高,deblock滤波器等。这两个参数非常重要,没有这两个参数解码器无法识别文件。

IDR

一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。
I和IDR帧都使用帧内预测。I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。

核心作用 : H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。故在每个IDR帧之前都需添加一个sps NALU和一个pps NALU来重置解码器。

根据此表我们可以推知,header为0x67该NALU为sps,0x68为pps,除此之外,一个NALU就是编码后的一帧数据。0x65为IDR帧,0x41为P帧,0x01为B帧。解释一下编码过程中相应的视频文件拆分的单位,sample为一帧,一个chunk是一个连续的sample序列,下面的解码层会再往下细分到slice片,再往下细分到最小编码单位宏块Macroblock:对于H.264视频编码格式这里我们不涉及到编解码,对于解封装而言,到sample层面就够了。

文章参考:简书作者小东邪啊https://www.jianshu.com/p/24f2a069dd7e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值