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

  mp4應該算是一種比較復雜的媒體格式了,起源于QuickTime。以前研究的時候就花了一番的功夫,尤其是如何把它完美的融入到視頻點播應用中,更是費盡了心思,主要問題是處理mp4文件龐大的“媒體頭”。當然,流媒體點播也可以采用flv格式來做,flv也可以封裝H.264視頻數據的,不過Adobe卻不推薦這么做,人家說畢竟mp4才是H.264最佳的存儲格式嘛。

  這幾天整理并重構了一下mp4文件的解析程序,融合了分解與合并的程序,以前是c語言寫的,應用在linux上運行的服務器程序上,現在改成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文件的幀列表,還挺不容易的,需要一層層解析,然后綜合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點播,還有一些其他的問題需要解決,我將在下一篇文章中介紹。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

??haibindev.cnblogs.com,合作請聯系QQ。(轉載請注明作者和出處)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



MP4視頻拆解可用的小工具


1.Gstreamer

2.libvlc

3.live555

4.ffmpeg

vlc -vvv test.mp4? 檢查視頻流格式



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383467.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383467.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383467.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MP4文件格式詳解

一、基本概念 1.mp4概述 MP4文件中的所有數據都裝在box(QuickTime中為atom)中,也就是說MP4文件由若干個box組成,每個box有類型和長度,可以將box理解為一個數據對象塊。box中可以包含另一個box,這種box稱為c…

H264—MP4格式及在MP4文件中提取H264的SPS、PPS及碼流

SkySeraph Apr 1st 2012 Email:skyseraph00163.com 一、MP4格式基本概念 MP4格式對應標準MPEG-4標準(ISO/IEC14496) 二、MP4封裝格式核心概念 1 MP4封裝格式對應標準為 ISO/IEC 14496-12(信息技術 視聽對象編碼的第12部分: ISO 基本媒體文件格式/Info…

AAC音頻格式分析

關于AAC音頻格式基本情況,可參考維基百科http://en.wikipedia.org/wiki/Advanced_Audio_Coding AAC音頻格式分析 AAC音頻格式有ADIF和ADTS: ADIF:Audio Data Interchange Format 音頻數據交換格式。這種格式的特征是可以確定的找到這個音頻數…

tar壓縮隱藏文件

如果想tar 壓縮包含隱藏文件的目錄,同時排除掉部分無用的目錄 tar -czvf 20161009.tar.gz * .[!.]* --exclude .git 在Linux下打包tar文件時添加密碼的方法 在當前目錄下有一個pma目錄的文件夾: 1、使用tar對文件壓縮加密: 代碼如下: # tar -zcvf - pma…

linux 怎么把^M去掉

在linux下,不可避免的會用VIM打開一些windows下編輯過的文本文件。我們會發現文件的每行結尾都會有一個^M符號,這是因為 DOS下的編輯器和Linux編輯器對文件行末的回車符處理不一致, 對于回車符的定義: windows:0D0A un…

關于cp命令中拷貝所有的寫法

今天在編寫一個腳本的時候,發現一個比較奇怪的問題:就是在使用cp拷貝當前目錄下所有文件到目標目錄的時候,源和目標大大不同。原來一直沒有留意有這樣的問題,后來查了些資料,才知道以前一直使用的格式有誤,…

cp -r 和 cp -R 的區別

今天倒騰linux根文件系統的時候發現 cp -r /dev /dev_bak 時,竟然會 將磁盤設備中的數據進行一次拷貝,而不是僅僅建立設備文件。于是到網上搜了一把,收獲不小。http://www.loveunix.net/html/200407/33920.html這里有人問同樣的問題&#xff…

Makefile選項CFLAGS,LDFLAGS,LIBS

CFLAGS 表示用于 C 編譯器的選項, CXXFLAGS 表示用于 C 編譯器的選項。 這兩個變量實際上涵蓋了編譯和匯編兩個步驟。 CFLAGS: 指定頭文件(.h文件)的路徑,如:CFLAGS-I/usr/include -I/path/include。同樣地…

smbclient和掛載samba共享目錄

1,列出某個IP地址所提供的共享文件夾 smbclient -L 198.168.0.1 -U marsaber%12332112345672,像FTP客戶端一樣使用smbclient smbclient //192.168.0.1/tmp -U marsaber%1233211234567 執行smbclient命令成功后,進入smbclient環境,出現提示符…

linux 下source命令

當我修改了/etc/profile文件,我想讓它立刻生效,而不用重新登錄;這時就想到用 source 命令,如:source /etc/profile對source進行了 學習 ,并且用它與sh 執行腳本進行了對比,現在總結一下。source命令&#x…

make Image uImage與zImage的區別

內核編譯(make)之后會生成兩個文件,一個Image,一個zImage,其中Image為內核映像文件,而zImage為內核的一種映像壓縮文件,Image大約為4M,而zImage不到2M。 那么uImage又是什么的&#…

ubuntu下tftp的安裝、配置、使用

1. 安裝$ apt-get install tftp-hpa tftpd-hpa2. 建立目錄$ mkdir /tftpboot # 這是建立tftp傳輸目錄。$ sudo chmod 0777 /tftpboot$ sudo touch test.txt # test.txt文件最好輸入內容以便區分3. 配置$ sudo vi /etc/default/tftpd-hpa# /etc/default/tftpd-hpaTFTP_USERNAME&…

ubuntu下搭建nfs服務器

1.1 搭建NFS服務器 NFS(Network FileSystem,網絡文件系統)是由SUN公司發展,并于1984年推出的技術,用于在不同機器,不同操作系統之間通過網絡互相分享各自的文件。NFS設計之初就是為了在不同的系統間使…

uboot的常用命令詳解

U-Boot還提供了更加詳細的命令幫助,通過help命令還可以查看每個命令的參數說明。由于開發過程的需要,有必要先把U-Boot命令的用法弄清楚。接下來,根據每一條命令的幫助信息,解釋一下這些命令的功能和參數。 進入uboot的命令行提示…

minicom 串口信息過長分行顯示

有時串口輸出一行信息比較多,一行顯示不下,這個時候,我們可以用minicom的本身組合鍵設置,超過一行時自動卷起。 minicom 組合鍵的用法是:先按CtrlA組合鍵,然后松開這兩個鍵,再按Z鍵。另外還有一…

uboot 的 bootcmd 和bootargs參數詳解

U-boot的環境變量值得注意的有兩個: bootcmd 和bootargs。 bootargsconsolettyS1,115200n8 mem32M0x0 ispmem8M0x2000000 rmem24M0x2800000 init/linuxrc rootfstypesquashfs root/dev/mtdblock2 rw mtdpartsjz_sfc:256k(boot),2560k(kernel),2048k(root),-(appfs) …

MTD和 uboot中的bootargs 下屬 mtdparts

MTD 設備是象閃存芯片、小型閃存卡、記憶棒等之類的設備,它們在嵌入式設備中的使用正在不斷增長。 MTD 驅動程序是在 Linux 下專門為嵌入式環境開發的新的一類驅動程序。相對于常規塊設備驅動程序,使用 MTD 驅動程序的主要優點在于 MTD 驅動程序是專門為…

Linux應用程序在內存中的地址布局

棧:局部變量(初始化的和未初始化的,但不包含局部靜態變量)、局部只讀變量(const)堆:動態分配的區域(如使用malloc函數申請的區域)BSS段:存儲未初始化的全局變…

比較zImage和uImage的區別

一、vmlinuz vmlinuz是可引導的、壓縮的內核。“vm”代表“Virtual Memory”。Linux 支持虛擬內存,不像老的操作系統比如DOS有640KB內存的限制。Linux能夠使用硬盤空間作為虛擬內存,因此得名“vm”。 vmlinuz的建立有兩種方式。一是編譯內核時通過“make…

編譯faac錯誤分析

編譯faac時遇到了以下的編譯錯誤: /home/xuxuequan/Ingenicwork/toolchain/mips-gcc472-glibc216-32bit/mips-linux-gnu/libc/usr/include/string.h:365:26: error:ambiguates old declaration const char* strcasestr(const char*, const char*) 解決方案&#x…