shaka-player 4.0.0 → 4.0.1

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.
Files changed (57) hide show
  1. package/.github/config.yml +1 -0
  2. package/.github/workflows/release-please.yaml +6 -11
  3. package/CHANGELOG.md +15 -0
  4. package/build/misspellings.txt +1 -0
  5. package/dist/controls.css +1 -1
  6. package/dist/locales.js +32 -32
  7. package/dist/shaka-player.compiled.d.ts +2 -1
  8. package/dist/shaka-player.compiled.debug.d.ts +2 -1
  9. package/dist/shaka-player.compiled.debug.externs.js +1 -0
  10. package/dist/shaka-player.compiled.debug.js +170 -165
  11. package/dist/shaka-player.compiled.debug.map +3 -3
  12. package/dist/shaka-player.compiled.externs.js +1 -0
  13. package/dist/shaka-player.compiled.js +783 -779
  14. package/dist/shaka-player.compiled.map +3 -3
  15. package/dist/shaka-player.ui.d.ts +2 -1
  16. package/dist/shaka-player.ui.debug.d.ts +2 -1
  17. package/dist/shaka-player.ui.debug.externs.js +1 -0
  18. package/dist/shaka-player.ui.debug.js +182 -177
  19. package/dist/shaka-player.ui.debug.map +3 -3
  20. package/dist/shaka-player.ui.externs.js +1 -0
  21. package/dist/shaka-player.ui.js +924 -920
  22. package/dist/shaka-player.ui.map +3 -3
  23. package/docs/tutorials/upgrade.md +4 -2
  24. package/externs/shaka/player.js +11 -0
  25. package/karma.conf.js +4 -0
  26. package/lib/dash/dash_parser.js +2 -2
  27. package/lib/hls/hls_parser.js +20 -11
  28. package/lib/media/drm_engine.js +16 -0
  29. package/lib/media/media_source_engine.js +91 -37
  30. package/lib/media/streaming_engine.js +1 -2
  31. package/lib/offline/indexeddb/storage_mechanism.js +4 -2
  32. package/lib/player.js +165 -107
  33. package/lib/text/vtt_text_parser.js +7 -7
  34. package/lib/util/config_utils.js +25 -0
  35. package/lib/util/error.js +7 -0
  36. package/lib/util/manifest_parser_utils.js +1 -1
  37. package/lib/util/mime_utils.js +48 -1
  38. package/lib/util/periods.js +5 -4
  39. package/lib/util/player_configuration.js +14 -14
  40. package/lib/util/stream_utils.js +4 -2
  41. package/package.json +4 -1
  42. package/test/hls/hls_live_unit.js +22 -0
  43. package/test/hls/manifest_text_parser_unit.js +19 -0
  44. package/test/offline/indexeddb_storage_unit.js +1 -1
  45. package/test/offline/storage_compatibility_unit.js +1 -1
  46. package/test/player_external.js +7 -1
  47. package/test/player_integration.js +6 -10
  48. package/test/player_src_equals_integration.js +81 -83
  49. package/test/player_unit.js +98 -1
  50. package/test/test/boot.js +9 -0
  51. package/test/test/externs/filters.js +4 -0
  52. package/test/test/util/simple_fakes.js +31 -2
  53. package/test/text/vtt_text_parser_unit.js +64 -5
  54. package/test/util/mime_utils_unit.js +54 -0
  55. package/test/util/periods_unit.js +79 -0
  56. package/ui/resolution_selection.js +1 -1
  57. package/docs/tutorials/gsoc-ideas-list.md +0 -3
@@ -535,7 +535,61 @@ describe('VttTextParser', () => {
535
535
  'Test\n\n' +
536
536
  '00:00:40.000 --> 00:00:50.000 line:-1\n' +
537
537
  'Test2',
538
- {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0});
538
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
539
+ /* sequenceMode= */ true);
540
+ });
541
+
542
+ it('ignores X-TIMESTAMP-MAP header if not in sequence mode', () => {
543
+ verifyHelper(
544
+ [
545
+ {startTime: 20, endTime: 40, payload: 'Test'},
546
+ {startTime: 40, endTime: 50, payload: 'Test2'},
547
+ ],
548
+ 'WEBVTT\n' +
549
+ 'X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:01:00:00.000\n\n' +
550
+ '00:00:20.000 --> 00:00:40.000 line:0\n' +
551
+ 'Test\n\n' +
552
+ '00:00:40.000 --> 00:00:50.000 line:-1\n' +
553
+ 'Test2',
554
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
555
+ /* sequenceMode= */ false);
556
+ });
557
+
558
+ it('parses X-TIMESTAMP-MAP header with non-zero local base', () => {
559
+ verifyHelper(
560
+ [
561
+ {startTime: 1800, endTime: 1810, payload: 'Test'},
562
+ {startTime: 1820, endTime: 1830, payload: 'Test2'},
563
+ ],
564
+ // 162000000 = 30 * 60 * 90k = 30 minutes for the TS part of the map.
565
+ // The local (VTT) part of the map is 1 hour.
566
+ // So text times of 1 hour map to media times of 30 minutes.
567
+ 'WEBVTT\n' +
568
+ 'X-TIMESTAMP-MAP=MPEGTS:162000000,LOCAL:01:00:00.000\n\n' +
569
+ '01:00:00.000 --> 01:00:10.000 line:0\n' +
570
+ 'Test\n\n' +
571
+ '01:00:20.000 --> 01:00:30.000 line:-1\n' +
572
+ 'Test2',
573
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
574
+ /* sequenceMode= */ true);
575
+ });
576
+
577
+ it('combines X-TIMESTAMP-MAP header with periodStart', () => {
578
+ verifyHelper(
579
+ [
580
+ {startTime: 130, endTime: 150, payload: 'Test'},
581
+ {startTime: 150, endTime: 160, payload: 'Test2'},
582
+ ],
583
+ // 900000 = 10 sec, so expect every timestamp to be 10
584
+ // seconds ahead of what is specified.
585
+ 'WEBVTT\n' +
586
+ 'X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n' +
587
+ '00:00:20.000 --> 00:00:40.000 line:0\n' +
588
+ 'Test\n\n' +
589
+ '00:00:40.000 --> 00:00:50.000 line:-1\n' +
590
+ 'Test2',
591
+ {periodStart: 100, segmentStart: 25, segmentEnd: 65, vttOffset: 0},
592
+ /* sequenceMode= */ true);
539
593
  });
540
594
 
541
595
  it('handles timestamp rollover with X-TIMESTAMP-MAP header', () => {
@@ -551,7 +605,8 @@ describe('VttTextParser', () => {
551
605
  'Test',
552
606
  // Non-null segmentStart takes precedence over X-TIMESTAMP-MAP.
553
607
  // This protects us from rollover in the MPEGTS field.
554
- {periodStart: 0, segmentStart: 95440, segmentEnd: 95550, vttOffset: 0});
608
+ {periodStart: 0, segmentStart: 95440, segmentEnd: 95550, vttOffset: 0},
609
+ /* sequenceMode= */ true);
555
610
 
556
611
  verifyHelper(
557
612
  [
@@ -564,7 +619,8 @@ describe('VttTextParser', () => {
564
619
  'X-TIMESTAMP-MAP=MPEGTS:9745408,LOCAL:00:00:00.000\n\n' +
565
620
  '00:00:00.000 --> 00:00:02.000 line:0\n' +
566
621
  'Test2',
567
- {periodStart: 0, segmentStart: 95550, segmentEnd: 95560, vttOffset: 0});
622
+ {periodStart: 0, segmentStart: 95550, segmentEnd: 95560, vttOffset: 0},
623
+ /* sequenceMode= */ true);
568
624
  });
569
625
 
570
626
  it('supports global style blocks', () => {
@@ -978,11 +1034,14 @@ describe('VttTextParser', () => {
978
1034
  * @param {!Array} cues
979
1035
  * @param {string} text
980
1036
  * @param {shaka.extern.TextParser.TimeContext} time
1037
+ * @param {boolean=} sequenceMode
981
1038
  */
982
- function verifyHelper(cues, text, time) {
1039
+ function verifyHelper(cues, text, time, sequenceMode = false) {
983
1040
  const data =
984
1041
  shaka.util.BufferUtils.toUint8(shaka.util.StringUtils.toUTF8(text));
985
- const result = new shaka.text.VttTextParser().parseMedia(data, time);
1042
+ const parser = new shaka.text.VttTextParser();
1043
+ parser.setSequenceMode(sequenceMode);
1044
+ const result = parser.parseMedia(data, time);
986
1045
 
987
1046
  const expected = cues.map((cue) => {
988
1047
  if (cue.nestedCues) {
@@ -0,0 +1,54 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ describe('MimeUtils', () => {
8
+ const getNormalizedCodec = (codecs) =>
9
+ shaka.util.MimeUtils.getNormalizedCodec(codecs);
10
+
11
+ it('normalizes codecs', () => {
12
+ expect(getNormalizedCodec('mp4a.66')).toBe('aac');
13
+ expect(getNormalizedCodec('mp4a.67')).toBe('aac');
14
+ expect(getNormalizedCodec('mp4a.68')).toBe('aac');
15
+
16
+ expect(getNormalizedCodec('mp3')).toBe('mp3');
17
+ expect(getNormalizedCodec('mp4a.69')).toBe('mp3');
18
+ expect(getNormalizedCodec('mp4a.6B')).toBe('mp3');
19
+ expect(getNormalizedCodec('mp4a.6b')).toBe('mp3');
20
+
21
+ expect(getNormalizedCodec('mp4a.40.2')).toBe('aac');
22
+ expect(getNormalizedCodec('mp4a.40.02')).toBe('aac');
23
+ expect(getNormalizedCodec('mp4a.40.5')).toBe('aac');
24
+ expect(getNormalizedCodec('mp4a.40.05')).toBe('aac');
25
+ expect(getNormalizedCodec('mp4a.40.29')).toBe('aac');
26
+ expect(getNormalizedCodec('mp4a.40.42')).toBe('aac');
27
+
28
+ expect(getNormalizedCodec('ac-3')).toBe('ac-3');
29
+ expect(getNormalizedCodec('mp4a.a5')).toBe('ac-3');
30
+ expect(getNormalizedCodec('mp4a.A5')).toBe('ac-3');
31
+
32
+ expect(getNormalizedCodec('ec-3')).toBe('ec-3');
33
+ expect(getNormalizedCodec('mp4a.a6')).toBe('ec-3');
34
+ expect(getNormalizedCodec('mp4a.A6')).toBe('ec-3');
35
+
36
+ expect(getNormalizedCodec('dtsc')).toBe('dtsc');
37
+ expect(getNormalizedCodec('mp4a.a9')).toBe('dtsc');
38
+
39
+ expect(getNormalizedCodec('dtsx')).toBe('dtsx');
40
+ expect(getNormalizedCodec('mp4a.b2')).toBe('dtsx');
41
+
42
+ expect(getNormalizedCodec('vp8')).toBe('vp8');
43
+ expect(getNormalizedCodec('vp8.0')).toBe('vp8');
44
+
45
+ expect(getNormalizedCodec('avc1')).toBe('avc');
46
+ expect(getNormalizedCodec('avc3')).toBe('avc');
47
+
48
+ expect(getNormalizedCodec('hvc1')).toBe('hevc');
49
+ expect(getNormalizedCodec('hev1')).toBe('hevc');
50
+
51
+ expect(getNormalizedCodec('dvh1.05')).toBe('dovi');
52
+ expect(getNormalizedCodec('dvhe.05')).toBe('dovi');
53
+ });
54
+ });
@@ -996,6 +996,85 @@ describe('PeriodCombiner', () => {
996
996
  expect(audio2.originalId).toBe('2,4');
997
997
  });
998
998
 
999
+ it('Matches streams with related codecs', async () => {
1000
+ const stream1 = makeVideoStream(1080);
1001
+ stream1.originalId = '1';
1002
+ stream1.bandwidth = 120000;
1003
+ stream1.codecs = 'hvc1.1.4.L126.B0';
1004
+
1005
+ const stream2 = makeVideoStream(1080);
1006
+ stream2.originalId = '2';
1007
+ stream2.bandwidth = 120000;
1008
+ stream2.codecs = 'hev1.2.4.L123.B0';
1009
+
1010
+ const stream3 = makeVideoStream(1080);
1011
+ stream3.originalId = '3';
1012
+ stream3.bandwidth = 120000;
1013
+ stream3.codecs = 'dvhe.05.01';
1014
+
1015
+ const stream4 = makeVideoStream(1080);
1016
+ stream4.originalId = '4';
1017
+ stream4.bandwidth = 120000;
1018
+ stream4.codecs = 'dvh1.05.01';
1019
+
1020
+ const stream5 = makeVideoStream(1080);
1021
+ stream5.originalId = '5';
1022
+ stream5.bandwidth = 120000;
1023
+ stream5.codecs = 'avc1.42001f';
1024
+
1025
+ const stream6 = makeVideoStream(1080);
1026
+ stream6.originalId = '6';
1027
+ stream6.bandwidth = 120000;
1028
+ stream6.codecs = 'avc3.42001f';
1029
+
1030
+ const stream7 = makeVideoStream(1080);
1031
+ stream7.originalId = '7';
1032
+ stream7.bandwidth = 120000;
1033
+ stream7.codecs = 'vp09.00.10.08';
1034
+
1035
+ const stream8 = makeVideoStream(1080);
1036
+ stream8.originalId = '8';
1037
+ stream8.bandwidth = 120000;
1038
+ stream8.codecs = 'vp09.01.20.08.01';
1039
+
1040
+ /** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
1041
+ const periods = [
1042
+ {
1043
+ id: '0',
1044
+ videoStreams: [
1045
+ stream1, stream3, stream5, stream7,
1046
+ ],
1047
+ audioStreams: [],
1048
+ textStreams: [],
1049
+ imageStreams: [],
1050
+ },
1051
+ {
1052
+ id: '1',
1053
+ videoStreams: [
1054
+ stream2, stream4, stream6, stream8,
1055
+ ],
1056
+ audioStreams: [],
1057
+ textStreams: [],
1058
+ imageStreams: [],
1059
+ },
1060
+ ];
1061
+
1062
+ await combiner.combinePeriods(periods, /* isDynamic= */ true);
1063
+ const variants = combiner.getVariants();
1064
+ expect(variants.length).toBe(4);
1065
+ // We can use the originalId field to see what each track is composed of.
1066
+ const video1 = variants[0].video;
1067
+ expect(video1.originalId).toBe('1,2');
1068
+
1069
+ const video2 = variants[1].video;
1070
+ expect(video2.originalId).toBe('3,4');
1071
+
1072
+ const video3 = variants[2].video;
1073
+ expect(video3.originalId).toBe('5,6');
1074
+
1075
+ const video4 = variants[3].video;
1076
+ expect(video4.originalId).toBe('7,8');
1077
+ });
999
1078
 
1000
1079
  it('Matches streams with most roles in common', async () => {
1001
1080
  const makeAudioStreamWithRoles = (roles) => {
@@ -90,7 +90,7 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
90
90
  return otherIdx == idx;
91
91
  });
92
92
 
93
- // Sort the tracks by height or bandwith depending on content type.
93
+ // Sort the tracks by height or bandwidth depending on content type.
94
94
  if (this.player.isAudioOnly()) {
95
95
  tracks.sort((t1, t2) => {
96
96
  goog.asserts.assert(t1.bandwidth != null, 'Null bandwidth');
@@ -1,3 +0,0 @@
1
- # Google Summer of Code Ideas List
2
-
3
- Please see the latest project ideas list [here](https://storage.googleapis.com/wvtemp/shaka/Shaka%20Player%20GSoC%20Projects%20List.pdf).