diff --git a/src/streaming/MediaPlayer.js b/src/streaming/MediaPlayer.js index a50f501211..21e8d0384a 100644 --- a/src/streaming/MediaPlayer.js +++ b/src/streaming/MediaPlayer.js @@ -1260,6 +1260,32 @@ function MediaPlayer() { mediaPlayerModel.setRichBufferThreshold(value); } + /** + * @param value + * @memberof module:MediaPlayer + * @instance + */ + function setBandwidthSafetyFactor(value) { + mediaPlayerModel.setBandwidthSafetyFactor(value); + } + + /** + * @return value + * @memberof module:MediaPlayer + * @instance + */ + function getBandwidthSafetyFactor() { + return mediaPlayerModel.getBandwidthSafetyFactor(); + } + + /** + * @param value + * @memberof module:MediaPlayer + * @instance + */ + function setAbandonLoadTimeout(value) { + mediaPlayerModel.setAbandonLoadTimeout(value); + } /** * @memberof module:MediaPlayer @@ -1586,6 +1612,9 @@ function MediaPlayer() { setAutoSwitchQuality: setAutoSwitchQuality, getAutoSwitchQualityFor: getAutoSwitchQualityFor, setAutoSwitchQualityFor: setAutoSwitchQualityFor, + setBandwidthSafetyFactor: setBandwidthSafetyFactor, + getBandwidthSafetyFactor: getBandwidthSafetyFactor, + setAbandonLoadTimeout: setAbandonLoadTimeout, retrieveManifest: retrieveManifest, addUTCTimingSource: addUTCTimingSource, removeUTCTimingSource: removeUTCTimingSource, diff --git a/src/streaming/controllers/AbrController.js b/src/streaming/controllers/AbrController.js index 7704cdbc60..207263ca8d 100644 --- a/src/streaming/controllers/AbrController.js +++ b/src/streaming/controllers/AbrController.js @@ -32,6 +32,7 @@ import SwitchRequest from '../rules/SwitchRequest'; import BitrateInfo from '../vo/BitrateInfo.js'; import ABRRulesCollection from '../rules/abr/ABRRulesCollection.js'; +import MediaPlayerModel from '../models/MediaPlayerModel.js'; import FragmentModel from '../models/FragmentModel.js'; import EventBus from '../../core/EventBus.js'; import Events from '../../core/events/Events.js'; @@ -41,8 +42,6 @@ import DashManifestExtensions from '../../dash/extensions/DashManifestExtensions import VideoModel from '../models/VideoModel.js'; const ABANDON_LOAD = 'abandonload'; -const BANDWIDTH_SAFETY = 0.9; -const ABANDON_TIMEOUT = 10000; const ALLOW_LOAD = 'allowload'; const DEFAULT_VIDEO_BITRATE = 1000; const DEFAULT_AUDIO_BITRATE = 100; @@ -69,7 +68,8 @@ function AbrController() { limitBitrateByPortal, manifestModel, manifestExt, - videoModel; + videoModel, + mediaPlayerModel; function setup() { autoSwitchBitrate = {video: true, audio: true}; @@ -81,7 +81,8 @@ function AbrController() { averageThroughputDict = {}; abandonmentStateDict = {}; streamProcessorDict = {}; - limitBitrateByPortal = true; + limitBitrateByPortal = false; + mediaPlayerModel = MediaPlayerModel(context).getInstance(); manifestModel = ManifestModel(context).getInstance(); manifestExt = DashManifestExtensions(context).getInstance(); videoModel = VideoModel(context).getInstance(); @@ -477,7 +478,7 @@ function AbrController() { function setupTimeout(type) { abandonmentTimeout = setTimeout(function () { setAbandonmentStateFor(type, ALLOW_LOAD); - }, ABANDON_TIMEOUT); + }, mediaPlayerModel.getAbandonLoadTimeout()); } if (switchRequest.confidence === SwitchRequest.STRONG) { @@ -542,7 +543,4 @@ function AbrController() { AbrController.__dashjs_factory_name = 'AbrController'; let factory = FactoryMaker.getSingletonFactory(AbrController); factory.ABANDON_LOAD = ABANDON_LOAD; -factory.BANDWIDTH_SAFETY = BANDWIDTH_SAFETY; -factory.DEFAULT_VIDEO_BITRATE = DEFAULT_VIDEO_BITRATE; -factory.DEFAULT_AUDIO_BITRATE = DEFAULT_AUDIO_BITRATE; export default factory; \ No newline at end of file diff --git a/src/streaming/models/MediaPlayerModel.js b/src/streaming/models/MediaPlayerModel.js index 6ff4decd35..c98152430e 100644 --- a/src/streaming/models/MediaPlayerModel.js +++ b/src/streaming/models/MediaPlayerModel.js @@ -6,6 +6,8 @@ const LIVE_DELAY_FRAGMENT_COUNT = 4; const DEFAULT_LOCAL_STORAGE_BITRATE_EXPIRATION = 360000; const DEFAULT_LOCAL_STORAGE_MEDIA_SETTINGS_EXPIRATION = 360000; +const BANDWIDTH_SAFETY_FACTOR = 0.9; +const ABANDON_LOAD_TIMEOUT = 10000; const BUFFER_TO_KEEP = 30; const BUFFER_PRUNING_INTERVAL = 30; @@ -31,7 +33,9 @@ function MediaPlayerModel() { bufferTimeAtTopQuality, bufferTimeAtTopQualityLongForm, longFormContentDurationThreshold, - richBufferThreshold; + richBufferThreshold, + bandwidthSafetyFactor, + abandonLoadTimeout; function setup() { UTCTimingSources = []; @@ -48,9 +52,28 @@ function MediaPlayerModel() { bufferTimeAtTopQualityLongForm = BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM; longFormContentDurationThreshold = LONG_FORM_CONTENT_DURATION_THRESHOLD; richBufferThreshold = RICH_BUFFER_THRESHOLD; + bandwidthSafetyFactor = BANDWIDTH_SAFETY_FACTOR; + abandonLoadTimeout = ABANDON_LOAD_TIMEOUT; } + //TODO Should we use Object.define to have setters/getters? makes more readable code on other side. + function setBandwidthSafetyFactor(value) { + bandwidthSafetyFactor = value; + } + + function getBandwidthSafetyFactor() { + return bandwidthSafetyFactor; + } + + function setAbandonLoadTimeout(value) { + abandonLoadTimeout = value; + } + + function getAbandonLoadTimeout() { + return abandonLoadTimeout; + } + function setStableBufferTime (value) { stableBufferTime = value; } @@ -176,6 +199,10 @@ function MediaPlayerModel() { } instance = { + setBandwidthSafetyFactor: setBandwidthSafetyFactor, + getBandwidthSafetyFactor: getBandwidthSafetyFactor, + setAbandonLoadTimeout: setAbandonLoadTimeout, + getAbandonLoadTimeout: getAbandonLoadTimeout, setLastBitrateCachingInfo: setLastBitrateCachingInfo, getLastBitrateCachingInfo: getLastBitrateCachingInfo, setLastMediaSettingsCachingInfo: setLastMediaSettingsCachingInfo, diff --git a/src/streaming/rules/abr/AbandonRequestsRule.js b/src/streaming/rules/abr/AbandonRequestsRule.js index f71d05f366..4734821369 100644 --- a/src/streaming/rules/abr/AbandonRequestsRule.js +++ b/src/streaming/rules/abr/AbandonRequestsRule.js @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ import SwitchRequest from '../SwitchRequest.js'; -import AbrController from '../../controllers/AbrController.js'; +import MediaPlayerModel from '../../models/MediaPlayerModel.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import Debug from '../../../core/Debug.js'; @@ -43,11 +43,13 @@ function AbandonRequestsRule(/*config*/) { let instance, fragmentDict, - abandonDict; + abandonDict, + mediaPlayerModel; function setup() { fragmentDict = {}; abandonDict = {}; + mediaPlayerModel = MediaPlayerModel(context).getInstance(); } function setFragmentRequestDict(type, id) { @@ -98,7 +100,7 @@ function AbandonRequestsRule(/*config*/) { callback(switchRequest); return; }else if (!abandonDict.hasOwnProperty(fragmentInfo.id)) { - var newQuality = abrController.getQualityForBitrate(mediaInfo, fragmentInfo.measuredBandwidthInKbps * AbrController.BANDWIDTH_SAFETY); + var newQuality = abrController.getQualityForBitrate(mediaInfo, fragmentInfo.measuredBandwidthInKbps * mediaPlayerModel.getBandwidthSafetyFactor()); switchRequest = SwitchRequest(context).create(newQuality, SwitchRequest.STRONG); abandonDict[fragmentInfo.id] = fragmentInfo; log('AbandonRequestsRule ( ', mediaType, 'frag id',fragmentInfo.id,') is asking to abandon and switch to quality to ', newQuality, ' measured bandwidth was', fragmentInfo.measuredBandwidthInKbps); diff --git a/src/streaming/rules/abr/ThroughputRule.js b/src/streaming/rules/abr/ThroughputRule.js index 22fccd8f85..bd876c896e 100644 --- a/src/streaming/rules/abr/ThroughputRule.js +++ b/src/streaming/rules/abr/ThroughputRule.js @@ -31,6 +31,7 @@ import SwitchRequest from '../SwitchRequest.js'; import BufferController from '../../controllers/BufferController.js'; import AbrController from '../../controllers/AbrController.js'; +import MediaPlayerModel from '../../models/MediaPlayerModel.js'; import HTTPRequest from '../../vo/metrics/HTTPRequest.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import Debug from '../../../core/Debug.js'; @@ -46,7 +47,13 @@ function ThroughputRule(config) { let metricsModel = config.metricsModel; let instance, - throughputArray; + throughputArray, + mediaPlayerModel; + + function setup() { + throughputArray = []; + mediaPlayerModel = MediaPlayerModel(context).getInstance(); + } function storeLastRequestThroughputByType(type, lastRequestThroughput) { throughputArray[type] = throughputArray[type] || []; @@ -78,7 +85,7 @@ function ThroughputRule(config) { arr.shift(); } - return (averageThroughput / 1000 ) * AbrController.BANDWIDTH_SAFETY; + return (averageThroughput / 1000 ) * mediaPlayerModel.getBandwidthSafetyFactor(); } function execute (rulesContext, callback) { @@ -135,7 +142,7 @@ function ThroughputRule(config) { } function reset() { - throughputArray = []; + setup(); } instance = { @@ -143,7 +150,7 @@ function ThroughputRule(config) { reset: reset }; - reset(); + setup(); return instance; } diff --git a/src/streaming/rules/scheduling/BufferLevelRule.js b/src/streaming/rules/scheduling/BufferLevelRule.js index cf95168f14..84a953f100 100644 --- a/src/streaming/rules/scheduling/BufferLevelRule.js +++ b/src/streaming/rules/scheduling/BufferLevelRule.js @@ -42,10 +42,12 @@ function BufferLevelRule(config) { let metricsModel = config.metricsModel; let textSourceBuffer = config.textSourceBuffer; - let mediaPlayerModel; + let mediaPlayerModel, + playbackController; function setup() { mediaPlayerModel = MediaPlayerModel(context).getInstance(); + playbackController = PlaybackController(context).getInstance(); } function execute(rulesContext, callback) { @@ -78,7 +80,7 @@ function BufferLevelRule(config) { //General VOD target non top quality and not stabilized on a given quality. bufferTarget = mediaPlayerModel.getStableBufferTime(); } else { - bufferTarget = PlaybackController(context).getInstance().getLiveDelay(); + bufferTarget = playbackController.getLiveDelay(); } if (type === 'fragmentedText') {