MP4简介

声明:

    在我的工作中需要查看一些关于MP4格式的问题,所以对MP4进行了简单的了解,这里对这部分知识做个简单的总结,但是文中主要是参考mp4文件格式解析,这里进行说明,同时我也使用了一些自己工作中的例子作讲解,希望可以对你有所帮助。

 

参考文章:

FFmpeg中mp4的demuxer(mov.c)代码阅读 : https://www.jianshu.com/p/f78defe0e485

介绍MP4格式的文章:

mp4文件格式解析 : https://www.jianshu.com/p/529c3729f357

多媒体文件格式之MP4 : https://www.cnblogs.com/tocy/p/media_container_3_mp4.html

Android音视频系列:视频容器操作篇 -- mp4容器打包实现 : https://mp.weixin.qq.com/s/BOkaNcPQWKkeAS1it3aE-w

 

软件推荐:Mp4Explorer

    一个非常友好,可以很清楚的将MP4各种需要的信息使用表格的方式例举出来的软件,界面为:

 

 

封装格式重要概念

1 box

mp4文件由若干个box组成。下面是box结构的一个示意图。

 

  • box由header和body组成,其中header指明box的size和type。size是包含box header的整个box的大小。
  • box type,通常是4个ASCII码的字符如“ftyp”、“moov”等,这些box type都是已经预定义好的,表示固定的含义。如果是“uuid”,表示该box为用户自定义扩展类型,如果box type是未定义的,应该将其忽略。
  • 如果header中的size为1,则表示box长度需要更多的bits位来描述,在后面会有一个64bits位的largesize用来描述box的长度。如果size为0,表示该box为文件的最后一个box,文件结尾(同样只存在于“mdat”类型的box中)。

 

2 track

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

3 sample

video sample即为一帧或者一组连续视频帧,audio sample即为一段连续的音频。

4. sample table

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

5. chunk

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

    mp4文件中,媒体内容在moov的box中。一个moov包含多个track。每个track就是一个随时间变化的媒体序列,track里的每个时间单位是一个sample,sample按照时间顺序排列。注意,一帧音频可以分解成多个音频sample,所以音频一般用sample作为单位,而不用帧。

    sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同,如下图所示。

 

 

重要box介绍:

 

 

实例分析:

 

    上图是我之前分析的一个MP4 文件的结构图,在这个文件中音频和视频是间隔放置的,其中红色的为音频,蓝色的为视频。而在每个音视频块中有其对应的偏移量(pos),也就是他们在文件中的位置。而在pos左右两边为音视频的dts值通过dts可以实现音视频的同步播放)。而再往两边对应的数据为音视频中每个chunk的偏移量(STCO)。chunk是由一个或者多个sample组成,如粉框中多个sample对应一个chunk。而在最左边和最右边是每个音视频的sample的大小(STSZ),我们可以通过偏移量和每个sample的大小来计算出每个chunk的大小以及他在文件中所在的位置。因此我们了解MP4文件的时候通常需要结合STCO表和STSZ表来了解MP4的组成结构。

    但是我们在了解了MP4音视频位置信息后不一定知道他是不是可以正常的播放,因为在播放器中,音视频的同步播放是要通过很多的信息来实现的,例如在视频播放之前我们需要知道一些信息来对播放器做初始化设置:

audio信息:

  1. smplrate:sample rate(采样率)。
  2. channel:通道个数。
  3. bitrate:比特率。
  4. audiosamplenum:音频sample的个数。
  5. 采样位数
  6. 音频格式

 

video信息:

  1. width、height:视频的宽/高。
  2. bitrate:比特率(码率),秒为单位。等于视频总的大小/时长。
  3. frames:视频帧数。
  4. fps:帧率(frame per second)。
  5. total_time:时间长度,ms为单位。等于duration/timescale。
  6. timescale:时间的粒度,1000表示1000个单位为1s。
  7. duration:时间粒度的个数。
  8. videosamplenum:视频sample的个数。

 

    在上面列举了对于音视频来说十分重要的参数,而这些参数就是通过解析moov中各个box获得的。可以通过参考上面重要box中的各个参数的说明来了解各个参数在哪个box中:

 

 

播放器中如何实现音视频同步:

    通过解析moov中各个box获得需要的参数对播放器进行初始化,之后就需要获得真正的音视频数据来做同步播放了,我们可以想象音视频为两队排队进入民政的情侣,他们只有一一对应好才能跟自己的女朋友结婚,否则就容易出现错误。而对于音视频来说也是这样的,只有dts相同的数据写入到播放器中才可以音视频同步播放。

    现在我们想一下,民政局其实是有窗口限制的,只能同时给一定数量的情侣办理结婚,办完一对走一对,接着办下一对。 这里我们认为这个民政局同时可以为10对情侣办理业务,也就是说播放器最多只能接受20个音频或者视频。如果不消耗用来显示输出而是让他们等待就会出问题。

    我们知道音视频的存放方式为:一段音频一段视频,依次交替。而回到我们的例子中就是男生和女生是分开排队的,一队男生一队女生,依次交替。现在他们需要进入民政局办理结婚了,我们理想的情况下是,一队男生进来后没有坐满民政局的窗口,这个时候一队女生来了,他们找到自己的男朋友,办理完手续就走了,由下一对接着办理。而对应在播放器中就是读入一段音频,这个时候内存还允许,继续读一段视频,音视频同步输出后,释放内存让后面的音视频使用。

    但是有的时候是有意外存在的,那就是这一队的男生超出了20个人,来了21个人,这个时候后面进来的不是女生,不能办理结婚,出现这个问题就需要民政局的办事人员去问在一号窗口的男生,“你的女朋友是谁啊,她在什么位置啊,我给你带过来”,这样你们办理完后面就好办理了。而这个过程相对于正常的流程来说需要民政局的人帮忙去后面找自己的女票是十分繁琐的事情。

    而对应到播放器中就是当音频的数据读满buffer的时候,这个时候还没有视频数据到来(或者视频数据读满buffer,而音频数据没有到来),播放器就需要去找此时排在最前面的音频对应dts的视频,这样就可以将他们写入播放器,从而释放音频的内存来存放其他的数据。而找视频的这个过程就需要使用到seek的操作。当从网络读取数据时,就需要使用HTTP去GET请求视频所有的位置,之后从这个位置开始读取数据。而通常上面这样的操作是十分繁琐的,也影响视频的下载。

    针对上面这种排序有问题的文件的一个修改办法就是加大buffer。这样可以接收更多的音视频,从而更容易做同步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章