shaka-player 3.2.2 → 3.2.3
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/CHANGELOG.md +46 -0
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/locales.js +30 -30
- package/dist/shaka-player.compiled.d.ts +21 -2
- package/dist/shaka-player.compiled.debug.d.ts +21 -2
- package/dist/shaka-player.compiled.debug.externs.js +22 -1
- package/dist/shaka-player.compiled.debug.js +205 -202
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +22 -1
- package/dist/shaka-player.compiled.js +727 -723
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +21 -2
- package/dist/shaka-player.ui.debug.d.ts +21 -2
- package/dist/shaka-player.ui.debug.externs.js +22 -1
- package/dist/shaka-player.ui.debug.js +221 -218
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +22 -1
- package/dist/shaka-player.ui.js +829 -825
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/player.js +8 -0
- package/externs/shaka/text.js +10 -0
- package/lib/dash/dash_parser.js +4 -2
- package/lib/hls/hls_parser.js +30 -0
- package/lib/media/segment_index.js +2 -1
- package/lib/media/segment_reference.js +19 -1
- package/lib/media/streaming_engine.js +5 -2
- package/lib/player.js +20 -13
- package/lib/polyfill/media_capabilities.js +30 -15
- package/lib/text/cue.js +6 -0
- package/lib/text/ttml_text_parser.js +84 -58
- package/lib/text/ui_text_displayer.js +17 -11
- package/lib/util/stream_utils.js +86 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +2 -2
- package/test/dash/dash_parser_manifest_unit.js +33 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +145 -0
- package/test/player_integration.js +41 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/ttml_utils.js +81 -0
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +495 -228
- package/test/util/stream_utils_unit.js +36 -30
- package/ui/less/buttons.less +0 -4
- package/ui/text_selection.js +1 -0
- package/externs/media_capabilities.js +0 -16
|
@@ -330,9 +330,9 @@ describe('Player Src Equals', () => {
|
|
|
330
330
|
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
331
331
|
|
|
332
332
|
const locationUri = new goog.Uri(location.href);
|
|
333
|
-
const
|
|
334
|
-
const
|
|
335
|
-
await player.addChaptersTrack(
|
|
333
|
+
const partialUri1 = new goog.Uri('/base/test/test/assets/chapters.vtt');
|
|
334
|
+
const absoluteUri1 = locationUri.resolve(partialUri1);
|
|
335
|
+
await player.addChaptersTrack(absoluteUri1.toString(), 'en');
|
|
336
336
|
|
|
337
337
|
await shaka.test.Util.delay(1.5);
|
|
338
338
|
|
|
@@ -345,11 +345,44 @@ describe('Player Src Equals', () => {
|
|
|
345
345
|
const chapter2 = chapters[1];
|
|
346
346
|
expect(chapter2.title).toBe('Chapter 2');
|
|
347
347
|
expect(chapter2.startTime).toBe(5);
|
|
348
|
-
expect(chapter2.endTime).toBe(
|
|
348
|
+
expect(chapter2.endTime).toBe(10);
|
|
349
349
|
const chapter3 = chapters[2];
|
|
350
350
|
expect(chapter3.title).toBe('Chapter 3');
|
|
351
|
-
expect(chapter3.startTime).toBe(
|
|
352
|
-
expect(chapter3.endTime).toBe(
|
|
351
|
+
expect(chapter3.startTime).toBe(10);
|
|
352
|
+
expect(chapter3.endTime).toBe(20);
|
|
353
|
+
|
|
354
|
+
const partialUri2 = new goog.Uri('/base/test/test/assets/chapters2.vtt');
|
|
355
|
+
const absoluteUri2 = locationUri.resolve(partialUri2);
|
|
356
|
+
await player.addChaptersTrack(absoluteUri2.toString(), 'en');
|
|
357
|
+
|
|
358
|
+
await shaka.test.Util.delay(1.5);
|
|
359
|
+
|
|
360
|
+
const chaptersUpdated = player.getChapters('en');
|
|
361
|
+
expect(chaptersUpdated.length).toBe(6);
|
|
362
|
+
const chapterUpdated1 = chaptersUpdated[0];
|
|
363
|
+
expect(chapterUpdated1.title).toBe('Chapter 1');
|
|
364
|
+
expect(chapterUpdated1.startTime).toBe(0);
|
|
365
|
+
expect(chapterUpdated1.endTime).toBe(5);
|
|
366
|
+
const chapterUpdated2 = chaptersUpdated[1];
|
|
367
|
+
expect(chapterUpdated2.title).toBe('Chapter 2');
|
|
368
|
+
expect(chapterUpdated2.startTime).toBe(5);
|
|
369
|
+
expect(chapterUpdated2.endTime).toBe(10);
|
|
370
|
+
const chapterUpdated3 = chaptersUpdated[2];
|
|
371
|
+
expect(chapterUpdated3.title).toBe('Chapter 3');
|
|
372
|
+
expect(chapterUpdated3.startTime).toBe(10);
|
|
373
|
+
expect(chapterUpdated3.endTime).toBe(20);
|
|
374
|
+
const chapterUpdated4 = chaptersUpdated[3];
|
|
375
|
+
expect(chapterUpdated4.title).toBe('Chapter 4');
|
|
376
|
+
expect(chapterUpdated4.startTime).toBe(20);
|
|
377
|
+
expect(chapterUpdated4.endTime).toBe(30);
|
|
378
|
+
const chapterUpdated5 = chaptersUpdated[4];
|
|
379
|
+
expect(chapterUpdated5.title).toBe('Chapter 5');
|
|
380
|
+
expect(chapterUpdated5.startTime).toBe(30);
|
|
381
|
+
expect(chapterUpdated5.endTime).toBe(40);
|
|
382
|
+
const chapterUpdated6 = chaptersUpdated[5];
|
|
383
|
+
expect(chapterUpdated6.title).toBe('Chapter 6');
|
|
384
|
+
expect(chapterUpdated6.startTime).toBe(40);
|
|
385
|
+
expect(chapterUpdated6.endTime).toBe(61.349);
|
|
353
386
|
});
|
|
354
387
|
|
|
355
388
|
it('add external chapters in srt format', async () => {
|
|
@@ -358,11 +391,11 @@ describe('Player Src Equals', () => {
|
|
|
358
391
|
const locationUri = new goog.Uri(location.href);
|
|
359
392
|
const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
|
|
360
393
|
const absoluteUri = locationUri.resolve(partialUri);
|
|
361
|
-
await player.addChaptersTrack(absoluteUri.toString(), '
|
|
394
|
+
await player.addChaptersTrack(absoluteUri.toString(), 'es');
|
|
362
395
|
|
|
363
396
|
await shaka.test.Util.delay(1.5);
|
|
364
397
|
|
|
365
|
-
const chapters = player.getChapters('
|
|
398
|
+
const chapters = player.getChapters('es');
|
|
366
399
|
expect(chapters.length).toBe(3);
|
|
367
400
|
const chapter1 = chapters[0];
|
|
368
401
|
expect(chapter1.title).toBe('Chapter 1');
|
package/test/player_unit.js
CHANGED
|
@@ -36,7 +36,7 @@ describe('Player', () => {
|
|
|
36
36
|
const originalLogWarn = shaka.log.warning;
|
|
37
37
|
const originalLogAlwaysWarn = shaka.log.alwaysWarn;
|
|
38
38
|
const originalIsTypeSupported = window.MediaSource.isTypeSupported;
|
|
39
|
-
const originalDecodingInfo =
|
|
39
|
+
const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo;
|
|
40
40
|
|
|
41
41
|
const fakeManifestUri = 'fake-manifest-uri';
|
|
42
42
|
const fakeMimeType = 'application/test';
|
|
@@ -93,7 +93,7 @@ describe('Player', () => {
|
|
|
93
93
|
// Since this is not an integration test, we don't want MediaCapabilities to
|
|
94
94
|
// fail assertions based on browser support for types. Pretend that all
|
|
95
95
|
// video and audio types are supported.
|
|
96
|
-
|
|
96
|
+
navigator.mediaCapabilities.decodingInfo = async (config) => {
|
|
97
97
|
await Promise.resolve();
|
|
98
98
|
const videoType = config['video'] ?
|
|
99
99
|
config['video'].contentType.split('/')[0] : null;
|
|
@@ -177,7 +177,7 @@ describe('Player', () => {
|
|
|
177
177
|
shaka.log.alwaysWarn = originalLogAlwaysWarn;
|
|
178
178
|
window.MediaSource.isTypeSupported = originalIsTypeSupported;
|
|
179
179
|
shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
|
|
180
|
-
|
|
180
|
+
navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
|
|
181
181
|
}
|
|
182
182
|
});
|
|
183
183
|
|
|
@@ -1092,8 +1092,8 @@ describe('Player', () => {
|
|
|
1092
1092
|
// Image tracks
|
|
1093
1093
|
manifest.addImageStream(53, (stream) => {
|
|
1094
1094
|
stream.originalId = 'thumbnail';
|
|
1095
|
-
stream.width =
|
|
1096
|
-
stream.height =
|
|
1095
|
+
stream.width = 200;
|
|
1096
|
+
stream.height = 400;
|
|
1097
1097
|
stream.bandwidth = 10;
|
|
1098
1098
|
stream.mimeType = 'image/jpeg';
|
|
1099
1099
|
stream.tilesLayout = '1x1';
|
|
@@ -1503,8 +1503,8 @@ describe('Player', () => {
|
|
|
1503
1503
|
audioBandwidth: null,
|
|
1504
1504
|
videoBandwidth: null,
|
|
1505
1505
|
bandwidth: 10,
|
|
1506
|
-
width:
|
|
1507
|
-
height:
|
|
1506
|
+
width: 200,
|
|
1507
|
+
height: 400,
|
|
1508
1508
|
frameRate: null,
|
|
1509
1509
|
pixelAspectRatio: null,
|
|
1510
1510
|
hdr: null,
|
|
@@ -2463,7 +2463,7 @@ describe('Player', () => {
|
|
|
2463
2463
|
it('throws CONTENT_UNSUPPORTED_BY_BROWSER', async () => {
|
|
2464
2464
|
window.MediaSource.isTypeSupported = (mimeType) => false;
|
|
2465
2465
|
|
|
2466
|
-
|
|
2466
|
+
navigator.mediaCapabilities.decodingInfo = async (config) => {
|
|
2467
2467
|
await Promise.resolve();
|
|
2468
2468
|
return {supported: false};
|
|
2469
2469
|
};
|
|
@@ -2827,7 +2827,7 @@ describe('Player', () => {
|
|
|
2827
2827
|
});
|
|
2828
2828
|
});
|
|
2829
2829
|
|
|
2830
|
-
|
|
2830
|
+
navigator.mediaCapabilities.decodingInfo = async (config) => {
|
|
2831
2831
|
await Promise.resolve();
|
|
2832
2832
|
const videoType = config['video'] ? config['video'].contentType : '';
|
|
2833
2833
|
if (videoType.includes('video') &&
|
|
@@ -3537,29 +3537,39 @@ describe('Player', () => {
|
|
|
3537
3537
|
|
|
3538
3538
|
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
3539
3539
|
|
|
3540
|
+
expect(player.getImageTracks()[0].width).toBe(100);
|
|
3541
|
+
expect(player.getImageTracks()[0].height).toBe(50);
|
|
3540
3542
|
const thumbnail0 = await player.getThumbnails(5, 0);
|
|
3541
3543
|
const thumbnail1 = await player.getThumbnails(5, 11);
|
|
3542
3544
|
const thumbnail2 = await player.getThumbnails(5, 21);
|
|
3543
3545
|
const thumbnail5 = await player.getThumbnails(5, 51);
|
|
3544
3546
|
expect(thumbnail0).toEqual(jasmine.objectContaining({
|
|
3547
|
+
imageHeight: 150,
|
|
3548
|
+
imageWidth: 200,
|
|
3545
3549
|
positionX: 0,
|
|
3546
3550
|
positionY: 0,
|
|
3547
3551
|
width: 100,
|
|
3548
3552
|
height: 50,
|
|
3549
3553
|
}));
|
|
3550
3554
|
expect(thumbnail1).toEqual(jasmine.objectContaining({
|
|
3555
|
+
imageHeight: 150,
|
|
3556
|
+
imageWidth: 200,
|
|
3551
3557
|
positionX: 100,
|
|
3552
3558
|
positionY: 0,
|
|
3553
3559
|
width: 100,
|
|
3554
3560
|
height: 50,
|
|
3555
3561
|
}));
|
|
3556
3562
|
expect(thumbnail2).toEqual(jasmine.objectContaining({
|
|
3563
|
+
imageHeight: 150,
|
|
3564
|
+
imageWidth: 200,
|
|
3557
3565
|
positionX: 0,
|
|
3558
3566
|
positionY: 50,
|
|
3559
3567
|
width: 100,
|
|
3560
3568
|
height: 50,
|
|
3561
3569
|
}));
|
|
3562
3570
|
expect(thumbnail5).toEqual(jasmine.objectContaining({
|
|
3571
|
+
imageHeight: 150,
|
|
3572
|
+
imageWidth: 200,
|
|
3563
3573
|
positionX: 100,
|
|
3564
3574
|
positionY: 100,
|
|
3565
3575
|
width: 100,
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.test.TtmlUtils');
|
|
8
|
+
|
|
9
|
+
shaka.test.TtmlUtils = class {
|
|
10
|
+
/**
|
|
11
|
+
* @param {!Array} expectedCues
|
|
12
|
+
* @param {!Array} actualCues
|
|
13
|
+
* @param {!Object} bodyProperties
|
|
14
|
+
* @param {Object=} divProperties
|
|
15
|
+
*/
|
|
16
|
+
static verifyHelper(expectedCues, actualCues, bodyProperties, divProperties) {
|
|
17
|
+
const mapExpected = (cue) => {
|
|
18
|
+
if (cue.region) {
|
|
19
|
+
cue.region = jasmine.objectContaining(cue.region);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (cue.nestedCues && (cue.nestedCues instanceof Array)) {
|
|
23
|
+
cue.nestedCues = cue.nestedCues.map(mapExpected);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (cue.isContainer == undefined) {
|
|
27
|
+
// If not specified to be true, check for isContainer to be false.
|
|
28
|
+
cue.isContainer = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return jasmine.objectContaining(cue);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {!Object} properties
|
|
36
|
+
* @return {!shaka.extern.Cue}
|
|
37
|
+
*/
|
|
38
|
+
const makeContainer = (properties) => {
|
|
39
|
+
const region = {
|
|
40
|
+
id: '',
|
|
41
|
+
viewportAnchorX: 0,
|
|
42
|
+
viewportAnchorY: 0,
|
|
43
|
+
regionAnchorX: 0,
|
|
44
|
+
regionAnchorY: 0,
|
|
45
|
+
width: 100,
|
|
46
|
+
height: 100,
|
|
47
|
+
widthUnits: shaka.text.CueRegion.units.PERCENTAGE,
|
|
48
|
+
heightUnits: shaka.text.CueRegion.units.PERCENTAGE,
|
|
49
|
+
viewportAnchorUnits: shaka.text.CueRegion.units.PERCENTAGE,
|
|
50
|
+
scroll: '',
|
|
51
|
+
};
|
|
52
|
+
const containerCue = /** @type {!shaka.extern.Cue} */ ({
|
|
53
|
+
region,
|
|
54
|
+
nestedCues: jasmine.any(Object),
|
|
55
|
+
payload: '',
|
|
56
|
+
startTime: 0,
|
|
57
|
+
endTime: Infinity,
|
|
58
|
+
isContainer: true,
|
|
59
|
+
});
|
|
60
|
+
Object.assign(containerCue, properties);
|
|
61
|
+
return mapExpected(containerCue);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (expectedCues.length == 0 && !divProperties) {
|
|
65
|
+
expect(actualCues.length).toBe(0);
|
|
66
|
+
} else {
|
|
67
|
+
// Body.
|
|
68
|
+
expect(actualCues.length).toBe(1);
|
|
69
|
+
const body = actualCues[0];
|
|
70
|
+
expect(body).toEqual(makeContainer(bodyProperties));
|
|
71
|
+
|
|
72
|
+
// Div.
|
|
73
|
+
expect(body.nestedCues.length).toBe(1);
|
|
74
|
+
const div = body.nestedCues[0];
|
|
75
|
+
expect(div).toEqual(makeContainer(divProperties || bodyProperties));
|
|
76
|
+
|
|
77
|
+
// Cues.
|
|
78
|
+
expect(div.nestedCues).toEqual(expectedCues.map(mapExpected));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
goog.require('shaka.test.TtmlUtils');
|
|
7
8
|
goog.require('shaka.test.Util');
|
|
8
9
|
goog.require('shaka.text.Mp4TtmlParser');
|
|
9
10
|
goog.require('shaka.util.BufferUtils');
|
|
@@ -48,7 +49,14 @@ describe('Mp4TtmlParser', () => {
|
|
|
48
49
|
parser.parseInit(ttmlInitSegment);
|
|
49
50
|
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
|
|
50
51
|
const ret = parser.parseMedia(ttmlSegmentMultipleMDAT, time);
|
|
51
|
-
|
|
52
|
+
// Bodies.
|
|
53
|
+
expect(ret.length).toBe(2);
|
|
54
|
+
// Divs.
|
|
55
|
+
expect(ret[0].nestedCues.length).toBe(1);
|
|
56
|
+
expect(ret[1].nestedCues.length).toBe(1);
|
|
57
|
+
// Cues.
|
|
58
|
+
expect(ret[0].nestedCues[0].nestedCues.length).toBe(10);
|
|
59
|
+
expect(ret[1].nestedCues[0].nestedCues.length).toBe(10);
|
|
52
60
|
});
|
|
53
61
|
|
|
54
62
|
it('accounts for offset', () => {
|
|
@@ -159,22 +167,7 @@ describe('Mp4TtmlParser', () => {
|
|
|
159
167
|
parser.parseInit(ttmlInitSegment);
|
|
160
168
|
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 0};
|
|
161
169
|
const result = parser.parseMedia(ttmlSegment, time);
|
|
162
|
-
verifyHelper(
|
|
170
|
+
shaka.test.TtmlUtils.verifyHelper(
|
|
171
|
+
cues, result, {startTime: 23, endTime: 53.5});
|
|
163
172
|
});
|
|
164
|
-
|
|
165
|
-
function verifyHelper(/** !Array */ expected, /** !Array */ actual) {
|
|
166
|
-
const mapExpected = (cue) => {
|
|
167
|
-
if (cue.region) {
|
|
168
|
-
cue.region = jasmine.objectContaining(cue.region);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (cue.nestedCues) {
|
|
172
|
-
cue.nestedCues = cue.nestedCues.map(mapExpected);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return jasmine.objectContaining(cue);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
expect(actual).toEqual(expected.map(mapExpected));
|
|
179
|
-
}
|
|
180
173
|
});
|