# Source: dash/DashMetrics.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 Constants from '../streaming/constants/Constants';
    import { HTTPRequest } from '../streaming/vo/metrics/HTTPRequest';
    import FactoryMaker from '../core/FactoryMaker';
    import MetricsConstants from '../streaming/constants/MetricsConstants';
    import Round10 from './utils/Round10';
    import MetricsModel from '../streaming/models/MetricsModel';
    import Utils from '../core/Utils';
    import {
        PlayList,
        PlayListTrace
    } from '../streaming/vo/metrics/PlayList';

    /**
     * @module DashMetrics
     * @description The DashMetrics module can be accessed using the MediaPlayer API getDashMetrics()
     * @param {object} config
     */

    function DashMetrics(config) {

        config = config || {};

        const context = this.context;
        let instance,
            playListTraceMetricsClosed,
            playListTraceMetrics,
            playListMetrics;

        let metricsModel = config.metricsModel;

        function setup() {
            metricsModel = metricsModel || MetricsModel(context).getInstance({settings: config.settings});
            resetInitialSettings();
        }

        function resetInitialSettings() {
            playListTraceMetricsClosed = true;
            playListTraceMetrics = null;
            playListMetrics = null;
        }

        /**
         * Returns the latest Representation switch for a given media type
         * @param {MediaType} mediaType
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentRepresentationSwitch(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);
            return getCurrent(metrics, MetricsConstants.TRACK_SWITCH);
        }

        /**
         * @param {MediaType} mediaType
         * @param {Date} t time of the switch event
         * @param {Date} mt media presentation time
         * @param {string} to id of representation
         * @param {string} lto if present, subrepresentation reference
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addRepresentationSwitch(mediaType, t, mt, to, lto) {
            metricsModel.addRepresentationSwitch(mediaType, t, mt, to, lto);
        }

        /**
         * Returns the current buffer state for a given media type
         * @param {MediaType} mediaType
         * @returns {number}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentBufferState(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);
            return getCurrent(metrics, MetricsConstants.BUFFER_STATE);
        }

        /**
         * Returns the current buffer level for a given media type
         * @param {MediaType} mediaType
         * @returns {number}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentBufferLevel(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);
            const metric = getCurrent(metrics, MetricsConstants.BUFFER_LEVEL);

            if (metric) {
                return Round10.round10(metric.level / 1000, -3);
            }

            return 0;
        }

        /**
         * @param {MediaType} mediaType
         * @param {number} t
         * @param {number} level
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addBufferLevel(mediaType, t, level) {
            metricsModel.addBufferLevel(mediaType, t, level);
        }

        /**
         * @param {MediaType} mediaType
         * @param {string} state
         * @param {number} target
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addBufferState(mediaType, state, target) {
            metricsModel.addBufferState(mediaType, state, target);
        }

        /**
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function clearAllCurrentMetrics () {
            metricsModel.clearAllCurrentMetrics();
        }

        /**
         * Returns the latest HTTP request for a given media type
         * @param {MediaType} mediaType
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentHttpRequest(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);

            if (!metrics) {
                return null;
            }

            const httpList = metrics.HttpList;
            let currentHttpList = null;

            let httpListLastIndex;

            if (!httpList || httpList.length <= 0) {
                return null;
            }

            httpListLastIndex = httpList.length - 1;

            while (httpListLastIndex >= 0) {
                if (httpList[httpListLastIndex].responsecode) {
                    currentHttpList = httpList[httpListLastIndex];
                    break;
                }
                httpListLastIndex--;
            }
            return currentHttpList;
        }

        /**
         * Returns all HTTP requests for a given media type
         * @param {MediaType} mediaType
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getHttpRequests(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);
            if (!metrics) {
                return [];
            }

            return !!metrics.HttpList ? metrics.HttpList : [];
        }

        /**
         * @param {MediaType} mediaType
         * @param {Array} loadingRequests
         * @param {Array} executedRequests
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addRequestsQueue(mediaType, loadingRequests, executedRequests) {
            metricsModel.addRequestsQueue(mediaType, loadingRequests, executedRequests);
        }

        /**
         * Returns the latest metrics for a given metric list and specific metric name
         * @param {MetricsList} metrics
         * @param {string} metricName
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrent(metrics, metricName) {
            if (!metrics) {
                return null;
            }
            const list = metrics[metricName];
            return (!list || list.length === 0) ? null : list[list.length - 1];
        }

        /**
         * Returns the number of dropped frames
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentDroppedFrames() {
            const metrics = metricsModel.getMetricsFor(Constants.VIDEO, true);
            return getCurrent(metrics, MetricsConstants.DROPPED_FRAMES);
        }

        /**
         * @param {number} quality
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addDroppedFrames(quality) {
            metricsModel.addDroppedFrames(Constants.VIDEO, quality);
        }

        /**
         * Returns the current scheduling info for a given media type
         * @param {MediaType} mediaType
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentSchedulingInfo(mediaType) {
            const metrics = metricsModel.getMetricsFor(mediaType, true);
            return getCurrent(metrics, MetricsConstants.SCHEDULING_INFO);
        }

        /**
         * @param {object} request
         * @param {string} state
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addSchedulingInfo(request, state) {
            metricsModel.addSchedulingInfo(
                request.mediaType,
                new Date(),
                request.type,
                request.startTime,
                request.availabilityStartTime,
                request.duration,
                request.quality,
                request.range,
                state);
        }

        /**
         * Returns the current manifest update information
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentManifestUpdate() {
            const streamMetrics = metricsModel.getMetricsFor(Constants.STREAM);
            return getCurrent(streamMetrics, MetricsConstants.MANIFEST_UPDATE);
        }

        /**
         * @param {object} updatedFields fields to be updated
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function updateManifestUpdateInfo(updatedFields) {
            const manifestUpdate = this.getCurrentManifestUpdate();
            metricsModel.updateManifestUpdateInfo(manifestUpdate, updatedFields);
        }

        /**
         * @param {object} streamInfo
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addManifestUpdateStreamInfo(streamInfo) {
            if (streamInfo) {
                const manifestUpdate = this.getCurrentManifestUpdate();
                metricsModel.addManifestUpdateStreamInfo(manifestUpdate, streamInfo.id, streamInfo.index, streamInfo.start, streamInfo.duration);
            }
        }

        /**
         * @param {object} request
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addManifestUpdate(request) {
            metricsModel.addManifestUpdate(Constants.STREAM, request.type, request.requestStartDate, request.requestEndDate);
        }

        /**
         * @param {object} request
         * @param {string} responseURL
         * @param {number} responseStatus
         * @param {object} responseHeaders
         * @param {object} traces
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addHttpRequest(request, responseURL, responseStatus, responseHeaders, traces, cmsd) {
            metricsModel.addHttpRequest(request.mediaType,
                null,
                request.type,
                request.url,
                request.quality,
                responseURL,
                request.serviceLocation || null,
                request.range || null,
                request.requestStartDate,
                request.firstByteDate,
                request.requestEndDate,
                responseStatus,
                request.duration,
                responseHeaders,
                traces,
                request.fileLoaderType,
                cmsd);
        }

        /**
         * @param {object} representation
         * @param {MediaType} mediaType
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addManifestUpdateRepresentationInfo(representation, mediaType) {
            if (representation) {
                const manifestUpdateInfo = this.getCurrentManifestUpdate();
                metricsModel.addManifestUpdateRepresentationInfo(manifestUpdateInfo, representation.id, representation.index, representation.streamIndex, mediaType, representation.presentationTimeOffset, representation.startNumber, representation.fragmentInfoType);
            }
        }

        /**
         * Returns the current DVR window
         * @param {MediaType} mediaType
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getCurrentDVRInfo(mediaType) {
            const metrics = mediaType ? metricsModel.getMetricsFor(mediaType, true) :
                metricsModel.getMetricsFor(Constants.VIDEO, true) || metricsModel.getMetricsFor(Constants.AUDIO, true);
            return getCurrent(metrics, MetricsConstants.DVR_INFO);
        }

        /**
         * @param {MediaType} mediaType
         * @param {Date} currentTime time of the switch event
         * @param {object} mpd mpd reference
         * @param {object} range range of the dvr info
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addDVRInfo(mediaType, currentTime, mpd, range) {
            metricsModel.addDVRInfo(mediaType, currentTime, mpd, range);
        }

        /**
         * Returns the value for a specific request headers used in the latest MPD request
         * @param {string} id
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getLatestMPDRequestHeaderValueByID(id) {
            if (!id) {
                return null;
            }

            let headers = {};
            let httpRequestList,
                httpRequest,
                i;

            httpRequestList = getHttpRequests(Constants.STREAM);

            for (i = httpRequestList.length - 1; i >= 0; i--) {
                httpRequest = httpRequestList[i];

                if (httpRequest.type === HTTPRequest.MPD_TYPE) {
                    headers = Utils.parseHttpHeaders(httpRequest._responseHeaders);
                    break;
                }
            }

            const value = headers[id.toLowerCase()];
            return value === undefined ? null : value;
        }

        /**
         * Returns the value for a specific request headers used in the latest fragment request
         * @param {MediaType} mediaType
         * @param {string} id
         * @returns {*}
         * @memberof module:DashMetrics
         * @instance
         */
        function getLatestFragmentRequestHeaderValueByID(mediaType, id) {
            if (!id) {
                return null;
            }

            let headers = {};
            let httpRequest = getCurrentHttpRequest(mediaType);
            if (httpRequest) {
                headers = Utils.parseHttpHeaders(httpRequest._responseHeaders);
            }

            const value = headers[id.toLowerCase()];
            return value === undefined ? null : value;
        }

        /**
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addPlayList() {
            if (playListMetrics) {
                metricsModel.addPlayList(playListMetrics);
                playListMetrics = null;
            }
        }

        /**
         * Create a new playlist metric
         * @param {number} mediaStartTime
         * @param {string} startReason
         * @ignore
         */
        function createPlaylistMetrics(mediaStartTime, startReason) {
            playListMetrics = new PlayList();

            playListMetrics.start = new Date();
            playListMetrics.mstart = mediaStartTime;
            playListMetrics.starttype = startReason;
        }

        /**
         * Create a playlist trace metric
         * @param {number} representationId
         * @param {number} mediaStartTime
         * @param {number} speed
         * @ignore
         */
        function createPlaylistTraceMetrics(representationId, mediaStartTime, speed) {
            if (playListTraceMetricsClosed === true ) {
                playListTraceMetricsClosed = false;
                playListTraceMetrics = new PlayListTrace();

                playListTraceMetrics.representationid = representationId;
                playListTraceMetrics.start = new Date();
                playListTraceMetrics.mstart = mediaStartTime;
                playListTraceMetrics.playbackspeed = speed !== null ? speed.toString() : null;
            }
        }

        /**
         * Update existing playlist trace metric
         * @param {object} traceToUpdate
         * @ignore
         */
        function updatePlayListTraceMetrics(traceToUpdate) {
            if (playListTraceMetrics) {
                for (let field in playListTraceMetrics) {
                    playListTraceMetrics[field] = traceToUpdate[field];
                }
            }
        }

        /**
         * Push a new playlist trace metric
         * @param endTime
         * @param reason
         * @ignore
         */
        function pushPlayListTraceMetrics(endTime, reason) {
            if (playListTraceMetricsClosed === false && playListMetrics && playListTraceMetrics && playListTraceMetrics.start) {
                const startTime = playListTraceMetrics.start;
                const duration = endTime.getTime() - startTime.getTime();
                playListTraceMetrics.duration = duration;
                playListTraceMetrics.stopreason = reason;
                playListMetrics.trace.push(playListTraceMetrics);
                playListTraceMetricsClosed = true;
            }
        }

        /**
         * @param {object} errors
         * @memberof module:DashMetrics
         * @instance
         * @ignore
         */
        function addDVBErrors(errors) {
            metricsModel.addDVBErrors(errors);
        }

        instance = {
            getCurrentRepresentationSwitch,
            getCurrentBufferState,
            getCurrentBufferLevel,
            getCurrentHttpRequest,
            getHttpRequests,
            getCurrentDroppedFrames,
            getCurrentSchedulingInfo,
            getCurrentDVRInfo,
            getCurrentManifestUpdate,
            getLatestFragmentRequestHeaderValueByID,
            getLatestMPDRequestHeaderValueByID,
            addRepresentationSwitch,
            addDVRInfo,
            updateManifestUpdateInfo,
            addManifestUpdateStreamInfo,
            addManifestUpdateRepresentationInfo,
            addManifestUpdate,
            addHttpRequest,
            addSchedulingInfo,
            addRequestsQueue,
            addBufferLevel,
            addBufferState,
            addDroppedFrames,
            addPlayList,
            addDVBErrors,
            createPlaylistMetrics,
            createPlaylistTraceMetrics,
            updatePlayListTraceMetrics,
            pushPlayListTraceMetrics,
            clearAllCurrentMetrics
        };

        setup();

        return instance;
    }

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

#### Search results