UNPKG

@l5i/dashjs

Version:

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

412 lines (352 loc) 13.7 kB
/** * 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 './constants/Constants'; import LiveEdgeFinder from './utils/LiveEdgeFinder'; import BufferController from './controllers/BufferController'; import TextBufferController from './text/TextBufferController'; import ScheduleController from './controllers/ScheduleController'; import RepresentationController from '../dash/controllers/RepresentationController'; import FactoryMaker from '../core/FactoryMaker'; import DashHandler from '../dash/DashHandler'; function StreamProcessor(config) { config = config || {}; let context = this.context; let indexHandler; let type = config.type; let errHandler = config.errHandler; let mimeType = config.mimeType; let timelineConverter = config.timelineConverter; let adapter = config.adapter; let manifestModel = config.manifestModel; let mediaPlayerModel = config.mediaPlayerModel; let stream = config.stream; let abrController = config.abrController; let playbackController = config.playbackController; let streamController = config.streamController; let mediaController = config.mediaController; let textController = config.textController; let domStorage = config.domStorage; let metricsModel = config.metricsModel; let dashMetrics = config.dashMetrics; let dashManifestModel = config.dashManifestModel; let instance, mediaInfo, mediaInfoArr, bufferController, scheduleController, liveEdgeFinder, representationController, fragmentModel, spExternalControllers; function setup() { if (playbackController && playbackController.getIsDynamic()) { liveEdgeFinder = LiveEdgeFinder(context).create({ timelineConverter: timelineConverter, streamProcessor: instance }); } resetInitialSettings(); } function initialize(mediaSource) { indexHandler = DashHandler(context).create({ mimeType: mimeType, timelineConverter: timelineConverter, dashMetrics: dashMetrics, metricsModel: metricsModel, mediaPlayerModel: mediaPlayerModel, baseURLController: config.baseURLController, errHandler: errHandler }); // initialize controllers indexHandler.initialize(instance); abrController.registerStreamType(type, instance); fragmentModel = stream.getFragmentController().getModel(type); fragmentModel.setStreamProcessor(instance); bufferController = createBufferControllerForType(type); scheduleController = ScheduleController(context).create({ type: type, mimeType: mimeType, metricsModel: metricsModel, adapter: adapter, dashMetrics: dashMetrics, dashManifestModel: dashManifestModel, timelineConverter: timelineConverter, mediaPlayerModel: mediaPlayerModel, abrController: abrController, playbackController: playbackController, streamController: streamController, textController: textController, streamProcessor: instance, mediaController: mediaController }); representationController = RepresentationController(context).create(); representationController.setConfig({ abrController: abrController, domStorage: domStorage, metricsModel: metricsModel, dashMetrics: dashMetrics, dashManifestModel: dashManifestModel, manifestModel: manifestModel, playbackController: playbackController, timelineConverter: timelineConverter, streamProcessor: instance }); bufferController.initialize(mediaSource); scheduleController.initialize(); representationController.initialize(); } function registerExternalController(controller) { spExternalControllers.push(controller); } function unregisterExternalController(controller) { var index = spExternalControllers.indexOf(controller); if (index !== -1) { spExternalControllers.splice(index, 1); } } function getExternalControllers() { return spExternalControllers; } function unregisterAllExternalController() { spExternalControllers = []; } function resetInitialSettings() { mediaInfoArr = []; mediaInfo = null; unregisterAllExternalController(); } function reset(errored, keepBuffers) { indexHandler.reset(); if (bufferController) { bufferController.reset(errored, keepBuffers); bufferController = null; } if (scheduleController) { scheduleController.reset(); scheduleController = null; } if (representationController) { representationController.reset(); representationController = null; } if (abrController) { abrController.unRegisterStreamType(type); } spExternalControllers.forEach(function (controller) { controller.reset(); }); resetInitialSettings(); type = null; stream = null; if (liveEdgeFinder) { liveEdgeFinder.reset(); liveEdgeFinder = null; } } function isUpdating() { return representationController ? representationController.isUpdating() : false; } function getType() { return type; } function getRepresentationController() { return representationController; } function getIndexHandler() { return indexHandler; } function getFragmentController() { return stream ? stream.getFragmentController() : null; } function getBuffer() { return bufferController.getBuffer(); } function setBuffer(buffer) { bufferController.setBuffer(buffer); } function getBufferController() { return bufferController; } function getFragmentModel() { return fragmentModel; } function getLiveEdgeFinder() { return liveEdgeFinder; } function getStreamInfo() { return stream ? stream.getStreamInfo() : null; } function addInbandEvents(events) { if (stream) { stream.addInbandEvents(events); } } function selectMediaInfo(newMediaInfo) { if (newMediaInfo !== mediaInfo && (!newMediaInfo || !mediaInfo || (newMediaInfo.type === mediaInfo.type))) { mediaInfo = newMediaInfo; } adapter.updateData(this); } function addMediaInfo(newMediaInfo, selectNewMediaInfo) { if (mediaInfoArr.indexOf(newMediaInfo) === -1) { mediaInfoArr.push(newMediaInfo); } if (selectNewMediaInfo) { this.selectMediaInfo(newMediaInfo); } } function getMediaInfoArr() { return mediaInfoArr; } function getMediaInfo() { return mediaInfo; } function getMediaSource() { return bufferController.getMediaSource(); } function setMediaSource(mediaSource) { bufferController.setMediaSource(mediaSource, getMediaInfo()); } function dischargePreBuffer() { bufferController.dischargePreBuffer(); } function getScheduleController() { return scheduleController; } function getRepresentationInfo(quality) { return adapter.getRepresentationInfo(representationController, quality); } function isBufferingCompleted() { if (bufferController) { return bufferController.getIsBufferingCompleted(); } return false; } function timeIsBuffered(time) { if (bufferController) { return bufferController.getRangeAt(time, 0) !== null; } return false; } function getBufferLevel() { return bufferController.getBufferLevel(); } function switchInitData(representationId, bufferResetEnabled) { if (bufferController) { bufferController.switchInitData(getStreamInfo().id, representationId, bufferResetEnabled); } } function createBuffer(previousBuffers) { return (bufferController.getBuffer() || bufferController.createBuffer(mediaInfo, previousBuffers)); } function switchTrackAsked() { scheduleController.switchTrackAsked(); } function createBufferControllerForType(type) { let controller = null; if (type === Constants.VIDEO || type === Constants.AUDIO) { controller = BufferController(context).create({ type: type, metricsModel: metricsModel, mediaPlayerModel: mediaPlayerModel, manifestModel: manifestModel, errHandler: errHandler, streamController: streamController, mediaController: mediaController, adapter: adapter, textController: textController, abrController: abrController, playbackController: playbackController, streamProcessor: instance }); } else { controller = TextBufferController(context).create({ type: type, mimeType: mimeType, metricsModel: metricsModel, mediaPlayerModel: mediaPlayerModel, manifestModel: manifestModel, errHandler: errHandler, streamController: streamController, mediaController: mediaController, adapter: adapter, textController: textController, abrController: abrController, playbackController: playbackController, streamProcessor: instance }); } return controller; } function getPlaybackController() { return playbackController; } instance = { initialize: initialize, isUpdating: isUpdating, getType: getType, getBufferController: getBufferController, getFragmentModel: getFragmentModel, getScheduleController: getScheduleController, getLiveEdgeFinder: getLiveEdgeFinder, getFragmentController: getFragmentController, getRepresentationController: getRepresentationController, getIndexHandler: getIndexHandler, getPlaybackController: getPlaybackController, getRepresentationInfo: getRepresentationInfo, getBufferLevel: getBufferLevel, switchInitData: switchInitData, isBufferingCompleted: isBufferingCompleted, timeIsBuffered: timeIsBuffered, createBuffer: createBuffer, getStreamInfo: getStreamInfo, selectMediaInfo: selectMediaInfo, addMediaInfo: addMediaInfo, switchTrackAsked: switchTrackAsked, getMediaInfoArr: getMediaInfoArr, getMediaInfo: getMediaInfo, getMediaSource: getMediaSource, setMediaSource: setMediaSource, dischargePreBuffer: dischargePreBuffer, getBuffer: getBuffer, setBuffer: setBuffer, registerExternalController: registerExternalController, unregisterExternalController: unregisterExternalController, getExternalControllers: getExternalControllers, unregisterAllExternalController: unregisterAllExternalController, addInbandEvents: addInbandEvents, reset: reset }; setup(); return instance; } StreamProcessor.__dashjs_factory_name = 'StreamProcessor'; export default FactoryMaker.getClassFactory(StreamProcessor);