天天看點

MP4檔案格式解析,及MP4檔案的分割算法

MP4檔案格式的解析,以及MP4檔案的分割算法

視訊點播應用中,更是費盡了心思,主要問題是處理mp4檔案龐大的“媒體頭”。當然,流媒體點播也可以采用flv格式來做,flv也可以封裝H.264視訊資料的,不過Adobe卻不推薦這麼做,人家說畢竟mp4才是H.264最佳的存儲格式嘛。

一、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的基本結構是:

MP4檔案格式解析,及MP4檔案的分割算法

  其中,size指明了整個box所占用的大小,包括header部分。如果box很大(例如存放具體視訊資料的mdat box),超過了uint32的最大數值,size就被設定為1,并用接下來的8位uint64來存放大小。

  一個mp4檔案有可能包含非常多的box,在很大程度上增加了解析的複雜性,這個網頁上​​http://mp4ra.org/atoms.html​​記錄了一些目前注冊過的box類型。看到這麼多box,如果要全部支援,一個個解析,怕是頭都要爆了。還好,大部分mp4檔案沒有那麼多的box類型,下圖就是一個簡化了的,常見的mp4檔案結構:

MP4檔案格式解析,及MP4檔案的分割算法

  一般來說,解析媒體檔案,最關心的部分是視訊檔案的寬高、時長、碼率、編碼格式、幀清單、關鍵幀清單,以及所對應的時戳和在檔案中的位置,這些資訊,在mp4中,是以特定的算法分開存放在stbl box下屬的幾個box中的,需要解析stbl下面所有的box,來還原媒體資訊。下表是對于以上幾個重要的box存放資訊的說明:

MP4檔案格式解析,及MP4檔案的分割算法

  看吧,要擷取到mp4檔案的幀清單,還挺不容易的,需要一層層解析,然後綜合stts stsc stsz stss stco等這幾個box的資訊,才能還原出幀清單,每一幀的時戳和偏移量。而且,你要照顧可能出現或者可能不出現的那些box。。。可以看的出來,mp4把幀sample進行了分組,也就是chunk,需要間接的通過chunk來描述幀,這樣做的理由是可以壓縮存儲空間,縮小媒體資訊所占用的檔案大小。這裡面,stsc box的解析相對來說比較複雜,它用了一種巧妙的方式來說明sample和chunk的映射關系,特别介紹一下。

MP4檔案格式解析,及MP4檔案的分割算法

  這是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

MP4檔案格式解析,及MP4檔案的分割算法

  2. 然後,通過stco或co64獲知chunk總個數之後,開始還原映射表

MP4檔案格式解析,及MP4檔案的分割算法

  讀出stsc之後,就可以綜合stbl下的所有box,推算出視訊和音頻幀清單,時戳和偏移量等資料。下面截圖展示擷取到的關鍵幀清單:

MP4檔案格式解析,及MP4檔案的分割算法

  有了關鍵幀清單之後,就可以繼續我們一下個題目,就是mp4檔案的分割。實作mp4的分割,是把mp4應用到點播系統中最關鍵的技術環節,做不到這個,就無法實作點播播放mp4影片的“拖動”。

二、MP4檔案的分割算法

  所謂“分割”,就是把大檔案切成小檔案,要實作mp4的分割,

  •   首先,需要擷取到關鍵幀清單
  •   然後,選擇要分割的時間段(比如從關鍵幀開始)
  •   接着,重新生成moov box(注意所有相關的box 以及 box size都需要改變)
  •   最後,拷貝對應的資料,生成新檔案

  第一點,上面已經介紹了,第二點,隻需要周遊關鍵幀清單,就能找到離你想要分割的時間段最接近的關鍵幀,第四點就是“copy-paste”的工作,關鍵在于第三點。因為這一步涉及到stbl下的所有box,必須重新生成entrys,同樣的,其他的box都還好,隻需要保留關鍵幀所對應的sample和chunk,其餘的删掉即可,隻是stsc box的比較麻煩,說起來比較啰嗦,還是直接看代碼吧:

MP4檔案格式解析,及MP4檔案的分割算法

  修改完box之後,需要重新生成moov box,由于moov box的大小以及時長等資訊都發生了改變,是以需要box的大小做相應的修改,這點千萬不能忘記,否則播放器會解析錯誤。重新生成box之後,還要計算一下分割後的資料的長度,由于資料長度也發生了改變,是以修改mdat box的大小的同時,要同時修改stbl下所有box的chunk offset,切記!