Source: media/stream_info.js

/**
 * @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.media.ManifestInfo');
goog.provide('shaka.media.PeriodInfo');
goog.provide('shaka.media.StreamConfig');
goog.provide('shaka.media.StreamInfo');
goog.provide('shaka.media.StreamSetInfo');

goog.require('shaka.media.ISegmentIndexSource');
goog.require('shaka.media.SegmentInitSource');
goog.require('shaka.player.DrmInfo');
goog.require('shaka.util.FailoverUri');



/**
 * Creates a StreamInfo.
 *
 * @constructor
 * @struct
 */
shaka.media.StreamInfo = function() {
  /** @type {number} */
  this.uniqueId = shaka.media.StreamInfo.nextUniqueId_++;

  /**
   * The StreamInfo owns the SegmentIndexSource.
   * @type {shaka.media.ISegmentIndexSource}
   */
  this.segmentIndexSource = null;

  /**
   * The StreamInfo owns the SegmentInitSource.
   * @type {shaka.media.SegmentInitSource}
   */
  this.segmentInitSource = null;

  /**
   * An ID specified within the manifest, which is not guaranteed to be unique.
   * @type {?string}
   */
  this.id = null;

  /**
   * An offset, in seconds, to apply to each timestamp within each media
   * segment that's put in buffer.
   * @type {number}
   */
  this.timestampOffset = 0;

  /**
   * The stream's required bandwidth in bits per second.
   * @type {?number}
   */
  this.bandwidth = null;

  /** @type {?number} */
  this.width = null;

  /** @type {?number} */
  this.height = null;

  /** @type {string} */
  this.mimeType = '';

  /** @type {string} */
  this.codecs = '';

  /**
   * Key IDs, provided in the manifest, as hex strings.
   * @type {!Array.<string>}
   */
  this.keyIds = [];

  /**
   * True if the stream is
   * 1. unencrypted;
   * 2. encrypted but a usable license is expected to be acquired;
   * 3. encrypted and a usable license has already been acquired.
   * @type {boolean}
   */
  this.allowedByKeySystem = false;

  /**
   * True if the application has not restricted the stream.
   * @type {boolean}
   */
  this.allowedByApplication = true;
};


/**
 * The next unique ID to assign to a StreamInfo.
 * @private {number}
 */
shaka.media.StreamInfo.nextUniqueId_ = 0;


/**
 * Destroys this StreamInfo.
 */
shaka.media.StreamInfo.prototype.destroy = function() {
  if (this.segmentIndexSource) {
    this.segmentIndexSource.destroy();
    this.segmentIndexSource = null;
  }

  if (this.segmentInitSource) {
    this.segmentInitSource.destroy();
    this.segmentInitSource = null;
  }
};


/**
 * @return {boolean} True if the stream is allowed by both the key system and
 *     the application; otherwise, return false.
 */
shaka.media.StreamInfo.prototype.usable = function() {
  return this.allowedByKeySystem && this.allowedByApplication;
};


/**
 * Gets the StreamInfos's content type, which is the first part of the MIME
 * type.
 *
 * @return {string}
 */
shaka.media.StreamInfo.prototype.getContentType = function() {
  return this.mimeType.split('/')[0];
};


/**
 * Gets the StreamInfos's full MIME type, which is a combintation of the
 * StreamInfos's |mimeType| and |codecs| fields.
 *
 * @return {string}
 */
shaka.media.StreamInfo.prototype.getFullMimeType = function() {
  var fullMimeType = this.mimeType || '';
  if (this.codecs) {
    fullMimeType += '; codecs="' + this.codecs + '"';
  }
  return fullMimeType;
};



/**
 * Creates a StreamSetInfo.
 *
 * @constructor
 * @struct
 */
shaka.media.StreamSetInfo = function() {
  /** @type {number} */
  this.uniqueId = shaka.media.StreamSetInfo.nextUniqueId_++;

  /** @type {?string} */
  this.id = null;

  /** @type {string} */
  this.lang = '';

  /** @type {string} */
  this.contentType = '';

  /** @type {boolean} */
  this.main = false;

  /** @type {!Array.<!shaka.media.StreamInfo>} */
  this.streamInfos = [];

  /**
   * The DrmInfos that are compatible with each StreamInfo.
   * @type {!Array.<!shaka.player.DrmInfo>}
   */
  this.drmInfos = [];
};


/**
 * The next unique ID to assign to a StreamSetInfo.
 * @private {number}
 */
shaka.media.StreamSetInfo.nextUniqueId_ = 0;


/**
 * Destroys this StreamSetInfo.
 * @suppress {checkTypes} to set otherwise non-nullable types to null.
 */
shaka.media.StreamSetInfo.prototype.destroy = function() {
  for (var i = 0; i < this.streamInfos.length; ++i) {
    this.streamInfos[i].destroy();
  }
  this.streamInfos = null;
  this.drmInfos = null;
};


/**
 * @return {!Array.<shaka.media.StreamConfig>}
 */
shaka.media.StreamSetInfo.prototype.getConfigs = function() {
  var configList = [];
  for (var i = 0; i < this.drmInfos.length; ++i) {
    var cfg = new shaka.media.StreamConfig();
    cfg.id = this.uniqueId;
    cfg.drmInfo = this.drmInfos[i];
    cfg.contentType = this.contentType;
    cfg.fullMimeType = this.streamInfos.length ?
                       this.streamInfos[0].getFullMimeType() : '';
    configList.push(cfg);
  }
  return configList;
};



/**
 * Creates a PeriodInfo.
 *
 * @constructor
 * @struct
 */
shaka.media.PeriodInfo = function() {
  /** @type {?string} */
  this.id = null;

  /** @type {number} */
  this.start = 0;

  /**
   * The period's duration, in seconds.
   * @type {?number}
   */
  this.duration = null;

  /** @type {!Array.<!shaka.media.StreamSetInfo>} */
  this.streamSetInfos = [];
};


/**
 * @return {!Array.<shaka.media.StreamConfig>}
 */
shaka.media.PeriodInfo.prototype.getConfigs = function() {
  var configList = [];
  for (var i = 0; i < this.streamSetInfos.length; ++i) {
    configList.push.apply(configList, this.streamSetInfos[i].getConfigs());
  }
  return configList;
};


/**
 * Destroys this PeriodInfo.
 * @suppress {checkTypes} to set otherwise non-nullable types to null.
 */
shaka.media.PeriodInfo.prototype.destroy = function() {
  for (var i = 0; i < this.streamSetInfos.length; ++i) {
    this.streamSetInfos[i].destroy();
  }
  this.streamSetInfos = null;
};



/**
 * Creates a ManifestInfo, which is a manifest-format-agnostic description of
 * the content.
 *
 * @constructor
 * @struct
 */
shaka.media.ManifestInfo = function() {
  /** @type {boolean} */
  this.live = false;

  /**
   * The interval, in seconds, to poll the media server for an updated
   * manifest, or null if updates are not required.
   * @type {?number}
   */
  this.updatePeriod = null;

  /**
   * The location of the updated manifest, if any.
   * @type {shaka.util.FailoverUri}
   */
  this.updateUrl = null;

  /** @type {?number} */
  this.availabilityStartTime = null;

  /** @type {number} */
  this.minBufferTime = 0;

  /** @type {!Array.<!shaka.media.PeriodInfo>} */
  this.periodInfos = [];
};


/**
 * Destroys this ManifestInfo.
 * @suppress {checkTypes} to set otherwise non-nullable types to null.
 */
shaka.media.ManifestInfo.prototype.destroy = function() {
  for (var i = 0; i < this.periodInfos.length; ++i) {
    this.periodInfos[i].destroy();
  }
  this.periodInfos = null;
};



/**
 * Creates a StreamConfig.
 *
 * @constructor
 * @struct
 */
shaka.media.StreamConfig = function() {
  /** @type {number} */
  this.id = 0;

  /** @type {shaka.player.DrmInfo} */
  this.drmInfo = null;

  /** @type {string} */
  this.contentType = '';

  /** @type {string} */
  this.fullMimeType = '';
};


/**
 * Gets the StreamConfig's basic MIME type, which does not contain codec
 * information.
 *
 * @return {string}
 */
shaka.media.StreamConfig.prototype.getBasicMimeType = function() {
  return this.fullMimeType.split(';')[0];
};