软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解

来源:互联网 发布:windows.hlp官方下载 编辑:程序博客网 时间:2024/06/16 18:31

https://github.com/332065255/flv2fmp4

代码库


软编码Flv 到Mp4 容器(一)
软编码Flv 到Mp4 容器(二) flv tag拆解
软编码Flv 到Mp4 容器(三) flv metadata tag解析
软编码Flv 到Mp4 容器(四) fmp4 总览和基础讲解
软编码Flv 到Mp4 容器(五) fmp4 ftyp box 和moov>mvhd box详解
软编码Flv 到Mp4 容器(六) fmp4 moov>trak>tkhd box 和 moov>trak>mdia>mdhd box讲解
软编码Flv 到Mp4 容器(七) fmp4 mdia>hdlr box 和 mdia>minf> smhd 和dinf box讲解
软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
软编码Flv 到Mp4 容器(九) fmp4 stts stsc stsz stco box 讲解
软编码Flv 到Mp4 容器(十) fmp4 mvex box 讲解
软编码Flv 到Mp4 容器(十一) fmp4 moof box详解
软编码Flv 到Mp4 容器(十二) fmp4 mdat box详解
软编码Flv 到Mp4 容器(十三) fmp4 生成ftyp和moov所必要的 flv数据


 - ftyp - moov     - mvhd     - trak         - tkhd         - mdia             - mdhd             - hdlr             - minf                 - smhd                 - dinf                     - dref                         - url                 - stbl                     -  stsd                         - mp4a(avc1)                             - esds(avcC)                     - stts                     - stsc                     - stsz                     - stco     - mvex        -trex - moof    - mfhd    - traf        -tfhd        -tfdt        -sdtp        -trun - mdat

首先对应标题的box在 fmp4容器中的位置
这一章非常复杂,代码量很大

stbl box

Box Type: ‘stbl’
Container: Media Information Box (‘minf’)
Mandatory: Yes
Quantity: Exactly one

定义

aligned(8) class SampleTableBox extends Box(‘stbl’) { }

stbl是一个容器box


stsd box

BoxTypes: ‘stsd’
Container: Sample Table Box (‘stbl’)
Mandatory: Yes
Quantity: Exactly one

定义

aligned(8) abstract class SampleEntry (unsigned int(32) format) extends Box(format){    const unsigned int(8)[6] reserved = 0;    unsigned int(16) data_reference_index;}class HintSampleEntry() extends SampleEntry (protocol) {     unsigned int(8) data [];}   // Visual Sequencesclass VisualSampleEntry(codingname) extends SampleEntry (codingname){ unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0;unsigned int(32)[3] pre_defined = 0;unsigned int(16) width;unsigned int(16) height;template unsigned int(32) horizresolution = 0x00480000; // 72 dpi template unsigned int(32) vertresolution = 0x00480000; // 72 dpiconst unsigned int(32) reserved = 0;template unsigned int(16) frame_count = 1;string[32] compressorname;template unsigned int(16) depth = 0x0018;int(16) pre_defined = -1;}   // Audio Sequencesclass AudioSampleEntry(codingname) extends SampleEntry (codingname){ const unsigned int(32)[2] reserved = 0;template unsigned int(16) channelcount = 2;template unsigned int(16) samplesize = 16;unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0 ;template unsigned int(32) samplerate = {timescale of media}<<16;}aligned(8) class SampleDescriptionBox (unsigned int(32) handler_type) extends FullBox('stsd', 0, 0){int i ;unsigned int(32) entry_count;for (i = 1 ; i u entry_count ; i++){      switch (handler_type){ //对应 hdlr box 中的handler_type          case ‘soun’: // for audio tracks            AudioSampleEntry();            break;         case ‘vide’: // for video tracks            VisualSampleEntry();            break;         casehint’: // Hint track            HintSampleEntry();break; }} }

stsd下的box分3种情况,soun box or vide box,另一个忽略不计

首先实现stsd box开头的Sample Entry

var STSD_PREFIX = new Uint8Array([            0x00, 0x00, 0x00, 0x00, // version(0) + flags  version字段后会有一个entry count字段            0x00, 0x00, 0x00, 0x01 // entry_count   根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。        ]);

选择实现vide box
先看vide box的定义

class VisualSampleEntry(codingname) extends SampleEntry (codingname){ unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0;unsigned int(32)[3] pre_defined = 0;unsigned int(16) width;unsigned int(16) height;template unsigned int(32) horizresolution = 0x00480000; // 72 dpi template unsigned int(32) vertresolution = 0x00480000; // 72 dpiconst unsigned int(32) reserved = 0;template unsigned int(16) frame_count = 1;string[32] compressorname;template unsigned int(16) depth = 0x0018;int(16) pre_defined = -1;}
let avc1 = new Uint8Array([            0x00, 0x00, 0x00, 0x00, // // reserved(4)    6个 保留位 Reserved:6个字节,设置为0;            0x00, 0x00, 0x00, 0x01, // reserved(2) + {{{{data_reference_index(2)  数据引用索引}}}}            0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2)            0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes  3*4个字节的保留位            0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00,            (width >>> 8) & 0xFF, // width: 2 bytes            (width) & 0xFF,            (height >>> 8) & 0xFF, // height: 2 bytes            (height) & 0xFF,            0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes 常数            0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes 常数            0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes 保留位            0x00, 0x01, // frame_count                  //frame_count表明多少帧压缩视频存储在每个样本。默认是1,每样一帧;它可能超过1每个样本的多个帧数            0x04, //    strlen compressorname: 32 bytes         String[32]            //32个8 bit    第一个8bit表示长度,剩下31个8bit表示内容            0x67, 0x31, 0x31, 0x31, // compressorname: 32 bytes    翻译过来是g111            0x00, 0x00, 0x00, 0x00, //            0x00, 0x00, 0x00, 0x00, //            0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00,            0x00, 0x18, // depth 颜色深度            0xFF, 0xFF // pre_defined = -1        ]);let avcc = 暂无

avcc box

软编码Flv 到Mp4 容器(外传一)avcc box


选择实现soun box

  // Audio Sequencesclass AudioSampleEntry(codingname) extends SampleEntry (codingname){ const unsigned int(32)[2] reserved = 0;template unsigned int(16) channelcount = 2;template unsigned int(16) samplesize = 16;unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0 ;template unsigned int(32) samplerate = {timescale of media}<<16;}
static mp4a(meta) {        let channelCount = meta.channelCount;        let sampleRate = meta.audioSampleRate;        let data = new Uint8Array([            0x00, 0x00, 0x00, 0x00, // reserved(4) 6个字节,设置为0;            0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)            0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 保留位            0x00, 0x00, 0x00, 0x00,            0x00, channelCount, // channelCount(2) 单声道还是双声道            0x00, 0x10, // sampleSize(2)            0x00, 0x00, 0x00, 0x00, // reserved(4) 4字节保留位            (sampleRate >>> 8) & 0xFF, // Audio sample rate 显然要右移16位才有意义    template unsigned int(32) samplerate = {timescale of media}<<16;            (sampleRate) & 0xFF,            0x00, 0x00        ]);        return MP4.box(MP4.types.mp4a, data, MP4.esds(meta));    }    static esds(meta) {        let config = meta.config;        let configSize = config.length;        let data = new Uint8Array([            0x00, 0x00, 0x00, 0x00, // version 0 + flags            0x03, // descriptor_type    MP4ESDescrTag            0x17 + configSize, // length3            0x00, 0x01, // es_id            0x00, // stream_priority            0x04, // descriptor_type    MP4DecConfigDescrTag            0x0F + configSize, // length            0x40, // codec: mpeg4_audio            /**             *当objectTypeIndication为0x40时,为MPEG-4 AudioMPEG-4 Audio generally is thought of as AAC              * but there is a whole framework of audio codecs that can Go in MPEG-4 Audio including AAC, BSAC, ALS, CELP,              * and something called MP3On4),如果想更细分formataac还是mp3,             * 可以读取MP4DecSpecificDescrdata[0]的前五位             */            0x15, // stream_type: Audio            0x00, 0x00, 0x00, // buffer_size            0x00, 0x00, 0x00, 0x00, // maxBitrate            0x00, 0x00, 0x00, 0x00, // avgBitrate            0x05 // descriptor_type MP4DecSpecificDescrTag        ].concat([            configSize        ]).concat(            config        ).concat([            0x06, 0x01, 0x02 // GASpecificConfig        ]));        return MP4.box(MP4.types.esds, data);    }

stsd介绍完毕

阅读全文
0 0