shaka-player 3.3.3 → 3.3.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.
Files changed (76) hide show
  1. package/.github/workflows/build-and-test.yaml +0 -1
  2. package/.github/workflows/release-please.yaml +6 -3
  3. package/.github/workflows/selenium-lab-tests.yaml +0 -1
  4. package/CHANGELOG.md +38 -0
  5. package/README.md +4 -4
  6. package/build/README.md +2 -2
  7. package/build/test.py +7 -1
  8. package/build/types/core +0 -1
  9. package/demo/demo.less +0 -1
  10. package/dist/controls.css +3 -3
  11. package/dist/controls.css.map +1 -1
  12. package/dist/demo.css +1 -1
  13. package/dist/demo.css.map +1 -1
  14. package/dist/deps.js +2 -3
  15. package/dist/locales.js +31 -31
  16. package/dist/shaka-player.compiled.d.ts +1 -0
  17. package/dist/shaka-player.compiled.debug.d.ts +1 -0
  18. package/dist/shaka-player.compiled.debug.externs.js +1 -0
  19. package/dist/shaka-player.compiled.debug.js +152 -150
  20. package/dist/shaka-player.compiled.debug.map +4 -4
  21. package/dist/shaka-player.compiled.externs.js +1 -0
  22. package/dist/shaka-player.compiled.js +844 -842
  23. package/dist/shaka-player.compiled.map +4 -4
  24. package/dist/shaka-player.ui.d.ts +1 -0
  25. package/dist/shaka-player.ui.debug.d.ts +1 -0
  26. package/dist/shaka-player.ui.debug.externs.js +1 -0
  27. package/dist/shaka-player.ui.debug.js +224 -222
  28. package/dist/shaka-player.ui.debug.map +4 -4
  29. package/dist/shaka-player.ui.externs.js +1 -0
  30. package/dist/shaka-player.ui.js +952 -950
  31. package/dist/shaka-player.ui.map +4 -4
  32. package/karma.conf.js +4 -0
  33. package/lib/abr/simple_abr_manager.js +2 -1
  34. package/lib/dash/dash_parser.js +2 -3
  35. package/lib/hls/hls_parser.js +37 -14
  36. package/lib/media/drm_engine.js +3 -0
  37. package/lib/media/media_source_engine.js +7 -1
  38. package/lib/offline/indexeddb/storage_mechanism.js +4 -2
  39. package/lib/offline/storage.js +92 -91
  40. package/lib/player.js +165 -107
  41. package/lib/util/config_utils.js +25 -0
  42. package/lib/util/error.js +7 -0
  43. package/lib/util/manifest_parser_utils.js +1 -1
  44. package/lib/util/mime_utils.js +62 -6
  45. package/lib/util/periods.js +5 -4
  46. package/lib/util/player_configuration.js +9 -14
  47. package/lib/util/stream_utils.js +4 -2
  48. package/package.json +2 -2
  49. package/test/cast/cast_utils_unit.js +1 -0
  50. package/test/dash/dash_parser_manifest_unit.js +0 -24
  51. package/test/hls/hls_live_unit.js +86 -7
  52. package/test/hls/manifest_text_parser_unit.js +19 -0
  53. package/test/media/media_source_engine_integration.js +1 -0
  54. package/test/media/media_source_engine_unit.js +4 -4
  55. package/test/media/streaming_engine_integration.js +2 -0
  56. package/test/offline/indexeddb_storage_unit.js +1 -1
  57. package/test/offline/storage_compatibility_unit.js +1 -1
  58. package/test/player_external.js +7 -1
  59. package/test/player_integration.js +6 -10
  60. package/test/player_src_equals_integration.js +81 -83
  61. package/test/player_unit.js +98 -1
  62. package/test/test/boot.js +9 -0
  63. package/test/test/externs/filters.js +4 -0
  64. package/test/test/util/simple_fakes.js +31 -2
  65. package/test/util/mime_utils_unit.js +54 -0
  66. package/test/util/periods_unit.js +79 -0
  67. package/ui/less/ad_controls.less +2 -2
  68. package/ui/less/buttons.less +1 -1
  69. package/ui/less/containers.less +5 -5
  70. package/ui/less/general.less +1 -1
  71. package/ui/less/range_elements.less +3 -2
  72. package/ui/less/tooltip.less +3 -3
  73. package/ui/seek_bar.js +2 -1
  74. package/.github/pull_request_template.md +0 -10
  75. package/docs/tutorials/gsoc-ideas-list.md +0 -3
  76. package/lib/util/mutex.js +0 -52
@@ -122,7 +122,13 @@ describe('Player', () => {
122
122
 
123
123
  player.createDrmEngine = () => drmEngine;
124
124
  player.createNetworkingEngine = () => networkingEngine;
125
- player.createPlayhead = () => playhead;
125
+ player.createPlayhead = (startTime) => {
126
+ const callableSetStartTime =
127
+ shaka.test.Util.spyFunc(playhead.setStartTime);
128
+ callableSetStartTime(startTime);
129
+ playhead.setStartTime.calls.reset();
130
+ return playhead;
131
+ };
126
132
  player.createMediaSourceEngine = () => mediaSourceEngine;
127
133
  player.createStreamingEngine = () => streamingEngine;
128
134
  }
@@ -154,6 +160,7 @@ describe('Player', () => {
154
160
  window.MediaSource.isTypeSupported = originalIsTypeSupported;
155
161
  shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
156
162
  navigator.mediaCapabilities.decodingInfo = originalDecodingInfo;
163
+ onError.calls.reset();
157
164
  }
158
165
  });
159
166
 
@@ -2632,6 +2639,51 @@ describe('Player', () => {
2632
2639
  expect(activeVariant.id).toBe(1);
2633
2640
  });
2634
2641
 
2642
+ // Regression test for https://github.com/shaka-project/shaka-player/issues/4190
2643
+ it('throws only one RESTRICTIONS_CANNOT_BE_MET error', async () => {
2644
+ manifest = shaka.test.ManifestGenerator.generate((manifest) => {
2645
+ manifest.addVariant(0, (variant) => {
2646
+ variant.addVideo(1, (stream) => {
2647
+ stream.keyIds = new Set(['abc']);
2648
+ });
2649
+ });
2650
+ });
2651
+
2652
+ // Check that error is RESTRICTIONS_CANNOT_BE_MET
2653
+ onError.and.callFake((e) => {
2654
+ const error = e.detail;
2655
+ shaka.test.Util.expectToEqualError(
2656
+ error,
2657
+ new shaka.util.Error(
2658
+ shaka.util.Error.Severity.CRITICAL,
2659
+ shaka.util.Error.Category.MANIFEST,
2660
+ shaka.util.Error.Code.RESTRICTIONS_CANNOT_BE_MET, {
2661
+ hasAppRestrictions: false,
2662
+ missingKeys: ['abc'],
2663
+ restrictedKeyStatuses: [],
2664
+ }));
2665
+ });
2666
+
2667
+ await player.load(fakeManifestUri, 0, fakeMimeType);
2668
+ const activeVariant = getActiveVariantTrack();
2669
+ expect(activeVariant.id).toBe(0);
2670
+
2671
+ abrManager.chooseIndex = 0;
2672
+ abrManager.chooseVariant.calls.reset();
2673
+
2674
+ onKeyStatus({'abc': 'output-restricted'});
2675
+
2676
+ // Ensure that RESTRICTIONS_CANNOT_BE_MET is thrown once
2677
+ expect(onError).toHaveBeenCalledTimes(1);
2678
+
2679
+ // It does not call chooseVariant
2680
+ expect(abrManager.chooseVariant).not.toHaveBeenCalled();
2681
+
2682
+ // The first variant is disallowed.
2683
+ expect(manifest.variants[0].id).toBe(0);
2684
+ expect(manifest.variants[0].allowedByKeySystem).toBe(false);
2685
+ });
2686
+
2635
2687
  it('doesn\'t switch if the active stream isn\'t restricted', async () => {
2636
2688
  manifest = shaka.test.ManifestGenerator.generate((manifest) => {
2637
2689
  manifest.addVariant(0, (variant) => {
@@ -3638,6 +3690,51 @@ describe('Player', () => {
3638
3690
  });
3639
3691
  });
3640
3692
 
3693
+ describe('config streaming.startAtSegmentBoundary', () => {
3694
+ // Test for https://github.com/shaka-project/shaka-player/issues/4188
3695
+ // In that issue, using streaming.startAtSegmentBoundary in v4.0.0 caused
3696
+ // an exception due to the use of a removed method.
3697
+ it('adjusts start time', async () => {
3698
+ player.configure('streaming.startAtSegmentBoundary', true);
3699
+
3700
+ // In order to adjust the start time to a segment boundary, we need
3701
+ // segment descriptions in the segment index. So create a non-default
3702
+ // fake manifest.
3703
+ const timeline = new shaka.media.PresentationTimeline(300, 0);
3704
+ timeline.setStatic(true);
3705
+ // This duration is used by useSegmentTemplate below to decide how many
3706
+ // references to generate.
3707
+ timeline.setDuration(300);
3708
+ manifest = shaka.test.ManifestGenerator.generate((manifest) => {
3709
+ manifest.presentationTimeline = timeline;
3710
+ manifest.addVariant(0, (variant) => {
3711
+ variant.addVideo(1, (stream) => {
3712
+ stream.useSegmentTemplate(
3713
+ '$Number$.mp4', /* segmentDuration= */ 10);
3714
+ });
3715
+ });
3716
+ });
3717
+
3718
+ await player.load(fakeManifestUri, 12, fakeMimeType);
3719
+
3720
+ expect(playhead.setStartTime).toHaveBeenCalledWith(10);
3721
+ });
3722
+
3723
+ it('does not fail with no segments', async () => {
3724
+ player.configure('streaming.startAtSegmentBoundary', true);
3725
+
3726
+ // Without useSegmentTemplate in the fake manifest, the call to
3727
+ // getIteratorForTime() in Player produces a null iterator. Using the
3728
+ // default fake manifest should cover that case. But just to make sure,
3729
+ // verify that we have no segments before calling load().
3730
+ const variant = manifest.variants[0];
3731
+ expect(variant.video.segmentIndex.getIteratorForTime(0)).toBeNull();
3732
+ expect(variant.audio.segmentIndex.getIteratorForTime(0)).toBeNull();
3733
+
3734
+ await player.load(fakeManifestUri, 0, fakeMimeType);
3735
+ });
3736
+ });
3737
+
3641
3738
  /**
3642
3739
  * Gets the currently active variant track.
3643
3740
  * @return {shaka.extern.Track}
package/test/test/boot.js CHANGED
@@ -242,6 +242,15 @@ window.xfilterDescribe = (describeName, cond, describeBody) => {
242
242
  window['describe'] = oldDescribe;
243
243
  };
244
244
 
245
+ /**
246
+ * A very short alias for filtering offline integration tests.
247
+ *
248
+ * @return {boolean}
249
+ */
250
+ window.offlineSupported = () => {
251
+ return shaka.offline.StorageMuxer.support();
252
+ };
253
+
245
254
  /**
246
255
  * Load node modules used in testing and install them into window.
247
256
  * @return {!Promise}
@@ -38,3 +38,7 @@ var filterDescribe = function(name, cond, callback) {};
38
38
  * @param {function()} callback
39
39
  */
40
40
  var xfilterDescribe = function(name, cond, callback) {};
41
+
42
+
43
+ /** @return {boolean} */
44
+ var offlineSupported = function() {};
@@ -152,9 +152,27 @@ shaka.test.FakeVideo = class {
152
152
  constructor(currentTime) {
153
153
  /** @const {!Object.<string, !Function>} */
154
154
  this.on = {}; // event listeners
155
+
155
156
  /** @type {!Array.<!TextTrack>} */
156
157
  this.textTracks = [];
157
158
 
159
+ // In a real video element, textTracks is an event target.
160
+ // Since Player listens to events on textTracks, we need to fake that
161
+ // interface.
162
+ this.textTracksEventTarget = new shaka.util.FakeEventTarget();
163
+ this.textTracks.addEventListener =
164
+ // eslint-disable-next-line no-restricted-syntax
165
+ this.textTracksEventTarget.addEventListener.bind(
166
+ this.textTracksEventTarget);
167
+ this.textTracks.removeEventListener =
168
+ // eslint-disable-next-line no-restricted-syntax
169
+ this.textTracksEventTarget.removeEventListener.bind(
170
+ this.textTracksEventTarget);
171
+ this.textTracks.dispatchEvent =
172
+ // eslint-disable-next-line no-restricted-syntax
173
+ this.textTracksEventTarget.dispatchEvent.bind(
174
+ this.textTracksEventTarget);
175
+
158
176
  this.currentTime = currentTime || 0;
159
177
  this.readyState = 0;
160
178
  this.playbackRate = 1;
@@ -173,6 +191,10 @@ shaka.test.FakeVideo = class {
173
191
  jasmine.createSpy('addTextTrack').and.callFake((kind, id) => {
174
192
  const track = new shaka.test.FakeTextTrack();
175
193
  this.textTracks.push(track);
194
+
195
+ const trackEvent = new shaka.util.FakeEvent('addtrack', {track});
196
+ this.textTracksEventTarget.dispatchEvent(trackEvent);
197
+
176
198
  return track;
177
199
  });
178
200
 
@@ -308,11 +330,18 @@ shaka.test.FakePlayhead = class {
308
330
  /** @type {!jasmine.Spy} */
309
331
  this.setRebufferingGoal = jasmine.createSpy('setRebufferingGoal');
310
332
 
333
+ /** @private {number} */
334
+ this.startTime_ = 0;
335
+
311
336
  /** @type {!jasmine.Spy} */
312
- this.setStartTime = jasmine.createSpy('setStartTime');
337
+ this.setStartTime = jasmine.createSpy('setStartTime')
338
+ .and.callFake((value) => {
339
+ this.startTime_ = value;
340
+ });
313
341
 
314
342
  /** @type {!jasmine.Spy} */
315
- this.getTime = jasmine.createSpy('getTime').and.returnValue(0);
343
+ this.getTime = jasmine.createSpy('getTime')
344
+ .and.callFake(() => this.startTime_);
316
345
 
317
346
  /** @type {!jasmine.Spy} */
318
347
  this.setBuffering = jasmine.createSpy('setBuffering');
@@ -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) => {
@@ -78,11 +78,11 @@
78
78
 
79
79
  /* This math is determining how far the button is from the right edge.
80
80
  * Ad panel's parent is centered and @bottom-controls-width wide, so
81
- * 100 - @bottom-controls-width = margins from both sides of the container.
81
+ * 100% - @bottom-controls-width = margins from both sides of the container.
82
82
  * That divided by 2 is margin on one side, so we take that, and move the
83
83
  * button from its normal position to the right by that percentage.
84
84
  */
85
- right: (100 - @bottom-controls-width) / 2 * -1;
85
+ right: calc((100% - @bottom-controls-width) / 2 * -1);
86
86
  display: flex;
87
87
  flex-direction: row;
88
88
  margin: 0;
@@ -26,7 +26,7 @@
26
26
  *
27
27
  * Based on tips from https://stackoverflow.com/a/12925343 */
28
28
  box-sizing: border-box;
29
- padding: @play-button-size-percentage / 2;
29
+ padding: calc(@play-button-size-percentage / 2);
30
30
  width: 0;
31
31
  height: 0;
32
32
 
@@ -161,7 +161,7 @@
161
161
  /* Consistent margins (external) and padding (internal) between controls. */
162
162
  .bottom-panels-elements-margin();
163
163
 
164
- padding: 0;
164
+ padding: 0 5px;
165
165
 
166
166
  /* Transparent backgrounds, no borders, and a pointer when you mouse over
167
167
  * them. */
@@ -337,8 +337,8 @@
337
337
 
338
338
  .shaka-spinner {
339
339
  /* This uses the same trickery as the big play button define
340
- the spinner's width and height. See .shaka-play-button
341
- for the detailed explanation. */
340
+ * the spinner's width and height. See .shaka-play-button
341
+ * for the detailed explanation. */
342
342
 
343
343
  /* For the padding thing to work, spinner div needs to be an
344
344
  overlay-parent and spinner svg - an overlay child. */
@@ -346,11 +346,11 @@
346
346
 
347
347
  margin: 0;
348
348
  box-sizing: border-box;
349
- padding: @spinner-size-percentage / 2;
349
+ padding: calc(@spinner-size-percentage / 2);
350
350
  width: 0;
351
351
  height: 0;
352
352
 
353
353
  /* Add a bit of a white shadow to keep our black spinner visible
354
- on a black background. */
354
+ * on a black background. */
355
355
  filter: drop-shadow(0 0 2px rgba(255 255 255 / 50%));
356
356
  }
@@ -37,7 +37,7 @@
37
37
  }
38
38
 
39
39
  .bottom-panels-elements-margin() {
40
- margin: 1px 6px;
40
+ margin: 1px;
41
41
  }
42
42
 
43
43
  /* For containers which host elements overlaying other things. */
@@ -39,7 +39,7 @@
39
39
  .overlay-parent();
40
40
 
41
41
  /* Vertical margins to occupy the same space as the thumb. */
42
- margin: (@thumb-size - @track-height)/2 6px;
42
+ margin: calc((@thumb-size - @track-height) / 2) 6px;
43
43
 
44
44
  /* Smaller height to contain the background for the virtual track. */
45
45
  height: @track-height;
@@ -109,7 +109,7 @@
109
109
 
110
110
  /* Position the top of the range element so that it is centered on the
111
111
  * container. Note that the container is actually smaller than the thumb. */
112
- top: (@track-height - @thumb-size) / 2;
112
+ top: calc((@track-height - @thumb-size) / 2);
113
113
 
114
114
  /* Make sure clicking at the very top of the bar still takes effect and is not
115
115
  * confused with clicking the video to play/pause it. */
@@ -140,6 +140,7 @@
140
140
 
141
141
  .shaka-volume-bar-container {
142
142
  width: 100px;
143
+ padding: 0;
143
144
  }
144
145
 
145
146
  .shaka-range-element {
@@ -48,7 +48,7 @@
48
48
 
49
49
  /* Override .material-icons-round text styling */
50
50
  font-family: Roboto-Regular, Roboto, sans-serif;
51
- line-height: @material-icons-width / 2;
51
+ line-height: calc(@material-icons-width / 2);
52
52
  white-space: nowrap;
53
53
  font-size: 13px;
54
54
 
@@ -60,10 +60,10 @@
60
60
 
61
61
  /* Positioning */
62
62
  position: absolute;
63
- bottom: @material-icons-width + 5px;
63
+ bottom: calc(@material-icons-width + 5px);
64
64
 
65
65
  /* Left attribute is set to half of the width of the parent button */
66
- left: @material-icons-width / 2;
66
+ left: calc(@material-icons-width / 2);
67
67
 
68
68
  /* The tooltip is also translated 50% to appear centered */
69
69
  .translateX(-0.5);
package/ui/seek_bar.js CHANGED
@@ -74,7 +74,8 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
74
74
  });
75
75
 
76
76
  /**
77
- * When user is scrubbing the seek bar - we should pause the video - see https://git.io/JUhHG
77
+ * When user is scrubbing the seek bar - we should pause the video - see
78
+ * https://github.com/google/shaka-player/pull/2898#issuecomment-705229215
78
79
  * but will conditionally pause or play the video after scrubbing
79
80
  * depending on its previous state
80
81
  *
@@ -1,10 +0,0 @@
1
- <!--
2
- Please remember to:
3
-
4
- 1. Use Conventional Commits syntax (fix: ..., feat: ..., etc.) in commits and
5
- PR title (https://www.conventionalcommits.org/)
6
- 2. Tag any related or fixed issues ("Issue #123", "Closes #420")
7
- 3. Sign the Google CLA if you haven't (https://cla.developers.google.com)
8
-
9
- You may delete this comment from the PR description.
10
- -->
@@ -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).
package/lib/util/mutex.js DELETED
@@ -1,52 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- goog.provide('shaka.util.Mutex');
8
-
9
-
10
- /**
11
- * @summary A simple mutex.
12
- */
13
- shaka.util.Mutex = class {
14
- /** Creates the mutex. */
15
- constructor() {
16
- /** @private {!Array.<function()>} */
17
- this.waiting_ = [];
18
-
19
- /** @private {number} */
20
- this.nextMutexId_ = 0;
21
-
22
- /** @private {number} */
23
- this.acquiredMutexId_ = 0;
24
- }
25
-
26
- /** @return {!Promise.<number>} mutexId */
27
- async acquire() {
28
- const mutexId = ++this.nextMutexId_;
29
- if (!this.acquiredMutexId_) {
30
- this.acquiredMutexId_ = mutexId;
31
- } else {
32
- await (new Promise((resolve, reject) => {
33
- this.waiting_.push(() => {
34
- this.acquiredMutexId_ = mutexId;
35
- resolve();
36
- });
37
- }));
38
- }
39
- return mutexId;
40
- }
41
-
42
- /** @param {number} mutexId */
43
- release(mutexId) {
44
- if (mutexId == this.acquiredMutexId_) {
45
- this.acquiredMutexId_ = 0;
46
- if (this.waiting_.length > 0) {
47
- const callback = this.waiting_.shift();
48
- callback();
49
- }
50
- }
51
- }
52
- };