<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    【多媒體封裝格式詳解】---MP4【4】

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    前面介紹過的幾種格式flv、mkv、asf等。他們音視頻的數據包一般都是按照文件的順序交叉安放。你解析完頭部信息后。剩下的一般就按照文件順序一個數據包一個數據包的解析就行了。但是MP4完全不是這種概念。他的媒體信息和數據是分開存放的。就是你想獲得數據之前必須要解析出每個幀數據所有的位置。mp4存放這個幀信息的是放在stbl這個box里。而真實的數據放在mdat中。接下來就講講stbl與mdat的對應關系。

    Sample Table Box(stbl)

    來一張典型的stbl結構圖: RFID設備管理軟件 常見子box

    stts:    Decoding Time to Sample Box 時間戳和Sample映射表
    stsd:   Sample Description Box
    stsz, stz2: Sample Size Boxes 每個Sample大小的表。
    stsc: Sample to chunk 的映射表。
    ‘stco’, ‘co64’: Chunk位置偏移表
    stss:關鍵幀index。

    1.解析stsd可獲得coding類型視頻寬高、音頻samplesize、channelcount這些和解碼器有關信息。

     

    [cpp] view plaincopy
    1. aligned(8) class SampleDescriptionBox (unsigned int(32) handler_type)  
    2. extends FullBox('stsd', 0, 0){  
    3. int i ;  
    4. unsigned int(32) entry_count;  
    5. for (i = 1 ; i u entry_count ; i++){  
    6. switch (handler_type){  
    7. case ‘soun’: // for audio tracks  
    8. AudioSampleEntry();  
    9. break;  
    10. case ‘vide’: // for video tracks  
    11. VisualSampleEntry();  
    12. break;  
    13. case ‘hint’: // Hint track  
    14. HintSampleEntry();  
    15. break;  
    16. }  
    17. }  
    18. }  

     

    [cpp] view plaincopy
    1. aligned(8) abstract class SampleEntry (unsigned int(32) format)  
    2. extends Box(format){  
    3. const unsigned int(8)[6] reserved = 0;  
    4. unsigned int(16) data_reference_index;  
    5. }  
    6. class HintSampleEntry() extends SampleEntry (protocol) {  
    7. unsigned int(8) data [];  
    8. }  
    9. // Visual Sequences  
    10. class VisualSampleEntry(codingname) extends SampleEntry (codingname){  
    11. unsigned int(16) pre_defined = 0;  
    12. const unsigned int(16) reserved = 0;  
    13. unsigned int(32)[3] pre_defined = 0;  
    14. unsigned int(16) width;  
    15. unsigned int(16) height;  
    16. template unsigned int(32) horizresolution = 0x00480000; // 72 dpi  
    17. template unsigned int(32) vertresolution = 0x00480000; // 72 dpi  
    18. const unsigned int(32) reserved = 0;  
    19. template unsigned int(16) frame_count = 1;  
    20. string[32] compressorname;  
    21. template unsigned int(16) depth = 0x0018;  
    22. int(16) pre_defined = -1;  
    23. }  
    24. // Audio Sequences  
    25. class AudioSampleEntry(codingname) extends SampleEntry (codingname){  
    26. const unsigned int(32)[2] reserved = 0;  
    27. template unsigned int(16) channelcount = 2;  
    28. template unsigned int(16) samplesize = 16;  
    29. unsigned int(16) pre_defined = 0;  
    30. const unsigned int(16) reserved = 0 ;  
    31. template unsigned int(32) samplerate = {timescale of media}<<16;  
    32. }  

     

     

    2.解析stsz box 可以獲得一個sample size的表

     

    [cpp] view plaincopy
    1. aligned(8) class SampleSizeBox extends FullBox(‘stsz’, version = 0, 0) {  
    2. unsigned int(32) sample_size;  
    3. unsigned int(32) sample_count;  
    4. if (sample_size==0) {  
    5. for (i=1; i u sample_count; i++) {  
    6. unsigned int(32) entry_size;  
    7. }  
    8. }  
    9. }  

    3.解析stts 

     

     

    [cpp] view plaincopy
    1. aligned(8) class TimeToSampleBox  
    2. extends FullBox(’stts’, version = 0, 0) {  
    3. unsigned int(32) entry_count;  
    4. int i;  
    5. for (i=0; i < entry_count; i++) {  
    6. unsigned int(32) sample_count;  
    7. unsigned int(32) sample_delta;  
    8. }  
    9. }  

     

    4.解析stsc 還原Sample 與chunk的映射表 

    RFID設備管理軟件

     


    Sample 是存儲的最基本單元,mp4把Sample 存在chunk中。chunk的長度、chunk的大小、chunk中Sample的數量及大小都是不定的。

    通過解析這部分box來還原這個映射表。

     

    [cpp] view plaincopy
    1. aligned(8) class SampleToChunkBox  
    2. extends FullBox(‘stsc’, version = 0, 0) {  
    3. unsigned int(32) entry_count;  
    4. for (i=1; i u entry_count; i++) {  
    5. unsigned int(32) first_chunk;  
    6. unsigned int(32) samples_per_chunk;  
    7. unsigned int(32) sample_description_index;  
    8. }  
    9. }  


    每個entry 表示著一組數據,entry_count 表示這數量。這一組其實是相同類型的chunk。

     

    first_chunk 表示 這一組相同類型的chunk中 的第一個chunk數。

    這些chunk 中包含的Sample 數量,即samples_per_chunk 是一致的。

    每個Sample 可以通過sample_description_index 去stsd box 找到描述信息。

    看ffmpeg中mov_read_stsc() 它把這些數據放在一個結構體數組中備用。

     

    [cpp] view plaincopy
    1. static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)  
    2. {  
    3.     AVStream *st;  
    4.     MOVStreamContext *sc;  
    5.     unsigned int i, entries;  
    6.   
    7.     if (c->fc->nb_streams < 1)  
    8.         return 0;  
    9.     st = c->fc->streams[c->fc->nb_streams-1];  
    10.     sc = st->priv_data;  
    11.   
    12.     avio_r8(pb); /* version */  
    13.     avio_rb24(pb); /* flags */  
    14.   
    15.     entries = avio_rb32(pb);  
    16.   
    17.     av_dlog(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);  
    18.   
    19.     if (!entries)  
    20.         return 0;  
    21.     if (entries >= UINT_MAX / sizeof(*sc->stsc_data))  
    22.         return AVERROR_INVALIDDATA;  
    23.     sc->stsc_data = av_malloc(entries * sizeof(*sc->stsc_data));  
    24.     if (!sc->stsc_data)  
    25.         return AVERROR(ENOMEM);  
    26.   
    27.     for (i = 0; i < entries && !pb->eof_reached; i++) {  
    28.         sc->stsc_data[i].first = avio_rb32(pb);  
    29.         sc->stsc_data[i].count = avio_rb32(pb);  
    30.         sc->stsc_data[i].id = avio_rb32(pb);  
    31.     }  
    32.   
    33.     sc->stsc_count = i;  
    34.   
    35.     if (pb->eof_reached)  
    36.         return AVERROR_EOF;  
    37.   
    38.     return 0;  
    39. }  

    在獲得完整的映射表,我們還需要chunk總個數信息。這些信息放在‘stco’, ‘co64’中。

     

    5.解析‘stco’, ‘co64’

    “stco”定義了每個thunk在媒體流中的位置。位置有兩種可能,32位的和64位的,后者對非常大的電影很有用。

    32位

     

    [cpp] view plaincopy
    1. aligned(8) class ChunkOffsetBox  
    2. extends FullBox(‘stco’, version = 0, 0) {  
    3. unsigned int(32) entry_count;  
    4. for (i=1; i u entry_count; i++) {  
    5. unsigned int(32) chunk_offset;  
    6. }  
    7. }  


    64位

     

     

    [cpp] view plaincopy
    1. aligned(8) class ChunkLargeOffsetBox  
    2. extends FullBox(‘co64’, version = 0, 0) {  
    3. unsigned int(32) entry_count;  
    4. for (i=1; i u entry_count; i++) {  
    5. unsigned int(64) chunk_offset;  
    6. }  
    7. }  

    從這個box我們就可以獲得 chunk 的總數量,entry_count

     

     from:http://blog.csdn.net/tx3344/article/details/8506131

    1.解析‘stco’, ‘co64’我們有了chunk 表,知道了chunk 的總數及每個chunk所在文件的位置。

    2.解析stsc 配合著上面的chunk表,我們就能弄個Sample與chunk的關系表。我們也就能獲得每個Sample的位置信息。

    3.配合上面的stts 時間表和解碼器信息等。搞出ES流已經不成問題了。

    4.想獲得關鍵幀的index,需要解析stss’

     

    [cpp] view plaincopy
      1. aligned(8) class SyncSampleBox  
      2. extends FullBox(‘stss’, version = 0, 0) {  
      3. unsigned int(32) entry_count;  
      4. int i;  
      5. for (i=0; i < entry_count; i++) {  
      6. unsigned int(32) sample_number;  
      7. }  
      8. }  
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全