mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-13 15:46:46 +03:00
feat!: Remove all deprecated things (#9162)
This commit is contained in:
committed by
GitHub
parent
9df740a006
commit
945c57ab77
@@ -71,7 +71,6 @@
|
||||
+../../lib/text/cue.js
|
||||
+../../lib/text/cue_region.js
|
||||
+../../lib/text/native_text_displayer.js
|
||||
+../../lib/text/simple_text_displayer.js
|
||||
+../../lib/text/speech_to_text.js
|
||||
+../../lib/text/stub_text_displayer.js
|
||||
+../../lib/text/text_engine.js
|
||||
@@ -95,7 +94,6 @@
|
||||
+../../lib/util/error.js
|
||||
+../../lib/util/event_manager.js
|
||||
+../../lib/util/exp_golomb.js
|
||||
+../../lib/util/fairplay_utils.js
|
||||
+../../lib/util/fake_event.js
|
||||
+../../lib/util/fake_event_target.js
|
||||
+../../lib/util/functional.js
|
||||
|
||||
@@ -75,9 +75,8 @@ destroyed.
|
||||
#### registration
|
||||
|
||||
At the end of the file, you should register the parser with the library. This
|
||||
will allow it to be used by the `Player`. There are two methods:
|
||||
`registerParserByExtension` and `registerParserByMime`. They both add parsers
|
||||
to a registry of manifest parsers. When the Player gets a URI, it will
|
||||
will allow it to be used by the `Player`. Use `registerParserByMime` to add the
|
||||
parser to the registry of manifest parsers. When the Player gets a URI, it will
|
||||
determine which parser to use. It will first try based on the file extension,
|
||||
then it will make a HEAD request to the URI to get back a MIME type.
|
||||
|
||||
|
||||
@@ -317,11 +317,6 @@ shaka.extern.IAdManager = class extends EventTarget {
|
||||
*/
|
||||
replaceServerSideAdTagParameters(adTagParameters) {}
|
||||
|
||||
/**
|
||||
* @return {!Array<!shaka.extern.AdCuePoint>}
|
||||
*/
|
||||
getServerSideCuePoints() {}
|
||||
|
||||
/**
|
||||
* @return {!Array<!shaka.extern.AdCuePoint>}
|
||||
*/
|
||||
|
||||
@@ -921,7 +921,6 @@ shaka.extern.HLSInterstitial;
|
||||
* endTime: number,
|
||||
* id: string,
|
||||
* timescale: number,
|
||||
* eventElement: Element,
|
||||
* eventNode: ?shaka.extern.xml.Node
|
||||
* }}
|
||||
*
|
||||
@@ -942,9 +941,6 @@ shaka.extern.HLSInterstitial;
|
||||
* Specifies an identifier for this instance of the region.
|
||||
* @property {number} timescale
|
||||
* Provides the timescale, in ticks per second.
|
||||
* @property {Element} eventElement
|
||||
* <b>DEPRECATED</b>: Use eventNode instead.
|
||||
* The XML element that defines the Event.
|
||||
* @property {?shaka.extern.xml.Node} eventNode
|
||||
* The XML element that defines the Event.
|
||||
* @exportDoc
|
||||
@@ -1399,7 +1395,6 @@ shaka.extern.xml.Node;
|
||||
* ignoreEmptyAdaptationSet: boolean,
|
||||
* ignoreMaxSegmentDuration: boolean,
|
||||
* keySystemsByURI: !Object<string, string>,
|
||||
* manifestPreprocessor: function(!Element),
|
||||
* manifestPreprocessorTXml: function(!shaka.extern.xml.Node),
|
||||
* sequenceMode: boolean,
|
||||
* useStreamOnceInPeriodFlattening: boolean,
|
||||
@@ -1459,11 +1454,6 @@ shaka.extern.xml.Node;
|
||||
* @property {Object<string, string>} keySystemsByURI
|
||||
* A map of scheme URI to key system name. Defaults to default key systems
|
||||
* mapping handled by Shaka.
|
||||
* @property {function(!Element)} manifestPreprocessor
|
||||
* <b>DEPRECATED</b>: Use manifestPreprocessorTXml instead.
|
||||
* Called immediately after the DASH manifest has been parsed into an
|
||||
* XMLDocument. Provides a way for applications to perform efficient
|
||||
* preprocessing of the manifest.
|
||||
* @property {function(!shaka.extern.xml.Node)} manifestPreprocessorTXml
|
||||
* Called immediately after the DASH manifest has been parsed into an
|
||||
* XMLDocument. Provides a way for applications to perform efficient
|
||||
@@ -1602,17 +1592,11 @@ shaka.extern.HlsManifestConfiguration;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* manifestPreprocessor: function(!Element),
|
||||
* manifestPreprocessorTXml: function(!shaka.extern.xml.Node),
|
||||
* sequenceMode: boolean,
|
||||
* keySystemsBySystemId: !Object<string, string>
|
||||
* }}
|
||||
*
|
||||
* @property {function(!Element)} manifestPreprocessor
|
||||
* <b>DEPRECATED</b>: Use manifestPreprocessorTXml instead.
|
||||
* Called immediately after the MSS manifest has been parsed into an
|
||||
* XMLDocument. Provides a way for applications to perform efficient
|
||||
* preprocessing of the manifest.
|
||||
* @property {function(!shaka.extern.xml.Node)} manifestPreprocessorTXml
|
||||
* Called immediately after the MSS manifest has been parsed into an
|
||||
* XMLDocument. Provides a way for applications to perform efficient
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
goog.provide('shaka.ads.AdManager');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.Player');
|
||||
goog.require('shaka.ads.AdsStats');
|
||||
goog.require('shaka.ads.ClientSideAdManager');
|
||||
@@ -736,19 +735,6 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array<!shaka.extern.AdCuePoint>}
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
getServerSideCuePoints() {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'AdManager.getServerSideCuePoints',
|
||||
'Please use getCuePoints function.');
|
||||
return this.getCuePoints();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array<!shaka.extern.AdCuePoint>}
|
||||
* @override
|
||||
@@ -942,410 +928,6 @@ shaka.ads.AdManager = class extends shaka.util.FakeEventTarget {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The event name for when a sequence of ads has been loaded.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.ADS_LOADED = 'ads-loaded';
|
||||
|
||||
/**
|
||||
* The event name for when an ad has started playing.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_STARTED = 'ad-started';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad playhead crosses first quartile.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_FIRST_QUARTILE = 'ad-first-quartile';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad playhead crosses midpoint.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_MIDPOINT = 'ad-midpoint';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad playhead crosses third quartile.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_THIRD_QUARTILE = 'ad-third-quartile';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad has completed playing.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_COMPLETE = 'ad-complete';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad has finished playing
|
||||
* (played all the way through, was skipped, or was unable to proceed
|
||||
* due to an error).
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_STOPPED = 'ad-stopped';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when an ad is skipped by the user.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_SKIPPED = 'ad-skipped';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad volume has changed.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_VOLUME_CHANGED = 'ad-volume-changed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad was muted.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_MUTED = 'ad-muted';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad was paused.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_PAUSED = 'ad-paused';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad was resumed after a pause.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_RESUMED = 'ad-resumed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad's skip status changes
|
||||
* (usually it becomes skippable when it wasn't before).
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_SKIP_STATE_CHANGED = 'ad-skip-state-changed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad's cue points (start/end markers)
|
||||
* have changed.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.CUEPOINTS_CHANGED = 'ad-cue-points-changed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the native IMA ad manager object has
|
||||
* loaded and become available.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.IMA_AD_MANAGER_LOADED = 'ima-ad-manager-loaded';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the native IMA stream manager object has
|
||||
* loaded and become available.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.IMA_STREAM_MANAGER_LOADED = 'ima-stream-manager-loaded';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad was clicked.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_CLICKED = 'ad-clicked';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when there is an update to the current ad's progress.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_PROGRESS = 'ad-progress';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad is buffering.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_BUFFERING = 'ad-buffering';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad's URL was hit.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_IMPRESSION = 'ad-impression';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad's duration changed.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_DURATION_CHANGED = 'ad-duration-changed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad was closed by the user.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_CLOSED = 'ad-closed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad data becomes available.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_LOADED = 'ad-loaded';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when all the ads were completed.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.ALL_ADS_COMPLETED = 'all-ads-completed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad changes from or to linear.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_LINEAR_CHANGED = 'ad-linear-changed';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad's metadata becomes available.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_METADATA = 'ad-metadata';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the ad display encountered a recoverable
|
||||
* error.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_RECOVERABLE_ERROR = 'ad-recoverable-error';
|
||||
|
||||
/**
|
||||
* The event name for when the ad manager dispatch errors.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_ERROR = 'ad-error';
|
||||
|
||||
/**
|
||||
* The event name for when the client side SDK signalled its readiness
|
||||
* to play a VPAID ad or an ad rule.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_BREAK_READY = 'ad-break-ready';
|
||||
|
||||
|
||||
/**
|
||||
* The event name for when the interaction callback for the ad was
|
||||
* triggered.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_INTERACTION = 'ad-interaction';
|
||||
|
||||
|
||||
/**
|
||||
* The name of the event for when an ad requires the main content to be paused.
|
||||
* Fired when the platform does not support multiple media elements.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_CONTENT_PAUSE_REQUESTED = 'ad-content-pause-requested';
|
||||
|
||||
|
||||
/**
|
||||
* The name of the event for when an ad requires the main content to be resumed.
|
||||
* Fired when the platform does not support multiple media elements.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_CONTENT_RESUME_REQUESTED = 'ad-content-resume-requested';
|
||||
|
||||
|
||||
/**
|
||||
* The name of the event for when an ad requires the video of the main content
|
||||
* to be attached.
|
||||
*
|
||||
* Deprecated, please use {@link shaka.ads.Utils}
|
||||
*
|
||||
* @const {string}
|
||||
* @export
|
||||
* @deprecated
|
||||
*/
|
||||
shaka.ads.AdManager.AD_CONTENT_ATTACH_REQUESTED = 'ad-content-attach-requested';
|
||||
|
||||
|
||||
/**
|
||||
* Set this is a default ad manager for the player.
|
||||
|
||||
+10
-34
@@ -11,6 +11,7 @@ goog.require('shaka.Player');
|
||||
goog.require('shaka.cast.CastSender');
|
||||
goog.require('shaka.cast.CastUtils');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.util.ArrayUtils');
|
||||
goog.require('shaka.util.Error');
|
||||
goog.require('shaka.util.EventManager');
|
||||
goog.require('shaka.util.FakeEvent');
|
||||
@@ -463,7 +464,6 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
const initState = {
|
||||
'video': {},
|
||||
'player': {},
|
||||
'playerAfterLoad': {},
|
||||
'manifest': this.localPlayer_.getAssetUri(),
|
||||
'startTime': null,
|
||||
'addThumbnailsTrackCalls': this.addThumbnailsTrackCalls_,
|
||||
@@ -492,14 +492,6 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
initState['player'][setter] = value;
|
||||
}
|
||||
|
||||
for (const pair of shaka.cast.CastUtils.PlayerInitAfterLoadState) {
|
||||
const getter = pair[0];
|
||||
const setter = pair[1];
|
||||
const value = /** @type {Object} */(this.localPlayer_)[getter]();
|
||||
|
||||
initState['playerAfterLoad'][setter] = value;
|
||||
}
|
||||
|
||||
return initState;
|
||||
}
|
||||
|
||||
@@ -564,9 +556,6 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
activeTextTrack = textTracks.find((t) => t.active);
|
||||
}
|
||||
|
||||
const isTextTrackVisible =
|
||||
this.sender_.get('player', 'isTextTrackVisible')();
|
||||
|
||||
// Now load the manifest, if present.
|
||||
if (assetUri) {
|
||||
// Don't autoplay the content until we finish setting up initial state.
|
||||
@@ -601,19 +590,16 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
this.localVideo_[name] = videoState[name];
|
||||
}
|
||||
|
||||
for (const pair of shaka.cast.CastUtils.PlayerInitAfterLoadState) {
|
||||
const getter = pair[0];
|
||||
const setter = pair[1];
|
||||
const value = this.sender_.get('player', getter)();
|
||||
/** @type {Object} */(this.localPlayer_)[setter](value);
|
||||
}
|
||||
|
||||
this.localPlayer_.setTextTrackVisibility(isTextTrackVisible);
|
||||
if (activeTextTrack) {
|
||||
this.localPlayer_.selectTextLanguage(
|
||||
activeTextTrack.language,
|
||||
activeTextTrack.roles,
|
||||
activeTextTrack.forced);
|
||||
const newTextTracks = this.localPlayer_.getTextTracks();
|
||||
const trackToSelect = newTextTracks.find((t) => {
|
||||
return t.language == activeTextTrack.language &&
|
||||
shaka.util.ArrayUtils.equal(t.roles, activeTextTrack.roles) &&
|
||||
t.forced == activeTextTrack.forced;
|
||||
});
|
||||
this.localPlayer_.selectTextTrack(trackToSelect);
|
||||
} else {
|
||||
this.localPlayer_.selectTextTrack();
|
||||
}
|
||||
|
||||
// Restore the original autoplay setting.
|
||||
@@ -819,16 +805,6 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
|
||||
if (name == 'getChapters') {
|
||||
// This does not follow our standard pattern (takes an arguments), and
|
||||
// therefore can't be proactively proxied and cached the way other
|
||||
// synchronous getters can.
|
||||
return () => {
|
||||
shaka.log.alwaysWarn(name + '() does not work while casting!');
|
||||
return [];
|
||||
};
|
||||
}
|
||||
} // if (this.sender_.isCasting())
|
||||
|
||||
// If we are casting, but the first update has not come in yet, use local
|
||||
|
||||
@@ -440,12 +440,6 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
|
||||
this.video_[k] = v;
|
||||
}
|
||||
|
||||
for (const k in initState['playerAfterLoad']) {
|
||||
const v = initState['playerAfterLoad'][k];
|
||||
// All player state vars are setters to be called.
|
||||
/** @type {Object} */(this.player_)[k](v);
|
||||
}
|
||||
|
||||
// Restore original autoplay setting.
|
||||
this.video_.autoplay = autoplay;
|
||||
if (initState['manifest']) {
|
||||
|
||||
@@ -305,8 +305,6 @@ shaka.cast.CastUtils.VideoVoidMethods = [
|
||||
shaka.cast.CastUtils.PlayerGetterMethods = new Map()
|
||||
// NOTE: The 'drmInfo' property is not proxied, as it is very large.
|
||||
.set('getAssetUri', 2)
|
||||
.set('getAudioLanguages', 4)
|
||||
.set('getAudioLanguagesAndRoles', 4)
|
||||
.set('getBufferFullness', 1)
|
||||
.set('getBufferedInfo', 2)
|
||||
.set('getExpiration', 2)
|
||||
@@ -315,13 +313,10 @@ shaka.cast.CastUtils.PlayerGetterMethods = new Map()
|
||||
// NOTE: The 'getManifestParserFactory' property is not proxied, as it would
|
||||
// not serialize.
|
||||
.set('getPlaybackRate', 2)
|
||||
.set('getTextLanguages', 4)
|
||||
.set('getTextLanguagesAndRoles', 4)
|
||||
.set('isAudioOnly', 10)
|
||||
.set('isBuffering', 1)
|
||||
.set('isInProgress', 1)
|
||||
.set('isLive', 10)
|
||||
.set('isTextTrackVisible', 1)
|
||||
.set('isVideoOnly', 10)
|
||||
.set('keySystem', 10)
|
||||
.set('seekRange', 1)
|
||||
@@ -380,16 +375,6 @@ shaka.cast.CastUtils.PlayerInitState = [
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Player getter and setter methods that are used to transfer state after
|
||||
* load() is resolved.
|
||||
* @const {!Array<!Array<string>>}
|
||||
*/
|
||||
shaka.cast.CastUtils.PlayerInitAfterLoadState = [
|
||||
['isTextTrackVisible', 'setTextTrackVisibility'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Player methods with no return value that are proxied while casting.
|
||||
* @const {!Array<string>}
|
||||
@@ -398,15 +383,11 @@ shaka.cast.CastUtils.PlayerVoidMethods = [
|
||||
'cancelTrickPlay',
|
||||
'configure',
|
||||
'configurationForLowLatency',
|
||||
'getChapters',
|
||||
'resetConfiguration',
|
||||
'retryStreaming',
|
||||
'selectAudioLanguage',
|
||||
'selectAudioTrack',
|
||||
'selectTextLanguage',
|
||||
'selectTextTrack',
|
||||
'selectVariantTrack',
|
||||
'selectVariantsByLabel',
|
||||
'selectVideoTrack',
|
||||
'setTextTrackVisibility',
|
||||
'trickPlay',
|
||||
|
||||
+1
-24
@@ -8,7 +8,6 @@ goog.provide('shaka.dash.DashParser');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.Uri');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.abr.Ewma');
|
||||
goog.require('shaka.dash.ContentProtection');
|
||||
goog.require('shaka.dash.MpdUtils');
|
||||
@@ -40,7 +39,6 @@ goog.require('shaka.util.StringUtils');
|
||||
goog.require('shaka.util.TimeUtils');
|
||||
goog.require('shaka.util.Timer');
|
||||
goog.require('shaka.util.TXml');
|
||||
goog.require('shaka.util.XmlUtils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -468,27 +466,7 @@ shaka.dash.DashParser = class {
|
||||
* @private
|
||||
*/
|
||||
async parseManifest_(data, finalManifestUri, rootElement) {
|
||||
let manifestData = data;
|
||||
const manifestPreprocessor = this.config_.dash.manifestPreprocessor;
|
||||
const defaultManifestPreprocessor =
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
|
||||
if (manifestPreprocessor != defaultManifestPreprocessor) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'manifest.dash.manifestPreprocessor configuration',
|
||||
'Please Use manifest.dash.manifestPreprocessorTXml instead.');
|
||||
const mpdElement =
|
||||
shaka.util.XmlUtils.parseXml(manifestData, rootElement);
|
||||
if (!mpdElement) {
|
||||
throw new shaka.util.Error(
|
||||
shaka.util.Error.Severity.CRITICAL,
|
||||
shaka.util.Error.Category.MANIFEST,
|
||||
shaka.util.Error.Code.DASH_INVALID_XML,
|
||||
finalManifestUri);
|
||||
}
|
||||
manifestPreprocessor(mpdElement);
|
||||
manifestData = shaka.util.XmlUtils.toArrayBuffer(mpdElement);
|
||||
}
|
||||
const mpd = shaka.util.TXml.parseXml(manifestData, rootElement);
|
||||
const mpd = shaka.util.TXml.parseXml(data, rootElement);
|
||||
if (!mpd) {
|
||||
throw new shaka.util.Error(
|
||||
shaka.util.Error.Severity.CRITICAL,
|
||||
@@ -3276,7 +3254,6 @@ shaka.dash.DashParser = class {
|
||||
endTime: endTime,
|
||||
id: eventNode.attributes['id'] || '',
|
||||
timescale: timescale,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
eventNode: TXml.cloneNode(eventNode),
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
goog.provide('shaka.dependencies');
|
||||
|
||||
goog.require('shaka.Deprecate');
|
||||
|
||||
/**
|
||||
* @export
|
||||
*/
|
||||
@@ -24,12 +22,6 @@ shaka.dependencies = class {
|
||||
if (!shaka.dependencies.Allowed[key]) {
|
||||
throw new Error(`${key} is not supported`);
|
||||
}
|
||||
if (key == shaka.dependencies.Allowed.muxjs) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'mux.js',
|
||||
'mux.js is no longer used in Shaka Player.');
|
||||
return;
|
||||
}
|
||||
shaka.dependencies.dependencies_.set(key, () => dep);
|
||||
}
|
||||
|
||||
@@ -56,7 +48,6 @@ shaka.dependencies = class {
|
||||
* @enum {string}
|
||||
*/
|
||||
shaka.dependencies.Allowed = {
|
||||
muxjs: 'muxjs',
|
||||
ISOBoxer: 'ISOBoxer',
|
||||
};
|
||||
|
||||
|
||||
+7
-30
@@ -6,7 +6,6 @@
|
||||
|
||||
goog.provide('shaka.lcevc.Dec');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.util.IReleasable');
|
||||
goog.require('shaka.util.ManifestParserUtils');
|
||||
|
||||
@@ -51,9 +50,6 @@ shaka.lcevc.Dec = class {
|
||||
/** @private {boolean} */
|
||||
this.isDualTrack_ = isDualTrack;
|
||||
|
||||
/** @private {boolean} */
|
||||
this.toBeDeprecated_ = false;
|
||||
|
||||
this.create_();
|
||||
}
|
||||
|
||||
@@ -114,18 +110,10 @@ shaka.lcevc.Dec = class {
|
||||
if (this.lcevcLib_.SupportObject.webGLSupport(this.canvas_)) {
|
||||
// Make sure the canvas is not hidden from a previous playback session.
|
||||
this.canvas_.classList.remove('shaka-hidden');
|
||||
// Initiate LCEVC Dec Library based on the type of module available.
|
||||
if (this.toBeDeprecated_) {
|
||||
this.dec_ = new this.lcevcLib_.LcevcDil(
|
||||
this.media_,
|
||||
this.canvas_,
|
||||
this.decConfig_);
|
||||
} else {
|
||||
this.dec_ = new this.lcevcLib_.LCEVCdec(
|
||||
this.media_,
|
||||
this.canvas_,
|
||||
this.decConfig_);
|
||||
}
|
||||
this.dec_ = new this.lcevcLib_.LCEVCdec(
|
||||
this.media_,
|
||||
this.canvas_,
|
||||
this.decConfig_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,16 +147,8 @@ shaka.lcevc.Dec = class {
|
||||
if (typeof LCEVCdec !== 'undefined') {
|
||||
this.lcevcLib_ = LCEVCdec;
|
||||
} else {
|
||||
if (typeof LcevcDil !== 'undefined') {
|
||||
this.lcevcLib_ = LcevcDil;
|
||||
this.toBeDeprecated_ = true;
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'LcevcDil',
|
||||
'lcevc_dil.js is deprecated, please use lcevc_dec.js instead');
|
||||
} else {
|
||||
shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
|
||||
return false;
|
||||
}
|
||||
shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Making Sure if there is a valid LCEVC Dec Library exists.
|
||||
@@ -225,10 +205,7 @@ shaka.lcevc.Dec = class {
|
||||
if (this.dec_) {
|
||||
this.dec_.setLevelSwitching(stream.id, true);
|
||||
this.dec_.setContainerFormat(containerFormat);
|
||||
// This functionality is only available on the LCEVC Dec Library.
|
||||
if (!this.toBeDeprecated_) {
|
||||
this.dec_.setStreamingFormat(streamingFormat);
|
||||
}
|
||||
this.dec_.setStreamingFormat(streamingFormat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
goog.provide('shaka.media.ManifestParser');
|
||||
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.device.DeviceFactory');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.util.Error');
|
||||
@@ -18,21 +17,6 @@ goog.require('shaka.util.Error');
|
||||
* @export
|
||||
*/
|
||||
shaka.media.ManifestParser = class {
|
||||
/**
|
||||
* Registers a manifest parser by file extension.
|
||||
*
|
||||
* @param {string} extension The file extension of the manifest.
|
||||
* @param {shaka.extern.ManifestParser.Factory} parserFactory The factory
|
||||
* used to create parser instances.
|
||||
* @export
|
||||
*/
|
||||
static registerParserByExtension(extension, parserFactory) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'ManifestParser.registerParserByExtension',
|
||||
'Please use an ManifestParser with registerParserByMime function.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a manifest parser by MIME type.
|
||||
*
|
||||
|
||||
+1
-23
@@ -7,7 +7,6 @@
|
||||
goog.provide('shaka.mss.MssParser');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.abr.Ewma');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.media.InitSegmentReference');
|
||||
@@ -27,7 +26,6 @@ goog.require('shaka.util.OperationManager');
|
||||
goog.require('shaka.util.PlayerConfiguration');
|
||||
goog.require('shaka.util.Timer');
|
||||
goog.require('shaka.util.TXml');
|
||||
goog.require('shaka.util.XmlUtils');
|
||||
|
||||
|
||||
/**
|
||||
@@ -298,27 +296,7 @@ shaka.mss.MssParser = class {
|
||||
* @private
|
||||
*/
|
||||
parseManifest_(data, finalManifestUri) {
|
||||
let manifestData = data;
|
||||
const manifestPreprocessor = this.config_.mss.manifestPreprocessor;
|
||||
const defaultManifestPreprocessor =
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
|
||||
if (manifestPreprocessor != defaultManifestPreprocessor) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'manifest.mss.manifestPreprocessor configuration',
|
||||
'Please Use manifest.mss.manifestPreprocessorTXml instead.');
|
||||
const mssElement =
|
||||
shaka.util.XmlUtils.parseXml(manifestData, 'SmoothStreamingMedia');
|
||||
if (!mssElement) {
|
||||
throw new shaka.util.Error(
|
||||
shaka.util.Error.Severity.CRITICAL,
|
||||
shaka.util.Error.Category.MANIFEST,
|
||||
shaka.util.Error.Code.MSS_INVALID_XML,
|
||||
finalManifestUri);
|
||||
}
|
||||
manifestPreprocessor(mssElement);
|
||||
manifestData = shaka.util.XmlUtils.toArrayBuffer(mssElement);
|
||||
}
|
||||
const mss = shaka.util.TXml.parseXml(manifestData, 'SmoothStreamingMedia');
|
||||
const mss = shaka.util.TXml.parseXml(data, 'SmoothStreamingMedia');
|
||||
if (!mss) {
|
||||
throw new shaka.util.Error(
|
||||
shaka.util.Error.Severity.CRITICAL,
|
||||
|
||||
+34
-955
File diff suppressed because it is too large
Load Diff
@@ -175,12 +175,10 @@ shaka.text.NativeTextDisplayer = class {
|
||||
if (trackId > -1) {
|
||||
this.player_.selectTextTrack(
|
||||
/** @type {!shaka.extern.TextTrack} */({id: trackId}));
|
||||
} else {
|
||||
this.player_.selectTextTrack();
|
||||
}
|
||||
}
|
||||
// The selectTextTrack() method does not accept null as parameter.
|
||||
// So we need to use setTextTrackVisibility() if no track selected.
|
||||
this.player_.setTextTrackVisibility(trackId > -1 &&
|
||||
this.trackNodes_.get(trackId).track.mode === 'showing');
|
||||
}).tickAfter(0);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*! @license
|
||||
* Shaka Player
|
||||
* Copyright 2016 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview
|
||||
*/
|
||||
|
||||
goog.provide('shaka.text.SimpleTextDisplayer');
|
||||
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.text.Utils');
|
||||
|
||||
|
||||
/**
|
||||
* A text displayer plugin using the browser's native VTTCue interface.
|
||||
*
|
||||
* @implements {shaka.extern.TextDisplayer}
|
||||
* @deprecated
|
||||
* @export
|
||||
*/
|
||||
shaka.text.SimpleTextDisplayer = class {
|
||||
/**
|
||||
* @param {HTMLMediaElement} video
|
||||
* @param {string} label
|
||||
*/
|
||||
constructor(video, label) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'SimpleTextDisplayer', 'Please migrate to NativeTextDisplayer');
|
||||
/** @private {HTMLMediaElement} */
|
||||
this.video_ = video;
|
||||
|
||||
/** @private {string} */
|
||||
this.textTrackLabel_ = label;
|
||||
|
||||
/** @private {TextTrack} */
|
||||
this.textTrack_ = null;
|
||||
|
||||
// TODO: Test that in all cases, the built-in CC controls in the video
|
||||
// element are toggling our TextTrack.
|
||||
|
||||
// If the video element has TextTracks, disable them. If we see one that
|
||||
// was created by a previous instance of Shaka Player, reuse it.
|
||||
for (const track of Array.from(this.video_.textTracks)) {
|
||||
if (track.kind === 'metadata' || track.kind === 'chapters') {
|
||||
continue;
|
||||
}
|
||||
// NOTE: There is no API available to remove a TextTrack from a video
|
||||
// element.
|
||||
track.mode = 'disabled';
|
||||
|
||||
if (track.label == this.textTrackLabel_) {
|
||||
this.textTrack_ = track;
|
||||
}
|
||||
}
|
||||
if (this.textTrack_) {
|
||||
this.textTrack_.mode = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
configure(config) {
|
||||
// Unused.
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
remove(start, end) {
|
||||
// Check that the displayer hasn't been destroyed.
|
||||
if (!this.textTrack_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const removeInRange = (cue) => {
|
||||
const inside = cue.startTime < end && cue.endTime > start;
|
||||
return inside;
|
||||
};
|
||||
|
||||
shaka.text.Utils.removeCuesFromTextTrack(this.textTrack_, removeInRange);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
append(cues) {
|
||||
if (!this.textTrack_) {
|
||||
return;
|
||||
}
|
||||
|
||||
shaka.text.Utils.appendCuesToTextTrack(this.textTrack_, cues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
destroy() {
|
||||
if (this.textTrack_) {
|
||||
const removeIt = (cue) => true;
|
||||
shaka.text.Utils.removeCuesFromTextTrack(this.textTrack_, removeIt);
|
||||
|
||||
// NOTE: There is no API available to remove a TextTrack from a video
|
||||
// element.
|
||||
this.textTrack_.mode = 'disabled';
|
||||
}
|
||||
|
||||
this.video_ = null;
|
||||
this.textTrack_ = null;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
isTextVisible() {
|
||||
if (!this.textTrack_) {
|
||||
return false;
|
||||
}
|
||||
return this.textTrack_.mode == 'showing';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
setTextVisibility(on) {
|
||||
if (on && !this.textTrack_) {
|
||||
this.createTextTrack_();
|
||||
}
|
||||
if (this.textTrack_) {
|
||||
this.textTrack_.mode = on ? 'showing' : 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
setTextLanguage(language) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @export
|
||||
*/
|
||||
enableTextDisplayer() {
|
||||
this.createTextTrack_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
createTextTrack_() {
|
||||
if (this.video_ && !this.textTrack_) {
|
||||
// As far as I can tell, there is no observable difference between setting
|
||||
// kind to 'subtitles' or 'captions' when creating the TextTrack object.
|
||||
// The individual text tracks from the manifest will still have their own
|
||||
// kinds which can be displayed in the app's UI.
|
||||
this.textTrack_ =
|
||||
this.video_.addTextTrack('subtitles', this.textTrackLabel_);
|
||||
this.textTrack_.mode = 'hidden';
|
||||
}
|
||||
}
|
||||
};
|
||||
+2
-15
@@ -7,7 +7,6 @@
|
||||
goog.provide('shaka.text.TextEngine');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.media.ClosedCaptionParser');
|
||||
goog.require('shaka.text.Cue');
|
||||
goog.require('shaka.util.BufferUtils');
|
||||
@@ -149,20 +148,8 @@ shaka.text.TextEngine = class {
|
||||
goog.asserts.assert(
|
||||
factory, 'Text type negotiation should have happened already');
|
||||
this.parser_ = factory();
|
||||
if (this.parser_.setSequenceMode) {
|
||||
this.parser_.setSequenceMode(sequenceMode);
|
||||
} else {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'Text parsers w/ setSequenceMode',
|
||||
'Text parsers should have a "setSequenceMode" method!');
|
||||
}
|
||||
if (this.parser_.setManifestType) {
|
||||
this.parser_.setManifestType(manifestType);
|
||||
} else {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'Text parsers w/ setManifestType',
|
||||
'Text parsers should have a "setManifestType" method!');
|
||||
}
|
||||
this.parser_.setSequenceMode(sequenceMode);
|
||||
this.parser_.setManifestType(manifestType);
|
||||
this.segmentRelativeVttTiming_ = segmentRelativeVttTiming;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*! @license
|
||||
* Shaka Player
|
||||
* Copyright 2016 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
goog.provide('shaka.util.FairPlayUtils');
|
||||
|
||||
goog.require('shaka.drm.FairPlay');
|
||||
|
||||
|
||||
/**
|
||||
* @summary A set of FairPlay utility functions. DEPRECATED: Please use
|
||||
* shaka.drm.FairPlay instead.
|
||||
* @deprecated
|
||||
* @export
|
||||
*/
|
||||
shaka.util.FairPlayUtils = class extends shaka.drm.FairPlay {
|
||||
// DEPRECATED
|
||||
};
|
||||
@@ -195,7 +195,6 @@ shaka.util.FakeEvent.EventName = {
|
||||
StateChanged: 'statechanged',
|
||||
Streaming: 'streaming',
|
||||
TextChanged: 'textchanged',
|
||||
TextTrackVisibility: 'texttrackvisibility',
|
||||
ThirdQuartile: 'thirdquartile',
|
||||
TimelineRegionAdded: 'timelineregionadded',
|
||||
TimelineRegionEnter: 'timelineregionenter',
|
||||
|
||||
@@ -149,8 +149,6 @@ shaka.util.PlayerConfiguration = class {
|
||||
'urn:uuid:3d5e6d35-9b9a-41e8-b843-dd3c6e72c42c':
|
||||
'com.huawei.wiseplay',
|
||||
},
|
||||
manifestPreprocessor:
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
||||
manifestPreprocessorTXml:
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
||||
sequenceMode: false,
|
||||
@@ -175,8 +173,6 @@ shaka.util.PlayerConfiguration = class {
|
||||
allowRangeRequestsToGuessMimeType: false,
|
||||
},
|
||||
mss: {
|
||||
manifestPreprocessor:
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
||||
manifestPreprocessorTXml:
|
||||
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
||||
sequenceMode: false,
|
||||
@@ -681,16 +677,6 @@ shaka.util.PlayerConfiguration = class {
|
||||
return selectedTracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Element} element
|
||||
* @return {!Element}
|
||||
*/
|
||||
static defaultManifestPreprocessor(element) {
|
||||
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
||||
[element],
|
||||
element);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!shaka.extern.xml.Node} element
|
||||
* @return {!shaka.extern.xml.Node}
|
||||
|
||||
@@ -894,39 +894,6 @@ shaka.util.TXml = class {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a tXml node to DOM element.
|
||||
* @param {shaka.extern.xml.Node} node
|
||||
* @return {!Element}
|
||||
*/
|
||||
static txmlNodeToDomElement(node) {
|
||||
const TXml = shaka.util.TXml;
|
||||
let namespace = '';
|
||||
const parts = node.tagName.split(':');
|
||||
if (parts.length > 0) {
|
||||
namespace = TXml.getKnownSchema(parts[0]);
|
||||
}
|
||||
const element = document.createElementNS(namespace, node.tagName);
|
||||
|
||||
for (const k in node.attributes) {
|
||||
const v = node.attributes[k];
|
||||
element.setAttribute(k, v);
|
||||
}
|
||||
|
||||
for (const child of node.children) {
|
||||
let childElement;
|
||||
if (typeof child == 'string') {
|
||||
childElement = new Text(child);
|
||||
} else {
|
||||
childElement = TXml.txmlNodeToDomElement(child);
|
||||
}
|
||||
element.appendChild(childElement);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones node and its children recursively. Skips parent.
|
||||
* @param {?shaka.extern.xml.Node} node
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
goog.provide('shaka.util.TsParser');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('shaka.Deprecate');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.util.ExpGolomb');
|
||||
goog.require('shaka.util.Id3Utils');
|
||||
@@ -523,28 +522,6 @@ shaka.util.TsParser = class {
|
||||
return pes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse AVC Nalus
|
||||
*
|
||||
* The code is based on hls.js
|
||||
* Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
|
||||
*
|
||||
* @param {shaka.extern.MPEG_PES} pes
|
||||
* @param {?shaka.extern.MPEG_PES=} nextPes
|
||||
* @return {!Array<shaka.extern.VideoNalu>}
|
||||
* @export
|
||||
*/
|
||||
parseAvcNalus(pes, nextPes) {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'TsParser.parseAvcNalus',
|
||||
'Please use parseNalus function instead.');
|
||||
const lastInfo = {
|
||||
nalu: null,
|
||||
state: null,
|
||||
};
|
||||
return this.parseNalus(pes, lastInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse AVC and HVC Nalus
|
||||
*
|
||||
@@ -868,23 +845,6 @@ shaka.util.TsParser = class {
|
||||
return nalus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the video resolution
|
||||
*
|
||||
* @return {{height: ?string, width: ?string}}
|
||||
* @export
|
||||
*/
|
||||
getVideoResolution() {
|
||||
shaka.Deprecate.deprecateFeature(5,
|
||||
'TsParser.getVideoResolution',
|
||||
'Please use getVideoInfo function instead.');
|
||||
const videoInfo = this.getVideoInfo();
|
||||
return {
|
||||
height: videoInfo.height,
|
||||
width: videoInfo.width,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the video information
|
||||
*
|
||||
|
||||
@@ -77,7 +77,6 @@ submenuopen
|
||||
textchanged
|
||||
textlang
|
||||
textrole
|
||||
texttrackvisibility
|
||||
thirdquartile
|
||||
timeandseekrangeupdated
|
||||
timelineregionadded
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@ Candidate features for future release cycles:
|
||||
- Background fetch for offline storage
|
||||
https://github.com/shaka-project/shaka-player/issues/879
|
||||
|
||||
v5.0
|
||||
v6.0
|
||||
- Conversion to Typescript (Smaller, more modular binary)
|
||||
|
||||
v4.17 - 2025 Q4
|
||||
v5.0 - 2025 Q4
|
||||
- Add automatic subtitles with translations (Experimental and disabled by default)
|
||||
https://github.com/shaka-project/shaka-player/issues/9110
|
||||
- Change dvvC box to free box for Dolby Vision workarounds
|
||||
|
||||
@@ -137,5 +137,4 @@ goog.require('shaka.ui.VRWebgl');
|
||||
goog.require('shaka.ui.Watermark');
|
||||
goog.require('shaka.util.Dom');
|
||||
goog.require('shaka.util.Error');
|
||||
goog.require('shaka.util.FairPlayUtils');
|
||||
goog.require('shaka.util.Iterables');
|
||||
|
||||
@@ -1181,7 +1181,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'PREROLL',
|
||||
schemeIdUri: 'urn:mpeg:dash:event:alternativeMPD:insert:2025',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1216,7 +1215,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'PREROLL',
|
||||
schemeIdUri: 'urn:mpeg:dash:event:alternativeMPD:replace:2025',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1253,7 +1251,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'PREROLL',
|
||||
schemeIdUri: 'urn:mpeg:dash:event:alternativeMPD:insert:2025',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1283,7 +1280,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'OVERLAY',
|
||||
schemeIdUri: 'urn:mpeg:dash:event:2012',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1356,7 +1352,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'OVERLAY',
|
||||
schemeIdUri: 'urn:mpeg:dash:event:2012',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1386,7 +1381,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'OVERLAY',
|
||||
schemeIdUri: 'urn:scte:dash:scte214-events',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
@@ -1477,7 +1471,6 @@ describe('Interstitial Ad manager', () => {
|
||||
id: 'OVERLAY',
|
||||
schemeIdUri: 'urn:scte:dash:scte214-events',
|
||||
eventNode,
|
||||
eventElement: TXml.txmlNodeToDomElement(eventNode),
|
||||
value: '',
|
||||
timescale: 1,
|
||||
};
|
||||
|
||||
@@ -316,7 +316,6 @@ describe('CastProxy', () => {
|
||||
// Local values that will be ignored:
|
||||
const fakeConfig = {key: 'value'};
|
||||
mockPlayer.getConfiguration.and.returnValue(fakeConfig);
|
||||
mockPlayer.isTextTrackVisible.and.returnValue(false);
|
||||
|
||||
// Set up the sender in casting mode:
|
||||
mockSender.isCasting.and.returnValue(true);
|
||||
@@ -326,7 +325,6 @@ describe('CastProxy', () => {
|
||||
const fakeConfig2 = {key2: 'value2'};
|
||||
const cache = {player: {
|
||||
getConfiguration: fakeConfig2,
|
||||
isTextTrackVisible: true,
|
||||
trickPlay: jasmine.createSpy('trickPlay'),
|
||||
}};
|
||||
mockSender.get.and.callFake((targetName, property) => {
|
||||
@@ -342,7 +340,6 @@ describe('CastProxy', () => {
|
||||
});
|
||||
|
||||
expect(proxy.getPlayer().getConfiguration()).toEqual(fakeConfig2);
|
||||
expect(proxy.getPlayer().isTextTrackVisible()).toBe(true);
|
||||
|
||||
// Call a method:
|
||||
expect(mockPlayer.trickPlay).not.toHaveBeenCalled();
|
||||
@@ -355,7 +352,6 @@ describe('CastProxy', () => {
|
||||
it('returns local values when we have no remote values yet', () => {
|
||||
const fakeConfig = {key: 'value'};
|
||||
mockPlayer.getConfiguration.and.returnValue(fakeConfig);
|
||||
mockPlayer.isTextTrackVisible.and.returnValue(true);
|
||||
|
||||
// Set up the sender in casting mode, but without any remote values:
|
||||
mockSender.isCasting.and.returnValue(true);
|
||||
@@ -371,7 +367,6 @@ describe('CastProxy', () => {
|
||||
|
||||
// Without remote values, we should still return the local ones.
|
||||
expect(proxy.getPlayer().getConfiguration()).toEqual(fakeConfig);
|
||||
expect(proxy.getPlayer().isTextTrackVisible()).toBe(true);
|
||||
|
||||
// Call a method:
|
||||
expect(mockPlayer.trickPlay).not.toHaveBeenCalled();
|
||||
@@ -494,7 +489,6 @@ describe('CastProxy', () => {
|
||||
},
|
||||
player: {
|
||||
getConfiguration: {key: 'value'},
|
||||
isTextTrackVisible: true,
|
||||
},
|
||||
};
|
||||
mockSender.get.and.callFake((targetName, property) => {
|
||||
@@ -509,7 +503,6 @@ describe('CastProxy', () => {
|
||||
it('transfers remote state back to local objects', async () => {
|
||||
// Nothing has been set yet:
|
||||
expect(mockPlayer.configure).not.toHaveBeenCalled();
|
||||
expect(mockPlayer.setTextTrackVisibility).not.toHaveBeenCalled();
|
||||
expect(mockVideo.loop).toBe(false);
|
||||
expect(mockVideo.playbackRate).toBe(1);
|
||||
|
||||
@@ -520,14 +513,11 @@ describe('CastProxy', () => {
|
||||
expect(mockPlayer.configure).toHaveBeenCalledWith(
|
||||
cache.player.getConfiguration);
|
||||
// Nothing else yet:
|
||||
expect(mockPlayer.setTextTrackVisibility).not.toHaveBeenCalled();
|
||||
expect(mockVideo.loop).toBe(false);
|
||||
expect(mockVideo.playbackRate).toBe(1);
|
||||
|
||||
// The rest is done async:
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(mockPlayer.setTextTrackVisibility).toHaveBeenCalledWith(
|
||||
cache.player.isTextTrackVisible);
|
||||
expect(mockVideo.loop).toBe(cache.video.loop);
|
||||
expect(mockVideo.playbackRate).toBe(cache.video.playbackRate);
|
||||
});
|
||||
@@ -580,8 +570,6 @@ describe('CastProxy', () => {
|
||||
expect(mockVideo.play).not.toHaveBeenCalled();
|
||||
|
||||
// State was still transferred, though:
|
||||
expect(mockPlayer.setTextTrackVisibility).toHaveBeenCalledWith(
|
||||
cache.player.isTextTrackVisible);
|
||||
expect(mockVideo.loop).toBe(cache.video.loop);
|
||||
expect(mockVideo.playbackRate).toBe(cache.video.playbackRate);
|
||||
});
|
||||
@@ -674,8 +662,7 @@ describe('CastProxy', () => {
|
||||
getAssetUri: jasmine.createSpy('getAssetUri'),
|
||||
getConfiguration: jasmine.createSpy('getConfiguration'),
|
||||
configure: jasmine.createSpy('configure'),
|
||||
isTextTrackVisible: jasmine.createSpy('isTextTrackVisible'),
|
||||
setTextTrackVisibility: jasmine.createSpy('setTextTrackVisibility'),
|
||||
selectTextTrack: jasmine.createSpy('selectTextTrack'),
|
||||
trickPlay: jasmine.createSpy('trickPlay'),
|
||||
destroy: jasmine.createSpy('destroy'),
|
||||
addEventListener: (eventName, listener) => {
|
||||
|
||||
@@ -99,9 +99,6 @@ filterDescribe('CastReceiver', castReceiverIntegrationSupport, () => {
|
||||
player: {
|
||||
configure: {},
|
||||
},
|
||||
playerAfterLoad: {
|
||||
setTextTrackVisibility: true,
|
||||
},
|
||||
video: {
|
||||
loop: true,
|
||||
playbackRate: 5,
|
||||
|
||||
@@ -249,9 +249,6 @@ filterDescribe('CastReceiver', castReceiverSupport, () => {
|
||||
player: {
|
||||
configure: fakeConfig,
|
||||
},
|
||||
playerAfterLoad: {
|
||||
setTextTrackVisibility: true,
|
||||
},
|
||||
video: {
|
||||
loop: true,
|
||||
playbackRate: 5,
|
||||
@@ -275,14 +272,11 @@ filterDescribe('CastReceiver', castReceiverSupport, () => {
|
||||
// App data next:
|
||||
expect(mockAppDataCallback).toHaveBeenCalledWith(fakeAppData);
|
||||
// Nothing else yet:
|
||||
expect(mockPlayer.setTextTrackVisibility).not.toHaveBeenCalled();
|
||||
expect(mockVideo.loop).toBe(false);
|
||||
expect(mockVideo.playbackRate).toBe(1);
|
||||
|
||||
// The rest is done async:
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(mockPlayer.setTextTrackVisibility).toHaveBeenCalledWith(
|
||||
fakeInitState.playerAfterLoad.setTextTrackVisibility);
|
||||
expect(mockVideo.loop).toBe(fakeInitState.video.loop);
|
||||
expect(mockVideo.playbackRate).toBe(fakeInitState.video.playbackRate);
|
||||
});
|
||||
@@ -392,8 +386,6 @@ filterDescribe('CastReceiver', castReceiverSupport, () => {
|
||||
expect(mockVideo.play).not.toHaveBeenCalled();
|
||||
|
||||
// State was still transferred, though:
|
||||
expect(mockPlayer.setTextTrackVisibility).toHaveBeenCalledWith(
|
||||
fakeInitState.playerAfterLoad.setTextTrackVisibility);
|
||||
expect(mockVideo.loop).toBe(fakeInitState.video.loop);
|
||||
expect(mockVideo.playbackRate).toBe(fakeInitState.video.playbackRate);
|
||||
});
|
||||
|
||||
@@ -1332,7 +1332,6 @@ describe('DashParser Live', () => {
|
||||
endTime: 60,
|
||||
id: '',
|
||||
timescale: 100,
|
||||
eventElement: jasmine.any(Element),
|
||||
eventNode: jasmine.any(Object),
|
||||
});
|
||||
expect(onTimelineRegionAddedSpy).toHaveBeenCalledWith({
|
||||
@@ -1342,7 +1341,6 @@ describe('DashParser Live', () => {
|
||||
endTime: 23,
|
||||
id: 'abc',
|
||||
timescale: 100,
|
||||
eventElement: jasmine.any(Element),
|
||||
eventNode: jasmine.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -365,7 +365,6 @@ describe('RegionObserver', () => {
|
||||
startTime: startTimeSeconds,
|
||||
endTime: endTimeSeconds,
|
||||
timescale: 1,
|
||||
eventElement: null,
|
||||
eventNode: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ describe('RegionTimeline', () => {
|
||||
startTime: startTimeSeconds,
|
||||
endTime: endTimeSeconds,
|
||||
timescale: 1,
|
||||
eventElement: null,
|
||||
eventNode: null,
|
||||
};
|
||||
}
|
||||
|
||||
+24
-165
@@ -306,145 +306,6 @@ describe('Player', () => {
|
||||
});
|
||||
}); // describe('getStats')
|
||||
|
||||
describe('setTextTrackVisibility', () => {
|
||||
// Repro for https://github.com/shaka-project/shaka-player/issues/1879.
|
||||
it('appends cues when enabled initially', async () => {
|
||||
let cues = [];
|
||||
/** @const {!shaka.test.FakeTextDisplayer} */
|
||||
const displayer = new shaka.test.FakeTextDisplayer();
|
||||
displayer.appendSpy.and.callFake((added) => {
|
||||
cues = cues.concat(added);
|
||||
});
|
||||
|
||||
player.configure('textDisplayFactory', () => displayer);
|
||||
|
||||
const preferredTextLanguage = 'fa'; // The same as in the content itself
|
||||
player.configure({preferredTextLanguage: preferredTextLanguage});
|
||||
|
||||
await player.load('test:sintel_realistic_compiled');
|
||||
|
||||
// Play until a time at which the external cues would be on screen.
|
||||
await video.play();
|
||||
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
||||
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
expect(displayer.isTextVisible()).toBe(true);
|
||||
expect(cues.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('appends cues for external text', async () => {
|
||||
let cues = [];
|
||||
/** @const {!shaka.test.FakeTextDisplayer} */
|
||||
const displayer = new shaka.test.FakeTextDisplayer();
|
||||
displayer.appendSpy.and.callFake((added) => {
|
||||
cues = cues.concat(added);
|
||||
});
|
||||
|
||||
player.configure('textDisplayFactory', () => displayer);
|
||||
|
||||
await player.load('test:sintel_no_text_compiled');
|
||||
const locationUri = new goog.Uri(location.href);
|
||||
const partialUri = new goog.Uri('/base/test/test/assets/text-clip.vtt');
|
||||
const absoluteUri = locationUri.resolve(partialUri);
|
||||
const newTrack = await player.addTextTrackAsync(
|
||||
absoluteUri.toString(), 'en', 'subtitles', 'text/vtt');
|
||||
|
||||
expect(player.getTextTracks()).toEqual([newTrack]);
|
||||
|
||||
player.selectTextTrack(newTrack);
|
||||
player.setTextTrackVisibility(true);
|
||||
await waiter.waitForEvent(player, 'texttrackvisibility');
|
||||
|
||||
// Play until a time at which the external cues would be on screen.
|
||||
await video.play();
|
||||
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 4, 20);
|
||||
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
expect(displayer.isTextVisible()).toBe(true);
|
||||
expect(cues.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// https://github.com/shaka-project/shaka-player/issues/2553
|
||||
it('does not change the selected track', async () => {
|
||||
await player.load('test:forced_subs_simulation_compiled');
|
||||
|
||||
// In this content, both text tracks have the same language and role, and
|
||||
// so should look identical in terms of choosing one to match a
|
||||
// preference. This is important to the test, so verify it first.
|
||||
const tracks = player.getTextTracks();
|
||||
expect(tracks[0].language).toBe(tracks[1].language);
|
||||
expect(tracks[0].roles).toEqual(tracks[1].roles);
|
||||
|
||||
const getTracksActive = () => player.getTextTracks().map((t) => t.active);
|
||||
|
||||
// If we choose a track first, then turn on text, the track should not
|
||||
// change. Try this with both tracks.
|
||||
player.setTextTrackVisibility(false);
|
||||
|
||||
player.selectTextTrack(tracks[0]);
|
||||
expect(getTracksActive()).toEqual([true, false]);
|
||||
player.setTextTrackVisibility(true);
|
||||
expect(getTracksActive()).toEqual([true, false]);
|
||||
|
||||
player.setTextTrackVisibility(false);
|
||||
|
||||
player.selectTextTrack(tracks[1]);
|
||||
expect(getTracksActive()).toEqual([false, true]);
|
||||
player.setTextTrackVisibility(true);
|
||||
expect(getTracksActive()).toEqual([false, true]);
|
||||
});
|
||||
|
||||
// https://github.com/shaka-project/shaka-player/issues/4821
|
||||
it('loads a single text stream', async () => {
|
||||
/** @type {!jasmine.Spy} */
|
||||
const textchanged = jasmine.createSpy('listener');
|
||||
|
||||
player.addEventListener('textchanged', Util.spyFunc(textchanged));
|
||||
|
||||
player.configure({preferredTextLanguage: 'en'});
|
||||
await player.load('test:sintel_no_text_compiled');
|
||||
|
||||
textchanged.calls.reset();
|
||||
|
||||
// Add preferred language text track.
|
||||
const locationUri = new goog.Uri(location.href);
|
||||
const partialUri = new goog.Uri('/base/test/test/assets/text-clip.vtt');
|
||||
const absoluteUri = locationUri.resolve(partialUri);
|
||||
await player.addTextTrackAsync(
|
||||
absoluteUri.toString(), 'en', 'subtitles', 'text/vtt');
|
||||
|
||||
expect(textchanged).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Add alternate language text track.
|
||||
// Two text tracks with same timings but different text
|
||||
// are necessary for test.
|
||||
const partialUri2 =
|
||||
new goog.Uri('/base/test/test/assets/text-clip-alt.vtt');
|
||||
const absoluteUri2 = locationUri.resolve(partialUri2);
|
||||
await player.addTextTrackAsync(
|
||||
absoluteUri2.toString(), 'fr', 'subtitles', 'text/vtt');
|
||||
|
||||
expect(textchanged).toHaveBeenCalledTimes(2);
|
||||
|
||||
const textTracks = player.getTextTracks();
|
||||
expect(textTracks.length).toBe(2);
|
||||
expect(textTracks[0].language).toBe('en');
|
||||
expect(textTracks[1].language).toBe('fr');
|
||||
|
||||
// Enable text visibility and immediately change language.
|
||||
// Only one set of cues should be active.
|
||||
// Cues should be of the selected language track.
|
||||
player.setTextTrackVisibility(true);
|
||||
player.selectTextLanguage('fr');
|
||||
video.currentTime = 5;
|
||||
await video.play();
|
||||
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
||||
|
||||
expect(video.textTracks[1].activeCues.length).toBe(1);
|
||||
expect(player.getTextTracks()[1].active).toBe(true);
|
||||
});
|
||||
}); // describe('setTextTrackVisibility')
|
||||
|
||||
describe('autoShowText', () => {
|
||||
async function textMatchesAudioDoesNot() {
|
||||
const preferredTextLanguage = 'fa'; // The same as in the content
|
||||
@@ -519,17 +380,20 @@ describe('Player', () => {
|
||||
|
||||
it('enables text if text matches and audio does not', async () => {
|
||||
await textMatchesAudioDoesNot();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
|
||||
it('disables text if text does not match', async () => {
|
||||
await textDoesNotMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
|
||||
it('disables text if both text and audio match', async () => {
|
||||
await textAndAudioMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
}); // IF_SUBTITLES_MAY_BE_NEEDED
|
||||
|
||||
@@ -542,17 +406,20 @@ describe('Player', () => {
|
||||
|
||||
it('enables text if text matches and audio does not', async () => {
|
||||
await textMatchesAudioDoesNot();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
|
||||
it('disables text if text does not match', async () => {
|
||||
await textDoesNotMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
|
||||
it('enables text if both text and audio match', async () => {
|
||||
await textAndAudioMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
}); // IF_PREFERRED_TEXT_LANGUAGE
|
||||
|
||||
@@ -563,17 +430,20 @@ describe('Player', () => {
|
||||
|
||||
it('enables text if text matches and audio does not', async () => {
|
||||
await textMatchesAudioDoesNot();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
|
||||
it('enables text if text does not match', async () => {
|
||||
await textDoesNotMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
|
||||
it('enables text if both text and audio match', async () => {
|
||||
await textAndAudioMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeDefined();
|
||||
});
|
||||
}); // ALWAYS
|
||||
|
||||
@@ -584,17 +454,20 @@ describe('Player', () => {
|
||||
|
||||
it('disables text if text matches and audio does not', async () => {
|
||||
await textMatchesAudioDoesNot();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
|
||||
it('disables text if text does not match', async () => {
|
||||
await textDoesNotMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
|
||||
it('disables text if both text and audio match', async () => {
|
||||
await textAndAudioMatch();
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
const activeTextTrack = player.getTextTracks().find((t) => t.active);
|
||||
expect(activeTextTrack).toBeUndefined();
|
||||
});
|
||||
}); // NEVER
|
||||
}); // AutoShowText
|
||||
@@ -724,20 +597,6 @@ describe('Player', () => {
|
||||
});
|
||||
}); // describe('TextDisplayer plugin')
|
||||
|
||||
describe('TextAndRoles', () => {
|
||||
// Regression Test. Makes sure that the language and role fields have been
|
||||
// properly exported from the player.
|
||||
it('exports language and roles fields', async () => {
|
||||
await player.load('test:sintel_compiled');
|
||||
const languagesAndRoles = player.getTextLanguagesAndRoles();
|
||||
expect(languagesAndRoles.length).toBeTruthy();
|
||||
for (const languageAndRole of languagesAndRoles) {
|
||||
expect(languageAndRole.language).not.toBeUndefined();
|
||||
expect(languageAndRole.role).not.toBeUndefined();
|
||||
}
|
||||
});
|
||||
}); // describe('TextAndRoles')
|
||||
|
||||
describe('streaming event', () => {
|
||||
// Calling switch early during load() caused a failed assertion in Player
|
||||
// and the track selection was ignored. Because this bug involved
|
||||
|
||||
@@ -110,7 +110,7 @@ describe('Player Src Equals', () => {
|
||||
|
||||
player.configure('preferredAudioLanguage', 'de');
|
||||
player.configure('preferredTextLanguage', 'el');
|
||||
player.setTextTrackVisibility(true);
|
||||
player.configure('autoShowText', shaka.config.AutoShowText.ALWAYS);
|
||||
|
||||
await loadWithSrcEquals(HLS_CONTENT_URI);
|
||||
|
||||
|
||||
@@ -277,19 +277,13 @@ describe('Player Src Equals', () => {
|
||||
// On platforms with audioTracks, such as Safari, we get one track, with
|
||||
// language set to whatever is in the mp4.
|
||||
if (video.audioTracks) {
|
||||
expect(player.getAudioLanguages()).toEqual(['en']);
|
||||
// Note that some browsers, such as Safari, say this is the 'main'
|
||||
// role, while others, such as Edge, do not. For the purposes of this
|
||||
// test, it doesn't matter what the role is.
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual(
|
||||
[{language: 'en', role: jasmine.any(String), label: null}]);
|
||||
expect(player.getAudioTracks())
|
||||
.toEqual([jasmine.objectContaining({language: 'en'})]);
|
||||
} else {
|
||||
expect(player.getAudioLanguages()).toEqual([]);
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual([]);
|
||||
expect(player.getAudioTracks()).toEqual([]);
|
||||
}
|
||||
|
||||
expect(player.getTextLanguages()).toEqual([]);
|
||||
expect(player.getTextLanguagesAndRoles()).toEqual([]);
|
||||
expect(player.getTextTracks()).toEqual([]);
|
||||
});
|
||||
|
||||
// Even though we loaded content using |src=| we should still be able to get
|
||||
|
||||
+60
-363
@@ -679,39 +679,6 @@ describe('Player', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setTextTrackVisibility', () => {
|
||||
beforeEach(() => {
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.addAudio(1);
|
||||
variant.addVideo(2);
|
||||
});
|
||||
manifest.addTextStream(3, (stream) => {
|
||||
stream.bandwidth = 100;
|
||||
stream.kind = 'caption';
|
||||
stream.label = 'Spanish';
|
||||
stream.language = 'es';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('load text stream if caption is visible', async () => {
|
||||
await player.setTextTrackVisibility(true);
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(streamingEngine.switchTextStream).toHaveBeenCalled();
|
||||
expect(shaka.test.Util.invokeSpy(streamingEngine.getCurrentTextStream))
|
||||
.not.toBe(null);
|
||||
});
|
||||
|
||||
it('does not load text stream if caption is invisible', async () => {
|
||||
await player.setTextTrackVisibility(false);
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(streamingEngine.switchTextStream).not.toHaveBeenCalled();
|
||||
expect(shaka.test.Util.invokeSpy(streamingEngine.getCurrentTextStream))
|
||||
.toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when config.streaming.preferNativeDash is set to true', () => {
|
||||
beforeAll(() => {
|
||||
shaka.media.ManifestParser.registerParserByMime(
|
||||
@@ -2494,13 +2461,15 @@ describe('Player', () => {
|
||||
expect(getActiveTextTrack().id).toBe(englishTextTrack.id);
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() takes precedence over ' +
|
||||
it('selectAudioTrack() takes precedence over ' +
|
||||
'preferredAudioLanguage', () => {
|
||||
// This preference is set in beforeEach, before load().
|
||||
expect(player.getConfiguration().preferredAudioLanguage).toBe('en');
|
||||
expect(getActiveVariantTrack().language).toBe('en');
|
||||
|
||||
player.selectAudioLanguage('es');
|
||||
const newAudioTrack = audioTracks.find((t) => t.language == 'es');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
|
||||
expect(streamingEngine.switchVariant).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchVariant.calls.argsFor(0);
|
||||
@@ -2509,10 +2478,13 @@ describe('Player', () => {
|
||||
expect(getActiveVariantTrack().language).toBe('es');
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() respects selected role', () => {
|
||||
it('selectAudioTrack() respects selected role', () => {
|
||||
expect(getActiveVariantTrack().roles).not.toContain('commentary');
|
||||
|
||||
player.selectAudioLanguage('en', 'commentary');
|
||||
const newAudioTrack = audioTracks.find((t) =>
|
||||
t.language == 'en' && t.roles.includes('commentary'));
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
|
||||
expect(streamingEngine.switchVariant).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchVariant.calls.argsFor(0);
|
||||
@@ -2521,115 +2493,61 @@ describe('Player', () => {
|
||||
expect(getActiveVariantTrack().roles).toContain('commentary');
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() ignores unplayable variants', () => {
|
||||
player.configure({
|
||||
restrictions: {minChannelsCount: 6},
|
||||
});
|
||||
player.selectAudioLanguage('es');
|
||||
expect(getActiveVariantTrack().channelsCount).toBe(6);
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() respects selected audio codec', () => {
|
||||
player.selectAudioLanguage('es', '', 0, 0, 'mp4a.40.2');
|
||||
it('selectAudioTrack() respects selected audio codec', () => {
|
||||
let newAudioTrack = audioTracks.find((t) =>
|
||||
t.language == 'es' && t.codecs == 'mp4a.40.2');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
expect(getActiveVariantTrack().audioCodec).toBe('mp4a.40.2');
|
||||
|
||||
player.selectAudioLanguage('es', '', 0, 0, 'ec-3');
|
||||
newAudioTrack = audioTracks.find((t) =>
|
||||
t.language == 'es' && t.codecs == 'ec-3');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
expect(getActiveVariantTrack().audioCodec).toBe('ec-3');
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() applies role only to audio', () => {
|
||||
it('selectAudioTrack() applies role only to audio', () => {
|
||||
expect(getActiveVariantTrack().roles).not.toContain('commentary');
|
||||
const videoRoles = getActiveVariantTrack().videoRoles;
|
||||
player.selectAudioLanguage('en', 'commentary');
|
||||
let newAudioTrack = audioTracks.find((t) =>
|
||||
t.language == 'en' && t.roles.includes('commentary'));
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
let args = streamingEngine.switchVariant.calls.argsFor(0);
|
||||
expect(args[0].audio.roles).toContain('commentary');
|
||||
expect(args[0].video.roles).toBe(videoRoles);
|
||||
|
||||
// Switch audio role from 'commentary' to 'main'.
|
||||
streamingEngine.switchVariant.calls.reset();
|
||||
player.selectAudioLanguage('en', 'main');
|
||||
newAudioTrack = audioTracks.find((t) =>
|
||||
t.language == 'en' && t.roles.includes('main'));
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
expect(streamingEngine.switchVariant).toHaveBeenCalled();
|
||||
args = streamingEngine.switchVariant.calls.argsFor(0);
|
||||
expect(args[0].audio.roles).toContain('main');
|
||||
expect(args[0].video.roles).toBe(videoRoles);
|
||||
});
|
||||
|
||||
it('selectAudioLanguage() does not change selected text track', () => {
|
||||
it('selectAudioTrack() does not change selected text track', () => {
|
||||
// This came up in a custom application that allows to select
|
||||
// from all tracks regardless of selected language.
|
||||
// We imitate this behavior by calling selectTextLanguage()
|
||||
// We imitate this behavior by calling selectTextTrack()
|
||||
// with one language and then selecting a track in a different
|
||||
// language.
|
||||
player.selectTextLanguage('en');
|
||||
const spanishTextTrack = textTracks.filter((t) => t.language == 'es')[0];
|
||||
player.selectTextTrack(spanishTextTrack);
|
||||
player.selectAudioLanguage('es');
|
||||
expect(getActiveTextTrack().id).toBe(spanishTextTrack.id);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/shaka-project/shaka-player/issues/2906
|
||||
// and https://github.com/shaka-project/shaka-player/issues/2909.
|
||||
it('selectAudioLanguage() can choose role-less tracks', async () => {
|
||||
// For this test, we use a different (and simpler) manifest.
|
||||
// Both audio tracks are English; one has a role, and one has no roles.
|
||||
// The role=description track comes first to reproduce the conditions in
|
||||
// #2909.
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(100, (variant) => {
|
||||
variant.bandwidth = 1300;
|
||||
variant.language = 'en';
|
||||
variant.addVideo(1, (stream) => {
|
||||
stream.originalId = 'video';
|
||||
stream.bandwidth = 1000;
|
||||
stream.width = 100;
|
||||
stream.height = 200;
|
||||
stream.frameRate = 1000000 / 42000;
|
||||
stream.pixelAspectRatio = '59:54';
|
||||
stream.roles = [];
|
||||
});
|
||||
variant.addAudio(2, (stream) => {
|
||||
stream.originalId = 'audio-en-description';
|
||||
stream.bandwidth = 100;
|
||||
stream.channelsCount = 2;
|
||||
stream.audioSamplingRate = 48000;
|
||||
stream.roles = ['description'];
|
||||
});
|
||||
});
|
||||
manifest.addVariant(101, (variant) => {
|
||||
variant.bandwidth = 2300;
|
||||
variant.language = 'en';
|
||||
variant.addExistingStream(1); // video
|
||||
variant.addAudio(3, (stream) => {
|
||||
stream.originalId = 'audio-en';
|
||||
stream.bandwidth = 100;
|
||||
stream.channelsCount = 2;
|
||||
stream.audioSamplingRate = 48000;
|
||||
stream.roles = [];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// No explicit preferred audio language is also part of #2909.
|
||||
player.configure('preferredAudioLanguage', undefined);
|
||||
|
||||
// Load again to get this test-specific manifest loaded.
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
|
||||
// #2909: The initial choice should be for the role-less track, even
|
||||
// though it is second in the manifest.
|
||||
expect(getActiveVariantTrack().audioRoles).toEqual([]);
|
||||
|
||||
player.selectAudioLanguage('en', 'description');
|
||||
expect(getActiveVariantTrack().audioRoles).toEqual(['description']);
|
||||
|
||||
// #2906: Selecting no particular role should prefer the track without any
|
||||
// roles.
|
||||
player.selectAudioLanguage('en');
|
||||
expect(getActiveVariantTrack().audioRoles).toEqual([]);
|
||||
let newTextTrack = textTracks.find((t) => t.language == 'en');
|
||||
player.selectTextTrack(newTextTrack);
|
||||
newTextTrack = textTracks.find((t) => t.language == 'es');
|
||||
player.selectTextTrack(newTextTrack);
|
||||
const newAudioTrack = audioTracks.find((t) => t.language == 'es');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
expect(getActiveTextTrack().id).toBe(newTextTrack.id);
|
||||
});
|
||||
|
||||
// https://github.com/shaka-project/shaka-player/issues/3262
|
||||
it('selectAudioLanguage() doesn\'t change resolution', () => {
|
||||
it('selectAudioTrack() doesn\'t change resolution', () => {
|
||||
player.configure('abr.enabled', false);
|
||||
abrManager.chooseIndex = 1;
|
||||
const lowResEn =
|
||||
@@ -2638,33 +2556,39 @@ describe('Player', () => {
|
||||
|
||||
// Switching to 'es' should keep the low-res stream and not choose the
|
||||
// high-res version.
|
||||
player.selectAudioLanguage('es');
|
||||
const newAudioTrack = audioTracks.find((t) => t.language == 'es');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
const lowResEs =
|
||||
variantTracks.filter((t) => t.language == 'es' && t.height == 200)[0];
|
||||
expect(getActiveVariantTrack().id).toBe(lowResEs.id);
|
||||
});
|
||||
|
||||
it('selectTextLanguage() does not change selected variant track', () => {
|
||||
it('selectTextTrack() does not change selected variant track', () => {
|
||||
// This came up in a custom application that allows to select
|
||||
// from all tracks regardless of selected language.
|
||||
// We imitate this behavior by calling selectAudioLanguage()
|
||||
// We imitate this behavior by calling selectAudioTrack()
|
||||
// with one language and then selecting a track in a different
|
||||
// language.
|
||||
player.selectAudioLanguage('es');
|
||||
const newAudioTrack = audioTracks.find((t) => t.language == 'es');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
const englishVariantTrack =
|
||||
variantTracks.filter((t) => t.language == 'en')[0];
|
||||
player.selectVariantTrack(englishVariantTrack);
|
||||
player.selectTextLanguage('es');
|
||||
const newTextTrack = textTracks.find((t) => t.language == 'es');
|
||||
player.selectTextTrack(newTextTrack);
|
||||
expect(getActiveVariantTrack().id).toBe(englishVariantTrack.id);
|
||||
});
|
||||
|
||||
it('selectTextLanguage() takes precedence over ' +
|
||||
it('selectTextTrack() takes precedence over ' +
|
||||
'preferredTextLanguage', () => {
|
||||
// This preference is set in beforeEach, before load().
|
||||
expect(player.getConfiguration().preferredTextLanguage).toBe('es');
|
||||
expect(getActiveTextTrack().language).toBe('es');
|
||||
|
||||
player.selectTextLanguage('en');
|
||||
const newTextTrack = textTracks.find((t) => t.language == 'en');
|
||||
player.selectTextTrack(newTextTrack);
|
||||
|
||||
expect(streamingEngine.switchTextStream).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchTextStream.calls.argsFor(0);
|
||||
@@ -2672,10 +2596,12 @@ describe('Player', () => {
|
||||
expect(getActiveTextTrack().language).toBe('en');
|
||||
});
|
||||
|
||||
it('selectTextLanguage() respects selected role', () => {
|
||||
it('selectTextTrack() respects selected role', () => {
|
||||
expect(getActiveTextTrack().roles).not.toContain('commentary');
|
||||
|
||||
player.selectTextLanguage('en', 'commentary');
|
||||
const newTextTrack = textTracks.find((t) =>
|
||||
t.language == 'en' && t.roles.includes('commentary'));
|
||||
player.selectTextTrack(newTextTrack);
|
||||
|
||||
expect(streamingEngine.switchTextStream).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchTextStream.calls.argsFor(0);
|
||||
@@ -2686,7 +2612,9 @@ describe('Player', () => {
|
||||
it('changing current audio language changes active stream', () => {
|
||||
expect(getActiveVariantTrack().language).not.toBe('es');
|
||||
expect(streamingEngine.switchVariant).not.toHaveBeenCalled();
|
||||
player.selectAudioLanguage('es');
|
||||
const newAudioTrack = audioTracks.find((t) => t.language == 'es');
|
||||
goog.asserts.assert(newAudioTrack, 'audio track must be non-null');
|
||||
player.selectAudioTrack(newAudioTrack);
|
||||
|
||||
expect(streamingEngine.switchVariant).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchVariant.calls.argsFor(0);
|
||||
@@ -2698,7 +2626,8 @@ describe('Player', () => {
|
||||
it('changing current text language changes active stream', () => {
|
||||
expect(getActiveTextTrack().language).not.toBe('en');
|
||||
expect(streamingEngine.switchTextStream).not.toHaveBeenCalled();
|
||||
player.selectTextLanguage('en');
|
||||
const newTextTrack = textTracks.find((t) => t.language == 'en');
|
||||
player.selectTextTrack(newTextTrack);
|
||||
|
||||
expect(streamingEngine.switchTextStream).toHaveBeenCalled();
|
||||
const args = streamingEngine.switchTextStream.calls.argsFor(0);
|
||||
@@ -2706,19 +2635,6 @@ describe('Player', () => {
|
||||
expect(getActiveTextTrack().language).toBe('en');
|
||||
});
|
||||
|
||||
// https://github.com/shaka-project/shaka-player/issues/2010
|
||||
it('changing text lang changes active stream when not streaming', () => {
|
||||
player.setTextTrackVisibility(false);
|
||||
|
||||
expect(getActiveTextTrack()).toBe(null);
|
||||
expect(streamingEngine.switchTextStream).not.toHaveBeenCalled();
|
||||
player.selectTextLanguage('en');
|
||||
player.setTextTrackVisibility(true);
|
||||
|
||||
expect(streamingEngine.switchTextStream).toHaveBeenCalled();
|
||||
expect(getActiveTextTrack().language).toBe('en');
|
||||
});
|
||||
|
||||
it('remembers the channel count when ABR is reenabled', () => {
|
||||
// We prefer 6 channels, and we are currently playing 6 channels.
|
||||
expect(player.getConfiguration().preferredAudioChannelCount).toBe(6);
|
||||
@@ -2875,48 +2791,6 @@ describe('Player', () => {
|
||||
expect(variantChanged).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('in selectTextLanguage', async () => {
|
||||
// The current text language.
|
||||
const currentLanguage = player.getTextTracks()
|
||||
.filter((t) => t.active)[0].language;
|
||||
const newLanguage = player.getTextTracks()
|
||||
.filter((t) => t.language != currentLanguage)[0].language;
|
||||
|
||||
// Call selectTextLanguage with a new language. Expect an event to
|
||||
// fire.
|
||||
player.selectTextLanguage(newLanguage);
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(textChanged).toHaveBeenCalled();
|
||||
textChanged.calls.reset();
|
||||
|
||||
// Call again with the same language, and expect no event to fire,
|
||||
// since nothing changed this time.
|
||||
player.selectTextLanguage(newLanguage);
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(textChanged).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('in selectAudioLanguage', async () => {
|
||||
// The current audio language.
|
||||
const currentLanguage = player.getVariantTracks()
|
||||
.filter((t) => t.active)[0].language;
|
||||
const newLanguage = player.getVariantTracks()
|
||||
.filter((t) => t.language != currentLanguage)[0].language;
|
||||
|
||||
// Call selectAudioLanguage with a new language. Expect an event to
|
||||
// fire.
|
||||
player.selectAudioLanguage(newLanguage);
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(variantChanged).toHaveBeenCalled();
|
||||
variantChanged.calls.reset();
|
||||
|
||||
// Call again with the same language, and expect no event to fire,
|
||||
// since nothing changed this time.
|
||||
player.selectAudioLanguage(newLanguage);
|
||||
await shaka.test.Util.shortDelay();
|
||||
expect(variantChanged).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('in selectAudioTrack', async () => {
|
||||
// New audio track.
|
||||
const newAudioTrack = player.getAudioTracks().find((t) => !t.active);
|
||||
@@ -2946,8 +2820,6 @@ describe('Player', () => {
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
|
||||
// Text was turned on during startup.
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
|
||||
expect(getActiveTextTrack()).toEqual(jasmine.objectContaining({
|
||||
id: 52,
|
||||
language: 'en',
|
||||
@@ -2993,48 +2865,6 @@ describe('Player', () => {
|
||||
await runTest(['en', 'es', 'pt-BR'], 'pt-PT', 2);
|
||||
});
|
||||
|
||||
it('enables text if its language differs from audio at start', async () => {
|
||||
// A manifest we can use to test text visibility.
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.language = 'pt';
|
||||
variant.addAudio(0);
|
||||
});
|
||||
manifest.addVariant(1, (variant) => {
|
||||
variant.language = 'en';
|
||||
variant.addAudio(1);
|
||||
});
|
||||
manifest.addTextStream(2, (stream) => {
|
||||
stream.language = 'pt';
|
||||
});
|
||||
manifest.addTextStream(3, (stream) => {
|
||||
stream.language = 'fr';
|
||||
});
|
||||
});
|
||||
|
||||
player.configure({
|
||||
preferredAudioLanguage: 'en',
|
||||
preferredTextLanguage: 'fr',
|
||||
});
|
||||
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
|
||||
// Text was turned on during startup.
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
|
||||
// Turn text back off.
|
||||
await player.setTextTrackVisibility(false);
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
|
||||
// Change text languages after startup.
|
||||
player.selectTextLanguage('pt');
|
||||
|
||||
// This should not turn text back on.
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
});
|
||||
|
||||
it('chooses an arbitrary language when none given', async () => {
|
||||
// The Player shouldn't allow changing between languages, so it should
|
||||
// choose an arbitrary language when none is given.
|
||||
@@ -4531,18 +4361,6 @@ describe('Player', () => {
|
||||
abrManager.switchCallback(manifest.variants[2]);
|
||||
});
|
||||
|
||||
describe('isTextTrackVisible', () => {
|
||||
it('does not throw before load', () => {
|
||||
player.isTextTrackVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setTextTrackVisibility', () => {
|
||||
it('does not throw before load', async () => {
|
||||
await player.setTextTrackVisibility(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAudioOnly', () => {
|
||||
it('detects audio-only content', async () => {
|
||||
// False before we've loaded anything.
|
||||
@@ -4697,8 +4515,6 @@ describe('Player', () => {
|
||||
});
|
||||
|
||||
describe('language methods', () => {
|
||||
let videoOnlyManifest;
|
||||
|
||||
beforeEach(() => {
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(1, (variant) => {
|
||||
@@ -4753,125 +4569,6 @@ describe('Player', () => {
|
||||
stream.roles = ['main', 'subtitle'];
|
||||
});
|
||||
});
|
||||
|
||||
videoOnlyManifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(1, (variant) => {
|
||||
variant.bandwidth = 400;
|
||||
variant.addVideo(1);
|
||||
});
|
||||
manifest.addVariant(2, (variant) => {
|
||||
variant.bandwidth = 800;
|
||||
variant.addVideo(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('get*Languages', () => {
|
||||
it('returns a list of languages', async () => {
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(player.getAudioLanguages()).toEqual(['fr', 'en', 'de']);
|
||||
expect(player.getTextLanguages()).toEqual(['es', 'en']);
|
||||
});
|
||||
|
||||
it('returns "und" for video-only tracks', async () => {
|
||||
manifest = videoOnlyManifest;
|
||||
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(player.getAudioLanguages()).toEqual(['und']);
|
||||
expect(player.getTextLanguages()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAudioLanguagesAndRoles', () => {
|
||||
it('ignores video roles and labels', async () => {
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.language = 'en';
|
||||
variant.addVideo(1, (stream) => {
|
||||
stream.roles = ['video-only-role'];
|
||||
stream.label = 'should not show up';
|
||||
});
|
||||
variant.addAudio(2, (stream) => {
|
||||
stream.roles = ['audio-only-role'];
|
||||
stream.language = 'en';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual([
|
||||
{language: 'en', role: 'audio-only-role', label: null},
|
||||
]);
|
||||
});
|
||||
|
||||
it('lists all language-role combinations', async () => {
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual([
|
||||
{language: 'fr', role: '', label: null},
|
||||
{language: 'en', role: 'main', label: null},
|
||||
{language: 'en', role: 'commentary', label: null},
|
||||
{language: 'de', role: 'foo', label: null},
|
||||
{language: 'de', role: 'bar', label: null},
|
||||
]);
|
||||
});
|
||||
|
||||
it('associates audio streams with their labels', async () => {
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.language = 'en';
|
||||
variant.addAudio(1, (stream) => {
|
||||
stream.roles = ['role-1'];
|
||||
stream.language = 'en';
|
||||
stream.label = 'english';
|
||||
});
|
||||
});
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.language = 'es';
|
||||
variant.addAudio(2, (stream) => {
|
||||
stream.roles = ['role-2', 'role-3'];
|
||||
stream.language = 'es';
|
||||
stream.label = 'spanish';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual([
|
||||
{language: 'en', role: 'role-1', label: 'english'},
|
||||
{language: 'es', role: 'role-2', label: 'spanish'},
|
||||
{language: 'es', role: 'role-3', label: 'spanish'},
|
||||
]);
|
||||
});
|
||||
|
||||
it('uses "und" for video-only tracks', async () => {
|
||||
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
||||
manifest.addVariant(0, (variant) => {
|
||||
variant.addVideo(1, (stream) => {
|
||||
stream.roles = ['video-only-role'];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(player.getAudioLanguagesAndRoles()).toEqual([
|
||||
{language: 'und', role: '', label: null},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTextLanguageAndRoles', () => {
|
||||
it('lists all language-role combinations', async () => {
|
||||
await player.load(fakeManifestUri, 0, fakeMimeType);
|
||||
expect(player.getTextLanguagesAndRoles()).toEqual([
|
||||
{language: 'es', role: 'baz', label: null},
|
||||
{language: 'es', role: 'qwerty', label: null},
|
||||
{language: 'en', role: 'main', label: null},
|
||||
{language: 'en', role: 'caption', label: null},
|
||||
{language: 'en', role: 'subtitle', label: null},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getThumbnails', () => {
|
||||
|
||||
@@ -64,11 +64,6 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
|
||||
/** @override */
|
||||
replaceServerSideAdTagParameters(adTagParameters) {}
|
||||
|
||||
/** @override */
|
||||
getServerSideCuePoints() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @override */
|
||||
getCuePoints() {
|
||||
return [];
|
||||
|
||||
@@ -348,13 +348,15 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
||||
getMediaElement: () => this.video,
|
||||
getLoadMode: () => shaka.Player.LoadMode.MEDIA_SOURCE,
|
||||
getTextTracks: () => textTracks,
|
||||
selectTextTrack: ({id}) => {
|
||||
const track = textTracks.find((t) => t.id === id);
|
||||
expect(track).toBeTruthy();
|
||||
track.active = true;
|
||||
selectTextTrack: (track) => {
|
||||
if (track) {
|
||||
const activeTrack = textTracks.find((t) => t.id === track.id);
|
||||
expect(activeTrack).toBeTruthy();
|
||||
this.textDisplayer.setTextVisibility(true);
|
||||
} else {
|
||||
this.textDisplayer.setTextVisibility(false);
|
||||
}
|
||||
},
|
||||
setTextTrackVisibility: (visible) =>
|
||||
this.textDisplayer.setTextVisibility(visible),
|
||||
};
|
||||
|
||||
this.video = shaka.test.UiUtils.createVideoElement();
|
||||
|
||||
@@ -44,6 +44,9 @@ shaka.test.FakeAbrManager = class {
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.disable = jasmine.createSpy('disable');
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.trySuggestStreams = jasmine.createSpy('trySuggestStreams');
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.segmentDownloaded = jasmine.createSpy('segmentDownloaded');
|
||||
|
||||
@@ -63,6 +66,12 @@ shaka.test.FakeAbrManager = class {
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.playbackRateChanged = jasmine.createSpy('playbackRateChanged');
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.setMediaElement = jasmine.createSpy('setMediaElement');
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.setCmsdManager = jasmine.createSpy('setCmsdManager');
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
this.configure = jasmine.createSpy('configure');
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@ describe('NativeTextDisplayer', () => {
|
||||
expect(track).toBeTruthy();
|
||||
track.active = true;
|
||||
},
|
||||
setTextTrackVisibility: (visible) =>
|
||||
displayer.setTextVisibility(visible),
|
||||
};
|
||||
video = new shaka.test.FakeVideo();
|
||||
/** @suppress {checkTypes} */
|
||||
|
||||
@@ -1,469 +0,0 @@
|
||||
/*! @license
|
||||
* Shaka Player
|
||||
* Copyright 2016 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
describe('SimpleTextDisplayer', () => {
|
||||
const originalVTTCue = window.VTTCue;
|
||||
const Cue = shaka.text.Cue;
|
||||
const SimpleTextDisplayer = shaka.text.SimpleTextDisplayer;
|
||||
|
||||
/** @type {!shaka.test.FakeVideo} */
|
||||
let video;
|
||||
/** @type {!shaka.test.FakeTextTrack} */
|
||||
let mockTrack;
|
||||
/** @type {!shaka.text.SimpleTextDisplayer} */
|
||||
let displayer;
|
||||
|
||||
beforeEach(() => {
|
||||
video = new shaka.test.FakeVideo();
|
||||
displayer = new SimpleTextDisplayer(video, shaka.Player.TextTrackLabel);
|
||||
displayer.enableTextDisplayer();
|
||||
|
||||
expect(video.textTracks.length).toBe(1);
|
||||
mockTrack = /** @type {!shaka.test.FakeTextTrack} */ (video.textTracks[0]);
|
||||
expect(mockTrack).toBeTruthy();
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @param {string} text
|
||||
*/
|
||||
function FakeVTTCue(start, end, text) {
|
||||
this.startTime = start;
|
||||
this.endTime = end;
|
||||
this.text = text;
|
||||
this.snapToLines = true;
|
||||
this.vertical = undefined;
|
||||
this.line = 'auto';
|
||||
this.position = 'auto';
|
||||
}
|
||||
window.VTTCue = /** @type {?} */(FakeVTTCue);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await displayer.destroy();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
window.VTTCue = originalVTTCue;
|
||||
});
|
||||
|
||||
describe('append', () => {
|
||||
it('sorts cues before inserting', () => {
|
||||
// See: https://bit.ly/2K9VX3s
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 10, endTime: 20, text: 'Test1'},
|
||||
{startTime: 20, endTime: 30, text: 'Test2'},
|
||||
{startTime: 30, endTime: 40, text: 'Test3'},
|
||||
],
|
||||
[
|
||||
new shaka.text.Cue(20, 30, 'Test2'),
|
||||
new shaka.text.Cue(30, 40, 'Test3'),
|
||||
new shaka.text.Cue(10, 20, 'Test1'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('appends equal time cues in reverse order', () => {
|
||||
// Regression test for https://github.com/shaka-project/shaka-player/issues/848
|
||||
|
||||
// When VTTCue is seen as the real thing (because of the presence of
|
||||
// VTTCue.prototype.line), then the reverse-order behavior comes into
|
||||
// play. The reverse order is only needed because of VTTCue spec
|
||||
// behavior.
|
||||
|
||||
// First we test the behavior with a real-looking VTTCue (in which
|
||||
// prototype.line merely exists). This simulates Chrome, Firefox, and
|
||||
// Safari.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
window.VTTCue.prototype['line'] = 'auto';
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 20, endTime: 40, text: 'Test1'},
|
||||
{startTime: 20, endTime: 40, text: 'Test2'},
|
||||
{startTime: 20, endTime: 40, text: 'Test3'},
|
||||
],
|
||||
[
|
||||
// Reverse order to compensate for the way line='auto' is
|
||||
// implemented in browsers.
|
||||
new shaka.text.Cue(20, 40, 'Test3'),
|
||||
new shaka.text.Cue(20, 40, 'Test2'),
|
||||
new shaka.text.Cue(20, 40, 'Test1'),
|
||||
]);
|
||||
|
||||
// Next we test the behavior with a VTTCue which is seen as a cheap
|
||||
// polyfill (in which prototype.line does not exist). This simulates
|
||||
// legacy Edge.
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
delete window.VTTCue.prototype['line'];
|
||||
displayer.remove(0, Infinity); // Clear the cues from above.
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 20, endTime: 40, text: 'Test1'},
|
||||
{startTime: 20, endTime: 40, text: 'Test2'},
|
||||
{startTime: 20, endTime: 40, text: 'Test3'},
|
||||
],
|
||||
[
|
||||
// Input order, since the displayer sees this as a fake VTTCue
|
||||
// implementation.
|
||||
new shaka.text.Cue(20, 40, 'Test1'),
|
||||
new shaka.text.Cue(20, 40, 'Test2'),
|
||||
new shaka.text.Cue(20, 40, 'Test3'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('appends nested cues', () => {
|
||||
const shakaCue = new shaka.text.Cue(10, 20, '');
|
||||
const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1 ');
|
||||
const nestedCue2 = new shaka.text.Cue(10, 20, 'Test2');
|
||||
|
||||
shakaCue.nestedCues = [nestedCue1, nestedCue2];
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 10, endTime: 20, text: 'Test1 Test2'},
|
||||
],
|
||||
[shakaCue]);
|
||||
});
|
||||
|
||||
it('flattens nested cue payloads correctly', () => {
|
||||
const level0ContainerCue = new shaka.text.Cue(10, 30, '');
|
||||
level0ContainerCue.isContainer = true;
|
||||
|
||||
const level1NonContainerCueA = new shaka.text.Cue(10, 20, '');
|
||||
const level1NonContainerCueB = new shaka.text.Cue(20, 30, '');
|
||||
|
||||
// Add a trailing whitespace character to get a space-delimited expected
|
||||
// result.
|
||||
const cueANestedCue0 = new shaka.text.Cue(10, 20, 'Cue A Test0 ');
|
||||
const cueANestedCue1 = new shaka.text.Cue(10, 20, 'Cue A Test1');
|
||||
const cueBNestedCue0 = new shaka.text.Cue(20, 30, 'Cue B Test0 ');
|
||||
const cueBNestedCue1 = new shaka.text.Cue(20, 30, 'Cue B Test1');
|
||||
|
||||
level1NonContainerCueA.nestedCues = [cueANestedCue0, cueANestedCue1];
|
||||
level1NonContainerCueB.nestedCues = [cueBNestedCue0, cueBNestedCue1];
|
||||
level0ContainerCue.nestedCues =
|
||||
[level1NonContainerCueA, level1NonContainerCueB];
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 10, endTime: 20, text: 'Cue A Test0 Cue A Test1'},
|
||||
{startTime: 20, endTime: 30, text: 'Cue B Test0 Cue B Test1'},
|
||||
],
|
||||
[level0ContainerCue]);
|
||||
});
|
||||
|
||||
// Regression test for b/159050711
|
||||
it('maintains the styles of the parent cue', () => {
|
||||
const shakaCue = new shaka.text.Cue(10, 20, '');
|
||||
const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1 ');
|
||||
const nestedCue2 = new shaka.text.Cue(10, 20, 'Test2');
|
||||
|
||||
shakaCue.nestedCues = [nestedCue1, nestedCue2];
|
||||
|
||||
shakaCue.lineAlign = Cue.lineAlign.CENTER;
|
||||
nestedCue1.lineAlign = Cue.lineAlign.START;
|
||||
nestedCue2.lineAlign = Cue.lineAlign.START;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 10,
|
||||
endTime: 20,
|
||||
text: 'Test1 Test2',
|
||||
lineAlign: 'center',
|
||||
},
|
||||
],
|
||||
[shakaCue]);
|
||||
});
|
||||
|
||||
it('creates style tags for cues with underline/italics/bold', () => {
|
||||
const shakaCue = new shaka.text.Cue(10, 20, '');
|
||||
|
||||
// First cue is underlined and italicized.
|
||||
const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1');
|
||||
nestedCue1.fontStyle = shaka.text.Cue.fontStyle.ITALIC;
|
||||
nestedCue1.textDecoration.push(shaka.text.Cue.textDecoration.UNDERLINE);
|
||||
|
||||
// Second cue is italicized and bolded.
|
||||
const nestedCue2 = new shaka.text.Cue(10, 20, 'Test2');
|
||||
nestedCue2.fontStyle = shaka.text.Cue.fontStyle.ITALIC;
|
||||
nestedCue2.fontWeight = shaka.text.Cue.fontWeight.BOLD;
|
||||
|
||||
// Third cue has no bold, italics, or underline.
|
||||
const nestedCue3 = new shaka.text.Cue(10, 20, 'Test3');
|
||||
|
||||
// Fourth cue is only underlined.
|
||||
const nestedCue4 = new shaka.text.Cue(10, 20, 'Test4');
|
||||
nestedCue4.textDecoration.push(shaka.text.Cue.textDecoration.UNDERLINE);
|
||||
|
||||
const expectedText =
|
||||
'<i><u>Test1</u></i><b><i>Test2</i></b>Test3<u>Test4</u>';
|
||||
shakaCue.nestedCues = [nestedCue1, nestedCue2, nestedCue3, nestedCue4];
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 10, endTime: 20, text: expectedText},
|
||||
],
|
||||
[shakaCue]);
|
||||
});
|
||||
|
||||
it('adds linebreaks when a linebreak cue is seen', () => {
|
||||
const shakaCue = new shaka.text.Cue(10, 20, '');
|
||||
const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1');
|
||||
|
||||
// Second cue is a linebreak cue.
|
||||
const nestedCue2 = new shaka.text.Cue(10, 20, '');
|
||||
nestedCue2.lineBreak = true;
|
||||
|
||||
const nestedCue3 = new shaka.text.Cue(10, 20, 'Test2');
|
||||
|
||||
shakaCue.nestedCues = [nestedCue1, nestedCue2, nestedCue3];
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 10, endTime: 20, text: 'Test1\nTest2'},
|
||||
],
|
||||
[shakaCue]);
|
||||
});
|
||||
|
||||
it('skips duplicate cues', () => {
|
||||
const cue1 = new shaka.text.Cue(10, 20, 'Test');
|
||||
displayer.append([cue1]);
|
||||
expect(mockTrack.addCue).toHaveBeenCalledTimes(1);
|
||||
mockTrack.addCue.calls.reset();
|
||||
|
||||
const cue2 = new shaka.text.Cue(10, 20, 'Test');
|
||||
displayer.append([cue2]);
|
||||
expect(mockTrack.addCue).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('removes cues which overlap the range', () => {
|
||||
const cue1 = new shaka.text.Cue(0, 1, 'Test');
|
||||
const cue2 = new shaka.text.Cue(1, 2, 'Test');
|
||||
const cue3 = new shaka.text.Cue(2, 3, 'Test');
|
||||
displayer.append([cue1, cue2, cue3]);
|
||||
|
||||
displayer.remove(0, 1);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledTimes(1);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({startTime: 0, endTime: 1}));
|
||||
mockTrack.removeCue.calls.reset();
|
||||
|
||||
displayer.remove(0.5, 1.001);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledTimes(1);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({startTime: 1, endTime: 2}));
|
||||
mockTrack.removeCue.calls.reset();
|
||||
|
||||
displayer.remove(3, 5);
|
||||
expect(mockTrack.removeCue).not.toHaveBeenCalled();
|
||||
mockTrack.removeCue.calls.reset();
|
||||
|
||||
displayer.remove(2.9999, Infinity);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledTimes(1);
|
||||
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({startTime: 2, endTime: 3}));
|
||||
mockTrack.removeCue.calls.reset();
|
||||
});
|
||||
|
||||
it('does nothing when nothing is buffered', () => {
|
||||
displayer.remove(0, 1);
|
||||
expect(mockTrack.removeCue).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('convertToTextTrackCue', () => {
|
||||
it('converts shaka.text.Cues to VttCues', () => {
|
||||
verifyHelper(
|
||||
[
|
||||
{startTime: 20, endTime: 40, text: 'Test4'},
|
||||
],
|
||||
[
|
||||
new shaka.text.Cue(20, 40, 'Test4'),
|
||||
]);
|
||||
|
||||
const cue1 = new shaka.text.Cue(20, 40, 'Test5');
|
||||
cue1.positionAlign = Cue.positionAlign.LEFT;
|
||||
cue1.lineAlign = Cue.lineAlign.START;
|
||||
cue1.size = 80;
|
||||
cue1.textAlign = Cue.textAlign.LEFT;
|
||||
cue1.writingMode = Cue.writingMode.VERTICAL_LEFT_TO_RIGHT;
|
||||
cue1.lineInterpretation = Cue.lineInterpretation.LINE_NUMBER;
|
||||
cue1.line = 5;
|
||||
cue1.position = 10;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 20,
|
||||
endTime: 40,
|
||||
text: 'Test5',
|
||||
lineAlign: 'start',
|
||||
positionAlign: 'line-left',
|
||||
size: 80,
|
||||
align: 'left',
|
||||
vertical: 'lr',
|
||||
snapToLines: true,
|
||||
line: 5,
|
||||
position: 10,
|
||||
},
|
||||
], [cue1]);
|
||||
|
||||
const cue2 = new shaka.text.Cue(30, 50, 'Test');
|
||||
cue2.positionAlign = Cue.positionAlign.RIGHT;
|
||||
cue2.lineAlign = Cue.lineAlign.END;
|
||||
cue2.textAlign = Cue.textAlign.RIGHT;
|
||||
cue2.writingMode = Cue.writingMode.VERTICAL_RIGHT_TO_LEFT;
|
||||
cue2.lineInterpretation = Cue.lineInterpretation.PERCENTAGE;
|
||||
cue2.line = 5;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 30,
|
||||
endTime: 50,
|
||||
text: 'Test',
|
||||
lineAlign: 'end',
|
||||
positionAlign: 'line-right',
|
||||
align: 'right',
|
||||
vertical: 'rl',
|
||||
snapToLines: false,
|
||||
line: 5,
|
||||
},
|
||||
], [cue2]);
|
||||
|
||||
const cue3 = new shaka.text.Cue(40, 60, 'Test1');
|
||||
cue3.positionAlign = Cue.positionAlign.CENTER;
|
||||
cue3.lineAlign = Cue.lineAlign.CENTER;
|
||||
cue3.textAlign = Cue.textAlign.START;
|
||||
cue3.direction = Cue.direction.HORIZONTAL_LEFT_TO_RIGHT;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 40,
|
||||
endTime: 60,
|
||||
text: 'Test1',
|
||||
lineAlign: 'center',
|
||||
positionAlign: 'center',
|
||||
align: 'start',
|
||||
vertical: undefined,
|
||||
},
|
||||
], [cue3]);
|
||||
|
||||
const cue4 = new shaka.text.Cue(40, 60, 'Test2');
|
||||
cue4.line = null;
|
||||
cue4.position = null;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 40,
|
||||
endTime: 60,
|
||||
text: 'Test2',
|
||||
line: 'auto',
|
||||
position: 'auto',
|
||||
},
|
||||
], [cue4]);
|
||||
|
||||
const cue5 = new shaka.text.Cue(40, 60, 'Test3');
|
||||
cue5.line = 0;
|
||||
cue5.position = 0;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 40,
|
||||
endTime: 60,
|
||||
text: 'Test3',
|
||||
line: 0,
|
||||
position: 0,
|
||||
},
|
||||
], [cue5]);
|
||||
});
|
||||
|
||||
it('works around browsers not supporting align=center', () => {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @param {string} text
|
||||
*/
|
||||
function FakeVTTCueWithoutAlignCenter(start, end, text) {
|
||||
let align = 'middle';
|
||||
Object.defineProperty(this, 'align', {
|
||||
get: () => align,
|
||||
set: (newValue) => {
|
||||
if (newValue != 'center') {
|
||||
align = newValue;
|
||||
}
|
||||
},
|
||||
});
|
||||
this.startTime = start;
|
||||
this.endTime = end;
|
||||
this.text = text;
|
||||
}
|
||||
window.VTTCue = /** @type {?} */(FakeVTTCueWithoutAlignCenter);
|
||||
|
||||
const cue1 = new shaka.text.Cue(20, 40, 'Test');
|
||||
cue1.textAlign = Cue.textAlign.CENTER;
|
||||
|
||||
verifyHelper(
|
||||
[
|
||||
{
|
||||
startTime: 20,
|
||||
endTime: 40,
|
||||
text: 'Test',
|
||||
align: 'middle',
|
||||
},
|
||||
],
|
||||
[cue1]);
|
||||
});
|
||||
|
||||
it('ignores cues with startTime >= endTime', () => {
|
||||
mockTrack.addCue.calls.reset();
|
||||
const cue1 = new shaka.text.Cue(60, 40, 'Test');
|
||||
const cue2 = new shaka.text.Cue(40, 40, 'Test');
|
||||
displayer.append([cue1, cue2]);
|
||||
expect(mockTrack.addCue).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroy', () => {
|
||||
it('disables the TextTrack it created', async () => {
|
||||
// There should only be the one track created by this displayer.
|
||||
expect(video.textTracks.length).toBe(1);
|
||||
|
||||
/** @type {!TextTrack} */
|
||||
const textTrack = video.textTracks[0];
|
||||
|
||||
// It should not be disabled before we destroy it.
|
||||
expect(textTrack.mode).not.toBe('disabled');
|
||||
|
||||
await displayer.destroy();
|
||||
|
||||
// It should be disabled after we destroy it.
|
||||
expect(textTrack.mode).toBe('disabled');
|
||||
});
|
||||
});
|
||||
|
||||
function createFakeCue(startTime, endTime) {
|
||||
return {startTime: startTime, endTime: endTime};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that vttCues are converted to shakaCues and appended.
|
||||
* @param {!Array} vttCues
|
||||
* @param {!Array<!shaka.text.Cue>} shakaCues
|
||||
*/
|
||||
function verifyHelper(vttCues, shakaCues) {
|
||||
mockTrack.addCue.calls.reset();
|
||||
displayer.append(shakaCues);
|
||||
const result = mockTrack.addCue.calls.allArgs().reduce(
|
||||
shaka.util.Functional.collapseArrays, []);
|
||||
expect(result).toEqual(vttCues.map((c) => jasmine.objectContaining(c)));
|
||||
}
|
||||
});
|
||||
@@ -22,6 +22,9 @@ describe('TextEngine', () => {
|
||||
/** @type {!jasmine.Spy} */
|
||||
let mockSetSequenceMode;
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
let mockSetManifestType;
|
||||
|
||||
/** @type {!jasmine.Spy} */
|
||||
let mockParseMedia;
|
||||
|
||||
@@ -31,12 +34,14 @@ describe('TextEngine', () => {
|
||||
beforeEach(() => {
|
||||
mockParseInit = jasmine.createSpy('mockParseInit');
|
||||
mockSetSequenceMode = jasmine.createSpy('mockSetSequenceMode');
|
||||
mockSetManifestType = jasmine.createSpy('mockSetManifestType');
|
||||
mockParseMedia = jasmine.createSpy('mockParseMedia');
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
mockParserPlugIn = function() {
|
||||
return {
|
||||
parseInit: mockParseInit,
|
||||
setSequenceMode: mockSetSequenceMode,
|
||||
setManifestType: mockSetManifestType,
|
||||
parseMedia: mockParseMedia,
|
||||
};
|
||||
};
|
||||
|
||||
+59
-24
@@ -147,7 +147,10 @@ describe('UI', () => {
|
||||
newLanguage = 'es';
|
||||
languageMenu = shaka.util.Dom.getElementByClassName(
|
||||
'shaka-audio-languages', videoContainer);
|
||||
setupLanguageTests(player.getAudioLanguagesAndRoles());
|
||||
const audioTracks = player.getAudioTracks();
|
||||
const uniqueLanguages =
|
||||
[...new Set(audioTracks.map((track) => track.language))];
|
||||
setupLanguageTests(uniqueLanguages);
|
||||
});
|
||||
|
||||
it('contains all the languages', () => {
|
||||
@@ -160,10 +163,18 @@ describe('UI', () => {
|
||||
});
|
||||
|
||||
it('choosing language through API has effect on UI', async () => {
|
||||
const selectAudioLanguage = (language) => {
|
||||
const audioTracks = player.getAudioTracks();
|
||||
const track = audioTracks.find((t) => t.language == language);
|
||||
if (track) {
|
||||
player.selectAudioTrack(track);
|
||||
}
|
||||
};
|
||||
|
||||
await verifyLanguageChangeViaAPI(
|
||||
'languageselectionupdated',
|
||||
() => player.getVariantTracks(),
|
||||
(language) => player.selectAudioLanguage(language));
|
||||
(language) => selectAudioLanguage(language));
|
||||
});
|
||||
}); // describe('audio')
|
||||
|
||||
@@ -173,7 +184,10 @@ describe('UI', () => {
|
||||
newLanguage = 'fr';
|
||||
languageMenu = shaka.util.Dom.getElementByClassName(
|
||||
'shaka-text-languages', videoContainer);
|
||||
setupLanguageTests(player.getTextLanguagesAndRoles());
|
||||
const textTracks = player.getTextTracks();
|
||||
const uniqueLanguages =
|
||||
[...new Set(textTracks.map((track) => track.language))];
|
||||
setupLanguageTests(uniqueLanguages);
|
||||
});
|
||||
|
||||
it('contains all the languages', () => {
|
||||
@@ -189,39 +203,58 @@ describe('UI', () => {
|
||||
it('choosing language through API has effect on UI', async () => {
|
||||
// Enable & verify the text, or else the text won't be streamed and the
|
||||
// language selection won't do anything.
|
||||
await player.setTextTrackVisibility(true);
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
let textTracks = player.getTextTracks();
|
||||
player.selectTextTrack(textTracks[0]);
|
||||
textTracks = player.getTextTracks();
|
||||
const activeTrack = textTracks.find((t) => t.active);
|
||||
expect(activeTrack).toBeDefined();
|
||||
|
||||
const selectTextLanguage = (language) => {
|
||||
const textTracks = player.getTextTracks();
|
||||
const track = textTracks.find((t) => t.language == language);
|
||||
if (track) {
|
||||
player.selectTextTrack(track);
|
||||
}
|
||||
};
|
||||
|
||||
await verifyLanguageChangeViaAPI(
|
||||
'captionselectionupdated',
|
||||
() => player.getTextTracks(),
|
||||
(language) => player.selectTextLanguage(language));
|
||||
(language) => selectTextLanguage(language));
|
||||
});
|
||||
|
||||
it('turning captions off through UI has effect on player', async () => {
|
||||
// Enable & verify the text.
|
||||
await player.setTextTrackVisibility(true);
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
|
||||
let textTracks = player.getTextTracks();
|
||||
player.selectTextTrack(textTracks[0]);
|
||||
textTracks = player.getTextTracks();
|
||||
let activeTrack = textTracks.find((t) => t.active);
|
||||
expect(activeTrack).toBeDefined();
|
||||
// Find and click the 'Off' button
|
||||
getOffButton().click();
|
||||
// Wait for the change to take effect
|
||||
await waiter.waitForEvent(player, 'texttrackvisibility');
|
||||
await waiter.waitForEvent(player, 'textchanged');
|
||||
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
textTracks = player.getTextTracks();
|
||||
activeTrack = textTracks.find((t) => t.active);
|
||||
expect(activeTrack).toBeUndefined();
|
||||
});
|
||||
|
||||
it('turning captions off through API has effect on UI', async () => {
|
||||
// This test is invalid if the text is not initially visible, because
|
||||
// setTextTrackVisibility() does nothing if there are no changes.
|
||||
await player.setTextTrackVisibility(true);
|
||||
expect(player.isTextTrackVisible()).toBe(true);
|
||||
// This test is invalid if the text is not initially visible.
|
||||
let textTracks = player.getTextTracks();
|
||||
player.selectTextTrack(textTracks[0]);
|
||||
textTracks = player.getTextTracks();
|
||||
let activeTrack = textTracks.find((t) => t.active);
|
||||
expect(activeTrack).toBeDefined();
|
||||
|
||||
const p = waiter.waitForEvent(controls, 'captionselectionupdated');
|
||||
|
||||
// Disable & verify the text.
|
||||
await player.setTextTrackVisibility(false);
|
||||
expect(player.isTextTrackVisible()).toBe(false);
|
||||
player.selectTextTrack();
|
||||
textTracks = player.getTextTracks();
|
||||
activeTrack = textTracks.find((t) => t.active);
|
||||
expect(activeTrack).toBeUndefined();
|
||||
|
||||
// Wait for the change to take effect
|
||||
await p;
|
||||
@@ -244,12 +277,10 @@ describe('UI', () => {
|
||||
}); // describe('caption selection')
|
||||
|
||||
/**
|
||||
* @param {!Array<shaka.extern.LanguageRole>} languagesAndRoles
|
||||
* @param {!Array<string>} langs
|
||||
*/
|
||||
function setupLanguageTests(languagesAndRoles) {
|
||||
langsFromContent = languagesAndRoles.map((langAndRole) => {
|
||||
return langAndRole.language;
|
||||
});
|
||||
function setupLanguageTests(langs) {
|
||||
langsFromContent = langs;
|
||||
|
||||
languageButtons = filterButtons(languageMenu.childNodes,
|
||||
['shaka-back-to-overflow-button', 'shaka-turn-captions-off-button']);
|
||||
@@ -360,8 +391,12 @@ describe('UI', () => {
|
||||
const selectedLanguage =
|
||||
getSelectedTrack(player.getVariantTracks()).language;
|
||||
if (selectedLanguage != preferredLanguage) {
|
||||
player.selectAudioLanguage(preferredLanguage);
|
||||
await waiter.waitForEvent(player, 'variantchanged');
|
||||
const audioTracks = player.getAudioTracks();
|
||||
const track = audioTracks.find((t) => t.language == preferredLanguage);
|
||||
if (track) {
|
||||
player.selectAudioTrack(track);
|
||||
await waiter.waitForEvent(player, 'variantchanged');
|
||||
}
|
||||
}
|
||||
|
||||
resolutionsMenu = shaka.util.Dom.getElementByClassName(
|
||||
|
||||
@@ -527,31 +527,6 @@ describe('tXml', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('txmlNodeToDomElement', () => {
|
||||
const node = {
|
||||
tagName: 'Event',
|
||||
parent: null,
|
||||
attributes: {
|
||||
'presentationTime': '0',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
tagName: 'scte35:Signal',
|
||||
parent: null,
|
||||
attributes: {},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
node.children[0].parent = node;
|
||||
|
||||
const element = TXml.txmlNodeToDomElement(node);
|
||||
expect(element.tagName).toBe('Event');
|
||||
expect(element.getAttribute('presentationTime')).toBe('0');
|
||||
const signal = element.firstElementChild;
|
||||
expect(signal.tagName).toBe('scte35:Signal');
|
||||
});
|
||||
|
||||
it('cloneNode', () => {
|
||||
expect(TXml.cloneNode(null)).toBe(null);
|
||||
const root = {
|
||||
|
||||
Vendored
+1
-1
@@ -2028,7 +2028,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
||||
const tracks = this.player_.getTextTracks();
|
||||
const hasTrack = tracks.some((track) => track.active);
|
||||
if (hasTrack) {
|
||||
this.player_.selectTextTrack(null);
|
||||
this.player_.selectTextTrack();
|
||||
} else {
|
||||
this.player_.selectTextTrack(this.lastSelectedTextTrack_);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ shaka.ui.TextSelection = class extends shaka.ui.SettingsMenu {
|
||||
const offButton = shaka.util.Dom.createButton();
|
||||
offButton.classList.add('shaka-turn-captions-off-button');
|
||||
this.eventManager.listen(offButton, 'click', () => {
|
||||
this.player.selectTextTrack(null);
|
||||
this.player.selectTextTrack();
|
||||
});
|
||||
|
||||
offButton.appendChild(this.captionsOffSpan_);
|
||||
|
||||
Reference in New Issue
Block a user