shaka-player 3.2.19 → 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/build-and-test.yaml +4 -4
- package/.github/workflows/demo-version-index.yaml +6 -0
- package/.github/workflows/selenium-lab-tests.yaml +78 -17
- package/.github/workflows/update-screenshots.yaml +142 -0
- package/AUTHORS +2 -1
- package/CHANGELOG.md +40 -0
- package/CONTRIBUTORS +4 -1
- package/demo/common/asset.js +15 -0
- package/demo/common/assets.js +4 -2
- package/demo/common/message_ids.js +1 -0
- package/demo/custom.js +19 -0
- package/demo/locales/en.json +1 -0
- package/demo/locales/source.json +4 -0
- package/demo/main.js +14 -0
- package/dist/controls.css +1 -1
- package/dist/demo.compiled.debug.js +150 -148
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +150 -148
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +1 -1
- package/dist/locales.js +30 -30
- package/dist/receiver.compiled.debug.js +19 -19
- package/dist/receiver.compiled.debug.map +2 -2
- package/dist/receiver.compiled.js +19 -19
- package/dist/receiver.compiled.map +2 -2
- package/dist/shaka-player.compiled.d.ts +13 -2
- package/dist/shaka-player.compiled.debug.d.ts +13 -2
- package/dist/shaka-player.compiled.debug.js +178 -176
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +294 -292
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +13 -2
- package/dist/shaka-player.ui.debug.d.ts +13 -2
- package/dist/shaka-player.ui.debug.js +117 -115
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +318 -316
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/errors.md +94 -0
- package/docs/tutorials/fairplay.md +2 -2
- package/docs/tutorials/index.json +2 -0
- package/docs/tutorials/widevine-service-certs.md +45 -0
- package/externs/ima.js +9 -0
- package/externs/shaka/net.js +1 -0
- package/externs/shaka/player.js +13 -7
- package/lib/ads/client_side_ad_manager.js +8 -5
- package/lib/hls/hls_parser.js +2 -0
- package/lib/media/media_source_engine.js +9 -4
- package/lib/media/streaming_engine.js +8 -3
- package/lib/media/transmuxer.js +13 -7
- package/lib/media/video_wrapper.js +3 -3
- package/lib/net/http_fetch_plugin.js +10 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/player.js +19 -2
- package/lib/polyfill/media_capabilities.js +15 -8
- package/lib/polyfill/mediasource.js +7 -2
- package/lib/text/mp4_vtt_parser.js +4 -0
- package/lib/text/text_engine.js +1 -0
- package/lib/text/ui_text_displayer.js +1 -0
- package/lib/text/vtt_text_parser.js +4 -5
- package/lib/util/manifest_parser_utils.js +1 -2
- package/lib/util/mime_utils.js +12 -1
- package/lib/util/stream_utils.js +28 -16
- 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 +20 -23
- 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/text/vtt_text_parser_unit.js +26 -2
- package/test/text/web_vtt_layout_integration.js +0 -3
- package/test/util/mime_utils_unit.js +10 -0
|
@@ -369,8 +369,7 @@ shaka.text.VttTextParser = class {
|
|
|
369
369
|
end += timeOffset;
|
|
370
370
|
|
|
371
371
|
// Get the payload.
|
|
372
|
-
const payload =
|
|
373
|
-
text.slice(1).join('\n').trim());
|
|
372
|
+
const payload = text.slice(1).join('\n').trim();
|
|
374
373
|
|
|
375
374
|
let cue = null;
|
|
376
375
|
if (styles.has('global')) {
|
|
@@ -427,7 +426,7 @@ shaka.text.VttTextParser = class {
|
|
|
427
426
|
const childNode = childNodes[0];
|
|
428
427
|
if (childNode.nodeType == Node.TEXT_NODE ||
|
|
429
428
|
childNode.nodeType == Node.CDATA_SECTION_NODE) {
|
|
430
|
-
rootCue.payload = payload;
|
|
429
|
+
rootCue.payload = VttTextParser.htmlUnescape_(payload);
|
|
431
430
|
return;
|
|
432
431
|
}
|
|
433
432
|
}
|
|
@@ -438,7 +437,7 @@ shaka.text.VttTextParser = class {
|
|
|
438
437
|
rootCue.nestedCues = cues;
|
|
439
438
|
} else {
|
|
440
439
|
shaka.log.warning('The cue\'s markup could not be parsed: ', payload);
|
|
441
|
-
rootCue.payload = payload;
|
|
440
|
+
rootCue.payload = VttTextParser.htmlUnescape_(payload);
|
|
442
441
|
}
|
|
443
442
|
}
|
|
444
443
|
|
|
@@ -682,7 +681,7 @@ shaka.text.VttTextParser = class {
|
|
|
682
681
|
}
|
|
683
682
|
if (text.length > 0) {
|
|
684
683
|
const textCue = nestedCue.clone();
|
|
685
|
-
textCue.payload = text;
|
|
684
|
+
textCue.payload = VttTextParser.htmlUnescape_(text);
|
|
686
685
|
cues.push(textCue);
|
|
687
686
|
}
|
|
688
687
|
isFirst = false;
|
|
@@ -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
|
@@ -50,7 +50,7 @@ shaka.util.MimeUtils = class {
|
|
|
50
50
|
return shaka.media.Transmuxer.convertTsCodecs(
|
|
51
51
|
contentType, fullMimeType);
|
|
52
52
|
}
|
|
53
|
-
} else if (contentType == ContentType.AUDIO) {
|
|
53
|
+
} else if (mimeType != 'video/mp2t' && contentType == ContentType.AUDIO) {
|
|
54
54
|
// video/mp2t is the correct mime type for TS audio, so only replace the
|
|
55
55
|
// word "video" with "audio" for non-TS audio content.
|
|
56
56
|
return fullMimeType.replace('video', 'audio');
|
|
@@ -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
|
@@ -703,26 +703,38 @@ shaka.util.StreamUtils = class {
|
|
|
703
703
|
}
|
|
704
704
|
|
|
705
705
|
if (audio) {
|
|
706
|
-
|
|
706
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
707
|
+
if (info.audioRobustness != '') {
|
|
708
|
+
if (!keySystemConfig.audio) {
|
|
709
|
+
// KeySystemTrackConfiguration
|
|
710
|
+
keySystemConfig.audio = {
|
|
711
|
+
robustness: info.audioRobustness,
|
|
712
|
+
};
|
|
713
|
+
} else {
|
|
714
|
+
keySystemConfig.audio.robustness =
|
|
715
|
+
keySystemConfig.audio.robustness || info.audioRobustness;
|
|
716
|
+
}
|
|
717
|
+
} else if (!keySystemConfig.audio) {
|
|
707
718
|
// KeySystemTrackConfiguration
|
|
708
|
-
keySystemConfig.audio = {
|
|
709
|
-
robustness: info.audioRobustness,
|
|
710
|
-
};
|
|
711
|
-
} else {
|
|
712
|
-
keySystemConfig.audio.robustness =
|
|
713
|
-
keySystemConfig.audio.robustness || info.audioRobustness;
|
|
719
|
+
keySystemConfig.audio = {};
|
|
714
720
|
}
|
|
715
721
|
}
|
|
716
722
|
|
|
717
723
|
if (video) {
|
|
718
|
-
|
|
724
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
725
|
+
if (info.videoRobustness != '') {
|
|
726
|
+
if (!keySystemConfig.video) {
|
|
727
|
+
// KeySystemTrackConfiguration
|
|
728
|
+
keySystemConfig.video = {
|
|
729
|
+
robustness: info.videoRobustness,
|
|
730
|
+
};
|
|
731
|
+
} else {
|
|
732
|
+
keySystemConfig.video.robustness =
|
|
733
|
+
keySystemConfig.video.robustness || info.videoRobustness;
|
|
734
|
+
}
|
|
735
|
+
} else if (!keySystemConfig.video) {
|
|
719
736
|
// KeySystemTrackConfiguration
|
|
720
|
-
keySystemConfig.video = {
|
|
721
|
-
robustness: info.videoRobustness,
|
|
722
|
-
};
|
|
723
|
-
} else {
|
|
724
|
-
keySystemConfig.video.robustness =
|
|
725
|
-
keySystemConfig.video.robustness || info.videoRobustness;
|
|
737
|
+
keySystemConfig.video = {};
|
|
726
738
|
}
|
|
727
739
|
}
|
|
728
740
|
}
|
|
@@ -809,7 +821,7 @@ shaka.util.StreamUtils = class {
|
|
|
809
821
|
const video = variant.video;
|
|
810
822
|
if (audio && currentVariant && currentVariant.audio) {
|
|
811
823
|
if (!StreamUtils.areStreamsCompatible_(audio, currentVariant.audio)) {
|
|
812
|
-
shaka.log.debug('
|
|
824
|
+
shaka.log.debug('Dropping variant - not compatible with active audio',
|
|
813
825
|
'active audio',
|
|
814
826
|
StreamUtils.getStreamSummaryString_(currentVariant.audio),
|
|
815
827
|
'variant.audio',
|
|
@@ -820,7 +832,7 @@ shaka.util.StreamUtils = class {
|
|
|
820
832
|
|
|
821
833
|
if (video && currentVariant && currentVariant.video) {
|
|
822
834
|
if (!StreamUtils.areStreamsCompatible_(video, currentVariant.video)) {
|
|
823
|
-
shaka.log.debug('
|
|
835
|
+
shaka.log.debug('Dropping variant - not compatible with active video',
|
|
824
836
|
'active video',
|
|
825
837
|
StreamUtils.getStreamSummaryString_(currentVariant.video),
|
|
826
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', () => {
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
describe('MediaCapabilities', () => {
|
|
8
|
-
const Util = shaka.test.Util;
|
|
9
8
|
const originalCast = window['cast'];
|
|
10
9
|
const originalVendor = navigator.vendor;
|
|
11
10
|
const originalUserAgent = navigator.userAgent;
|
|
@@ -68,7 +67,6 @@ describe('MediaCapabilities', () => {
|
|
|
68
67
|
width: 512,
|
|
69
68
|
},
|
|
70
69
|
};
|
|
71
|
-
shaka.polyfill.MediaCapabilities.memoizedMediaKeySystemAccessRequests_ = {};
|
|
72
70
|
|
|
73
71
|
mockCanDisplayType = jasmine.createSpy('canDisplayType');
|
|
74
72
|
mockCanDisplayType.and.returnValue(false);
|
|
@@ -168,30 +166,29 @@ describe('MediaCapabilities', () => {
|
|
|
168
166
|
expect(result.keySystemAccess).toEqual(mockResult);
|
|
169
167
|
});
|
|
170
168
|
|
|
171
|
-
it('
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
it('falls back to isTypeSupported() when cast namespace is not available',
|
|
170
|
+
async () => {
|
|
171
|
+
// Temporarily remove window.cast to trigger error. It's restored
|
|
172
|
+
// after every test.
|
|
173
|
+
delete window['cast'];
|
|
175
174
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
shaka.util.Error.Code.CAST_API_UNAVAILABLE));
|
|
183
|
-
const isTypeSupportedSpy =
|
|
184
|
-
spyOn(window['MediaSource'], 'isTypeSupported').and.returnValue(true);
|
|
175
|
+
const isChromecastSpy =
|
|
176
|
+
spyOn(shaka['util']['Platform'],
|
|
177
|
+
'isChromecast').and.returnValue(true);
|
|
178
|
+
const isTypeSupportedSpy =
|
|
179
|
+
spyOn(window['MediaSource'], 'isTypeSupported')
|
|
180
|
+
.and.returnValue(true);
|
|
185
181
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
navigator.mediaCapabilities.decodingInfo(mockDecodingConfig))
|
|
189
|
-
.toBeRejectedWith(expected);
|
|
182
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
183
|
+
await navigator.mediaCapabilities.decodingInfo(mockDecodingConfig);
|
|
190
184
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
185
|
+
expect(mockCanDisplayType).not.toHaveBeenCalled();
|
|
186
|
+
// 1 (during install()) + 1 (for video config check).
|
|
187
|
+
expect(isChromecastSpy).toHaveBeenCalledTimes(2);
|
|
188
|
+
// 1 (fallback in canCastDisplayType()) +
|
|
189
|
+
// 1 (mockDecodingConfig.audio).
|
|
190
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledTimes(2);
|
|
191
|
+
});
|
|
195
192
|
|
|
196
193
|
it('falls back to isTypeSupported() when canDisplayType() missing',
|
|
197
194
|
async () => {
|
|
@@ -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
|
/**
|
|
@@ -431,6 +431,7 @@ const widevineDrmServers = {
|
|
|
431
431
|
|
|
432
432
|
/** @type {AVMetadataType} */
|
|
433
433
|
const axinomMultiDrmVideoSegment = {
|
|
434
|
+
// Taken from Axinom's v6 test vector.
|
|
434
435
|
initSegmentUri: '/base/test/test/assets/multidrm-video-init.mp4',
|
|
435
436
|
mdhdOffset: 0x1d1,
|
|
436
437
|
segmentUri: '/base/test/test/assets/multidrm-video-segment.mp4',
|
|
@@ -445,6 +446,7 @@ const axinomMultiDrmVideoSegment = {
|
|
|
445
446
|
|
|
446
447
|
/** @type {AVMetadataType} */
|
|
447
448
|
const axinomMultiDrmAudioSegment = {
|
|
449
|
+
// Taken from Axinom's v6 test vector.
|
|
448
450
|
initSegmentUri: '/base/test/test/assets/multidrm-audio-init.mp4',
|
|
449
451
|
mdhdOffset: 0x192,
|
|
450
452
|
segmentUri: '/base/test/test/assets/multidrm-audio-segment.mp4',
|
|
@@ -459,20 +461,15 @@ const axinomMultiDrmAudioSegment = {
|
|
|
459
461
|
|
|
460
462
|
/** @type {!Object.<string, string>} */
|
|
461
463
|
const axinomDrmServers = {
|
|
464
|
+
// NOTE: These are not Axinom's actual servers. These are test servers for
|
|
465
|
+
// Widevine and PlayReady that let us specify the known key IDs and keys for
|
|
466
|
+
// Axinom's v6 test vectors. Axinom's own servers started returning 403
|
|
467
|
+
// errors for these older test vectors, and we were forced to switch to
|
|
468
|
+
// something stable and independent.
|
|
462
469
|
'com.widevine.alpha':
|
|
463
|
-
'https://
|
|
470
|
+
'https://cwip-shaka-proxy.appspot.com/specific_key?blodJidXR9eARuql0dNLWg=GX8m9XLIZNIzizrl0RTqnA',
|
|
464
471
|
'com.microsoft.playready':
|
|
465
|
-
'https://
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
/** @type {!Object.<string, string>} */
|
|
469
|
-
const axinomDrmHeaders = {
|
|
470
|
-
'X-AxDRM-Message':
|
|
471
|
-
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5' +
|
|
472
|
-
'X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc' +
|
|
473
|
-
'2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIj' +
|
|
474
|
-
'oiNmU1YTFkMjYtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflO' +
|
|
475
|
-
'Pv9qHnu3ZWJNZ12jgkqTabmwXbDWk_47tLNE',
|
|
472
|
+
'https://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(kid:6e5a1d26-2757-47d7-8046-eaa5d1d34b5a,contentkey:GX8m9XLIZNIzizrl0RTqnA==,sl:150)',
|
|
476
473
|
};
|
|
477
474
|
|
|
478
475
|
/** @type {TextMetadataType} */
|
|
@@ -568,7 +565,6 @@ shaka.test.TestScheme.DATA = {
|
|
|
568
565
|
audio: axinomMultiDrmAudioSegment,
|
|
569
566
|
text: vttSegment,
|
|
570
567
|
licenseServers: axinomDrmServers,
|
|
571
|
-
licenseRequestHeaders: axinomDrmHeaders,
|
|
572
568
|
duration: 30,
|
|
573
569
|
},
|
|
574
570
|
|
|
@@ -580,7 +576,6 @@ shaka.test.TestScheme.DATA = {
|
|
|
580
576
|
initData: undefined,
|
|
581
577
|
}),
|
|
582
578
|
licenseServers: axinomDrmServers,
|
|
583
|
-
licenseRequestHeaders: axinomDrmHeaders,
|
|
584
579
|
duration: 30,
|
|
585
580
|
},
|
|
586
581
|
|
|
@@ -170,6 +170,14 @@ describe('Mp4VttParser', () => {
|
|
|
170
170
|
verifyHelper(cues, result);
|
|
171
171
|
});
|
|
172
172
|
|
|
173
|
+
it('handles empty media segments', () => {
|
|
174
|
+
const parser = new shaka.text.Mp4VttParser();
|
|
175
|
+
parser.parseInit(vttInitSegment);
|
|
176
|
+
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0};
|
|
177
|
+
const result = parser.parseMedia(new Uint8Array(0), time);
|
|
178
|
+
verifyHelper([], result);
|
|
179
|
+
});
|
|
180
|
+
|
|
173
181
|
it('rejects init segment with no vtt', () => {
|
|
174
182
|
const error = shaka.test.Util.jasmineError(new shaka.util.Error(
|
|
175
183
|
shaka.util.Error.Severity.CRITICAL,
|
|
@@ -776,11 +776,35 @@ describe('VttTextParser', () => {
|
|
|
776
776
|
it('support escaped html payload', () => {
|
|
777
777
|
verifyHelper(
|
|
778
778
|
[
|
|
779
|
-
{
|
|
779
|
+
{
|
|
780
|
+
startTime: 20.1,
|
|
781
|
+
endTime: 40.505,
|
|
782
|
+
payload: '"Test & 1"\u{a0}',
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
startTime: 41,
|
|
786
|
+
endTime: 42,
|
|
787
|
+
payload: '',
|
|
788
|
+
nestedCues: [
|
|
789
|
+
{
|
|
790
|
+
startTime: 41,
|
|
791
|
+
endTime: 42,
|
|
792
|
+
payload: 'Test',
|
|
793
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
startTime: 41,
|
|
797
|
+
endTime: 42,
|
|
798
|
+
payload: '&',
|
|
799
|
+
},
|
|
800
|
+
],
|
|
801
|
+
},
|
|
780
802
|
],
|
|
781
803
|
'WEBVTT\n\n' +
|
|
782
804
|
'00:00:20.100 --> 00:00:40.505\n' +
|
|
783
|
-
'"Test & 1" 
|
|
805
|
+
'"Test & 1" \n\n' +
|
|
806
|
+
'00:00:41.000 --> 00:00:42.000\n' +
|
|
807
|
+
'<i>Test</i>&',
|
|
784
808
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
785
809
|
});
|
|
786
810
|
|