MP4文件格式的解析

MP4文件格式的解析,以及MP4文件的切割算法

  mp4应该算是一种比較复杂的媒体格式了,起源于QuickTime。曾经研究的时候就花了一番的功夫,尤其是怎样把它完美的融入到视频点播应用中,更是费尽了心思,主要问题是处理mp4文件庞大的“媒体头”。当然,流媒体点播也能够採用flv格式来做。flv也能够封装H.264视频数据的,只是Adobe却不推荐这么做,人家说毕竟mp4才是H.264最佳的存储格式嘛。

  这几天整理并重构了一下mp4文件的解析程序,融合了分解与合并的程序,曾经是c语言写的,应用在linux上执行的server程序上,如今改成c++,方便我在其它项目中使用它。至于用不用移植一份c#的,临时用不到。等有必要了再说吧。这篇文章先简介一下mp4文件的大体结构,以及它的切割算法,之后再写文章介绍怎样把mp4完美应用在点播项目中。

 

一、MP4格式分析                  

  MP4(MPEG-4 Part 14)是一种常见的多媒体容器格式。它是在“ISO/IEC 14496-14”标准文件里定义的,属于MPEG-4的一部分,是“ISO/IEC 14496-12(MPEG-4 Part 12 ISO base media file format)”标准中所定义的媒体格式的一种实现,后者定义了一种通用的媒体文件结构标准。MP4是一种描写叙述较为全面的容器格式,被觉得能够在当中嵌入不论什么形式的数据,各种编码的视频、音频等都不在话下,只是我们常见的大部分的MP4文件存放的AVC(H.264)MPEG-4(Part 2)编码的视频和AAC编码的音频。

MP4格式的官方文件后缀名是“.mp4”,还有其它的以mp4为基础进行的扩展或者是缩水版本号的格式。包含:M4V,  3GP, F4V等。

  mp4是由一个个“box”组成的。大box中存放小box。一级嵌套一级来存放媒体信息。box的基本结构是:

  

  当中。size指明了整个box所占用的大小,包含header部分。

假设box非常大(比如存放详细视频数据的mdat box)。超过了uint32的最大数值。size就被设置为1。并用接下来的8位uint64来存放大小。

  一个mp4文件有可能包括非常多的box,在非常大程度上添加了解析的复杂性,这个网页上http://mp4ra.org/atoms.html记录了一些当前注冊过的box类型。

看到这么多box,假设要所有支持。一个个解析。怕是头都要爆了。还好。大部分mp4文件没有那么多的box类型,下图就是一个简化了的,常见的mp4文件结构:

  

  一般来说。解析媒体文件,最关心的部分是视频文件的宽高、时长、码率、编码格式、帧列表、关键帧列表,以及所相应的时戳和在文件里的位置,这些信息,在mp4中,是以特定的算法分开存放在stbl box下属的几个box中的。须要解析stbl以下全部的box,来还原媒体信息。

下表是对于以上几个重要的box存放信息的说明:

  看吧,要获取到mp4文件的帧列表,还挺不easy的。须要一层层解析,然后综合stts stsc stsz stss stco等这几个box的信息。才干还原出帧列表。每一帧的时戳和偏移量。并且。你要照应可能出现或者可能不出现的那些box。

。。

能够看的出来。mp4把帧sample进行了分组,也就是chunk,须要间接的通过chunk来描写叙述帧,这样做的理由是能够压缩存储空间,缩小媒体信息所占用的文件大小。

这里面。stsc box的解析相对来说比較复杂,它用了一种巧妙的方式来说明sample和chunk的映射关系。特别介绍一下。

  这是stsc box的结构,前几项的意义就不解释了。能够看到stsc box里每一个entry结构体都存有三项数据,它们的意思是:“从first_chunk这个chunk序号開始。每一个chunk都有samples_per_chunk个数的sample。并且每一个sample都能够通过sample_description_index这个索引,在stsd box中找到描写叙述信息”。也就是说。每一个entry结构体描写叙述的是一组chunk,它们有同样的特点,那就是每一个chunk包括samples_per_chunk个sample,好,那你要问,这组同样特点的chunk有多少个?请通过下一个entry结构体来推算,用下一个entry的first_chunk减去本次的first_chunk,就得到了这组chunk的个数。

最后一个entry结构体则表明从该first_chunk到最后一个chunk。每一个chunk都有sampls_per_chunk个sample。非常拗口吧,只是,就是这个意思:)

因为这样的算法无法得知文件全部chunk的个数,所以你必须借助于stco或co64。直接上代码可能会清楚些:

  1. 首先直接分析entry

  2. 然后,通过stco或co64获知chunk总个数之后,開始还原映射表

  读出stsc之后。就能够综合stbl下的全部box,推算出视频和音频帧列表,时戳和偏移量等数据。以下截图展示获取到的关键帧列表:

     

  有了关键帧列表之后。就能够继续我们一下个题目。就是mp4文件的切割。实现mp4的切割,是把mp4应用到点播系统中最关键的技术环节,做不到这个。就无法实现点播播放mp4影片的“拖动”。

  

二、MP4文件的切割算法

  所谓“切割”,就是把大文件切成小文件,要实现mp4的切割,

  •   首先,须要获取到关键帧列表
  •   然后,选择要切割的时间段(比方从关键帧開始)
  •   接着,又一次生成moov box(注意全部相关的box 以及 box size都须要改变)
  •   最后。拷贝相应的数据,生成新文件

  第一点,上面已经介绍了。第二点。仅仅须要遍历关键帧列表,就能找到离你想要切割的时间段最接近的关键帧,第四点就是“copy-paste”的工作,关键在于第三点。

由于这一步涉及到stbl下的全部box,必须又一次生成entrys。相同的。其它的box都还好,仅仅须要保留关键帧所相应的sample和chunk。其余的删掉就可以,仅仅是stsc box的比較麻烦,说起来比較啰嗦,还是直接看代码吧:

  改动完box之后。须要又一次生成moov box。因为moov box的大小以及时长等信息都发生了改变,所以须要box的大小做对应的改动。这点千万不能忘记,否则播放器会解析错误。又一次生成box之后,还要计算一下切割后的数据的长度。因为数据长度也发生了改变,所以改动mdat box的大小的同一时候,要同一时候改动stbl下全部box的chunk offset,切记!

  下面是整个的逻辑过程:

  好了,全部这些都实现之后。就具备了做mp4点播系统的条件了。

只是,要做mp4点播。另一些其它的问题须要解决。我将在下一篇文章中介绍。

转载于:https://www.cnblogs.com/jzdwajue/p/7382409.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值