UNPKG

dashjs

Version:

A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.

35 lines (34 loc) 14.3 kB
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _DashConstants=require('./constants/DashConstants');var _DashConstants2=_interopRequireDefault(_DashConstants);var _FragmentRequest=require('../streaming/vo/FragmentRequest');var _FragmentRequest2=_interopRequireDefault(_FragmentRequest);var _DashJSError=require('../streaming/vo/DashJSError');var _DashJSError2=_interopRequireDefault(_DashJSError);var _HTTPRequest=require('../streaming/vo/metrics/HTTPRequest');var _Events=require('../core/events/Events');var _Events2=_interopRequireDefault(_Events);var _EventBus=require('../core/EventBus');var _EventBus2=_interopRequireDefault(_EventBus);var _Errors=require('../core/errors/Errors');var _Errors2=_interopRequireDefault(_Errors);var _FactoryMaker=require('../core/FactoryMaker');var _FactoryMaker2=_interopRequireDefault(_FactoryMaker);var _Debug=require('../core/Debug');var _Debug2=_interopRequireDefault(_Debug);var _URLUtils=require('../streaming/utils/URLUtils');var _URLUtils2=_interopRequireDefault(_URLUtils);var _Representation=require('./vo/Representation');var _Representation2=_interopRequireDefault(_Representation);var _SegmentsUtils=require('./utils/SegmentsUtils');var _SegmentsController=require('./controllers/SegmentsController');var _SegmentsController2=_interopRequireDefault(_SegmentsController);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function DashHandler(config){config=config||{};var context=this.context;var eventBus=(0,_EventBus2.default)(context).getInstance();var urlUtils=(0,_URLUtils2.default)(context).getInstance();var timelineConverter=config.timelineConverter;var dashMetrics=config.dashMetrics;var baseURLController=config.baseURLController;var instance=void 0,logger=void 0,segmentIndex=void 0,lastSegment=void 0,requestedTime=void 0,currentTime=void 0,streamProcessor=void 0,segmentsController=void 0;function setup(){logger=(0,_Debug2.default)(context).getInstance().getLogger(instance);resetInitialSettings();segmentsController=(0,_SegmentsController2.default)(context).create(config);eventBus.on(_Events2.default.INITIALIZATION_LOADED,onInitializationLoaded,instance);eventBus.on(_Events2.default.SEGMENTS_LOADED,onSegmentsLoaded,instance);}function initialize(StreamProcessor){streamProcessor=StreamProcessor;segmentsController.initialize(isDynamic());}function getType(){return streamProcessor?streamProcessor.getType():null;}function isDynamic(){var streamInfo=streamProcessor?streamProcessor.getStreamInfo():null;return streamInfo?streamInfo.manifestInfo.isDynamic:null;}function getMediaInfo(){return streamProcessor?streamProcessor.getMediaInfo():null;}function getStreamProcessor(){return streamProcessor;}function setCurrentTime(value){currentTime=value;}function getCurrentTime(){return currentTime;}function resetIndex(){segmentIndex=-1;lastSegment=null;}function resetInitialSettings(){resetIndex();currentTime=0;requestedTime=null;streamProcessor=null;segmentsController=null;}function reset(){resetInitialSettings();eventBus.off(_Events2.default.INITIALIZATION_LOADED,onInitializationLoaded,instance);eventBus.off(_Events2.default.SEGMENTS_LOADED,onSegmentsLoaded,instance);}function setRequestUrl(request,destination,representation){var baseURL=baseURLController.resolve(representation.path);var url=void 0,serviceLocation=void 0;if(!baseURL||destination===baseURL.url||!urlUtils.isRelative(destination)){url=destination;}else{url=baseURL.url;serviceLocation=baseURL.serviceLocation;if(destination){url=urlUtils.resolve(destination,url);}}if(urlUtils.isRelative(url)){return false;}request.url=url;request.serviceLocation=serviceLocation;return true;}function generateInitRequest(representation,mediaType){var request=new _FragmentRequest2.default();var period=representation.adaptation.period;var presentationStartTime=period.start;var isDynamicStream=isDynamic();request.mediaType=mediaType;request.type=_HTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE;request.range=representation.range;request.availabilityStartTime=timelineConverter.calcAvailabilityStartTimeFromPresentationTime(presentationStartTime,period.mpd,isDynamicStream);request.availabilityEndTime=timelineConverter.calcAvailabilityEndTimeFromPresentationTime(presentationStartTime+period.duration,period.mpd,isDynamicStream);request.quality=representation.index;request.mediaInfo=getMediaInfo();request.representationId=representation.id;if(setRequestUrl(request,representation.initialization,representation)){request.url=(0,_SegmentsUtils.replaceTokenForTemplate)(request.url,'Bandwidth',representation.bandwidth);return request;}}function getInitRequest(representation){if(!representation)return null;var request=generateInitRequest(representation,getType());return request;}function setExpectedLiveEdge(liveEdge){timelineConverter.setExpectedLiveEdge(liveEdge);dashMetrics.updateManifestUpdateInfo({presentationStartTime:liveEdge});}function updateRepresentation(voRepresentation,keepIdx){var hasInitialization=_Representation2.default.hasInitialization(voRepresentation);var hasSegments=_Representation2.default.hasSegments(voRepresentation);var error=void 0;voRepresentation.segmentAvailabilityRange=timelineConverter.calcSegmentAvailabilityRange(voRepresentation,isDynamic());if(voRepresentation.segmentAvailabilityRange.end<voRepresentation.segmentAvailabilityRange.start&&!voRepresentation.useCalculatedLiveEdgeTime){error=new _DashJSError2.default(_Errors2.default.SEGMENTS_UNAVAILABLE_ERROR_CODE,_Errors2.default.SEGMENTS_UNAVAILABLE_ERROR_MESSAGE,{availabilityDelay:voRepresentation.segmentAvailabilityRange.start-voRepresentation.segmentAvailabilityRange.end});eventBus.trigger(_Events2.default.REPRESENTATION_UPDATED,{sender:this,representation:voRepresentation,error:error});return;}if(isDynamic()){setExpectedLiveEdge(voRepresentation.segmentAvailabilityRange.end);}if(!keepIdx){resetIndex();}segmentsController.update(voRepresentation,getType(),hasInitialization,hasSegments);if(hasInitialization&&hasSegments){eventBus.trigger(_Events2.default.REPRESENTATION_UPDATED,{sender:this,representation:voRepresentation});}}function getRequestForSegment(segment){if(segment===null||segment===undefined){return null;}var request=new _FragmentRequest2.default();var representation=segment.representation;var bandwidth=representation.adaptation.period.mpd.manifest.Period_asArray[representation.adaptation.period.index].AdaptationSet_asArray[representation.adaptation.index].Representation_asArray[representation.index].bandwidth;var url=segment.media;url=(0,_SegmentsUtils.replaceTokenForTemplate)(url,'Number',segment.replacementNumber);url=(0,_SegmentsUtils.replaceTokenForTemplate)(url,'Time',segment.replacementTime);url=(0,_SegmentsUtils.replaceTokenForTemplate)(url,'Bandwidth',bandwidth);url=(0,_SegmentsUtils.replaceIDForTemplate)(url,representation.id);url=(0,_SegmentsUtils.unescapeDollarsInTemplate)(url);request.mediaType=getType();request.type=_HTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE;request.range=segment.mediaRange;request.startTime=segment.presentationStartTime;request.duration=segment.duration;request.timescale=representation.timescale;request.availabilityStartTime=segment.availabilityStartTime;request.availabilityEndTime=segment.availabilityEndTime;request.wallStartTime=segment.wallStartTime;request.quality=representation.index;request.index=segment.availabilityIdx;request.mediaInfo=getMediaInfo();request.adaptationIndex=representation.adaptation.index;request.representationId=representation.id;if(setRequestUrl(request,url,representation)){return request;}}function isMediaFinished(representation){var isFinished=false;var isDynamicMedia=isDynamic();if(!isDynamicMedia){if(segmentIndex>=representation.availableSegmentsNumber){isFinished=true;}}else{if(lastSegment){var time=parseFloat((lastSegment.presentationStartTime-representation.adaptation.period.start).toFixed(5));var endTime=lastSegment.duration>0?time+1.5*lastSegment.duration:time;var duration=representation.adaptation.period.duration;isFinished=endTime>=duration;}}return isFinished;}function getSegmentRequestForTime(representation,time,options){var request=void 0;if(!representation||!representation.segmentInfoType){return null;}var type=getType();var idx=segmentIndex;var keepIdx=options?options.keepIdx:false;var ignoreIsFinished=options&&options.ignoreIsFinished?true:false;if(requestedTime!==time){// When playing at live edge with 0 delay we may loop back with same time and index until it is available. Reduces verboseness of logs. requestedTime=time;logger.debug('Getting the request for '+type+' time : '+time);}var segment=segmentsController.getSegmentByTime(representation,time);if(segment){segmentIndex=segment.availabilityIdx;lastSegment=segment;logger.debug('Index for '+type+' time '+time+' is '+segmentIndex);request=getRequestForSegment(segment);}else{var finished=!ignoreIsFinished?isMediaFinished(representation):false;if(finished){request=new _FragmentRequest2.default();request.action=_FragmentRequest2.default.ACTION_COMPLETE;request.index=segmentIndex-1;request.mediaType=type;request.mediaInfo=getMediaInfo();logger.debug('Signal complete in getSegmentRequestForTime -',type);}}if(keepIdx&&idx>=0){segmentIndex=representation.segmentInfoType===_DashConstants2.default.SEGMENT_TIMELINE&&isDynamic()?segmentIndex:idx;}return request;}function getNextSegmentRequest(representation){var request=void 0;if(!representation||!representation.segmentInfoType){return null;}var mediaStartTime=lastSegment?lastSegment.mediaStartTime:-1;var type=getType();requestedTime=null;var indexToRequest=segmentIndex+1;logger.debug('Getting the next request at index: '+indexToRequest+', type: '+type);// check that there is a segment in this index var segment=segmentsController.getSegmentByIndex(representation,indexToRequest,mediaStartTime);if(!segment&&!isEndlessMedia(representation)){logger.debug('No segment found at index: '+indexToRequest+'. Wait for next loop');return null;}else{if(segment){request=getRequestForSegment(segment);segmentIndex=segment.availabilityIdx;}else{segmentIndex=indexToRequest;}}if(segment){lastSegment=segment;request=getRequestForSegment(segment);}else{var finished=isMediaFinished(representation,segment);if(finished){request=new _FragmentRequest2.default();request.action=_FragmentRequest2.default.ACTION_COMPLETE;request.index=segmentIndex-1;request.mediaType=type;request.mediaInfo=getMediaInfo();logger.debug('Signal complete -',type);}}return request;}function isEndlessMedia(representation){return!isDynamic()||isDynamic()&&isFinite(representation.adaptation.period.duration);}function onInitializationLoaded(e){var representation=e.representation;if(!representation.segments)return;eventBus.trigger(_Events2.default.REPRESENTATION_UPDATED,{sender:this,representation:representation});}function onSegmentsLoaded(e){if(e.error||getType()!==e.mediaType)return;var fragments=e.segments;var representation=e.representation;var segments=[];var count=0;var i=void 0,len=void 0,s=void 0,seg=void 0;for(i=0,len=fragments.length;i<len;i++){s=fragments[i];seg=(0,_SegmentsUtils.getTimeBasedSegment)(timelineConverter,isDynamic(),representation,s.startTime,s.duration,s.timescale,s.media,s.mediaRange,count);if(seg){segments.push(seg);seg=null;count++;}}len=segments.length;representation.segmentAvailabilityRange={start:segments[0].presentationStartTime,end:segments[len-1].presentationStartTime};representation.availableSegmentsNumber=len;representation.segments=segments;if(segments&&segments.length>0){if(isDynamic()){var _lastSegment=segments[segments.length-1];var liveEdge=_lastSegment.presentationStartTime-8;// the last segment is the Expected, not calculated, live edge. setExpectedLiveEdge(liveEdge);}}if(!_Representation2.default.hasInitialization(representation)){return;}eventBus.trigger(_Events2.default.REPRESENTATION_UPDATED,{sender:this,representation:representation});}instance={initialize:initialize,getStreamProcessor:getStreamProcessor,getInitRequest:getInitRequest,getSegmentRequestForTime:getSegmentRequestForTime,getNextSegmentRequest:getNextSegmentRequest,updateRepresentation:updateRepresentation,setCurrentTime:setCurrentTime,getCurrentTime:getCurrentTime,reset:reset,resetIndex:resetIndex};setup();return instance;}/** * The copyright in this software is being made available under the BSD License, * included below. This software may be subject to other third party and contributor * rights, including patent rights, and no such rights are granted under this license. * * Copyright (c) 2013, Dash Industry Forum. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of Dash Industry Forum nor the names of its * contributors may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */DashHandler.__dashjs_factory_name='DashHandler';exports.default=_FactoryMaker2.default.getClassFactory(DashHandler); //# sourceMappingURL=DashHandler.js.map