shaka-player 3.2.20 → 3.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/selenium-lab-tests.yaml +23 -1
- package/AUTHORS +2 -1
- package/CHANGELOG.md +18 -0
- package/CONTRIBUTORS +4 -1
- package/dist/controls.css +1 -1
- package/dist/locales.js +28 -28
- package/dist/shaka-player.compiled.d.ts +6 -2
- package/dist/shaka-player.compiled.debug.d.ts +6 -2
- package/dist/shaka-player.compiled.debug.js +148 -146
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +264 -263
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +6 -2
- package/dist/shaka-player.ui.debug.d.ts +6 -2
- package/dist/shaka-player.ui.debug.js +87 -85
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +296 -295
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/fairplay.md +2 -2
- package/externs/shaka/net.js +1 -0
- package/externs/shaka/player.js +13 -7
- package/lib/ads/client_side_ad_manager.js +2 -2
- package/lib/media/media_source_engine.js +9 -4
- package/lib/media/streaming_engine.js +8 -3
- package/lib/net/http_fetch_plugin.js +10 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/player.js +17 -2
- package/lib/polyfill/media_capabilities.js +13 -0
- package/lib/text/mp4_vtt_parser.js +4 -0
- package/lib/text/text_engine.js +1 -0
- package/lib/util/manifest_parser_utils.js +1 -2
- package/lib/util/mime_utils.js +11 -0
- package/lib/util/stream_utils.js +2 -2
- package/maintained-branches.md +3 -4
- package/package.json +1 -1
- package/test/media/content_workarounds_unit.js +43 -0
- package/test/media/drm_engine_integration.js +4 -17
- package/test/media/streaming_engine_unit.js +6 -1
- package/test/net/networking_engine_unit.js +6 -1
- package/test/player_integration.js +39 -0
- package/test/player_unit.js +54 -0
- package/test/polyfill/media_capabilities_unit.js +0 -1
- package/test/test/assets/text-clip-alt.vtt +63 -0
- package/test/test/util/fake_drm_engine.js +3 -0
- package/test/test/util/simple_fakes.js +3 -0
- package/test/test/util/test_scheme.js +9 -14
- package/test/text/mp4_vtt_parser_unit.js +8 -0
- package/test/util/mime_utils_unit.js +10 -0
|
@@ -25,14 +25,14 @@ is used by the browser to generate the license request. If you don't use the
|
|
|
25
25
|
default content ID derivation, you need to specify a custom init data transform:
|
|
26
26
|
|
|
27
27
|
```js
|
|
28
|
-
player.configure('drm.initDataTransform', (initData, initDataType) => {
|
|
28
|
+
player.configure('drm.initDataTransform', (initData, initDataType, drmInfo) => {
|
|
29
29
|
if (initDataType != 'skd')
|
|
30
30
|
return initData;
|
|
31
31
|
|
|
32
32
|
// 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
|
|
33
33
|
const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
|
|
34
34
|
const contentId = getMyContentId(skdUri);
|
|
35
|
-
const cert =
|
|
35
|
+
const cert = drmInfo.serverCertificate;
|
|
36
36
|
return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
|
|
37
37
|
});
|
|
38
38
|
```
|
package/externs/shaka/net.js
CHANGED
package/externs/shaka/player.js
CHANGED
|
@@ -571,9 +571,7 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
571
571
|
* clearKeys: !Object.<string, string>,
|
|
572
572
|
* delayLicenseRequestUntilPlayed: boolean,
|
|
573
573
|
* advanced: Object.<string, shaka.extern.AdvancedDrmConfiguration>,
|
|
574
|
-
* initDataTransform:
|
|
575
|
-
* ((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
|
|
576
|
-
* undefined),
|
|
574
|
+
* initDataTransform:(shaka.extern.InitDataTransform|undefined),
|
|
577
575
|
* logLicenseExchange: boolean,
|
|
578
576
|
* updateExpirationTime: number,
|
|
579
577
|
* preferredKeySystems: !Array.<string>
|
|
@@ -597,10 +595,7 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
597
595
|
* <i>Optional.</i> <br>
|
|
598
596
|
* A dictionary which maps key system IDs to advanced DRM configuration for
|
|
599
597
|
* those key systems.
|
|
600
|
-
* @property
|
|
601
|
-
* {((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
|
|
602
|
-
* undefined)}
|
|
603
|
-
* initDataTransform
|
|
598
|
+
* @property {shaka.extern.InitDataTransform|undefined} initDataTransform
|
|
604
599
|
* <i>Optional.</i><br>
|
|
605
600
|
* If given, this function is called with the init data from the
|
|
606
601
|
* manifest/media and should return the (possibly transformed) init data to
|
|
@@ -622,6 +617,17 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
622
617
|
*/
|
|
623
618
|
shaka.extern.DrmConfiguration;
|
|
624
619
|
|
|
620
|
+
/**
|
|
621
|
+
* @typedef {function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array}
|
|
622
|
+
*
|
|
623
|
+
* @description
|
|
624
|
+
* A callback function to handle custom content ID signaling for FairPlay
|
|
625
|
+
* content.
|
|
626
|
+
*
|
|
627
|
+
* @exportDoc
|
|
628
|
+
*/
|
|
629
|
+
shaka.extern.InitDataTransform;
|
|
630
|
+
|
|
625
631
|
|
|
626
632
|
/**
|
|
627
633
|
* @typedef {{
|
|
@@ -212,9 +212,9 @@ shaka.ads.ClientSideAdManager = class {
|
|
|
212
212
|
// seen the ads actually play until requestAds() is called.
|
|
213
213
|
// Note: We listen for a play event to avoid autoplay issues that might
|
|
214
214
|
// crash IMA.
|
|
215
|
-
this.
|
|
215
|
+
this.eventManager_.listenOnce(this.video_, 'play', () => {
|
|
216
216
|
this.imaAdsManager_.start();
|
|
217
|
-
}
|
|
217
|
+
});
|
|
218
218
|
} catch (adError) {
|
|
219
219
|
// If there was a problem with the VAST response,
|
|
220
220
|
// we we won't be getting an ad. Hide ad UI if we showed it already
|
|
@@ -182,6 +182,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
182
182
|
'audio/mp4; codecs="ec-3"',
|
|
183
183
|
'audio/mp4; codecs="opus"',
|
|
184
184
|
'audio/mp4; codecs="flac"',
|
|
185
|
+
'audio/mp4; codecs="dtsc"', // DTS Digital Surround
|
|
186
|
+
'audio/mp4; codecs="dtse"', // DTS Express
|
|
187
|
+
'audio/mp4; codecs="dtsx"', // DTS:X
|
|
185
188
|
// WebM types
|
|
186
189
|
'video/webm; codecs="vp8"',
|
|
187
190
|
'video/webm; codecs="vp9"',
|
|
@@ -515,7 +518,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
515
518
|
// For HLS CEA-608/708 CLOSED-CAPTIONS, text data is embedded in
|
|
516
519
|
// the video stream, so textEngine may not have been initialized.
|
|
517
520
|
if (!this.textEngine_) {
|
|
518
|
-
this.reinitText(
|
|
521
|
+
this.reinitText(shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE);
|
|
519
522
|
}
|
|
520
523
|
|
|
521
524
|
if (transmuxedData.metadata) {
|
|
@@ -542,7 +545,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
542
545
|
contentType, () => this.append_(contentType, transmuxedSegment));
|
|
543
546
|
} else if (hasClosedCaptions) {
|
|
544
547
|
if (!this.textEngine_) {
|
|
545
|
-
this.reinitText(
|
|
548
|
+
this.reinitText(shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE);
|
|
546
549
|
}
|
|
547
550
|
// If it is the init segment for closed captions, initialize the closed
|
|
548
551
|
// caption parser.
|
|
@@ -711,8 +714,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
711
714
|
async endOfStream(reason) {
|
|
712
715
|
await this.enqueueBlockingOperation_(() => {
|
|
713
716
|
// If endOfStream() has already been called on the media source,
|
|
714
|
-
// don't call it again.
|
|
715
|
-
|
|
717
|
+
// don't call it again. Also do not call if readyState is
|
|
718
|
+
// 'closed' (not attached to video element) since it is not a
|
|
719
|
+
// valid operation.
|
|
720
|
+
if (this.ended() || this.mediaSource_.readyState === 'closed') {
|
|
716
721
|
return;
|
|
717
722
|
}
|
|
718
723
|
// Tizen won't let us pass undefined, but it will let us omit the
|
|
@@ -77,6 +77,9 @@ shaka.media.StreamingEngine = class {
|
|
|
77
77
|
/** @private {?shaka.extern.Stream} */
|
|
78
78
|
this.currentTextStream_ = null;
|
|
79
79
|
|
|
80
|
+
/** @private {number} */
|
|
81
|
+
this.textStreamSequenceId_ = 0;
|
|
82
|
+
|
|
80
83
|
/**
|
|
81
84
|
* Maps a content type, e.g., 'audio', 'video', or 'text', to a MediaState.
|
|
82
85
|
*
|
|
@@ -220,6 +223,8 @@ shaka.media.StreamingEngine = class {
|
|
|
220
223
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
221
224
|
goog.asserts.assert(!this.mediaStates_.has(ContentType.TEXT),
|
|
222
225
|
'Should not call loadNewTextStream_ while streaming text!');
|
|
226
|
+
this.textStreamSequenceId_++;
|
|
227
|
+
const currentSequenceId = this.textStreamSequenceId_;
|
|
223
228
|
|
|
224
229
|
try {
|
|
225
230
|
// Clear MediaSource's buffered text, so that the new text stream will
|
|
@@ -241,7 +246,7 @@ shaka.media.StreamingEngine = class {
|
|
|
241
246
|
const streamText =
|
|
242
247
|
textDisplayer.isTextVisible() || this.config_.alwaysStreamText;
|
|
243
248
|
|
|
244
|
-
if (streamText) {
|
|
249
|
+
if (streamText && (this.textStreamSequenceId_ == currentSequenceId)) {
|
|
245
250
|
const state = this.createMediaState_(stream);
|
|
246
251
|
this.mediaStates_.set(ContentType.TEXT, state);
|
|
247
252
|
this.scheduleUpdate_(state, 0);
|
|
@@ -1477,10 +1482,10 @@ shaka.media.StreamingEngine = class {
|
|
|
1477
1482
|
'waiting for another stream to recover...');
|
|
1478
1483
|
}
|
|
1479
1484
|
|
|
1480
|
-
// QuotaExceededError gets thrown if
|
|
1485
|
+
// QuotaExceededError gets thrown if eviction didn't help to make room
|
|
1481
1486
|
// for a segment. We want to wait for a while (4 seconds is just an
|
|
1482
1487
|
// arbitrary number) before updating to give the playhead a chance to
|
|
1483
|
-
// advance, so we don't
|
|
1488
|
+
// advance, so we don't immediately throw again.
|
|
1484
1489
|
this.scheduleUpdate_(mediaState, 4);
|
|
1485
1490
|
}
|
|
1486
1491
|
|
|
@@ -227,6 +227,16 @@ shaka.net.HttpFetchPlugin = class {
|
|
|
227
227
|
} else {
|
|
228
228
|
return false;
|
|
229
229
|
}
|
|
230
|
+
// Old fetch implementations hasn't body and ReadableStream implementation
|
|
231
|
+
// See: https://github.com/shaka-project/shaka-player/issues/5088
|
|
232
|
+
if (window.Response) {
|
|
233
|
+
const response = new Response('');
|
|
234
|
+
if (!response.body) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
230
240
|
return !!(window.fetch && window.AbortController);
|
|
231
241
|
}
|
|
232
242
|
};
|
|
@@ -299,6 +299,7 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
299
299
|
if (!responseAndGotProgress.gotProgress &&
|
|
300
300
|
this.onProgressUpdated_ &&
|
|
301
301
|
!response.fromCache &&
|
|
302
|
+
request.method != 'HEAD' &&
|
|
302
303
|
type == shaka.net.NetworkingEngine.RequestType.SEGMENT) {
|
|
303
304
|
this.onProgressUpdated_(response.timeMs, response.data.byteLength);
|
|
304
305
|
}
|
package/lib/player.js
CHANGED
|
@@ -1148,6 +1148,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1148
1148
|
*/
|
|
1149
1149
|
shouldUseSrcEquals_(payload) {
|
|
1150
1150
|
const Platform = shaka.util.Platform;
|
|
1151
|
+
const MimeUtils = shaka.util.MimeUtils;
|
|
1151
1152
|
|
|
1152
1153
|
// If we are using a platform that does not support media source, we will
|
|
1153
1154
|
// fall back to src= to handle all playback.
|
|
@@ -1202,7 +1203,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1202
1203
|
// version there.
|
|
1203
1204
|
|
|
1204
1205
|
// Native HLS can be preferred on any platform via this flag:
|
|
1205
|
-
if (
|
|
1206
|
+
if (MimeUtils.isHlsType(mimeType) &&
|
|
1207
|
+
this.config_.streaming.preferNativeHls) {
|
|
1206
1208
|
return true;
|
|
1207
1209
|
}
|
|
1208
1210
|
|
|
@@ -3898,6 +3900,19 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3898
3900
|
firstVariantWithLabel.language, '', 0, label);
|
|
3899
3901
|
|
|
3900
3902
|
this.chooseVariantAndSwitch_();
|
|
3903
|
+
} else if (this.video_ && this.video_.audioTracks) {
|
|
3904
|
+
const audioTracks = Array.from(this.video_.audioTracks);
|
|
3905
|
+
|
|
3906
|
+
let trackMatch = null;
|
|
3907
|
+
|
|
3908
|
+
for (const audioTrack of audioTracks) {
|
|
3909
|
+
if (audioTrack.label == label) {
|
|
3910
|
+
trackMatch = audioTrack;
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
if (trackMatch) {
|
|
3914
|
+
this.switchHtml5Track_(trackMatch);
|
|
3915
|
+
}
|
|
3901
3916
|
}
|
|
3902
3917
|
}
|
|
3903
3918
|
|
|
@@ -6461,7 +6476,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6461
6476
|
* @define {string} A version number taken from git at compile time.
|
|
6462
6477
|
* @export
|
|
6463
6478
|
*/
|
|
6464
|
-
shaka.Player.version = 'v3.2.
|
|
6479
|
+
shaka.Player.version = 'v3.2.21-uncompiled';
|
|
6465
6480
|
|
|
6466
6481
|
// Initialize the deprecation system using the version string we just set
|
|
6467
6482
|
// on the player.
|
|
@@ -101,6 +101,19 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
101
101
|
if (shaka.util.Platform.isChromecast()) {
|
|
102
102
|
isSupported =
|
|
103
103
|
shaka.polyfill.MediaCapabilities.canCastDisplayType_(videoConfig);
|
|
104
|
+
} else if (shaka.util.Platform.isTizen()) {
|
|
105
|
+
let extendedType = videoConfig.contentType;
|
|
106
|
+
if (videoConfig.width && videoConfig.height) {
|
|
107
|
+
extendedType += `; width=${videoConfig.width}`;
|
|
108
|
+
extendedType += `; height=${videoConfig.height}`;
|
|
109
|
+
}
|
|
110
|
+
if (videoConfig.framerate) {
|
|
111
|
+
extendedType += `; framerate=${videoConfig.framerate}`;
|
|
112
|
+
}
|
|
113
|
+
if (videoConfig.bitrate) {
|
|
114
|
+
extendedType += `; bitrate=${videoConfig.bitrate}`;
|
|
115
|
+
}
|
|
116
|
+
isSupported = MediaSource.isTypeSupported(extendedType);
|
|
104
117
|
} else {
|
|
105
118
|
isSupported = MediaSource.isTypeSupported(videoConfig.contentType);
|
|
106
119
|
}
|
package/lib/text/text_engine.js
CHANGED
|
@@ -134,6 +134,7 @@ shaka.text.TextEngine = class {
|
|
|
134
134
|
// into TextEngine and TextDisplayer.
|
|
135
135
|
if (mimeType == shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE ||
|
|
136
136
|
mimeType == shaka.util.MimeUtils.CEA708_CLOSED_CAPTION_MIMETYPE) {
|
|
137
|
+
this.parser_ = null;
|
|
137
138
|
return;
|
|
138
139
|
}
|
|
139
140
|
|
|
@@ -185,8 +185,7 @@ shaka.util.ManifestParserUtils.AUDIO_CODEC_REGEXPS_ = [
|
|
|
185
185
|
/^mp4a/,
|
|
186
186
|
/^[ae]c-3$/,
|
|
187
187
|
/^ac-4$/,
|
|
188
|
-
/^dts[
|
|
189
|
-
/^[du]dts$/, // DTS Surround Sound
|
|
188
|
+
/^dts[cex]$/, // DTS Digital Surround (dtsc), DTS Express (dtse), DTS:X (dtsx)
|
|
190
189
|
];
|
|
191
190
|
|
|
192
191
|
|
package/lib/util/mime_utils.js
CHANGED
|
@@ -194,6 +194,17 @@ shaka.util.MimeUtils = class {
|
|
|
194
194
|
return value;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Checks if the given MIME type is HLS MIME type.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} mimeType
|
|
201
|
+
* @return {boolean}
|
|
202
|
+
*/
|
|
203
|
+
static isHlsType(mimeType) {
|
|
204
|
+
return mimeType === 'application/x-mpegurl' ||
|
|
205
|
+
mimeType === 'application/vnd.apple.mpegurl';
|
|
206
|
+
}
|
|
207
|
+
|
|
197
208
|
/**
|
|
198
209
|
* Get the base and profile of a codec string. Where [0] will be the codec
|
|
199
210
|
* base and [1] will be the profile.
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -821,7 +821,7 @@ shaka.util.StreamUtils = class {
|
|
|
821
821
|
const video = variant.video;
|
|
822
822
|
if (audio && currentVariant && currentVariant.audio) {
|
|
823
823
|
if (!StreamUtils.areStreamsCompatible_(audio, currentVariant.audio)) {
|
|
824
|
-
shaka.log.debug('
|
|
824
|
+
shaka.log.debug('Dropping variant - not compatible with active audio',
|
|
825
825
|
'active audio',
|
|
826
826
|
StreamUtils.getStreamSummaryString_(currentVariant.audio),
|
|
827
827
|
'variant.audio',
|
|
@@ -832,7 +832,7 @@ shaka.util.StreamUtils = class {
|
|
|
832
832
|
|
|
833
833
|
if (video && currentVariant && currentVariant.video) {
|
|
834
834
|
if (!StreamUtils.areStreamsCompatible_(video, currentVariant.video)) {
|
|
835
|
-
shaka.log.debug('
|
|
835
|
+
shaka.log.debug('Dropping variant - not compatible with active video',
|
|
836
836
|
'active video',
|
|
837
837
|
StreamUtils.getStreamSummaryString_(currentVariant.video),
|
|
838
838
|
'variant.video',
|
package/maintained-branches.md
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
We are currently maintaining the following branches of Shaka Player:
|
|
4
4
|
|
|
5
|
-
- v4.
|
|
6
|
-
- v4.
|
|
7
|
-
-
|
|
8
|
-
- v3.2 (in use by the Cast Application Framework)
|
|
5
|
+
- v4.3 (latest, also in use by the Cast Application Framework)
|
|
6
|
+
- v4.2 (previous)
|
|
7
|
+
- No active LTS branches at this time
|
|
9
8
|
|
|
10
9
|
Other branches are no longer receiving bug fixes, and we recommend you upgrade
|
|
11
10
|
to a maintained branch. For details on upgrading, please see our
|
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
describe('ContentWorkarounds', () => {
|
|
8
|
+
const encryptionBoxes = {
|
|
9
|
+
'encv': ['hev1', 'hvc1', 'avc1', 'avc3'],
|
|
10
|
+
'enca': ['ac-3', 'ec-3', 'mp4a'],
|
|
11
|
+
};
|
|
12
|
+
for (const encryptionBox of Object.keys(encryptionBoxes)) {
|
|
13
|
+
for (const box of encryptionBoxes[encryptionBox]) {
|
|
14
|
+
it(`adds ${encryptionBox} box for ${box}`, () => {
|
|
15
|
+
const boxType = [];
|
|
16
|
+
for (const char of box) {
|
|
17
|
+
boxType.push(char.charCodeAt(0));
|
|
18
|
+
}
|
|
19
|
+
const unencrypted = new Uint8Array([
|
|
20
|
+
0x00, 0x00, 0x00, 0x20, // size
|
|
21
|
+
0x73, 0x74, 0x73, 0x64, // stsd
|
|
22
|
+
0x01, // version
|
|
23
|
+
0x12, 0x34, 0x56, // flags
|
|
24
|
+
0x00, 0x00, 0x00, 0x01, // count
|
|
25
|
+
0x00, 0x00, 0x00, 0x10, // size
|
|
26
|
+
...boxType, // box type
|
|
27
|
+
0x01, // version
|
|
28
|
+
0x12, 0x34, 0x56, // flags
|
|
29
|
+
0x00, 0x11, 0x22, 0x33, // payload
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const faked =
|
|
33
|
+
shaka.media.ContentWorkarounds.fakeEncryption(unencrypted);
|
|
34
|
+
const spy = jasmine.createSpy('boxCallback');
|
|
35
|
+
new shaka.util.Mp4Parser()
|
|
36
|
+
.fullBox('stsd', shaka.util.Mp4Parser.sampleDescription)
|
|
37
|
+
.box(encryptionBox, /** @type {!Function} */ (spy))
|
|
38
|
+
.parse(faked);
|
|
39
|
+
expect(spy).toHaveBeenCalled();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -74,19 +74,6 @@ describe('DrmEngine', () => {
|
|
|
74
74
|
onEventSpy = jasmine.createSpy('onEvent');
|
|
75
75
|
|
|
76
76
|
networkingEngine = new shaka.net.NetworkingEngine();
|
|
77
|
-
networkingEngine.registerRequestFilter((type, request) => {
|
|
78
|
-
if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
request.headers['X-AxDRM-Message'] = [
|
|
83
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lk',
|
|
84
|
-
'IjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6e',
|
|
85
|
-
'yJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiNmU1YTFkMj',
|
|
86
|
-
'YtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflOPv9qHnu3ZWJNZ12j',
|
|
87
|
-
'gkqTabmwXbDWk_47tLNE',
|
|
88
|
-
].join('');
|
|
89
|
-
});
|
|
90
77
|
|
|
91
78
|
const playerInterface = {
|
|
92
79
|
netEngine: networkingEngine,
|
|
@@ -99,22 +86,22 @@ describe('DrmEngine', () => {
|
|
|
99
86
|
drmEngine = new shaka.media.DrmEngine(playerInterface);
|
|
100
87
|
const config = shaka.util.PlayerConfiguration.createDefault().drm;
|
|
101
88
|
config.servers['com.widevine.alpha'] =
|
|
102
|
-
'https://
|
|
89
|
+
'https://cwip-shaka-proxy.appspot.com/specific_key?blodJidXR9eARuql0dNLWg=GX8m9XLIZNIzizrl0RTqnA';
|
|
103
90
|
config.servers['com.microsoft.playready'] =
|
|
104
|
-
'https://
|
|
91
|
+
'https://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(kid:6e5a1d26-2757-47d7-8046-eaa5d1d34b5a,contentkey:GX8m9XLIZNIzizrl0RTqnA==,sl:150)';
|
|
105
92
|
drmEngine.configure(config);
|
|
106
93
|
|
|
107
94
|
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
108
95
|
manifest.addVariant(0, (variant) => {
|
|
109
96
|
variant.addVideo(1, (stream) => {
|
|
110
97
|
stream.encrypted = true;
|
|
111
|
-
stream.addDrmInfo('com.widevine.alpha');
|
|
112
98
|
stream.addDrmInfo('com.microsoft.playready');
|
|
99
|
+
stream.addDrmInfo('com.widevine.alpha');
|
|
113
100
|
});
|
|
114
101
|
variant.addAudio(2, (stream) => {
|
|
115
102
|
stream.encrypted = true;
|
|
116
|
-
stream.addDrmInfo('com.widevine.alpha');
|
|
117
103
|
stream.addDrmInfo('com.microsoft.playready');
|
|
104
|
+
stream.addDrmInfo('com.widevine.alpha');
|
|
118
105
|
});
|
|
119
106
|
});
|
|
120
107
|
});
|
|
@@ -3275,7 +3275,12 @@ describe('StreamingEngine', () => {
|
|
|
3275
3275
|
netEngine.request.and.callFake((requestType, request) => {
|
|
3276
3276
|
const buffer = new ArrayBuffer(0);
|
|
3277
3277
|
/** @type {shaka.extern.Response} */
|
|
3278
|
-
const response = {
|
|
3278
|
+
const response = {
|
|
3279
|
+
uri: request.uris[0],
|
|
3280
|
+
originalUri: request.uris[0],
|
|
3281
|
+
data: buffer,
|
|
3282
|
+
headers: {},
|
|
3283
|
+
};
|
|
3279
3284
|
return shaka.util.AbortableOperation.completed(response);
|
|
3280
3285
|
});
|
|
3281
3286
|
|
|
@@ -1226,6 +1226,11 @@ describe('NetworkingEngine', /** @suppress {accessControls} */ () => {
|
|
|
1226
1226
|
|
|
1227
1227
|
/** @return {shaka.extern.Response} */
|
|
1228
1228
|
function createResponse() {
|
|
1229
|
-
return {
|
|
1229
|
+
return {
|
|
1230
|
+
uri: '',
|
|
1231
|
+
originalUri: '',
|
|
1232
|
+
data: new ArrayBuffer(5),
|
|
1233
|
+
headers: {},
|
|
1234
|
+
};
|
|
1230
1235
|
}
|
|
1231
1236
|
}); // describe('NetworkingEngine')
|
|
@@ -336,6 +336,45 @@ describe('Player', () => {
|
|
|
336
336
|
player.setTextTrackVisibility(true);
|
|
337
337
|
expect(getTracksActive()).toEqual([false, true]);
|
|
338
338
|
});
|
|
339
|
+
|
|
340
|
+
// https://github.com/shaka-project/shaka-player/issues/4821
|
|
341
|
+
it('loads a single text stream', async () => {
|
|
342
|
+
player.configure({preferredTextLanguage: 'en'});
|
|
343
|
+
await player.load('test:sintel_no_text_compiled');
|
|
344
|
+
|
|
345
|
+
// Add preferred language text track.
|
|
346
|
+
const locationUri = new goog.Uri(location.href);
|
|
347
|
+
const partialUri = new goog.Uri('/base/test/test/assets/text-clip.vtt');
|
|
348
|
+
const absoluteUri = locationUri.resolve(partialUri);
|
|
349
|
+
await player.addTextTrackAsync(
|
|
350
|
+
absoluteUri.toString(), 'en', 'subtitles', 'text/vtt');
|
|
351
|
+
|
|
352
|
+
// Add alternate language text track.
|
|
353
|
+
// Two text tracks with same timings but different text
|
|
354
|
+
// are necessary for test.
|
|
355
|
+
const partialUri2 =
|
|
356
|
+
new goog.Uri('/base/test/test/assets/text-clip-alt.vtt');
|
|
357
|
+
const absoluteUri2 = locationUri.resolve(partialUri2);
|
|
358
|
+
await player.addTextTrackAsync(
|
|
359
|
+
absoluteUri2.toString(), 'fr', 'subtitles', 'text/vtt');
|
|
360
|
+
|
|
361
|
+
const textTracks = player.getTextTracks();
|
|
362
|
+
expect(textTracks.length).toBe(2);
|
|
363
|
+
expect(textTracks[0].language).toBe('en');
|
|
364
|
+
expect(textTracks[1].language).toBe('fr');
|
|
365
|
+
|
|
366
|
+
// Enable text visibilty and immediately change language.
|
|
367
|
+
// Only one set of cues should be active.
|
|
368
|
+
// Cues should be of the selected language track.
|
|
369
|
+
player.setTextTrackVisibility(true);
|
|
370
|
+
player.selectTextLanguage('fr');
|
|
371
|
+
video.currentTime = 5;
|
|
372
|
+
video.play();
|
|
373
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
374
|
+
|
|
375
|
+
expect(video.textTracks[0].activeCues.length).toBe(1);
|
|
376
|
+
expect(player.getTextTracks()[1].active).toBe(true);
|
|
377
|
+
});
|
|
339
378
|
}); // describe('setTextTrackVisibility')
|
|
340
379
|
|
|
341
380
|
describe('plays', () => {
|
package/test/player_unit.js
CHANGED
|
@@ -370,6 +370,60 @@ describe('Player', () => {
|
|
|
370
370
|
expect(streamingEngine.unloadTextStream).not.toHaveBeenCalled();
|
|
371
371
|
});
|
|
372
372
|
});
|
|
373
|
+
|
|
374
|
+
describe('when config.streaming.preferNativeHls is set to true', () => {
|
|
375
|
+
beforeEach(() => {
|
|
376
|
+
shaka.media.ManifestParser.registerParserByMime(
|
|
377
|
+
'application/x-mpegurl',
|
|
378
|
+
() => new shaka.test.FakeManifestParser(manifest));
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
afterEach(() => {
|
|
382
|
+
shaka.media.ManifestParser.unregisterParserByMime(
|
|
383
|
+
'application/x-mpegurl');
|
|
384
|
+
video.canPlayType.calls.reset();
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('only applies to HLS streams', async () => {
|
|
388
|
+
video.canPlayType.and.returnValue('maybe');
|
|
389
|
+
spyOn(shaka.util.Platform, 'anyMediaElement').and.returnValue(video);
|
|
390
|
+
spyOn(shaka.util.Platform, 'supportsMediaSource').and.returnValue(true);
|
|
391
|
+
spyOn(shaka.util.Platform, 'isApple').and.returnValue(false);
|
|
392
|
+
// Make sure player.load() resolves for src=
|
|
393
|
+
spyOn(shaka.util.MediaReadyState, 'waitForReadyState').and.callFake(
|
|
394
|
+
(mediaElement, readyState, eventManager, callback) => {
|
|
395
|
+
callback();
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
player.configure({
|
|
399
|
+
streaming: {
|
|
400
|
+
preferNativeHls: true,
|
|
401
|
+
useNativeHlsOnSafari: false,
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
await player.load(fakeManifestUri, undefined, 'application/x-mpegurl');
|
|
406
|
+
|
|
407
|
+
expect(player.getLoadMode()).toBe(shaka.Player.LoadMode.SRC_EQUALS);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('does not apply to non-HLS streams', async () => {
|
|
411
|
+
video.canPlayType.and.returnValue('maybe');
|
|
412
|
+
spyOn(shaka.util.Platform, 'supportsMediaSource').and.returnValue(true);
|
|
413
|
+
spyOn(shaka.util.Platform, 'isApple').and.returnValue(false);
|
|
414
|
+
|
|
415
|
+
player.configure({
|
|
416
|
+
streaming: {
|
|
417
|
+
preferNativeHls: true,
|
|
418
|
+
useNativeHlsOnSafari: false,
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
423
|
+
|
|
424
|
+
expect(player.getLoadMode()).toBe(shaka.Player.LoadMode.MEDIA_SOURCE);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
373
427
|
}); // describe('load/unload')
|
|
374
428
|
|
|
375
429
|
describe('getConfiguration', () => {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
WEBVTT
|
|
2
|
+
|
|
3
|
+
00:04.000 --> 00:07.300
|
|
4
|
+
Journal de bord du capitaine.
|
|
5
|
+
Date stellaire 41636.9.
|
|
6
|
+
|
|
7
|
+
00:07.500 --> 00:11.800
|
|
8
|
+
Comme nous le craignions, l'épave
|
|
9
|
+
du cargo Odin de la Fédération,
|
|
10
|
+
|
|
11
|
+
00:12.100 --> 00:16.400
|
|
12
|
+
percuté par un astéroïde,
|
|
13
|
+
ne révèle aucun signe de vie.
|
|
14
|
+
|
|
15
|
+
00:16.700 --> 00:19.000
|
|
16
|
+
Mais trois nacelles
|
|
17
|
+
de sauvetage manquaient,
|
|
18
|
+
|
|
19
|
+
00:19.300 --> 00:21.900
|
|
20
|
+
laissant supposer
|
|
21
|
+
qu'il y aurait des survivants.
|
|
22
|
+
|
|
23
|
+
00:22.700 --> 00:27.700
|
|
24
|
+
- Mise sur orbite Angel One, paré.
|
|
25
|
+
- Quel genre d'endroit, Data ?
|
|
26
|
+
|
|
27
|
+
00:28.200 --> 00:31.600
|
|
28
|
+
Planète de Classe-M.
|
|
29
|
+
Faune et flore à base de carbone.
|
|
30
|
+
|
|
31
|
+
00:31.900 --> 00:34.300
|
|
32
|
+
Population éparse
|
|
33
|
+
et forme de vie intelligente.
|
|
34
|
+
|
|
35
|
+
00:34.600 --> 00:38.400
|
|
36
|
+
Développement technique équivalent
|
|
37
|
+
au milieu du 20ème siècle terrien.
|
|
38
|
+
|
|
39
|
+
00:38.800 --> 00:41.000
|
|
40
|
+
C'est presque un retour aux sources.
|
|
41
|
+
|
|
42
|
+
00:41.300 --> 00:43.600
|
|
43
|
+
Si jamais des survivants
|
|
44
|
+
ont pu aller si loin,
|
|
45
|
+
|
|
46
|
+
00:43.800 --> 00:49.000
|
|
47
|
+
c'était la planète la plus proche.
|
|
48
|
+
La distance qui nous a pris 2 jours
|
|
49
|
+
|
|
50
|
+
00:49.500 --> 00:52.400
|
|
51
|
+
aurait pris 5 mois aux nacelles
|
|
52
|
+
de sauvetage du Odin.
|
|
53
|
+
|
|
54
|
+
00:52.600 --> 00:54.700
|
|
55
|
+
Cinq mois, six jours, onze heures,
|
|
56
|
+
deux min...
|
|
57
|
+
|
|
58
|
+
00:54.900 --> 00:58.400
|
|
59
|
+
- Merci, Data.
|
|
60
|
+
- ..et 57 secondes.
|
|
61
|
+
|
|
62
|
+
00:58.600 --> 01:01.300
|
|
63
|
+
Signal audio provenant d'Angel One.
|
|
@@ -74,6 +74,9 @@ shaka.test.FakeDrmEngine = class {
|
|
|
74
74
|
/** @type {!jasmine.Spy} */
|
|
75
75
|
this.supportsVariant = jasmine.createSpy('supportsVariant');
|
|
76
76
|
this.supportsVariant.and.returnValue(true);
|
|
77
|
+
|
|
78
|
+
/** @type {!jasmine.Spy} */
|
|
79
|
+
this.setSrcEquals = jasmine.createSpy('setSrcEquals');
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
/**
|