shaka-player 4.3.14 → 4.3.15

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.
@@ -107,7 +107,7 @@ shaka.Deprecate = class {
107
107
  libraryVersion,
108
108
  '. Additional information:',
109
109
  description,
110
- ].join('');
110
+ ].join(' ');
111
111
 
112
112
  shaka.log.alwaysError(errorMessage);
113
113
  goog.asserts.assert(false, errorMessage);
@@ -3382,7 +3382,22 @@ shaka.hls.HlsParser = class {
3382
3382
  * @return {?shaka.extern.DrmInfo}
3383
3383
  * @private
3384
3384
  */
3385
- static identityDrmParser_(drmTag) {
3385
+ static identityDrmParser_(drmTag, mimeType) {
3386
+ if (mimeType == 'video/mp2t') {
3387
+ throw new shaka.util.Error(
3388
+ shaka.util.Error.Severity.CRITICAL,
3389
+ shaka.util.Error.Category.MANIFEST,
3390
+ shaka.util.Error.Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
3391
+ }
3392
+
3393
+ if (shaka.util.Platform.isMediaKeysPolyfilled()) {
3394
+ throw new shaka.util.Error(
3395
+ shaka.util.Error.Severity.CRITICAL,
3396
+ shaka.util.Error.Category.MANIFEST,
3397
+ shaka.util.Error.Code
3398
+ .HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED);
3399
+ }
3400
+
3386
3401
  const method = drmTag.getRequiredAttrValue('METHOD');
3387
3402
  const VALID_METHODS = ['SAMPLE-AES', 'SAMPLE-AES-CTR'];
3388
3403
  if (!VALID_METHODS.includes(method)) {
@@ -176,7 +176,8 @@ shaka.media.ManifestParser = class {
176
176
  shaka.util.Error.Severity.CRITICAL,
177
177
  shaka.util.Error.Category.MANIFEST,
178
178
  shaka.util.Error.Code.UNABLE_TO_GUESS_MANIFEST_TYPE,
179
- uri);
179
+ uri,
180
+ mimeType);
180
181
  }
181
182
 
182
183
 
package/lib/player.js CHANGED
@@ -2120,7 +2120,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2120
2120
  this.abrManager_ = abrFactory();
2121
2121
  if (typeof this.abrManager_.setMediaElement != 'function') {
2122
2122
  shaka.Deprecate.deprecateFeature(5,
2123
- 'AbrManager',
2123
+ 'AbrManager w/o setMediaElement',
2124
2124
  'Please use an AbrManager with setMediaElement function.');
2125
2125
  this.abrManager_.setMediaElement = () => {};
2126
2126
  }
@@ -7032,7 +7032,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
7032
7032
  * @export
7033
7033
  */
7034
7034
  // eslint-disable-next-line no-useless-concat
7035
- shaka.Player.version = 'v4.3.14' + '-uncompiled'; // x-release-please-version
7035
+ shaka.Player.version = 'v4.3.15' + '-uncompiled'; // x-release-please-version
7036
7036
 
7037
7037
  // Initialize the deprecation system using the version string we just set
7038
7038
  // on the player.
@@ -32,11 +32,12 @@ shaka.polyfill.MediaSource = class {
32
32
 
33
33
  if (!window.MediaSource) {
34
34
  shaka.log.info('No MSE implementation available.');
35
- } else if (window.cast && cast.__platform__ &&
36
- cast.__platform__.canDisplayType) {
35
+ } else if (shaka.util.Platform.isChromecast()) {
37
36
  shaka.log.info('Patching Chromecast MSE bugs.');
38
- // Chromecast cannot make accurate determinations via isTypeSupported.
39
- shaka.polyfill.MediaSource.patchCastIsTypeSupported_();
37
+ // Chromecast fails on some TS content, even though it is supposed to
38
+ // support it. Better to transmux.
39
+ // See https://github.com/shaka-project/shaka-player/issues/5278
40
+ shaka.polyfill.MediaSource.rejectContainer_('mp2t');
40
41
  } else if (safariVersion) {
41
42
  // NOTE: shaka.Player.isBrowserSupported() has its own restrictions on
42
43
  // Safari version.
@@ -161,38 +162,6 @@ shaka.polyfill.MediaSource = class {
161
162
  };
162
163
  }
163
164
 
164
- /**
165
- * Patch isTypeSupported() to chain to a private API on the Chromecast which
166
- * can query for support of detailed content parameters.
167
- *
168
- * @private
169
- */
170
- static patchCastIsTypeSupported_() {
171
- const originalIsTypeSupported = MediaSource.isTypeSupported;
172
-
173
- MediaSource.isTypeSupported = (mimeType) => {
174
- // Parse the basic MIME type from its parameters.
175
- const pieces = mimeType.split(/ *; */);
176
- pieces.shift(); // Remove basic MIME type from pieces.
177
-
178
- const hasCodecs = pieces.some((piece) => piece.startsWith('codecs='));
179
- if (!hasCodecs) {
180
- // Though the original reason for this special case was not documented,
181
- // it is presumed to be because the platform won't accept a MIME type
182
- // without codecs in canDisplayType. It is valid, however, in
183
- // isTypeSupported.
184
- return originalIsTypeSupported(mimeType);
185
- }
186
-
187
- // Only canDisplayType can check extended MIME type parameters on this
188
- // platform (such as frame rate, resolution, etc).
189
- // In previous versions of this polyfill, the MIME type parameters were
190
- // manipulated, filtered, or extended. This is no longer true, so we pass
191
- // the full MIME type to the platform as we received it.
192
- return cast.__platform__.canDisplayType(mimeType);
193
- };
194
- }
195
-
196
165
  /**
197
166
  * Patch isTypeSupported() to translate vp09 codec strings into vp9, to allow
198
167
  * such content to play on older smart TVs.
@@ -673,13 +673,14 @@ shaka.text.VttTextParser = class {
673
673
  refCue.fontFamily, cue.fontFamily);
674
674
  cue.fontSize = VttTextParser.getOrDefault_(
675
675
  refCue.fontSize, cue.fontSize);
676
+ cue.textShadow = VttTextParser.getOrDefault_(
677
+ refCue.textShadow, cue.textShadow);
676
678
 
677
679
  // Overwrite with new values as unable to determine
678
680
  // if new value is set or not
679
681
  cue.fontWeight = refCue.fontWeight;
680
682
  cue.fontStyle = refCue.fontStyle;
681
683
  cue.opacity = refCue.opacity;
682
- cue.textShadow = refCue.textShadow;
683
684
  cue.wrapLine = refCue.wrapLine;
684
685
  }
685
686
 
package/lib/util/error.js CHANGED
@@ -506,6 +506,7 @@ shaka.util.Error.Code = {
506
506
  * <li>Configure the server to accept a HEAD request for the manifest.
507
507
  * </ul>
508
508
  * <br> error.data[0] is the manifest URI.
509
+ * <br> error.data[1] is the detected or specified MIME type.
509
510
  */
510
511
  'UNABLE_TO_GUESS_MANIFEST_TYPE': 4000,
511
512
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.3.14",
4
+ "version": "4.3.15",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -48,7 +48,7 @@
48
48
  "karma-spec-reporter": "^0.0.34",
49
49
  "karma-webdriver-launcher": "^1.0.8",
50
50
  "lcevc_dil.js": "^1.1.20",
51
- "less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
51
+ "less": "^4.2.0",
52
52
  "less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
53
53
  "material-design-lite": "^1.3.0",
54
54
  "mux.js": "^6.2.0",
@@ -3743,6 +3743,34 @@ describe('HlsParser', () => {
3743
3743
  await verifyError(master, media, error, /* onCreateSegmentIndex= */ true);
3744
3744
  });
3745
3745
 
3746
+ it('if SAMPLE-AES encryption with MSE and mp2t content', async () => {
3747
+ const master = [
3748
+ '#EXTM3U\n',
3749
+ '#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1",',
3750
+ 'RESOLUTION=960x540,FRAME-RATE=60\n',
3751
+ 'video\n',
3752
+ ].join('');
3753
+
3754
+ const media = [
3755
+ '#EXTM3U\n',
3756
+ '#EXT-X-TARGETDURATION:6\n',
3757
+ '#EXT-X-PLAYLIST-TYPE:VOD\n',
3758
+ '#EXT-X-KEY:METHOD=SAMPLE-AES,',
3759
+ 'URI="fake",\n',
3760
+ '#EXTINF:5,\n',
3761
+ '#EXT-X-BYTERANGE:121090@616\n',
3762
+ 'main.ts',
3763
+ ].join('');
3764
+
3765
+ const error = new shaka.util.Error(
3766
+ shaka.util.Error.Severity.CRITICAL,
3767
+ shaka.util.Error.Category.MANIFEST,
3768
+ Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
3769
+
3770
+ await verifyError(master, media, error, /* onCreateSegmentIndex= */ true);
3771
+ });
3772
+
3773
+
3746
3774
  describe('if required tags are missing', () => {
3747
3775
  /**
3748
3776
  * @param {string} master
@@ -1197,13 +1197,21 @@ describe('Player', () => {
1197
1197
  'com.widevine.alpha': bogusUrl,
1198
1198
  'com.microsoft.playready': bogusUrl,
1199
1199
  });
1200
- await player.load('test:sintel-enc_compiled');
1200
+
1201
+ // This load may be interrupted, so ignore errors and don't wait.
1202
+ const loadPromise =
1203
+ player.load('test:sintel-enc_compiled').catch(() => {});
1201
1204
 
1202
1205
  await errorPromise;
1203
1206
  expect(unloadPromise).not.toBeNull();
1207
+
1204
1208
  if (unloadPromise) {
1205
1209
  await unloadPromise;
1206
1210
  }
1211
+
1212
+ // This should be done, and errors ignored. But don't leave any Promise
1213
+ // unresolved.
1214
+ await loadPromise;
1207
1215
  });
1208
1216
  }); // describe('unloading')
1209
1217
 
@@ -464,11 +464,11 @@ describe('Player Load Graph', () => {
464
464
 
465
465
  // Make the two requests one-after-another so that we don't have any idle
466
466
  // time between them.
467
- const attachRequest = player.attach(video);
468
- const loadRequest = player.load('test:sintel');
467
+ const attach = player.attach(video);
468
+ const load = player.load('test:sintel');
469
469
 
470
- await attachRequest;
471
- await expectAsync(loadRequest).toBeRejected();
470
+ await attach;
471
+ await expectAsync(load).toBeRejected();
472
472
 
473
473
  // Wait a couple interrupter cycles to allow the player to enter idle
474
474
  // state.
@@ -506,10 +506,12 @@ describe('Player Load Graph', () => {
506
506
  // Normally the player would initialize media source after attaching to
507
507
  // the media element, however since we don't support media source, it
508
508
  // should stop at the attach state.
509
- player.attach(video, /* initMediaSource= */ true);
509
+ const attach = player.attach(video, /* initMediaSource= */ true);
510
510
 
511
511
  const event = await spyIsCalled(stateIdleSpy);
512
512
  expect(event.state).toBe('attach');
513
+
514
+ await attach;
513
515
  });
514
516
 
515
517
  it('loading ignores media source path', async () => {
@@ -518,10 +520,12 @@ describe('Player Load Graph', () => {
518
520
  // Normally the player would load content like this with the media source
519
521
  // path, but since we don't have media source support, it should use the
520
522
  // src= path.
521
- player.load(SMALL_MP4_CONTENT_URI);
523
+ const load = player.load(SMALL_MP4_CONTENT_URI);
522
524
 
523
525
  const event = await spyIsCalled(stateIdleSpy);
524
526
  expect(event.state).toBe('src-equals');
527
+
528
+ await load;
525
529
  });
526
530
 
527
531
  it('unloading ignores init media source flag', async () => {
@@ -531,10 +535,12 @@ describe('Player Load Graph', () => {
531
535
  // Normally the player would try to go to the media source state because
532
536
  // we are saying to initialize media source after unloading, but since we
533
537
  // don't have media source, it should stop at the attach state.
534
- player.unload(/* initMediaSource= */ true);
538
+ const unload = player.unload(/* initMediaSource= */ true);
535
539
 
536
540
  const event = await spyIsCalled(stateIdleSpy);
537
541
  expect(event.state).toBe('attach');
542
+
543
+ await unload;
538
544
  });
539
545
  });
540
546
 
@@ -114,8 +114,8 @@ describe('Player Src Equals', () => {
114
114
  expect(video.currentTime).toBeLessThan(2.0);
115
115
 
116
116
  // Trigger a seek and then wait for the seek to take effect.
117
- // This seek target is very close to the duration of the video.
118
- video.currentTime = 10;
117
+ // This seek target is very close to the duration of the video (10.01s).
118
+ video.currentTime = 9.5;
119
119
  await waiter.waitForMovementOrFailOnTimeout(video, /* timeout= */10);
120
120
 
121
121
  // Make sure the playhead is roughly where we expect it to be after
@@ -559,15 +559,21 @@ describe('Player', () => {
559
559
  });
560
560
 
561
561
  describe('when config.streaming.preferNativeHls is set to true', () => {
562
- beforeEach(() => {
562
+ beforeAll(() => {
563
563
  shaka.media.ManifestParser.registerParserByMime(
564
564
  'application/x-mpegurl',
565
565
  () => new shaka.test.FakeManifestParser(manifest));
566
566
  });
567
567
 
568
+ afterAll(() => {
569
+ // IMPORTANT: restore the ORIGINAL parser. DO NOT just unregister the
570
+ // fake!
571
+ shaka.media.ManifestParser.registerParserByMime(
572
+ 'application/x-mpegurl',
573
+ () => new shaka.hls.HlsParser());
574
+ });
575
+
568
576
  afterEach(() => {
569
- shaka.media.ManifestParser.unregisterParserByMime(
570
- 'application/x-mpegurl');
571
577
  video.canPlayType.calls.reset();
572
578
  });
573
579
 
@@ -1072,6 +1072,37 @@ describe('VttTextParser', () => {
1072
1072
  {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
1073
1073
  });
1074
1074
 
1075
+ it('passes text-shadow when multiple classes included', () => {
1076
+ verifyHelper(
1077
+ [
1078
+ {
1079
+ startTime: 20,
1080
+ endTime: 40,
1081
+ payload: '',
1082
+ nestedCues: [
1083
+ {
1084
+ startTime: 20,
1085
+ endTime: 40,
1086
+ payload: 'Test',
1087
+ fontStyle: Cue.fontStyle.ITALIC,
1088
+ textShadow: 'black 5%',
1089
+ },
1090
+ ],
1091
+ },
1092
+ ],
1093
+ 'WEBVTT\n\n' +
1094
+ 'STYLE\n' +
1095
+ '::cue(.shadow) {\n' +
1096
+ ' text-shadow: black 5%;\n' +
1097
+ '}\n' +
1098
+ '::cue(.italic) {\n' +
1099
+ ' font-style: italic;\n' +
1100
+ '}\n\n' +
1101
+ '00:00:20.000 --> 00:00:40.000\n' +
1102
+ '<c.shadow.italic>Test</c>',
1103
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
1104
+ });
1105
+
1075
1106
  it('supports karaoke style text', () => {
1076
1107
  verifyHelper(
1077
1108
  [
@@ -24,6 +24,7 @@
24
24
  /* Set the fonts for all other content. */
25
25
  * {
26
26
  font-family: Roboto-Regular, Roboto, sans-serif, TengwarTelcontar;
27
+ -webkit-font-smoothing: antialiased;
27
28
  }
28
29
  }
29
30