dashjs
Version:
A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.
78 lines (77 loc) • 25.2 kB
JavaScript
;Object.defineProperty(exports,"__esModule",{value:true});var _Constants=require('../constants/Constants');var _Constants2=_interopRequireDefault(_Constants);var _BufferController=require('./BufferController');var _BufferController2=_interopRequireDefault(_BufferController);var _EventBus=require('../../core/EventBus');var _EventBus2=_interopRequireDefault(_EventBus);var _Events=require('../../core/events/Events');var _Events2=_interopRequireDefault(_Events);var _FactoryMaker=require('../../core/FactoryMaker');var _FactoryMaker2=_interopRequireDefault(_FactoryMaker);var _Debug=require('../../core/Debug');var _Debug2=_interopRequireDefault(_Debug);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}/**
* 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.
*/var LIVE_UPDATE_PLAYBACK_TIME_INTERVAL_MS=500;function PlaybackController(){var context=this.context;var eventBus=(0,_EventBus2.default)(context).getInstance();var instance=void 0,logger=void 0,streamController=void 0,dashMetrics=void 0,adapter=void 0,videoModel=void 0,timelineConverter=void 0,liveStartTime=void 0,wallclockTimeIntervalId=void 0,commonEarliestTime=void 0,liveDelay=void 0,bufferedRange=void 0,streamInfo=void 0,isDynamic=void 0,mediaPlayerModel=void 0,playOnceInitialized=void 0,lastLivePlaybackTime=void 0,availabilityStartTime=void 0,compatibleWithPreviousStream=void 0,isLowLatencySeekingInProgress=void 0,playbackStalled=void 0,minPlaybackRateChange=void 0,uriFragmentModel=void 0,settings=void 0;function setup(){logger=(0,_Debug2.default)(context).getInstance().getLogger(instance);reset();}function initialize(StreamInfo,compatible){streamInfo=StreamInfo;addAllListeners();isDynamic=streamInfo.manifestInfo.isDynamic;isLowLatencySeekingInProgress=false;playbackStalled=false;liveStartTime=streamInfo.start;compatibleWithPreviousStream=compatible;var ua=typeof navigator!=='undefined'?navigator.userAgent.toLowerCase():'';// Detect safari browser (special behavior for low latency streams)
var isSafari=/safari/.test(ua)&&!/chrome/.test(ua);minPlaybackRateChange=isSafari?0.25:0.02;eventBus.on(_Events2.default.DATA_UPDATE_COMPLETED,onDataUpdateCompleted,this);eventBus.on(_Events2.default.BYTES_APPENDED_END_FRAGMENT,onBytesAppended,this);eventBus.on(_Events2.default.LOADING_PROGRESS,onFragmentLoadProgress,this);eventBus.on(_Events2.default.BUFFER_LEVEL_STATE_CHANGED,onBufferLevelStateChanged,this);eventBus.on(_Events2.default.PERIOD_SWITCH_STARTED,onPeriodSwitchStarted,this);eventBus.on(_Events2.default.PLAYBACK_PROGRESS,onPlaybackProgression,this);eventBus.on(_Events2.default.PLAYBACK_TIME_UPDATED,onPlaybackProgression,this);eventBus.on(_Events2.default.PLAYBACK_ENDED,onPlaybackEnded,this);if(playOnceInitialized){playOnceInitialized=false;play();}}function onPeriodSwitchStarted(e){if(!isDynamic&&e.fromStreamInfo&&commonEarliestTime[e.fromStreamInfo.id]!==undefined){delete bufferedRange[e.fromStreamInfo.id];delete commonEarliestTime[e.fromStreamInfo.id];}}function getTimeToStreamEnd(){return parseFloat((getStreamEndTime()-getTime()).toFixed(5));}function getStreamEndTime(){var startTime=getStreamStartTime(true);var offset=isDynamic&&streamInfo?startTime-streamInfo.start:0;return startTime+(streamInfo?streamInfo.duration-offset:offset);}function play(){if(streamInfo&&videoModel&&videoModel.getElement()){videoModel.play();}else{playOnceInitialized=true;}}function isPaused(){return streamInfo&&videoModel?videoModel.isPaused():null;}function pause(){if(streamInfo&&videoModel){videoModel.pause();}}function isSeeking(){return streamInfo&&videoModel?videoModel.isSeeking():null;}function seek(time,stickToBuffered,internalSeek){if(streamInfo&&videoModel){if(internalSeek===true){if(time!==videoModel.getTime()){// Internal seek = seek video model only (disable 'seeking' listener),
// buffer(s) are already appended at given time (see onBytesAppended())
videoModel.removeEventListener('seeking',onPlaybackSeeking);logger.info('Requesting seek to time: '+time);videoModel.setCurrentTime(time,stickToBuffered);}}else{eventBus.trigger(_Events2.default.PLAYBACK_SEEK_ASKED);logger.info('Requesting seek to time: '+time);videoModel.setCurrentTime(time,stickToBuffered);}}}function seekToLive(){var DVRMetrics=dashMetrics.getCurrentDVRInfo();var DVRWindow=DVRMetrics?DVRMetrics.range:null;seek(DVRWindow.end-mediaPlayerModel.getLiveDelay(),true,false);}function getTime(){return streamInfo&&videoModel?videoModel.getTime():null;}function getNormalizedTime(){var t=getTime();if(isDynamic&&!isNaN(availabilityStartTime)){var timeOffset=availabilityStartTime/1000;// Fix current time for firefox and safari (returned as an absolute time)
if(t>timeOffset){t-=timeOffset;}}return t;}function getPlaybackRate(){return streamInfo&&videoModel?videoModel.getPlaybackRate():null;}function getPlayedRanges(){return streamInfo&&videoModel?videoModel.getPlayedRanges():null;}function getEnded(){return streamInfo&&videoModel?videoModel.getEnded():null;}function getIsDynamic(){return isDynamic;}function getStreamController(){return streamController;}function setLiveStartTime(value){liveStartTime=value;}function getLiveStartTime(){return liveStartTime;}/**
* Computes the desirable delay for the live edge to avoid a risk of getting 404 when playing at the bleeding edge
* @param {number} fragmentDuration - seconds?
* @param {number} dvrWindowSize - seconds?
* @returns {number} object
* @memberof PlaybackController#
*/function computeLiveDelay(fragmentDuration,dvrWindowSize){var delay=void 0,ret=void 0,startTime=void 0;var END_OF_PLAYLIST_PADDING=10;var suggestedPresentationDelay=adapter.getSuggestedPresentationDelay();if(settings.get().streaming.useSuggestedPresentationDelay&&suggestedPresentationDelay!==null){delay=suggestedPresentationDelay;}else if(settings.get().streaming.lowLatencyEnabled){delay=0;}else if(mediaPlayerModel.getLiveDelay()){delay=mediaPlayerModel.getLiveDelay();// If set by user, this value takes precedence
}else if(!isNaN(fragmentDuration)){delay=fragmentDuration*settings.get().streaming.liveDelayFragmentCount;}else{delay=streamInfo.manifestInfo.minBufferTime*2;}startTime=adapter.getAvailabilityStartTime();if(startTime!==null){availabilityStartTime=startTime;}if(dvrWindowSize>0){// cap target latency to:
// - dvrWindowSize / 2 for short playlists
// - dvrWindowSize - END_OF_PLAYLIST_PADDING for longer playlists
var targetDelayCapping=Math.max(dvrWindowSize-END_OF_PLAYLIST_PADDING,dvrWindowSize/2);ret=Math.min(delay,targetDelayCapping);}else{ret=delay;}liveDelay=ret;return ret;}function getLiveDelay(){return liveDelay;}function getCurrentLiveLatency(){if(!isDynamic||isNaN(availabilityStartTime)){return NaN;}var currentTime=getNormalizedTime();if(isNaN(currentTime)||currentTime===0){return 0;}var now=new Date().getTime()+timelineConverter.getClientTimeOffset()*1000;return Math.max(((now-availabilityStartTime-currentTime*1000)/1000).toFixed(3),0);}function reset(){liveStartTime=NaN;playOnceInitialized=false;commonEarliestTime={};liveDelay=0;availabilityStartTime=0;bufferedRange={};if(videoModel){eventBus.off(_Events2.default.DATA_UPDATE_COMPLETED,onDataUpdateCompleted,this);eventBus.off(_Events2.default.BUFFER_LEVEL_STATE_CHANGED,onBufferLevelStateChanged,this);eventBus.off(_Events2.default.BYTES_APPENDED_END_FRAGMENT,onBytesAppended,this);eventBus.off(_Events2.default.LOADING_PROGRESS,onFragmentLoadProgress,this);eventBus.off(_Events2.default.PERIOD_SWITCH_STARTED,onPeriodSwitchStarted,this);eventBus.off(_Events2.default.PLAYBACK_PROGRESS,onPlaybackProgression,this);eventBus.off(_Events2.default.PLAYBACK_TIME_UPDATED,onPlaybackProgression,this);eventBus.off(_Events2.default.PLAYBACK_ENDED,onPlaybackEnded,this);stopUpdatingWallclockTime();removeAllListeners();}wallclockTimeIntervalId=null;videoModel=null;streamInfo=null;isDynamic=null;}function setConfig(config){if(!config)return;if(config.streamController){streamController=config.streamController;}if(config.dashMetrics){dashMetrics=config.dashMetrics;}if(config.mediaPlayerModel){mediaPlayerModel=config.mediaPlayerModel;}if(config.adapter){adapter=config.adapter;}if(config.videoModel){videoModel=config.videoModel;}if(config.timelineConverter){timelineConverter=config.timelineConverter;}if(config.uriFragmentModel){uriFragmentModel=config.uriFragmentModel;}if(config.settings){settings=config.settings;}}function getStartTimeFromUriParameters(){var fragData=uriFragmentModel.getURIFragmentData();var uriParameters=void 0;if(fragData){uriParameters={};var r=parseInt(fragData.r,10);if(r>=0&&streamInfo&&r<streamInfo.manifestInfo.DVRWindowSize&&fragData.t===null){fragData.t=Math.max(Math.floor(Date.now()/1000)-streamInfo.manifestInfo.DVRWindowSize,streamInfo.manifestInfo.availableFrom.getTime()/1000+streamInfo.start)+r;}uriParameters.fragS=parseFloat(fragData.s);uriParameters.fragT=parseFloat(fragData.t);}return uriParameters;}/**
* @param {boolean} ignoreStartOffset - ignore URL fragment start offset if true
* @param {number} liveEdge - liveEdge value
* @returns {number} object
* @memberof PlaybackController#
*/function getStreamStartTime(ignoreStartOffset,liveEdge){var presentationStartTime=void 0;var startTimeOffset=NaN;if(!ignoreStartOffset){var uriParameters=getStartTimeFromUriParameters();if(uriParameters){startTimeOffset=!isNaN(uriParameters.fragS)?uriParameters.fragS:uriParameters.fragT;}else{startTimeOffset=0;}}else{startTimeOffset=streamInfo?streamInfo.start:startTimeOffset;}if(isDynamic){if(!isNaN(startTimeOffset)&&streamInfo){presentationStartTime=startTimeOffset-streamInfo.manifestInfo.availableFrom.getTime()/1000;if(presentationStartTime>liveStartTime||presentationStartTime<(!isNaN(liveEdge)?liveEdge-streamInfo.manifestInfo.DVRWindowSize:NaN)){presentationStartTime=null;}}presentationStartTime=presentationStartTime||liveStartTime;}else{if(streamInfo){if(!isNaN(startTimeOffset)&&startTimeOffset<Math.max(streamInfo.manifestInfo.duration,streamInfo.duration)&&startTimeOffset>=0){presentationStartTime=startTimeOffset;}else{var earliestTime=commonEarliestTime[streamInfo.id];//set by ready bufferStart after first onBytesAppended
presentationStartTime=earliestTime!==undefined?Math.max(earliestTime.audio!==undefined?earliestTime.audio:0,earliestTime.video!==undefined?earliestTime.video:0,streamInfo.start):streamInfo.start;}}}return presentationStartTime;}function getActualPresentationTime(currentTime){var DVRMetrics=dashMetrics.getCurrentDVRInfo();var DVRWindow=DVRMetrics?DVRMetrics.range:null;var actualTime=void 0;if(!DVRWindow)return NaN;if(currentTime>DVRWindow.end){actualTime=Math.max(DVRWindow.end-streamInfo.manifestInfo.minBufferTime*2,DVRWindow.start);}else if(currentTime+0.250<DVRWindow.start&&DVRWindow.start-currentTime>DVRWindow.start-315360000){// Checking currentTime plus 250ms as the 'timeupdate' is fired with a frequency between 4Hz and 66Hz
// https://developer.mozilla.org/en-US/docs/Web/Events/timeupdate
// http://w3c.github.io/html/single-page.html#offsets-into-the-media-resource
// Checking also duration of the DVR makes sense. We detected temporary situations in which currentTime
// is bad reported by the browser which causes playback to jump to start (315360000 = 1 year)
actualTime=DVRWindow.start;}else{actualTime=currentTime;}return actualTime;}function startUpdatingWallclockTime(){if(wallclockTimeIntervalId!==null)return;var tick=function tick(){onWallclockTime();};wallclockTimeIntervalId=setInterval(tick,settings.get().streaming.wallclockTimeUpdateInterval);}function stopUpdatingWallclockTime(){clearInterval(wallclockTimeIntervalId);wallclockTimeIntervalId=null;}function updateCurrentTime(){if(isPaused()||!isDynamic||videoModel.getReadyState()===0)return;var currentTime=getNormalizedTime();var actualTime=getActualPresentationTime(currentTime);var timeChanged=!isNaN(actualTime)&&actualTime!==currentTime;if(timeChanged){seek(actualTime);}}function onDataUpdateCompleted(e){if(e.error)return;var representationInfo=adapter.convertDataToRepresentationInfo(e.currentRepresentation);var info=representationInfo.mediaInfo.streamInfo;if(streamInfo.id!==info.id)return;streamInfo=info;updateCurrentTime();}function onCanPlay(){eventBus.trigger(_Events2.default.CAN_PLAY);}function onPlaybackStart(){logger.info('Native video element event: play');updateCurrentTime();startUpdatingWallclockTime();eventBus.trigger(_Events2.default.PLAYBACK_STARTED,{startTime:getTime()});}function onPlaybackWaiting(){logger.info('Native video element event: waiting');eventBus.trigger(_Events2.default.PLAYBACK_WAITING,{playingTime:getTime()});}function onPlaybackPlaying(){logger.info('Native video element event: playing');eventBus.trigger(_Events2.default.PLAYBACK_PLAYING,{playingTime:getTime()});}function onPlaybackPaused(){logger.info('Native video element event: pause');eventBus.trigger(_Events2.default.PLAYBACK_PAUSED,{ended:getEnded()});}function onPlaybackSeeking(){var seekTime=getTime();logger.info('Seeking to: '+seekTime);startUpdatingWallclockTime();eventBus.trigger(_Events2.default.PLAYBACK_SEEKING,{seekTime:seekTime});}function onPlaybackSeeked(){logger.info('Native video element event: seeked');eventBus.trigger(_Events2.default.PLAYBACK_SEEKED);// Reactivate 'seeking' event listener (see seek())
videoModel.addEventListener('seeking',onPlaybackSeeking);}function onPlaybackTimeUpdated(){if(streamInfo){eventBus.trigger(_Events2.default.PLAYBACK_TIME_UPDATED,{timeToEnd:getTimeToStreamEnd(),time:getTime()});}}function updateLivePlaybackTime(){var now=Date.now();if(!lastLivePlaybackTime||now>lastLivePlaybackTime+LIVE_UPDATE_PLAYBACK_TIME_INTERVAL_MS){lastLivePlaybackTime=now;onPlaybackTimeUpdated();}}function onPlaybackProgress(){eventBus.trigger(_Events2.default.PLAYBACK_PROGRESS);}function onPlaybackRateChanged(){var rate=getPlaybackRate();logger.info('Native video element event: ratechange: ',rate);eventBus.trigger(_Events2.default.PLAYBACK_RATE_CHANGED,{playbackRate:rate});}function onPlaybackMetaDataLoaded(){logger.info('Native video element event: loadedmetadata');eventBus.trigger(_Events2.default.PLAYBACK_METADATA_LOADED);startUpdatingWallclockTime();}// Event to handle the native video element ended event
function onNativePlaybackEnded(){logger.info('Native video element event: ended');pause();stopUpdatingWallclockTime();eventBus.trigger(_Events2.default.PLAYBACK_ENDED,{'isLast':streamController.getActiveStreamInfo().isLast});}// Handle DASH PLAYBACK_ENDED event
function onPlaybackEnded(e){if(wallclockTimeIntervalId&&e.isLast){// PLAYBACK_ENDED was triggered elsewhere, react.
logger.info('onPlaybackEnded -- PLAYBACK_ENDED but native video element didn\'t fire ended');videoModel.setCurrentTime(getStreamEndTime());pause();stopUpdatingWallclockTime();}}function onPlaybackError(event){var target=event.target||event.srcElement;eventBus.trigger(_Events2.default.PLAYBACK_ERROR,{error:target.error});}function onWallclockTime(){eventBus.trigger(_Events2.default.WALLCLOCK_TIME_UPDATED,{isDynamic:isDynamic,time:new Date()});// Updates playback time for paused dynamic streams
// (video element doesn't call timeupdate when the playback is paused)
if(getIsDynamic()&&isPaused()){updateLivePlaybackTime();}}function checkTimeInRanges(time,ranges){if(ranges&&ranges.length>0){for(var i=0,len=ranges.length;i<len;i++){if(time>=ranges.start(i)&&time<ranges.end(i)){return true;}}}return false;}function onPlaybackProgression(){if(isDynamic&&settings.get().streaming.lowLatencyEnabled&&settings.get().streaming.lowLatencyEnabled>0&&!isPaused()&&!isSeeking()){if(needToCatchUp()){startPlaybackCatchUp();}else{stopPlaybackCatchUp();}}}function getBufferLevel(){var bufferLevel=null;streamController.getActiveStreamProcessors().forEach(function(p){var bl=p.getBufferLevel();if(bufferLevel===null){bufferLevel=bl;}else{bufferLevel=Math.min(bufferLevel,bl);}});return bufferLevel;}function needToCatchUp(){return settings.get().streaming.liveCatchUpPlaybackRate>0&&getTime()>0&&Math.abs(getCurrentLiveLatency()-mediaPlayerModel.getLiveDelay())>settings.get().streaming.liveCatchUpMinDrift;}function startPlaybackCatchUp(){if(videoModel){var cpr=settings.get().streaming.liveCatchUpPlaybackRate;var _liveDelay=mediaPlayerModel.getLiveDelay();var deltaLatency=getCurrentLiveLatency()-_liveDelay;var d=deltaLatency*5;// Playback rate must be between (1 - cpr) - (1 + cpr)
// ex: if cpr is 0.5, it can have values between 0.5 - 1.5
var s=cpr*2/(1+Math.pow(Math.E,-d));var newRate=1-cpr+s;// take into account situations in which there are buffer stalls,
// in which increasing playbackRate to reach target latency will
// just cause more and more stall situations
if(playbackStalled){var bufferLevel=getBufferLevel();if(bufferLevel>_liveDelay/2){playbackStalled=false;}else if(deltaLatency>0){newRate=1.0;}}// don't change playbackrate for small variations (don't overload element with playbackrate changes)
if(Math.abs(videoModel.getPlaybackRate()-newRate)>minPlaybackRateChange){videoModel.setPlaybackRate(newRate);}if(settings.get().streaming.liveCatchUpMaxDrift>0&&!isLowLatencySeekingInProgress&&deltaLatency>settings.get().streaming.liveCatchUpMaxDrift){logger.info('Low Latency catchup mechanism. Latency too high, doing a seek to live point');isLowLatencySeekingInProgress=true;seekToLive();}else{isLowLatencySeekingInProgress=false;}}}function stopPlaybackCatchUp(){if(videoModel){videoModel.setPlaybackRate(1.0);}}function onBytesAppended(e){var earliestTime=void 0,initialStartTime=void 0;var ranges=e.bufferedRanges;if(!ranges||!ranges.length)return;if(commonEarliestTime[streamInfo.id]&&commonEarliestTime[streamInfo.id].started===true){//stream has already been started.
return;}var type=e.sender.getType();if(bufferedRange[streamInfo.id]===undefined){bufferedRange[streamInfo.id]=[];}bufferedRange[streamInfo.id][type]=ranges;if(commonEarliestTime[streamInfo.id]===undefined){commonEarliestTime[streamInfo.id]=[];commonEarliestTime[streamInfo.id].started=false;}if(commonEarliestTime[streamInfo.id][type]===undefined){commonEarliestTime[streamInfo.id][type]=Math.max(ranges.start(0),streamInfo.start);}var hasVideoTrack=streamController.isTrackTypePresent(_Constants2.default.VIDEO);var hasAudioTrack=streamController.isTrackTypePresent(_Constants2.default.AUDIO);initialStartTime=getStreamStartTime(false);if(hasAudioTrack&&hasVideoTrack){//current stream has audio and video contents
if(!isNaN(commonEarliestTime[streamInfo.id].audio)&&!isNaN(commonEarliestTime[streamInfo.id].video)){if(commonEarliestTime[streamInfo.id].audio<commonEarliestTime[streamInfo.id].video){// common earliest is video time
// check buffered audio range has video time, if ok, we seek, otherwise, we wait some other data
earliestTime=commonEarliestTime[streamInfo.id].video>initialStartTime?commonEarliestTime[streamInfo.id].video:initialStartTime;ranges=bufferedRange[streamInfo.id].audio;}else{// common earliest is audio time
// check buffered video range has audio time, if ok, we seek, otherwise, we wait some other data
earliestTime=commonEarliestTime[streamInfo.id].audio>initialStartTime?commonEarliestTime[streamInfo.id].audio:initialStartTime;ranges=bufferedRange[streamInfo.id].video;}if(checkTimeInRanges(earliestTime,ranges)){if(!isSeeking()&&!compatibleWithPreviousStream&&earliestTime!==0){seek(earliestTime,true,true);}commonEarliestTime[streamInfo.id].started=true;}}}else{//current stream has only audio or only video content
if(commonEarliestTime[streamInfo.id][type]){earliestTime=commonEarliestTime[streamInfo.id][type]>initialStartTime?commonEarliestTime[streamInfo.id][type]:initialStartTime;if(!isSeeking()&&!compatibleWithPreviousStream){seek(earliestTime,false,true);}commonEarliestTime[streamInfo.id].started=true;}}}function onFragmentLoadProgress(e){// If using fetch and stream mode is not available, readjust live latency so it is 20% higher than segment duration
if(e.stream===false&&settings.get().streaming.lowLatencyEnabled&&!isNaN(e.request.duration)){var minDelay=1.2*e.request.duration;if(minDelay>mediaPlayerModel.getLiveDelay()){logger.warn('Browser does not support fetch API with StreamReader. Increasing live delay to be 20% higher than segment duration:',minDelay.toFixed(2));var s={streaming:{liveDelay:minDelay}};settings.update(s);}}}function onBufferLevelStateChanged(e){// do not stall playback when get an event from Stream that is not active
if(e.streamInfo.id!==streamInfo.id)return;if(settings.get().streaming.lowLatencyEnabled){if(e.state===_BufferController2.default.BUFFER_EMPTY&&!isSeeking()){if(!playbackStalled){playbackStalled=true;stopPlaybackCatchUp();}}}else{videoModel.setStallState(e.mediaType,e.state===_BufferController2.default.BUFFER_EMPTY);}}function onPlaybackStalled(e){eventBus.trigger(_Events2.default.PLAYBACK_STALLED,{e:e});}function addAllListeners(){videoModel.addEventListener('canplay',onCanPlay);videoModel.addEventListener('play',onPlaybackStart);videoModel.addEventListener('waiting',onPlaybackWaiting);videoModel.addEventListener('playing',onPlaybackPlaying);videoModel.addEventListener('pause',onPlaybackPaused);videoModel.addEventListener('error',onPlaybackError);videoModel.addEventListener('seeking',onPlaybackSeeking);videoModel.addEventListener('seeked',onPlaybackSeeked);videoModel.addEventListener('timeupdate',onPlaybackTimeUpdated);videoModel.addEventListener('progress',onPlaybackProgress);videoModel.addEventListener('ratechange',onPlaybackRateChanged);videoModel.addEventListener('loadedmetadata',onPlaybackMetaDataLoaded);videoModel.addEventListener('stalled',onPlaybackStalled);videoModel.addEventListener('ended',onNativePlaybackEnded);}function removeAllListeners(){videoModel.removeEventListener('canplay',onCanPlay);videoModel.removeEventListener('play',onPlaybackStart);videoModel.removeEventListener('waiting',onPlaybackWaiting);videoModel.removeEventListener('playing',onPlaybackPlaying);videoModel.removeEventListener('pause',onPlaybackPaused);videoModel.removeEventListener('error',onPlaybackError);videoModel.removeEventListener('seeking',onPlaybackSeeking);videoModel.removeEventListener('seeked',onPlaybackSeeked);videoModel.removeEventListener('timeupdate',onPlaybackTimeUpdated);videoModel.removeEventListener('progress',onPlaybackProgress);videoModel.removeEventListener('ratechange',onPlaybackRateChanged);videoModel.removeEventListener('loadedmetadata',onPlaybackMetaDataLoaded);videoModel.removeEventListener('stalled',onPlaybackStalled);videoModel.removeEventListener('ended',onNativePlaybackEnded);}instance={initialize:initialize,setConfig:setConfig,getStartTimeFromUriParameters:getStartTimeFromUriParameters,getStreamStartTime:getStreamStartTime,getTimeToStreamEnd:getTimeToStreamEnd,getTime:getTime,getNormalizedTime:getNormalizedTime,getPlaybackRate:getPlaybackRate,getPlayedRanges:getPlayedRanges,getEnded:getEnded,getIsDynamic:getIsDynamic,getStreamController:getStreamController,setLiveStartTime:setLiveStartTime,getLiveStartTime:getLiveStartTime,computeLiveDelay:computeLiveDelay,getLiveDelay:getLiveDelay,getCurrentLiveLatency:getCurrentLiveLatency,play:play,isPaused:isPaused,pause:pause,isSeeking:isSeeking,seek:seek,reset:reset};setup();return instance;}PlaybackController.__dashjs_factory_name='PlaybackController';exports.default=_FactoryMaker2.default.getSingletonFactory(PlaybackController);
//# sourceMappingURL=PlaybackController.js.map