# Source: streaming/models/MediaPlayerModel.js

    /**
     * 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.
     */
    import Debug from '../../core/Debug';
    import FactoryMaker from '../../core/FactoryMaker';
    import Settings from '../../core/Settings';

    const DEFAULT_MIN_BUFFER_TIME = 12;
    const DEFAULT_MIN_BUFFER_TIME_FAST_SWITCH = 20;
    const LOW_LATENCY_REDUCTION_FACTOR = 10;
    const LOW_LATENCY_MULTIPLY_FACTOR = 5;
    const DEFAULT_CATCHUP_MAX_DRIFT = 12;
    const DEFAULT_CATCHUP_PLAYBACK_RATE_MIN = -0.5;
    const DEFAULT_CATCHUP_PLAYBACK_RATE_MAX = 0.5;
    const CATCHUP_PLAYBACK_RATE_MIN_LIMIT = -0.5;
    const CATCHUP_PLAYBACK_RATE_MAX_LIMIT = 1;

    /**
     * We use this model as a wrapper/proxy between Settings.js and classes that are using parameters from Settings.js.
     * In some cases we require additional logic to be applied and the settings might need to be adjusted before being used.
     * @class
     * @constructor
     */
    function MediaPlayerModel() {

        let instance,
            logger,
            playbackController,
            serviceDescriptionController;

        const context = this.context;
        const settings = Settings(context).getInstance();

        function setup() {
            logger = Debug(context).getInstance().getLogger(instance);
        }

        function setConfig(config) {
            if (config.playbackController) {
                playbackController = config.playbackController;
            }
            if (config.serviceDescriptionController) {
                serviceDescriptionController = config.serviceDescriptionController;
            }
        }

        /**
         * Checks the supplied min playback rate is a valid vlaue and within supported limits
         * @param {number} rate - Supplied min playback rate
         * @param {boolean} log - wether to shown warning or not
         * @returns {number} corrected min playback rate
         */
        function _checkMinPlaybackRate (rate, log) {
            if (isNaN(rate)) return 0;
            if (rate > 0) {
                if (log) {
                    logger.warn(`Supplied minimum playback rate is a positive value when it should be negative or 0. The supplied rate will not be applied and set to 0: 100% playback speed.`)
                }
                return 0;
            }
            if (rate < CATCHUP_PLAYBACK_RATE_MIN_LIMIT) {
                if (log) {
                    logger.warn(`Supplied minimum playback rate is out of range and will be limited to ${CATCHUP_PLAYBACK_RATE_MIN_LIMIT}: ${CATCHUP_PLAYBACK_RATE_MIN_LIMIT * 100}% playback speed.`);
                }
                return CATCHUP_PLAYBACK_RATE_MIN_LIMIT;
            }
            return rate;
        };

        /**
         * Checks the supplied max playback rate is a valid vlaue and within supported limits
         * @param {number} rate - Supplied max playback rate
         * @param {boolean} log - wether to shown warning or not
         * @returns {number} corrected max playback rate
         */
        function _checkMaxPlaybackRate (rate, log) {
            if (isNaN(rate)) return 0;
            if (rate < 0) {
                if (log) {
                    logger.warn(`Supplied maximum playback rate is a negative value when it should be negative or 0. The supplied rate will not be applied and set to 0: 100% playback speed.`)
                }
                return 0;
            }
            if (rate > CATCHUP_PLAYBACK_RATE_MAX_LIMIT) {
                if (log) {
                    logger.warn(`Supplied maximum playback rate is out of range and will be limited to ${CATCHUP_PLAYBACK_RATE_MAX_LIMIT}: ${(1 + CATCHUP_PLAYBACK_RATE_MAX_LIMIT) * 100}% playback speed.`);
                }
                return CATCHUP_PLAYBACK_RATE_MAX_LIMIT;
            }
            return rate;
        };

        /**
         * Returns the maximum drift allowed before applying a seek back to the live edge when the catchup mode is enabled
         * @return {number}
         */
        function getCatchupMaxDrift() {
            if (!isNaN(settings.get().streaming.liveCatchup.maxDrift) && settings.get().streaming.liveCatchup.maxDrift > 0) {
                return settings.get().streaming.liveCatchup.maxDrift;
            }

            const serviceDescriptionSettings = serviceDescriptionController.getServiceDescriptionSettings();
            if (serviceDescriptionSettings && serviceDescriptionSettings.liveCatchup && !isNaN(serviceDescriptionSettings.liveCatchup.maxDrift) && serviceDescriptionSettings.liveCatchup.maxDrift > 0) {
                return serviceDescriptionSettings.liveCatchup.maxDrift;
            }

            return DEFAULT_CATCHUP_MAX_DRIFT;
        }

        /**
         * Returns the minimum and maximum playback rates to be used when applying the catchup mechanism
         * If only one of the min/max values has been set then the other will default to 0 (no playback rate change).
         * @return {number}
         */
        function getCatchupPlaybackRates(log) {
            const settingsPlaybackRate = settings.get().streaming.liveCatchup.playbackRate;

            if(!isNaN(settingsPlaybackRate.min) || !isNaN(settingsPlaybackRate.max)) {
                return {
                    min: _checkMinPlaybackRate(settingsPlaybackRate.min, log),
                    max: _checkMaxPlaybackRate(settingsPlaybackRate.max, log),
                }
            }

            const serviceDescriptionSettings = serviceDescriptionController.getServiceDescriptionSettings();
            if (serviceDescriptionSettings && serviceDescriptionSettings.liveCatchup && (!isNaN(serviceDescriptionSettings.liveCatchup.playbackRate.min) || !isNaN(serviceDescriptionSettings.liveCatchup.playbackRate.max))) {
                const sdPlaybackRate = serviceDescriptionSettings.liveCatchup.playbackRate;
                return {
                    min: _checkMinPlaybackRate(sdPlaybackRate.min, log),
                    max: _checkMaxPlaybackRate(sdPlaybackRate.max, log),
                }
            }

            return {
                min: DEFAULT_CATCHUP_PLAYBACK_RATE_MIN,
                max: DEFAULT_CATCHUP_PLAYBACK_RATE_MAX
            }
        }

        /**
         * Returns whether the catchup mode is activated via the settings or internally in the PlaybackController
         * @return {boolean}
         */
        function getCatchupModeEnabled() {
            if (settings.get().streaming.liveCatchup.enabled !== null) {
                return settings.get().streaming.liveCatchup.enabled;
            }

            return playbackController.getInitialCatchupModeActivated();
        }

        /**
         * Returns the min,max or initial bitrate for a specific media type.
         * @param {string} field
         * @param {string} mediaType
         */
        function getAbrBitrateParameter(field, mediaType) {
            try {
                const setting = settings.get().streaming.abr[field][mediaType];
                if(!isNaN(setting) && setting !== -1) {
                    return setting;
                }

                const serviceDescriptionSettings = serviceDescriptionController.getServiceDescriptionSettings();
                if(serviceDescriptionSettings && serviceDescriptionSettings[field] && !isNaN(serviceDescriptionSettings[field][mediaType])) {
                    return serviceDescriptionSettings[field][mediaType];
                }

                return -1;
            }
            catch(e) {
                return -1;
            }
        }

        /**
         * Returns the initial buffer level taking the stable buffer time into account
         * @return {number}
         */
        function getInitialBufferLevel() {
            const initialBufferLevel = settings.get().streaming.buffer.initialBufferLevel;

            if (isNaN(initialBufferLevel) || initialBufferLevel < 0) {
                return 0;
            }

            return Math.min(getStableBufferTime(), initialBufferLevel);
        }

        /**
         * Returns the stable buffer time taking the live delay into account
         * @return {number}
         */
        function getStableBufferTime() {
            let stableBufferTime = settings.get().streaming.buffer.stableBufferTime > 0 ? settings.get().streaming.buffer.stableBufferTime : settings.get().streaming.buffer.fastSwitchEnabled ? DEFAULT_MIN_BUFFER_TIME_FAST_SWITCH : DEFAULT_MIN_BUFFER_TIME;
            const liveDelay = playbackController.getLiveDelay();

            return !isNaN(liveDelay) && liveDelay > 0 ? Math.min(stableBufferTime, liveDelay) : stableBufferTime;
        }

        /**
         * Returns the number of retry attempts for a specific media type
         * @param type
         * @return {number}
         */
        function getRetryAttemptsForType(type) {
            const lowLatencyMultiplyFactor = !isNaN(settings.get().streaming.retryAttempts.lowLatencyMultiplyFactor) ? settings.get().streaming.retryAttempts.lowLatencyMultiplyFactor : LOW_LATENCY_MULTIPLY_FACTOR;

            return playbackController.getLowLatencyModeEnabled() ? settings.get().streaming.retryAttempts[type] * lowLatencyMultiplyFactor : settings.get().streaming.retryAttempts[type];
        }

        /**
         * Returns the retry interval for a specific media type
         * @param type
         * @return {number}
         */
        function getRetryIntervalsForType(type) {
            const lowLatencyReductionFactor = !isNaN(settings.get().streaming.retryIntervals.lowLatencyReductionFactor) ? settings.get().streaming.retryIntervals.lowLatencyReductionFactor : LOW_LATENCY_REDUCTION_FACTOR;

            return playbackController.getLowLatencyModeEnabled() ? settings.get().streaming.retryIntervals[type] / lowLatencyReductionFactor : settings.get().streaming.retryIntervals[type];
        }

        function reset() {
        }

        instance = {
            getCatchupMaxDrift,
            getCatchupModeEnabled,
            getStableBufferTime,
            getInitialBufferLevel,
            getRetryAttemptsForType,
            getRetryIntervalsForType,
            getCatchupPlaybackRates,
            getAbrBitrateParameter,
            setConfig,
            reset
        };

        setup();

        return instance;
    }

    MediaPlayerModel.__dashjs_factory_name = 'MediaPlayerModel';
    export default FactoryMaker.getSingletonFactory(MediaPlayerModel);

#### Search results