DASH研究

2021-06-27  本文已影响0人  请叫我小飞鹅

MP4格式研究

mp4解析在线地址:mp4parser

一个mp4就是一个容器: 每个mp4是由多个box组成,每个box可以嵌套子box,这个box称为container box。
mp4分有传统的regular mp4, 和为适应流媒体的fragmented Mp4(fMp4)。

在fMp4格式中包含一系列的segments(moof+mdat的组合),这些segments可以被独立的request(利用byte-range request),这有利于在不同质量级别的码流之间做码率切换操作

在regular mp4中,如果我们要在两个码流之间做码率切换,就需要找到两个码流中对应时间点的byte position,然而这时候我们只有一个巨大的mdat box,要在这里面找到一个具体的byte position无疑是复杂的。而且,在regular mp4中,有时moov会在巨大的mdat box之后,这也会影响起播的速度。
moofbox(此box存在于fmp4中),这个box是视频分片的描述信息。并不是MP4文件必须的部分,但在我们常见的可在线播放的MP4格式文件中确是重中之重。

sidx 名字 大小
header size Uint32
header type Int32
header larsesize(if size==1) Uint64
data version Uint8
data none Uint24
data reference_ID Uint32
data timescale Uint32
data earliest_presentation_time Uint32
data first_offset Uint32
data reserved Uint16
data reference_count Uint16
data type/size/duration * reference_count Uint32
data SAP * reference_count Uint32
解析代码如下

const mp4 = {
  parseSidx (dataView, offset) {
      /* 
          注意:
          此方法只能解析sidx -> dash只需解析sidx就行
          以及header里面size不等于1和0的情况 -> 这里需要将来支持一下
          以及data部分version为0的情况 
       */

      let hex2a = function (hex) {
          var str = '';
          for (var i = 0; i < hex.length; i += 2)
              str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
          return str;
      };
      let trim1 = function (str) {
          return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
      };
      const msg = {};
      msg.len = dataView.getUint32(offset); offset += 4;//获取header头size
      let type = dataView.getInt32(offset); offset += 4;
      msg.type = trim1(hex2a(type.toString(16)));//获取header头type

      msg.version = dataView.getUint8(offset); offset += 4;//获取version
      msg.reference_ID = dataView.getUint32(offset);offset += 4;//获取reference_ID
      msg.timescale = dataView.getUint32(offset);offset += 4;//timescale
      msg.earliest_presentation_time = dataView.getUint32(offset); offset += 4;//earliest_presentation_time
      msg.first_offset = dataView.getUint32(offset);  offset += 4;//first_offset
      msg.reserved = dataView.getUint16(offset) ;offset += 2;//reserved
      msg.reference_count = dataView.getUint16(offset) ;offset += 2;//reference_count
      msg.entries = [];
      let reference_count = msg.reference_count;
      while (reference_count--) {
          let entry = {};
          let fourBytes = dataView.getUint32(offset); offset += 4;
          entry['reference_type'] = (fourBytes >> 31) & 1;
          entry['referenced_size'] = (fourBytes & 0x7fffffff);
          entry['subsegment_duration'] = dataView.getUint32(offset);offset += 4;
          fourBytes = dataView.getUint32(offset);offset += 4;
          entry['starts_with_SAP'] = (fourBytes >> 31) & 1;
          entry['SAP_type'] = (fourBytes >> 29) & 7;
          entry['SAP_delta_time'] = (fourBytes & 0x0fffffff);
          msg.entries.push(entry);
      }
      return msg;
  }
};

export {mp4};

video播放原理

其他技术知识点

const api = {
       requestFullScreen : () => {
            const el = this.model.BaseNode;
            const rfs = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullscreen;      
            if(typeof rfs != "undefined" && rfs) {
                rfs.call(el);
                utils.evt.addEvent(window, 'resize', this.evtHandler.fullWindowOnEscKey);
            };
            return;
        },
        exitFullScreen : () => {
            if (document.exitFullscreen) {  
                document.exitFullscreen();  
            }  
            else if (document.mozCancelFullScreen) {  
                document.mozCancelFullScreen();  
            }  
            else if (document.webkitCancelFullScreen) {  
                document.webkitCancelFullScreen();  
            }  
            else if (document.msExitFullscreen) {  
                document.msExitFullscreen();  
            } 
            utils.evt.removeEvent(window, 'resize', this.evtHandler.fullWindowOnEscKey);
        },
        checkFull : () => {
            //let isFUll = document.fullscreenEnabled || window.fullScreen || document.webkitIsFullScreen || document.msFullscreenEnabled || false;
            let isFull = document.fullscreenElement  || document.webkitCurrentFullScreenElement || document.mozFullScreenElement || null;
            return isFUll;
        },
};
const evtHandler = {
        fullWindowOnEscKey : (evt) => {
            if (!this.tools.checkFull()) {
                utils.dom.removeClassName(this.model.BaseNode, 'krv-fullscreen');
                this.tools.exitFullScreen();
            }
        }
};

上一篇下一篇

猜你喜欢

热点阅读