shaka-player 4.1.4 → 4.1.6
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 +42 -22
- package/.github/workflows/compute-incremental-coverage.py +14 -3
- package/.github/workflows/custom-actions/set-commit-status/action.yaml +1 -5
- package/.github/workflows/deflake.yaml +28 -0
- package/.github/workflows/demo-version-index.yaml +1 -1
- package/.github/workflows/nightly-demo.yaml +1 -1
- package/.github/workflows/release-please.yaml +5 -5
- package/.github/workflows/report-incremental-coverage.yaml +1 -1
- package/.github/workflows/selenium-lab-tests.yaml +21 -10
- package/AUTHORS +3 -0
- package/CHANGELOG.md +35 -0
- package/CONTRIBUTORS +3 -0
- package/demo/common/message_ids.js +1 -0
- package/demo/config.js +3 -1
- package/demo/locales/en.json +1 -0
- package/demo/locales/source.json +4 -0
- package/dist/demo.compiled.debug.js +6 -6
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +6 -6
- package/dist/demo.compiled.map +2 -2
- package/dist/deps.js +3 -3
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +3 -3
- package/dist/receiver.compiled.debug.map +2 -2
- package/dist/receiver.compiled.js +3 -3
- package/dist/receiver.compiled.map +2 -2
- package/dist/shaka-player.compiled.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.externs.js +25 -24
- package/dist/shaka-player.compiled.debug.js +233 -224
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +25 -24
- package/dist/shaka-player.compiled.js +800 -797
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +3 -2
- package/dist/shaka-player.ui.debug.d.ts +3 -2
- package/dist/shaka-player.ui.debug.externs.js +25 -24
- package/dist/shaka-player.ui.debug.js +286 -278
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +25 -24
- package/dist/shaka-player.ui.js +939 -935
- package/dist/shaka-player.ui.map +4 -4
- package/docs/jsdoc-template/publish.js +33 -0
- package/docs/jsdoc-template/tmpl/container.tmpl +4 -1
- package/docs/jsdoc.conf.json +1 -0
- package/docs/tutorials/welcome.md +2 -2
- package/externs/shaka/manifest_parser.js +4 -1
- package/externs/shaka/player.js +7 -1
- package/lib/ads/client_side_ad_manager.js +12 -2
- package/lib/cast/cast_sender.js +39 -14
- package/lib/cea/cea608_memory.js +4 -0
- package/lib/hls/hls_parser.js +48 -15
- package/lib/media/drm_engine.js +59 -7
- package/lib/media/media_source_engine.js +43 -15
- package/lib/media/playhead.js +1 -1
- package/lib/media/streaming_engine.js +79 -14
- package/lib/offline/indexeddb/storage_mechanism.js +24 -0
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +17 -5
- package/lib/polyfill/media_capabilities.js +7 -6
- package/lib/text/ttml_text_parser.js +69 -87
- package/lib/text/vtt_text_parser.js +1 -1
- package/lib/util/error.js +7 -0
- package/lib/util/periods.js +9 -9
- package/lib/util/platform.js +19 -5
- package/lib/util/player_configuration.js +4 -0
- package/lib/util/pssh.js +2 -1
- package/lib/util/stream_utils.js +2 -1
- package/lib/util/xml_utils.js +45 -6
- package/package.json +1 -1
- package/test/cea/cea608_memory_unit.js +88 -0
- package/test/dash/dash_parser_content_protection_unit.js +1 -0
- package/test/dash/dash_parser_live_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +1 -0
- package/test/dash/dash_parser_segment_base_unit.js +1 -0
- package/test/dash/dash_parser_segment_list_unit.js +1 -0
- package/test/dash/dash_parser_segment_template_unit.js +1 -0
- package/test/hls/hls_live_unit.js +169 -247
- package/test/hls/hls_parser_unit.js +60 -2
- package/test/media/drm_engine_unit.js +61 -0
- package/test/media/media_source_engine_integration.js +36 -0
- package/test/media/media_source_engine_unit.js +118 -1
- package/test/media/streaming_engine_integration.js +9 -7
- package/test/media/streaming_engine_unit.js +29 -0
- package/test/offline/offline_integration.js +3 -3
- package/test/offline/storage_integration.js +30 -0
- package/test/player_integration.js +2 -2
- package/test/test/util/dash_parser_util.js +2 -0
- package/test/test/util/ttml_utils.js +0 -2
- package/test/text/ttml_text_parser_unit.js +46 -0
- package/test/text/vtt_text_parser_unit.js +23 -1
- package/test/ui/text_displayer_layout_unit.js +17 -2
- package/test/util/periods_unit.js +149 -11
- package/test/util/xml_utils_unit.js +64 -0
- package/ui/controls.js +0 -7
|
@@ -219,6 +219,21 @@ filterDescribe('TextDisplayer layout', supportsScreenshots, () => {
|
|
|
219
219
|
|
|
220
220
|
/** @param {string} prefix Prepended to screenshot names */
|
|
221
221
|
function defineTests(prefix) {
|
|
222
|
+
// Due to a Safari implementation bug, the browser only does the correct
|
|
223
|
+
// thing for "end-time-edge-case" on Safari 16+. Skip the tests on earlier
|
|
224
|
+
// versions.
|
|
225
|
+
const safariVersion = shaka.util.Platform.safariVersion();
|
|
226
|
+
if (prefix == 'native' && safariVersion && safariVersion < 16) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Due to updates in the rendering and/or default styles in Chrome, the
|
|
231
|
+
// screenshots for native rendering only match in Chrome 106+.
|
|
232
|
+
const chromeVersion = shaka.util.Platform.chromeVersion();
|
|
233
|
+
if (prefix == 'native' && chromeVersion && chromeVersion < 106) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
222
237
|
it('basic cue', async () => {
|
|
223
238
|
textDisplayer.append([
|
|
224
239
|
new shaka.text.Cue(0, 1, 'Captain\'s log, stardate 41636.9'),
|
|
@@ -262,8 +277,8 @@ filterDescribe('TextDisplayer layout', supportsScreenshots, () => {
|
|
|
262
277
|
|
|
263
278
|
// Regression test for #3151
|
|
264
279
|
// Only one cue should be displayed. Note, however, that we don't control
|
|
265
|
-
// this in a browser's native display. As of
|
|
266
|
-
// the right thing in native text display. Chrome
|
|
280
|
+
// this in a browser's native display. As of Sep 2022, both Firefox and
|
|
281
|
+
// Safari>=16 do the right thing in native text display. Chrome and Edge
|
|
267
282
|
// show both cues in this edge case. When we control the display of text
|
|
268
283
|
// through the UI & DOM, we can always get the timing right.
|
|
269
284
|
it('cues ending exactly now', async () => {
|
|
@@ -12,6 +12,14 @@ describe('PeriodCombiner', () => {
|
|
|
12
12
|
/** @type {shaka.util.PeriodCombiner} */
|
|
13
13
|
let combiner;
|
|
14
14
|
|
|
15
|
+
const makeAudioStreamWithRoles = (id, roles, primary = true) => {
|
|
16
|
+
const stream = makeAudioStream('en');
|
|
17
|
+
stream.originalId = id;
|
|
18
|
+
stream.roles = roles;
|
|
19
|
+
stream.primary = primary;
|
|
20
|
+
return stream;
|
|
21
|
+
};
|
|
22
|
+
|
|
15
23
|
beforeEach(() => {
|
|
16
24
|
combiner = new shaka.util.PeriodCombiner();
|
|
17
25
|
});
|
|
@@ -1127,20 +1135,149 @@ describe('PeriodCombiner', () => {
|
|
|
1127
1135
|
const variants = combiner.getVariants();
|
|
1128
1136
|
|
|
1129
1137
|
expect(variants).toEqual(jasmine.arrayWithExactContents([
|
|
1130
|
-
makeAVVariant(1080, 'en'),
|
|
1131
|
-
makeAVVariant(1080, 'en'),
|
|
1138
|
+
makeAVVariant(1080, 'en', 2, ['role1', 'role2']),
|
|
1139
|
+
makeAVVariant(1080, 'en', 2, ['role1']),
|
|
1132
1140
|
]));
|
|
1133
1141
|
|
|
1134
1142
|
// We can use the originalId field to see what each track is composed of.
|
|
1135
|
-
|
|
1136
|
-
expect(
|
|
1137
|
-
|
|
1143
|
+
expect(variants[0].audio.originalId).toBe('stream1,stream3');
|
|
1144
|
+
expect(variants[1].audio.originalId).toBe('stream2,stream4');
|
|
1145
|
+
});
|
|
1138
1146
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1147
|
+
it('Matches streams with roles in common', async () => {
|
|
1148
|
+
/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
|
|
1149
|
+
const periods = [
|
|
1150
|
+
{
|
|
1151
|
+
id: '1',
|
|
1152
|
+
videoStreams: [
|
|
1153
|
+
makeVideoStream(720),
|
|
1154
|
+
makeVideoStream(1080),
|
|
1155
|
+
],
|
|
1156
|
+
audioStreams: [
|
|
1157
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1158
|
+
makeAudioStreamWithRoles('stream2', ['description'], false),
|
|
1159
|
+
],
|
|
1160
|
+
textStreams: [],
|
|
1161
|
+
imageStreams: [],
|
|
1162
|
+
},
|
|
1163
|
+
{
|
|
1164
|
+
id: '2',
|
|
1165
|
+
videoStreams: [
|
|
1166
|
+
makeVideoStream(720),
|
|
1167
|
+
makeVideoStream(1080),
|
|
1168
|
+
],
|
|
1169
|
+
audioStreams: [
|
|
1170
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1171
|
+
makeAudioStreamWithRoles('stream2', ['description'], false),
|
|
1172
|
+
],
|
|
1173
|
+
textStreams: [],
|
|
1174
|
+
imageStreams: [],
|
|
1175
|
+
},
|
|
1176
|
+
];
|
|
1177
|
+
|
|
1178
|
+
await combiner.combinePeriods(periods, /* isDynamic= */ false);
|
|
1179
|
+
const variants = combiner.getVariants();
|
|
1180
|
+
|
|
1181
|
+
console.log(variants);
|
|
1182
|
+
|
|
1183
|
+
expect(variants.length).toBe(4);
|
|
1184
|
+
|
|
1185
|
+
expect(variants).toEqual(jasmine.arrayWithExactContents([
|
|
1186
|
+
makeAVVariant(720, 'en', 2, ['main']),
|
|
1187
|
+
makeAVVariant(1080, 'en', 2, ['main']),
|
|
1188
|
+
makeAVVariant(720, 'en', 2, ['description']),
|
|
1189
|
+
makeAVVariant(1080, 'en', 2, ['description']),
|
|
1190
|
+
]));
|
|
1191
|
+
|
|
1192
|
+
// We can use the originalId field to see what each track is composed of.
|
|
1193
|
+
expect(variants[0].audio.originalId).toBe('stream1,stream1');
|
|
1194
|
+
expect(variants[1].audio.originalId).toBe('stream1,stream1');
|
|
1195
|
+
expect(variants[2].audio.originalId).toBe('stream2,stream2');
|
|
1196
|
+
expect(variants[3].audio.originalId).toBe('stream2,stream2');
|
|
1142
1197
|
});
|
|
1143
1198
|
|
|
1199
|
+
it('Matches streams with mismatched roles', async () => {
|
|
1200
|
+
/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
|
|
1201
|
+
const periods = [
|
|
1202
|
+
{
|
|
1203
|
+
id: '0',
|
|
1204
|
+
videoStreams: [
|
|
1205
|
+
makeVideoStream(720),
|
|
1206
|
+
makeVideoStream(1080),
|
|
1207
|
+
],
|
|
1208
|
+
audioStreams: [
|
|
1209
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1210
|
+
],
|
|
1211
|
+
textStreams: [],
|
|
1212
|
+
imageStreams: [],
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
id: '1',
|
|
1216
|
+
videoStreams: [
|
|
1217
|
+
makeVideoStream(720),
|
|
1218
|
+
makeVideoStream(1080),
|
|
1219
|
+
],
|
|
1220
|
+
audioStreams: [
|
|
1221
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1222
|
+
makeAudioStreamWithRoles('stream2', ['description'], false),
|
|
1223
|
+
],
|
|
1224
|
+
textStreams: [],
|
|
1225
|
+
imageStreams: [],
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
id: '2',
|
|
1229
|
+
videoStreams: [
|
|
1230
|
+
makeVideoStream(720),
|
|
1231
|
+
makeVideoStream(1080),
|
|
1232
|
+
],
|
|
1233
|
+
audioStreams: [
|
|
1234
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1235
|
+
],
|
|
1236
|
+
textStreams: [],
|
|
1237
|
+
imageStreams: [],
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
id: '3',
|
|
1241
|
+
videoStreams: [
|
|
1242
|
+
makeVideoStream(720),
|
|
1243
|
+
makeVideoStream(1080),
|
|
1244
|
+
],
|
|
1245
|
+
audioStreams: [
|
|
1246
|
+
makeAudioStreamWithRoles('stream1', ['main']),
|
|
1247
|
+
makeAudioStreamWithRoles('stream2', ['description'], false),
|
|
1248
|
+
],
|
|
1249
|
+
textStreams: [],
|
|
1250
|
+
imageStreams: [],
|
|
1251
|
+
},
|
|
1252
|
+
];
|
|
1253
|
+
|
|
1254
|
+
await combiner.combinePeriods(periods, /* isDynamic= */ false);
|
|
1255
|
+
const variants = combiner.getVariants();
|
|
1256
|
+
|
|
1257
|
+
console.log(variants);
|
|
1258
|
+
|
|
1259
|
+
expect(variants.length).toBe(4);
|
|
1260
|
+
|
|
1261
|
+
expect(variants).toEqual(jasmine.arrayWithExactContents([
|
|
1262
|
+
makeAVVariant(720, 'en', 2, ['main']),
|
|
1263
|
+
makeAVVariant(1080, 'en', 2, ['main']),
|
|
1264
|
+
makeAVVariant(720, 'en', 2, ['description', 'main']),
|
|
1265
|
+
makeAVVariant(1080, 'en', 2, ['description', 'main']),
|
|
1266
|
+
]));
|
|
1267
|
+
|
|
1268
|
+
// We can use the originalId field to see what each track is composed of.
|
|
1269
|
+
expect(variants[0].audio.originalId)
|
|
1270
|
+
.toBe('stream1,stream1,stream1,stream1');
|
|
1271
|
+
|
|
1272
|
+
expect(variants[1].audio.originalId)
|
|
1273
|
+
.toBe('stream1,stream1,stream1,stream1');
|
|
1274
|
+
|
|
1275
|
+
expect(variants[2].audio.originalId)
|
|
1276
|
+
.toBe('stream1,stream2,stream1,stream2');
|
|
1277
|
+
|
|
1278
|
+
expect(variants[3].audio.originalId)
|
|
1279
|
+
.toBe('stream1,stream2,stream1,stream2');
|
|
1280
|
+
});
|
|
1144
1281
|
|
|
1145
1282
|
it('The number of variants stays stable after many periods ' +
|
|
1146
1283
|
'when going between similar content and varying ads', async () => {
|
|
@@ -1148,7 +1285,7 @@ describe('PeriodCombiner', () => {
|
|
|
1148
1285
|
// https://github.com/shaka-project/shaka-player/issues/2716
|
|
1149
1286
|
// that used to cause our period flattening logic to keep
|
|
1150
1287
|
// creating new variants for every new period added.
|
|
1151
|
-
// It's ok to create a few additional
|
|
1288
|
+
// It's ok to create a few additional variants/streams,
|
|
1152
1289
|
// but we should stabilize eventually and keep the number
|
|
1153
1290
|
// of variants from growing indefinitely.
|
|
1154
1291
|
|
|
@@ -1334,7 +1471,7 @@ describe('PeriodCombiner', () => {
|
|
|
1334
1471
|
expect(isCandidateBetter).toBe(WORSE);
|
|
1335
1472
|
|
|
1336
1473
|
// Make sure it works correctly whether it's the candidate or the best
|
|
1337
|
-
// value that is
|
|
1474
|
+
// value that is equal to the output.
|
|
1338
1475
|
isCandidateBetter = PeriodCombiner.compareClosestPreferLower(
|
|
1339
1476
|
/* output= */ 5, /* bestValue= */ 3, /* candidateValue= */ 5);
|
|
1340
1477
|
expect(isCandidateBetter).toBe(BETTER);
|
|
@@ -1461,11 +1598,12 @@ describe('PeriodCombiner', () => {
|
|
|
1461
1598
|
* @param {number=} channels
|
|
1462
1599
|
* @return {shaka.extern.Variant}
|
|
1463
1600
|
*/
|
|
1464
|
-
function makeAVVariant(height, language, channels = 2) {
|
|
1601
|
+
function makeAVVariant(height, language, channels = 2, roles = []) {
|
|
1465
1602
|
const variant = jasmine.objectContaining({
|
|
1466
1603
|
language,
|
|
1467
1604
|
audio: jasmine.objectContaining({
|
|
1468
1605
|
language,
|
|
1606
|
+
roles,
|
|
1469
1607
|
channelsCount: channels,
|
|
1470
1608
|
}),
|
|
1471
1609
|
video: jasmine.objectContaining({
|
|
@@ -371,5 +371,69 @@ describe('XmlUtils', () => {
|
|
|
371
371
|
expect(XmlUtils.parseFloat(HUGE_NUMBER_STRING)).toBe(Infinity);
|
|
372
372
|
expect(XmlUtils.parseFloat('-' + HUGE_NUMBER_STRING)).toBe(-Infinity);
|
|
373
373
|
});
|
|
374
|
+
|
|
375
|
+
describe('parseXmlString', () => {
|
|
376
|
+
it('parses a simple XML document', () => {
|
|
377
|
+
const xmlString = [
|
|
378
|
+
'<?xml version="1.0"?>',
|
|
379
|
+
'<Root>',
|
|
380
|
+
' <Child></Child>',
|
|
381
|
+
'</Root>',
|
|
382
|
+
].join('\n');
|
|
383
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Root');
|
|
384
|
+
expect(doc).not.toBeNull();
|
|
385
|
+
expect(doc.tagName).toBe('Root');
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('returns null on an empty XML document', () => {
|
|
389
|
+
const xmlString = '';
|
|
390
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Root');
|
|
391
|
+
expect(doc).toBeNull();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('returns null on malformed XML', () => {
|
|
395
|
+
const xmlString = [
|
|
396
|
+
'<?xml version="1.0"?>',
|
|
397
|
+
'<Root>',
|
|
398
|
+
' <Child</Child>',
|
|
399
|
+
'</Root>',
|
|
400
|
+
].join('\n');
|
|
401
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Root');
|
|
402
|
+
expect(doc).toBeNull();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('returns null on root element mismatch', () => {
|
|
406
|
+
const xmlString = [
|
|
407
|
+
'<?xml version="1.0"?>',
|
|
408
|
+
'<Root>',
|
|
409
|
+
' <Child></Child>',
|
|
410
|
+
'</Root>',
|
|
411
|
+
].join('\n');
|
|
412
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Document');
|
|
413
|
+
expect(doc).toBeNull();
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('returns null on XML that embeds HTML', () => {
|
|
417
|
+
const xmlString = [
|
|
418
|
+
'<?xml version="1.0"?>',
|
|
419
|
+
'<Root>',
|
|
420
|
+
' <Child xmlns="http://www.w3.org/1999/xhtml"></Child>',
|
|
421
|
+
'</Root>',
|
|
422
|
+
].join('\n');
|
|
423
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Root');
|
|
424
|
+
expect(doc).toBeNull();
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('returns null on XML that embeds SVG', () => {
|
|
428
|
+
const xmlString = [
|
|
429
|
+
'<?xml version="1.0"?>',
|
|
430
|
+
'<Root>',
|
|
431
|
+
' <Child xmlns="http://www.w3.org/2000/svg"></Child>',
|
|
432
|
+
'</Root>',
|
|
433
|
+
].join('\n');
|
|
434
|
+
const doc = XmlUtils.parseXmlString(xmlString, 'Root');
|
|
435
|
+
expect(doc).toBeNull();
|
|
436
|
+
});
|
|
437
|
+
});
|
|
374
438
|
});
|
|
375
439
|
|
package/ui/controls.js
CHANGED
|
@@ -1011,13 +1011,6 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
1011
1011
|
await this.onScreenRotation_();
|
|
1012
1012
|
});
|
|
1013
1013
|
}
|
|
1014
|
-
|
|
1015
|
-
this.eventManager_.listen(document, 'fullscreenchange', () => {
|
|
1016
|
-
if (this.ad_) {
|
|
1017
|
-
this.ad_.resize(
|
|
1018
|
-
this.localVideo_.offsetWidth, this.localVideo_.offsetHeight);
|
|
1019
|
-
}
|
|
1020
|
-
});
|
|
1021
1014
|
}
|
|
1022
1015
|
|
|
1023
1016
|
|