c實現(xiàn)mp4解封裝-創(chuàng)新互聯(lián)

文章目錄
    • 前序
    • MP4簡介
      • MP4的定義
      • MP4的封裝格式
    • Box類型詳解
      • Box格式
      • ftyp box
      • mvhd box
      • tkhd box
      • hdlr box
      • mdat box
      • stbl box
      • stsd box
      • stco box
      • stsc box
      • stsz box
      • stts box
      • stss box
    • demuxer demo的實現(xiàn)(視頻數(shù)據(jù)部分)
    • 總結(jié):
    • 工具介紹
    • 源碼
    • 參考

我們提供的服務(wù)有:做網(wǎng)站、網(wǎng)站設(shè)計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、江孜ssl等。為上千余家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的江孜網(wǎng)站制作公司前序

最近為了更加深入了解音視頻demux這塊的功能,準(zhǔn)備著手寫個demuxer,提取視頻流。

MP4簡介 MP4的定義

MP4是一種常用的視音頻流封裝格式,按照指定的協(xié)議來存放媒體數(shù)據(jù);因為mp4是基于蘋果QuickTime文件格式,所以與mov有很多相同之處,在蘋果開發(fā)者平臺可以看到詳細(xì)的有關(guān)封裝文檔(https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25615)

MP4的封裝格式
  • MP4格式預(yù)覽—mp4是由多個box嵌套組成的
    在這里插入圖片描述

  • MP4主要的頂部box

    ftyp box:描述MP4鎖遵循的規(guī)范和版本

    mdat box :存放媒體數(shù)據(jù)

    moov box:存放媒體參數(shù)(pps、sps等)相關(guān)信息和用于索引媒體數(shù)據(jù)存儲位置的信息

  • MP4常用box
    在這里插入圖片描述

Box類型詳解 Box格式

在這里插入圖片描述

  1. size字段為整個box的大小,包括box header和box body
  2. type為box的類型,通常為四字節(jié)的字符串,例如ftyp
  3. 當(dāng)size == 0時,box的大小為large size
  4. 當(dāng)box為full box時,存在version和flags字段,具體含義因box不同而不同
  5. 若box沒有嵌套其他box,例如ftyp box,則box body部分根據(jù)具體規(guī)范解析相應(yīng)字段;若box為container box,則box body部分嵌套其它box,還需一步步解套獲取最終的數(shù)據(jù)
ftyp box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

  • major_brand:比如常見的 isom、mp41、mp42、avc1、qt等。它表示“最好”基于哪種格式來解析當(dāng)前的文件。舉例,major_brand 是 A,compatible_brands 是 A1,當(dāng)解碼器同時支持 A、A1 規(guī)范時,最好使用A規(guī)范來解碼當(dāng)前媒體文件,如果不支持A規(guī)范,但支持A1規(guī)范,那么,可以使用A1規(guī)范來解碼;

  • minor_version:提供 major_brand 的說明信息,比如版本號,不得用來判斷媒體文件是否符合某個標(biāo)準(zhǔn)/規(guī)范;

  • compatible_brands:文件兼容的brand列表。比如 mp41 的兼容 brand 為 isom。通過兼容列表里的 brand 規(guī)范,可以將文件 部分(或全部)解碼出來;

mvhd box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • version :一字節(jié)用于指定mvhd的版本

    • flags:3字節(jié),預(yù)留

    • Create time:媒體創(chuàng)建時間,與UTC時間不同的是,此時間是從1904年1月1日0:0:0開始計算的,而utc是從1970年1月1日0:0:0開始計算,故Create time須要減去時間差換算成utc時間

      // 注:66年時間差不是66*365*24*3600來計算
      creation_time_utc = creation_time - (66年時間差) = creation_time - 2082844800
    • Modification time:媒體最后被修改的時間,計算方式同Create time

    • Timescale:一秒包含的時間單位(整數(shù))。舉個例子,如果timescale等于1000,那么,一秒包含1000個時間單位(后面track等的時間,都要用這個來換算,比如track的duration為10,000,那么,track的實際時長為10,000/1000=10s);

    • Duration:影片時長(整數(shù)),根據(jù)文件中的track的信息推導(dǎo)出來,等于時間最長的track的duration;

    • Preferred rate:推薦的播放速率,32位整數(shù),高16位、低16位分別代表整數(shù)部分、小數(shù)部分([16.16]),舉例 0x0001 0000 代表1.0,正常播放速度;

    • Preferred volume:播放音量,16位整數(shù),高8位、低8位分別代表整數(shù)部分、小數(shù)部分([8.8]),舉例 0x01 00 表示 1.0,即大音量;

    • Matrix struct:視頻的轉(zhuǎn)換矩陣,詳情看

      Basic Data Types

    • Next_track_ID:32位整數(shù),非0,一般可以忽略不計。當(dāng)要添加一個新的track到這個影片時,可以使用的track id,必須比當(dāng)前已經(jīng)使用的track id要大。也就是說,添加新的track時,需要遍歷所有track,確認(rèn)可用的track id;

tkhd box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • version:tkhd box的版本;
    • flags:按位或操作獲得,默認(rèn)值是7(0x000001 | 0x000002 | 0x000004),表示這個track是啟用的、用于播放的 且 用于預(yù)覽的。
      • Track_enabled:值為0x000001,表示這個track是啟用的,當(dāng)值為0x000000,表示這個track沒有啟用;
      • Track_in_movie:值為0x000002,表示當(dāng)前track在播放時會用到;
      • Track_in_preview:值為0x000004,表示當(dāng)前track用于預(yù)覽模式;
    • Creation time:當(dāng)前track的創(chuàng)建時間;
    • Modification time:當(dāng)前track的最近修改時間;
    • Track ID:當(dāng)前track的唯一標(biāo)識,不能為0,不能重復(fù);
    • Duration:當(dāng)前track的完整時長(需要除以timescale得到具體秒數(shù));
    • Layer:視頻軌道的疊加順序,數(shù)字越小越靠近觀看者,比如1比2靠上,0比1靠上;
    • Alternate_group:當(dāng)前track的分組ID,alternate_group值相同的track在同一個分組里面。同個分組里的track,同一時間只能有一個track處于播放狀態(tài)。當(dāng)alternate_group為0時,表示當(dāng)前track沒有跟其他track處于同個分組。一個分組里面,也可以只有一個track;
    • Volume:audio track的音量,介于0.0~1.0之間;
    • Matrix structure:視頻的變換矩陣;
    • Track width:視頻的寬
    • Track height:視頻的高
hdlr box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:hdlr box的版本
    • Flags:置0
    • Component type:四字節(jié)子串定義handler的類型;此字段只有兩種值合法:'mhlr’(media handlers)和’dhlr’(data handlers)
    • Component subtype:針對Component type進(jìn)行細(xì)分類型,例如’vide’定義為視頻數(shù)據(jù),'soun’定義為音頻數(shù)據(jù)
    • Component manufacturer:保留,置0
    • Component flags:保留,置0
    • Component flags mask:保留,置0
    • Component name:子串指定Component 的名字,可能為空
mdat box
  • 數(shù)據(jù)結(jié)構(gòu)分布圖
    在這里插入圖片描述

    注意:取到的frame前四個字節(jié)為frame數(shù)據(jù)的長度字節(jié),須要偏移去掉

stbl box

主要存放了媒體參數(shù)(pps、sps、vps等)相關(guān)信息和用于解析mdat中視音頻數(shù)據(jù)的關(guān)鍵信息

  • stsd:給出視音頻的相關(guān)參數(shù)信息,有高寬、音量、位深度和每個sample多少個frame
  • stco:chunk在文件中的偏移
  • stsc:每個chunk中包含幾個sample
  • stsz:每個sample的size(單位是字節(jié))
  • stts:每個sample的時長
  • stss:哪些sample是關(guān)鍵幀
stsd box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stsd box的版本
    • Flags:置0
    • Number of entries:Sample description table的個數(shù)
    • Sample description table:以視頻為例,此時Sample description table字段中為若干個視頻編碼相關(guān)的box,例如avc1 box
      • avc1 box

        • 字段分布圖
          在這里插入圖片描述

        • 字段解析

          這個在https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html的“Sample Description Atoms”一節(jié)可以研究下

      • avcC box(包含了視頻關(guān)鍵參數(shù),在ISO/IEC 14496-15中定義)

        • 字段分布圖
          在這里插入圖片描述

        • 字段解析

          • num_of_sps:sps的個數(shù)
          • sps_length:sps的長度
          • sps_nal_unit:長度為sps_length的sps
          • num_of_pps:pps的個數(shù)
          • pps_length:pps的長度
          • pps_nal_unit:長度為pps_length的pps

          其他字段可以自行在ISO/IEC 14496-15中查到

stco box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stco box的版本
    • Flags:置0
    • Number of entries:chunk的個數(shù)
    • Chunk offset table:每個chunk在整個視頻文件的偏移值,每個值的長度為4字節(jié)
stsc box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stsc box的版本
    • Flags:置0
    • Number of entries:”Sample-to-chunk table”的條數(shù)
    • Sample-to-chunk table:
      • First chunk:chunk的索引
      • Samples per chunk:從’First chunk’開始,每個chunk中sample的個數(shù)
      • Sample description ID:stsd box中‘Sample description table’的下標(biāo)
  • Sample-to-chunk table示意圖
    在這里插入圖片描述

    • chunk1-chunk2:每個chunk中有3個sample,并且Sample description ID為23
    • chunk3-chunk4:每個chunk中有1個sample,并且Sample description ID為23
    • chunk5:每個chunk中有3個sample,并且Sample description ID為24
stsz box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stsz box的版本
    • Flags:置0
    • Sample size:為0則表示所有sample的大小不一定一樣,不為0則表示所有sample的大小一樣
    • Number of entries:”Sample size table”的條數(shù)
    • Sample size table:每個sample的size,每個sample size的長度為4字節(jié)
stts box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stts box的版本
    • Flags:置0
    • Number of entries:“Time-to-sample table”的條數(shù)
    • Time-to-sample table:
      • Sample count:具有相同“Sample duration”的個數(shù)
      • Sample duration:sample的時長(以timescale為計量)
  • Time-to-sample table:示意圖
    在這里插入圖片描述

    sample1 - sample4的sample duration是4

stss box
  • 字段分布圖
    在這里插入圖片描述

  • 字段解析

    • Version:stts box的版本
    • Flags:置0
    • Number of entries:“Sync sample table”的條數(shù)
    • Sync sample table:關(guān)鍵幀對應(yīng)的sample index
demuxer demo的實現(xiàn)(視頻數(shù)據(jù)部分)
  1. 獲取sps pps參數(shù)

    1. 解析stsd box,其中contain avc1 box和avcC box(此步驟詳解見上文)

    2. 解析avcC box可以獲取到sps和pps

      以下為ISO/IEC 14496-15中解析avcC的偽代碼

    aligned(8) class AVCDecoderConfigurationRecord { unsigned int(8) configurationVersion = 1; 
    	 unsigned int(8) AVCProfileIndication; 
    	 unsigned int(8) profile_compatibility; 
    	 unsigned int(8) AVCLevelIndication; 
    	 bit(6) reserved = ‘111111’b; 
    	 unsigned int(2) lengthSizeMinusOne; 
    	 bit(3) reserved = ‘111’b; 
    	 unsigned int(5) numOfSequenceParameterSets; 
    	 for (i=0; i< numOfSequenceParameterSets; i++) { unsigned int(16) sequenceParameterSetLength ; 
    		 bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit; 
    	 } 
    	 unsigned int(8) numOfPictureParameterSets; 
    	 for (i=0; i< numOfPictureParameterSets; i++) { unsigned int(16) pictureParameterSetLength; 
    		 bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; 
     }
    
     if( profile_idc == 100 || profile_idc == 110 || 
    	 profile_idc == 122 || profile_idc == 144 ) 
    	 { bit(6) reserved = ‘111111’b; 
    		 unsigned int(2) chroma_format; 
    		 bit(5) reserved = ‘11111’b; 
    		 unsigned int(3) bit_depth_luma_minus8; 
    		 bit(5) reserved = ‘11111’b; 
    		 unsigned int(3) bit_depth_chroma_minus8; 
    		 unsigned int(8) numOfSequenceParameterSetExt; 
    		 for (i=0; i< numOfSequenceParameterSetExt; i++) {	 unsigned int(16) sequenceParameterSetExtLength; 
    			 bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit; 
    		 } 
    	 } 
    }
  2. 獲取關(guān)鍵幀位置

    解析stss box可以知道哪一個sample中包含關(guān)鍵幀

  3. 獲取chunk位置

    解析stco box可以獲取到每個chunk在視頻文件中的索引

  4. 獲取每個chunk中sample個數(shù)

    解析stsc box可以獲取到每個chunk包含多少個sample

  5. 獲取sample大小

    解析stsz box可以獲取到每個sample的大小

  6. 獲取frame位置(demo視頻文件一個sample只包含一個frame,所以sample的位置和大小就是frame的位置和大小)

    1. 根據(jù)stsd解析到每個sample中有多少個frame
    2. 然后再根據(jù)trunk的位置和sample的大小來定位frame起始地址
    3. mdat中frame的數(shù)據(jù)格式為: | 4字節(jié)數(shù)據(jù)長度 | frame數(shù)據(jù)|,所以根據(jù)字節(jié)長度讀取相應(yīng)個數(shù)frame
  7. 獲取到一幀數(shù)據(jù)后

    1. 判斷當(dāng)前frame為I幀,則添加寫入(start_code+sps) + (start_code+pps) + (start_code + frame數(shù)據(jù))到輸出文件
    2. 判斷當(dāng)前frame不為I幀,則寫入(start_code + frame數(shù)據(jù))到輸出文件
  8. 保存成h264文件,可使用ffplay和potplay播放

注意:有些非字串的字段為大端字節(jié)序,須要轉(zhuǎn)換

總結(jié):
  1. 解析非字符串的數(shù)據(jù)時,需要注意大小端的問題
  2. 解析對應(yīng)的box獲取到sps、vps、pps
  3. 解析對應(yīng)的box拿到視頻幀數(shù)據(jù)
  4. 將視頻幀寫入本地文件的時候要注意
    1. 視頻幀前四個字節(jié)為視頻幀數(shù)據(jù)長度
    2. 若為I幀則需要加上sps、vps、pps
    3. 視頻幀注意加上start_code
工具介紹
  1. mp4info—可以看到相關(guān)box的字節(jié)信息,但發(fā)現(xiàn)對avcC的解析漏掉了幾個字節(jié)
    在這里插入圖片描述

  2. mp4 exploer—可以更加直觀的看到視音頻數(shù)據(jù)信息
    在這里插入圖片描述

源碼

https://github.com/TaoChou/demuxer-c

參考
  1. https://zhuanlan.zhihu.com/p/333765990
  2. https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691
  3. ISO/IEC 14496-15

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

文章標(biāo)題:c實現(xiàn)mp4解封裝-創(chuàng)新互聯(lián)
瀏覽地址:http://bm7419.com/article26/didscg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序品牌網(wǎng)站建設(shè)、Google移動網(wǎng)站建設(shè)、建站公司、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)