UNPKG

dashjs

Version:

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

343 lines (342 loc) 25.3 kB
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _FactoryMaker=require('./FactoryMaker');var _FactoryMaker2=_interopRequireDefault(_FactoryMaker);var _Utils=require('./Utils.js');var _Utils2=_interopRequireDefault(_Utils);var _Debug=require('../core/Debug');var _Debug2=_interopRequireDefault(_Debug);var _Constants=require('../streaming/constants/Constants');var _Constants2=_interopRequireDefault(_Constants);var _HTTPRequest=require('../streaming/vo/metrics/HTTPRequest');function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return 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. *//** @module Settings * @description Define the configuration parameters of Dash.js MediaPlayer. * @see {@link module:Settings~PlayerSettings PlayerSettings} for further information about the supported configuration properties *//** * @typedef {Object} PlayerSettings * @property {module:Settings~DebugSettings} [debug] Debug related settings * @property {module:Settings~StreamingSettings} [streaming] Streaming related settings * @example * * // Full settings object * settings = { * debug: { * logLevel: Debug.LOG_LEVEL_WARNING * }, * streaming: { * metricsMaxListDepth: 1000, * abandonLoadTimeout: 10000, * liveDelayFragmentCount: 4, * liveDelay: null, * scheduleWhilePaused: true, * fastSwitchEnabled: false, * bufferPruningInterval: 10, * bufferToKeep: 20, * bufferAheadToKeep: 80, * jumpGaps: true, * smallGapLimit: 1.5, * stableBufferTime: 12, * bufferTimeAtTopQuality: 30, * bufferTimeAtTopQualityLongForm: 60, * longFormContentDurationThreshold: 600, * wallclockTimeUpdateInterval: 50, * lowLatencyEnabled: false, * keepProtectionMediaKeys: false, * useManifestDateHeaderTimeSource: true, * useSuggestedPresentationDelay: false, * manifestUpdateRetryInterval: 100, * liveCatchUpMinDrift: 0.02, * liveCatchUpMaxDrift: 0, * liveCatchUpPlaybackRate: 0.5, * lastBitrateCachingInfo: { enabled: true, ttl: 360000 }, * lastMediaSettingsCachingInfo: { enabled: true, ttl: 360000 }, * cacheLoadThresholds: { video: 50, audio: 5 }, * retryIntervals: { * MPD: 500, * XLinkExpansion: 500, * InitializationSegment: 1000, * IndexSegment: 1000, * MediaSegment: 1000, * BitstreamSwitchingSegment: 1000, * other: 1000 * }, * retryAttempts: { * MPD: 3, * XLinkExpansion: 1, * InitializationSegment: 3, * IndexSegment: 3, * MediaSegment: 3, * BitstreamSwitchingSegment: 3, * other: 3 * }, * abr: { * movingAverageMethod: Constants.MOVING_AVERAGE_SLIDING_WINDOW, * ABRStrategy: Constants.ABR_STRATEGY_DYNAMIC, * bandwidthSafetyFactor: 0.9, * useDefaultABRRules: true, * useBufferOccupancyABR: false, * useDeadTimeLatency: true, * limitBitrateByPortal: false, * usePixelRatioInLimitBitrateByPortal: false, * maxBitrate: { audio: -1, video: -1 }, * minBitrate: { audio: -1, video: -1 }, * maxRepresentationRatio: { audio: 1, video: 1 }, * initialBitrate: { audio: -1, video: -1 }, * initialRepresentationRatio: { audio: -1, video: -1 }, * autoSwitchBitrate: { audio: true, video: true } * } * } * } *//** * @typedef {Object} DebugSettings * @property {number} [logLevel=dashjs.Debug.LOG_LEVEL_WARNING] * Sets up the log level. The levels are cumulative. For example, if you set the log level * to dashjs.Debug.LOG_LEVEL_WARNING all warnings, errors and fatals will be logged. Possible values. * * <ul> * <li>dashjs.Debug.LOG_LEVEL_NONE<br/> * No message is written in the browser console. * * <li>dashjs.Debug.LOG_LEVEL_FATAL<br/> * Log fatal errors. An error is considered fatal when it causes playback to fail completely. * * <li>dashjs.Debug.LOG_LEVEL_ERROR<br/> * Log error messages. * * <li>dashjs.Debug.LOG_LEVEL_WARNING<br/> * Log warning messages. * * <li>dashjs.Debug.LOG_LEVEL_INFO<br/> * Log info messages. * * <li>dashjs.Debug.LOG_LEVEL_DEBUG<br/> * Log debug messages. * </ul> *//** * @typedef {Object} AbrSettings * @property {string} [movingAverageMethod="slidingWindow"] * Sets the moving average method used for smoothing throughput estimates. Valid methods are * "slidingWindow" and "ewma". The call has no effect if an invalid method is passed. * * The sliding window moving average method computes the average throughput using the last four segments downloaded. * If the stream is live (as opposed to VOD), then only the last three segments are used. * If wide variations in throughput are detected, the number of segments can be dynamically increased to avoid oscillations. * * The exponentially weighted moving average (EWMA) method computes the average using exponential smoothing. * Two separate estimates are maintained, a fast one with a three-second half life and a slow one with an eight-second half life. * The throughput estimate at any time is the minimum of the fast and slow estimates. * This allows a fast reaction to a bandwidth drop and prevents oscillations on bandwidth spikes. * @property {string} [ABRStrategy="abrDynamic"] Returns the current ABR strategy being used: "abrDynamic", "abrBola" or "abrThroughput". * @property {number} [bandwidthSafetyFactor=0.9] * Standard ABR throughput rules multiply the throughput by this value. It should be between 0 and 1, * with lower values giving less rebuffering (but also lower quality). * @property {boolean} [useDefaultABRRules=true] Should the default ABR rules be used, or the custom ones added. * @property {boolean} [useBufferOccupancyABR=false] Whether to use the BOLA abr rule. * @property {boolean} [useDeadTimeLatency=true] * If true, only the download portion will be considered part of the download bitrate * and latency will be regarded as static. If false, the reciprocal of the whole * transfer time will be used. * @property {boolean} [limitBitrateByPortal=false] If true, the size of the video portal will limit the max chosen video resolution. * @property {boolean} [usePixelRatioInLimitBitrateByPortal=false] * Sets whether to take into account the device's pixel ratio when defining the portal dimensions. * Useful on, for example, retina displays. * @property {module:Settings~AudioVideoSettings} [maxBitrate={audio: -1, video: -1}] The maximum bitrate that the ABR algorithms will choose. Use NaN for no limit. * @property {module:Settings~AudioVideoSettings} [minBitrate={audio: -1, video: -1}] The minimum bitrate that the ABR algorithms will choose. Use NaN for no limit. * @property {module:Settings~AudioVideoSettings} [maxRepresentationRatio={audio: 1, video: 1}] * When switching multi-bitrate content (auto or manual mode) this property specifies the maximum representation allowed, * as a proportion of the size of the representation set. * * You can set or remove this cap at anytime before or during playback. To clear this setting you set the value to 1. * * If both this and maxAllowedBitrate are defined, maxAllowedBitrate is evaluated first, then maxAllowedRepresentation, * i.e. the lowest value from executing these rules is used. * * This feature is typically used to reserve higher representations for playback only when connected over a fast connection. * @property {module:Settings~AudioVideoSettings} [initialBitrate={audio: -1, video: -1}] Explicitly set the starting bitrate for audio or video * @property {module:Settings~AudioVideoSettings} [initialRepresentationRatio={audio: -1, video: -1}] Explicitly set the initial representation ratio. If initalBitrate is specified, this is ignored. * @property {module:Settings~AudioVideoSettings} [autoSwitchBitrate={audio: true, video: true}] Indicates whether the player should enable ABR algorithms to switch the bitrate. *//** * @typedef {Object} StreamingSettings * @property {number} [metricsMaxListDepth=1000] Maximum list depth of metrics. * @property {number} [abandonLoadTimeout=10000] * A timeout value in seconds, which during the ABRController will block switch-up events. * This will only take effect after an abandoned fragment event occurs. * @property {number} [liveDelayFragmentCount=4] * Changing this value will lower or increase live stream latency. The detected segment duration will be multiplied by this value * to define a time in seconds to delay a live stream from the live edge. Lowering this value will lower latency but may decrease * the player's ability to build a stable buffer. * @property {number} [liveDelay] * <p>Equivalent in seconds of setLiveDelayFragmentCount</p> * <p>Lowering this value will lower latency but may decrease the player's ability to build a stable buffer.</p> * <p>This value should be less than the manifest duration by a couple of segment durations to avoid playback issues</p> * <p>If set, this parameter will take precedence over setLiveDelayFragmentCount and manifest info</p> * @property {boolean} [scheduleWhilePaused=true] * Set to true if you would like dash.js to keep downloading fragments in the background * when the video element is paused. * @property {boolean} [fastSwitchEnabled=false] * When enabled, after an ABR up-switch in quality, instead of requesting and appending the next fragment * at the end of the current buffer range it is requested and appended closer to the current time * When enabled, The maximum time to render a higher quality is current time + (1.5 * fragment duration). * * Note, When ABR down-switch is detected, we appended the lower quality at the end of the buffer range to preserve the * higher quality media for as long as possible. * * If enabled, it should be noted there are a few cases when the client will not replace inside buffer range but rather * just append at the end. 1. When the buffer level is less than one fragment duration 2. The client * is in an Abandonment State due to recent fragment abandonment event. * * Known issues: * 1. In IE11 with auto switching off, if a user switches to a quality they can not download in time the * fragment may be appended in the same range as the playhead or even in the past, in IE11 it may cause a stutter * or stall in playback. * @property {number} [bufferPruningInterval=10] The interval of pruning buffer in sconds. * @property {number} [bufferToKeep=20] * This value influences the buffer pruning logic. * Allows you to modify the buffer that is kept in source buffer in seconds. * 0|-----------bufferToPrune-----------|-----bufferToKeep-----|currentTime| * @property {number} [bufferAheadToKeep=80] * This value influences the buffer pruning logic. * Allows you to modify the buffer ahead of current time position that is kept in source buffer in seconds. * <pre>0|--------|currentTime|-----bufferAheadToKeep----|----bufferToPrune-----------|end|</pre> * @property {boolean} [jumpGaps=true] Sets whether player should jump small gaps (discontinuities) in the buffer. * @property {number} [smallGapLimit=1.8] Time in seconds for a gap to be considered small. * @property {number} [stableBufferTime=12] * The time that the internal buffer target will be set to post startup/seeks (NOT top quality). * * When the time is set higher than the default you will have to wait longer * to see automatic bitrate switches but will have a larger buffer which * will increase stability. * @property {number} [bufferTimeAtTopQuality=30] * The time that the internal buffer target will be set to once playing the top quality. * If there are multiple bitrates in your adaptation, and the media is playing at the highest * bitrate, then we try to build a larger buffer at the top quality to increase stability * and to maintain media quality. * @property {number} [bufferTimeAtTopQualityLongForm=60] The time that the internal buffer target will be set to once playing the top quality for long form content. * @property {number} [longFormContentDurationThreshold=600] * The threshold which defines if the media is considered long form content. * This will directly affect the buffer targets when playing back at the top quality. * @property {number} [wallclockTimeUpdateInterval=50] How frequently the wallclockTimeUpdated internal event is triggered (in milliseconds). * @property {boolean} [lowLatencyEnabled=false] Enable or disable low latency mode * @property {boolean} [keepProtectionMediaKeys=false] * Set the value for the ProtectionController and MediaKeys life cycle. If true, the * ProtectionController and then created MediaKeys and MediaKeySessions will be preserved during * the MediaPlayer lifetime. * @property {boolean} [useManifestDateHeaderTimeSource=true] * <p>Allows you to enable the use of the Date Header, if exposed with CORS, as a timing source for live edge detection. The * use of the date header will happen only after the other timing source that take precedence fail or are omitted as described. * @property {boolean} [useSuggestedPresentationDelay=false] * <p>Set to true if you would like to override the default live delay and honor the SuggestedPresentationDelay attribute in by the manifest.</p> * @property {number} [manifestUpdateRetryInterval=100] * For live streams, set the interval-frequency in milliseconds at which * dash.js will check if the current manifest is still processed before * downloading the next manifest once the minimumUpdatePeriod time has * @property {number} [liveCatchUpMinDrift=0.02] * Use this method to set the minimum latency deviation allowed before activating catch-up mechanism. In low latency mode, * when the difference between the measured latency and the target one, * as an absolute number, is higher than the one sets with this method, then dash.js increases/decreases * playback rate until target latency is reached. * * LowLatencyMinDrift should be provided in seconds, and it uses values between 0.0 and 0.5. * * Note: Catch-up mechanism is only applied when playing low latency live streams. * @property {number} [liveCatchUpMaxDrift=0] * Use this method to set the maximum latency deviation allowed before dash.js to do a seeking to live position. In low latency mode, * when the difference between the measured latency and the target one, * as an absolute number, is higher than the one sets with this method, then dash.js does a seek to live edge position minus * the target live delay. * * LowLatencyMaxDriftBeforeSeeking should be provided in seconds. If 0, then seeking operations won't be used for * fixing latency deviations. * * Note: Catch-up mechanism is only applied when playing low latency live streams. * @property {number} [liveCatchUpPlaybackRate=0.5] * Use this method to set the maximum catch up rate, as a percentage, for low latency live streams. In low latency mode, * when measured latency is higher/lower than the target one, * dash.js increases/decreases playback rate respectively up to (+/-) the percentage defined with this method until target is reached. * * Valid values for catch up rate are in range 0-0.5 (0-50%). Set it to 0 to turn off live catch up feature. * * Note: Catch-up mechanism is only applied when playing low latency live streams. * @property {module:Settings~CachingInfoSettings} [lastBitrateCachingInfo={enabled: true, ttl: 360000}] * Set to false if you would like to disable the last known bit rate from being stored during playback and used * to set the initial bit rate for subsequent playback within the expiration window. * * The default expiration is one hour, defined in milliseconds. If expired, the default initial bit rate (closest to 1000 kbps) will be used * for that session and a new bit rate will be stored during that session. * @property {module:Settings~CachingInfoSettings} [lastMediaSettingsCachingInfo={enabled: true, ttl: 360000}] * Set to false if you would like to disable the last known lang for audio (or camera angle for video) from being stored during playback and used * to set the initial settings for subsequent playback within the expiration window. * * The default expiration is one hour, defined in milliseconds. If expired, the default settings will be used * for that session and a new settings will be stored during that session. * @property {module:Settings~AudioVideoSettings} [cacheLoadThresholds={video: 50, audio: 5}] * For a given media type, the threshold which defines if the response to a fragment * request is coming from browser cache or not. * @property {module:Settings~RequestTypeSettings} [retryIntervals] Time in milliseconds of which to reload a failed file load attempt. * @property {module:Settings~RequestTypeSettings} [retryAttempts] Total number of retry attempts that will occur on a file load before it fails. * @property {module:Settings~AbrSettings} abr Adaptive Bitrate algorithm related settings. *//** * @typedef {Object} CachingInfoSettings * @property {boolean} [enable] Enable or disable the caching feature. * @property {number} [ttl] Time to live. A value defined in milliseconds representing how log to cache the settings for. *//** * @typedef {Object} module:Settings~AudioVideoSettings * @property {number|boolean} [audio] Configuration for audio media type of tracks. * @property {number|boolean} [video] Configuration for video media type of tracks. *//** * @typedef {Object} RequestTypeSettings * @property {number} [MPD] Manifest type of requests * @property {number} [XLinkExpansion] XLink expansion type of requests * @property {number} [InitializationSegment] Request to retrieve an initialization segment * @property {number} [IndexSegment] Request to retrieve an index segment (SegmentBase) * @property {number} [MediaSegment] Request to retrieve a media segment (video/audio/image/text chunk) * @property {number} [BitstreamSwitchingSegment] Bitrate stream switching type of request * @property {number} [other] Other type of request * *//** * @class * @ignore */function Settings(){var _retryIntervals,_retryAttempts;var instance=void 0;/** * @const {PlayerSettings} defaultSettings * @ignore */var defaultSettings={debug:{logLevel:_Debug2.default.LOG_LEVEL_WARNING},streaming:{metricsMaxListDepth:1000,abandonLoadTimeout:10000,liveDelayFragmentCount:4,liveDelay:null,scheduleWhilePaused:true,fastSwitchEnabled:false,bufferPruningInterval:10,bufferToKeep:20,bufferAheadToKeep:80,jumpGaps:true,smallGapLimit:1.5,stableBufferTime:12,bufferTimeAtTopQuality:30,bufferTimeAtTopQualityLongForm:60,longFormContentDurationThreshold:600,wallclockTimeUpdateInterval:50,lowLatencyEnabled:false,keepProtectionMediaKeys:false,useManifestDateHeaderTimeSource:true,useSuggestedPresentationDelay:false,manifestUpdateRetryInterval:100,liveCatchUpMinDrift:0.02,liveCatchUpMaxDrift:0,liveCatchUpPlaybackRate:0.5,lastBitrateCachingInfo:{enabled:true,ttl:360000},lastMediaSettingsCachingInfo:{enabled:true,ttl:360000},cacheLoadThresholds:{video:50,audio:5},retryIntervals:(_retryIntervals={},_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.MPD_TYPE,500),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE,500),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE,1000),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE,1000),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE,1000),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE,1000),_defineProperty(_retryIntervals,_HTTPRequest.HTTPRequest.OTHER_TYPE,1000),_retryIntervals),retryAttempts:(_retryAttempts={},_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.MPD_TYPE,3),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE,1),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE,3),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE,3),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE,3),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE,3),_defineProperty(_retryAttempts,_HTTPRequest.HTTPRequest.OTHER_TYPE,3),_retryAttempts),abr:{movingAverageMethod:_Constants2.default.MOVING_AVERAGE_SLIDING_WINDOW,ABRStrategy:_Constants2.default.ABR_STRATEGY_DYNAMIC,bandwidthSafetyFactor:0.9,useDefaultABRRules:true,useBufferOccupancyABR:false,useDeadTimeLatency:true,limitBitrateByPortal:false,usePixelRatioInLimitBitrateByPortal:false,maxBitrate:{audio:-1,video:-1},minBitrate:{audio:-1,video:-1},maxRepresentationRatio:{audio:1,video:1},initialBitrate:{audio:-1,video:-1},initialRepresentationRatio:{audio:-1,video:-1},autoSwitchBitrate:{audio:true,video:true}}}};var settings=_Utils2.default.clone(defaultSettings);//Merge in the settings. If something exists in the new config that doesn't match the schema of the default config, //regard it as an error and log it. function mixinSettings(source,dest,path){for(var n in source){if(source.hasOwnProperty(n)){if(dest.hasOwnProperty(n)){if(_typeof(source[n])==='object'){mixinSettings(source[n],dest[n],path.slice()+n+'.');}else{dest[n]=_Utils2.default.clone(source[n]);}}}}}/** * Return the settings object. Don't copy/store this object, you won't get updates. * @func * @instance */function get(){return settings;}/** * @func * @instance * @param {object} settingsObj - This should be a partial object of the Settings.Schema type. That is, fields defined should match the path (e.g. * settingsObj.streaming.abr.autoSwitchBitrate.audio -> defaultSettings.streaming.abr.autoSwitchBitrate.audio). Where an element's path does * not match it is ignored, and a warning is logged. * * Use to change the settings object. Any new values defined will overwrite the settings and anything undefined will not change. * Implementers of new settings should add it in an approriate namespace to the defaultSettings object and give it a default value (that is not undefined). * */function update(settingsObj){if((typeof settingsObj==='undefined'?'undefined':_typeof(settingsObj))==='object'){mixinSettings(settingsObj,settings,'');}}/** * Resets the settings object. Everything is set to its default value. * @func * @instance * */function reset(){settings=_Utils2.default.clone(defaultSettings);}instance={get:get,update:update,reset:reset};return instance;}Settings.__dashjs_factory_name='Settings';var factory=_FactoryMaker2.default.getSingletonFactory(Settings);exports.default=factory; //# sourceMappingURL=Settings.js.map