/** * @license * Copyright 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ goog.provide('shaka.player.DashVideoSource'); goog.require('shaka.dash.MpdProcessor'); goog.require('shaka.dash.MpdRequest'); goog.require('shaka.dash.mpd'); goog.require('shaka.features'); goog.require('shaka.media.IAbrManager'); goog.require('shaka.media.SimpleAbrManager'); goog.require('shaka.player.DrmInfo'); goog.require('shaka.player.StreamVideoSource'); goog.require('shaka.util.EWMA'); goog.require('shaka.util.EWMABandwidthEstimator'); goog.require('shaka.util.FailoverUri'); goog.require('shaka.util.IBandwidthEstimator'); goog.require('shaka.util.TypedBind'); /** * Creates a DashVideoSource. * @param {string} mpdUrl The MPD URL. * @param {?shaka.player.DashVideoSource.ContentProtectionCallback} * interpretContentProtection A callback to interpret the ContentProtection * elements in the MPD. * @param {shaka.util.IBandwidthEstimator} estimator * @param {shaka.media.IAbrManager} abrManager * * @constructor * @struct * @extends {shaka.player.StreamVideoSource} * @exportDoc */ shaka.player.DashVideoSource = function(mpdUrl, interpretContentProtection, estimator, abrManager) { if (!estimator) { // For backward compatibility, provide an instance of the default // implementation if none is provided. estimator = new shaka.util.EWMABandwidthEstimator(); } if (!abrManager) { abrManager = new shaka.media.SimpleAbrManager(); } shaka.player.StreamVideoSource.call(this, null, estimator, abrManager); /** @private {string} */ this.mpdUrl_ = mpdUrl; /** @private {shaka.dash.mpd.Mpd} */ this.oldMpd_ = null; /** @private {?shaka.player.DashVideoSource.ContentProtectionCallback} */ this.interpretContentProtection_ = interpretContentProtection; /** @private {!Array.} */ this.captionsUrl_ = []; /** @private {!Array.} */ this.captionsLang_ = []; /** @private {!Array.} */ this.captionsMime_ = []; /** @private {shaka.util.FailoverUri.NetworkCallback} */ this.networkCallback_ = null; }; goog.inherits(shaka.player.DashVideoSource, shaka.player.StreamVideoSource); if (shaka.features.Dash) { goog.exportSymbol('shaka.player.DashVideoSource', shaka.player.DashVideoSource); } /** * A callback to the application to interpret DASH ContentProtection elements. * * The first parameter is the scheme ID URI. * The second parameter is the ContentProtection XML element. * * The callback should return an array of {@link shaka.player.DrmInfo.Config} * objects. A return value of null or an empty array indicates that the * ContentProtection XML element could not be understood by the application. An * empty {@link shaka.player.DrmInfo.Config} object or one with an empty * key system indicates that the content is unencrypted. * * Note: the 'cenc:pssh' element is automatically parsed by the library. * So, if the MPD specifies an explicit PSSH then the application does not have * to manually convert it into an initData value * (see {@link shaka.player.DrmInfo.Config}). * * @typedef {function(string, !Node): Array.} * @exportDoc */ shaka.player.DashVideoSource.ContentProtectionCallback; /** * Adds the given URL as a source for text tracks in addition to those * specified in the MPD. This has no effect after load(). * * @param {string} url The |url| of the file to load from. * @param {string=} opt_lang Optional language of the text track, * defaults to 'en'. * @param {string=} opt_mime Optional MIME type of the file, defaults * to 'text/vtt'. * @export */ shaka.player.DashVideoSource.prototype.addExternalCaptions = function(url, opt_lang, opt_mime) { this.captionsUrl_.push(url); this.captionsLang_.push(opt_lang || ''); this.captionsMime_.push(opt_mime || ''); }; /** * Sets the callback used to modify each segment request's URL and headers. * * @param {!shaka.util.FailoverUri.NetworkCallback} callback * @export */ shaka.player.DashVideoSource.prototype.setNetworkCallback = function(callback) { this.networkCallback_ = callback; }; /** @override */ shaka.player.DashVideoSource.prototype.destroy = function() { this.interpretContentProtection_ = null; this.networkCallback_ = null; this.oldMpd_ = null; shaka.player.StreamVideoSource.prototype.destroy.call(this); }; /** @override */ shaka.player.DashVideoSource.prototype.load = function() { var url = new shaka.util.FailoverUri(this.networkCallback_, [new goog.Uri(this.mpdUrl_)]); var mpdRequest = new shaka.dash.MpdRequest(url, this.mpdRequestTimeout); return mpdRequest.send().then(shaka.util.TypedBind(this, /** @param {!shaka.dash.mpd.Mpd} mpd */ function(mpd) { this.oldMpd_ = mpd; for (var i = 0; i < this.captionsUrl_.length; i++) { mpd.addExternalCaptions(this.captionsUrl_[i], this.captionsLang_[i], this.captionsMime_[i]); } if (!shaka.features.Live && mpd.type == 'dynamic') { var error = new Error('Live manifest support not enabled.'); error.type = 'app'; return Promise.reject(error); } var mpdProcessor = new shaka.dash.MpdProcessor(this.interpretContentProtection_); this.manifestInfo = mpdProcessor.process(mpd, this.networkCallback_); var baseClassLoad = shaka.player.StreamVideoSource.prototype.load; var p = baseClassLoad.call(this); return p; }) ); }; if (shaka.features.Live) { /** @override */ shaka.player.DashVideoSource.prototype.onUpdateManifest = function(url) { var mpdRequest = new shaka.dash.MpdRequest(url, this.mpdRequestTimeout); return mpdRequest.send().then(shaka.util.TypedBind(this, /** @param {!shaka.dash.mpd.Mpd} mpd */ function(mpd) { this.oldMpd_ = mpd; var mpdProcessor = new shaka.dash.MpdProcessor(this.interpretContentProtection_); var newManifestInfo = mpdProcessor.process(mpd, this.networkCallback_); return Promise.resolve(newManifestInfo); }) ); }; /** @override */ shaka.player.DashVideoSource.prototype.onUpdateLocalManifest = function() { shaka.asserts.assert(this.oldMpd_); var mpdProcessor = new shaka.dash.MpdProcessor(this.interpretContentProtection_); var newManifestInfo = mpdProcessor.process(/** @type {!shaka.dash.mpd.Mpd} */ (this.oldMpd_), this.networkCallback_); return Promise.resolve(newManifestInfo); }; }