shaka-player 4.9.2 → 4.9.4

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.
@@ -11,5 +11,5 @@
11
11
  */
12
12
 
13
13
 
14
- /** @type {boolean} */
14
+ /** @type {string} */
15
15
  window.shakaMediaKeysPolyfill;
@@ -268,7 +268,8 @@ shaka.abr.SimpleAbrManager = class {
268
268
 
269
269
  if (currentBandwidth >= minBandwidth &&
270
270
  currentBandwidth <= maxBandwidth &&
271
- chosen.bandwidth != item.bandwidth) {
271
+ (chosen.bandwidth != item.bandwidth ||
272
+ this.isSameBandwidthAndHigherResolution_(chosen, item))) {
272
273
  chosen = item;
273
274
  }
274
275
  }
@@ -537,6 +538,23 @@ shaka.abr.SimpleAbrManager = class {
537
538
  return v1.width - v2.width;
538
539
  });
539
540
  }
541
+
542
+ /**
543
+ * @param {shaka.extern.Variant} chosenVariant
544
+ * @param {shaka.extern.Variant} newVariant
545
+ * @return {boolean}
546
+ * @private
547
+ */
548
+ isSameBandwidthAndHigherResolution_(chosenVariant, newVariant) {
549
+ if (chosenVariant.bandwidth != newVariant.bandwidth) {
550
+ return false;
551
+ }
552
+ if (!chosenVariant.video || !newVariant.video) {
553
+ return false;
554
+ }
555
+ return chosenVariant.video.width < newVariant.video.width ||
556
+ chosenVariant.video.height < newVariant.video.height;
557
+ }
540
558
  };
541
559
 
542
560
 
@@ -489,7 +489,7 @@ shaka.hls.HlsParser = class {
489
489
  mediaSequenceNumber);
490
490
  stream.segmentIndex.evict(playlistStartTime);
491
491
  }
492
- const oldSegment = segments[0];
492
+ const oldSegment = stream.segmentIndex.earliestReference();
493
493
  goog.asserts.assert(oldSegment, 'Should have segments!');
494
494
 
495
495
  streamInfo.minTimestamp = oldSegment.startTime;
@@ -4282,7 +4282,7 @@ shaka.hls.HlsParser = class {
4282
4282
  }
4283
4283
 
4284
4284
  const uri = drmTag.getRequiredAttrValue('URI');
4285
- const parsedData = shaka.net.DataUriPlugin.parseRaw(uri);
4285
+ const parsedData = shaka.net.DataUriPlugin.parseRaw(uri.split('?')[0]);
4286
4286
 
4287
4287
  // The data encoded in the URI is a PSSH box to be used as init data.
4288
4288
  const pssh = shaka.util.BufferUtils.toUint8(parsedData.data);
@@ -4325,7 +4325,7 @@ shaka.hls.HlsParser = class {
4325
4325
  }
4326
4326
 
4327
4327
  const uri = drmTag.getRequiredAttrValue('URI');
4328
- const parsedData = shaka.net.DataUriPlugin.parseRaw(uri);
4328
+ const parsedData = shaka.net.DataUriPlugin.parseRaw(uri.split('?')[0]);
4329
4329
 
4330
4330
  // The data encoded in the URI is a PlayReady Pro Object, so we need
4331
4331
  // convert it to pssh.
@@ -36,7 +36,8 @@ shaka.media.ContentWorkarounds = class {
36
36
  */
37
37
  static fakeEncryption(initSegmentBuffer, uri) {
38
38
  const ContentWorkarounds = shaka.media.ContentWorkarounds;
39
- let initSegment = shaka.util.BufferUtils.toUint8(initSegmentBuffer);
39
+ const initSegment = shaka.util.BufferUtils.toUint8(initSegmentBuffer);
40
+ let modifiedInitSegment = initSegment;
40
41
  let isEncrypted = false;
41
42
  /** @type {shaka.extern.ParsedBox} */
42
43
  let stsdBox;
@@ -166,11 +167,24 @@ shaka.media.ContentWorkarounds = class {
166
167
  const insertedBoxType =
167
168
  shaka.util.Mp4Parser.typeToString(workItem.newType);
168
169
  shaka.log.debug(`Inserting "${insertedBoxType}" box into init segment.`);
169
- initSegment = ContentWorkarounds.insertEncryptionMetadata_(
170
- initSegment, stsdBox, workItem.box, ancestorBoxes, workItem.newType);
170
+ modifiedInitSegment = ContentWorkarounds.insertEncryptionMetadata_(
171
+ modifiedInitSegment, stsdBox, workItem.box, ancestorBoxes,
172
+ workItem.newType);
171
173
  }
172
174
 
173
- return initSegment;
175
+ // Edge Windows needs the unmodified init segment to be appended after the
176
+ // patched one, otherwise video element throws following error:
177
+ // CHUNK_DEMUXER_ERROR_APPEND_FAILED: Sample encryption info is not
178
+ // available.
179
+ if (shaka.util.Platform.isEdge() && shaka.util.Platform.isWindows()) {
180
+ const doubleInitSegment = new Uint8Array(initSegment.byteLength +
181
+ modifiedInitSegment.byteLength);
182
+ doubleInitSegment.set(modifiedInitSegment);
183
+ doubleInitSegment.set(initSegment, modifiedInitSegment.byteLength);
184
+ return doubleInitSegment;
185
+ }
186
+
187
+ return modifiedInitSegment;
174
188
  }
175
189
 
176
190
  /**
@@ -197,11 +211,12 @@ shaka.media.ContentWorkarounds = class {
197
211
  const newInitSegment =
198
212
  new Uint8Array(initSegment.byteLength + metadataBoxArray.byteLength);
199
213
 
200
- // For Xbox One, we cut and insert at the start of the source box. For
201
- // other platforms, we cut and insert at the end of the source box. It's
214
+ // For Xbox One & Edge, we cut and insert at the start of the source box.
215
+ // For other platforms, we cut and insert at the end of the source box. It's
202
216
  // not clear why this is necessary on Xbox One, but it seems to be evidence
203
217
  // of another bug in the firmware implementation of MediaSource & EME.
204
- const cutPoint = shaka.util.Platform.isXboxOne() ?
218
+ const cutPoint =
219
+ (shaka.util.Platform.isXboxOne() || shaka.util.Platform.isEdge()) ?
205
220
  sourceBox.start :
206
221
  sourceBox.start + sourceBox.size;
207
222
 
@@ -12,6 +12,7 @@ goog.require('shaka.net.NetworkingEngine');
12
12
  goog.require('shaka.transmuxer.TransmuxerEngine');
13
13
  goog.require('shaka.util.BufferUtils');
14
14
  goog.require('shaka.util.Destroyer');
15
+ goog.require('shaka.util.DrmUtils');
15
16
  goog.require('shaka.util.Error');
16
17
  goog.require('shaka.util.EventManager');
17
18
  goog.require('shaka.util.FakeEvent');
@@ -178,12 +179,18 @@ shaka.media.DrmEngine = class {
178
179
 
179
180
  // |video_| will be |null| if we never attached to a video element.
180
181
  if (this.video_) {
181
- goog.asserts.assert(!this.video_.src, 'video src must be removed first!');
182
+ // Webkit EME implementation requires the src to be defined to clear
183
+ // the MediaKeys.
184
+ if (!shaka.util.Platform.isMediaKeysPolyfilled('webkit')) {
185
+ goog.asserts.assert(!this.video_.src,
186
+ 'video src must be removed first!');
187
+ }
182
188
 
183
189
  try {
184
190
  await this.video_.setMediaKeys(null);
185
191
  } catch (error) {
186
192
  // Ignore any failures while removing media keys from the video element.
193
+ shaka.log.debug(`DrmEngine.destroyNow_ exception`, error);
187
194
  }
188
195
 
189
196
  this.video_ = null;
@@ -762,28 +769,6 @@ shaka.media.DrmEngine = class {
762
769
  return drmInfo ? drmInfo.keySystem : '';
763
770
  }
764
771
 
765
- /**
766
- * @param {?string} keySystem
767
- * @return {boolean} */
768
- static isPlayReadyKeySystem(keySystem) {
769
- if (keySystem) {
770
- return !!keySystem.match(/^com\.(microsoft|chromecast)\.playready/);
771
- }
772
-
773
- return false;
774
- }
775
-
776
- /**
777
- * @param {?string} keySystem
778
- * @return {boolean} */
779
- static isFairPlayKeySystem(keySystem) {
780
- if (keySystem) {
781
- return !!keySystem.match(/^com\.apple\.fps/);
782
- }
783
-
784
- return false;
785
- }
786
-
787
772
  /**
788
773
  * Check if DrmEngine (as initialized) will likely be able to support the
789
774
  * given content type.
@@ -1502,7 +1487,7 @@ shaka.media.DrmEngine = class {
1502
1487
  }
1503
1488
  // NOTE: allowCrossSiteCredentials can be set in a request filter.
1504
1489
 
1505
- if (shaka.media.DrmEngine.isPlayReadyKeySystem(
1490
+ if (shaka.util.DrmUtils.isPlayReadyKeySystem(
1506
1491
  this.currentDrmInfo_.keySystem)) {
1507
1492
  this.unpackPlayReadyRequest_(request);
1508
1493
  }
@@ -1686,7 +1671,7 @@ shaka.media.DrmEngine = class {
1686
1671
  // NOTE that we skip this if byteLength != 16. This is used for Edge
1687
1672
  // which uses single-byte dummy key IDs.
1688
1673
  // However, unlike Edge and Chromecast, Tizen doesn't have this problem.
1689
- if (shaka.media.DrmEngine.isPlayReadyKeySystem(
1674
+ if (shaka.util.DrmUtils.isPlayReadyKeySystem(
1690
1675
  this.currentDrmInfo_.keySystem) &&
1691
1676
  keyId.byteLength == 16 &&
1692
1677
  (shaka.util.Platform.isEdge() || shaka.util.Platform.isPS4())) {
@@ -53,15 +53,17 @@ shaka.media.MediaSourceEngine = class {
53
53
  * The text displayer that will be used with the text engine.
54
54
  * MediaSourceEngine takes ownership of the displayer. When
55
55
  * MediaSourceEngine is destroyed, it will destroy the displayer.
56
- * @param {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)=}
57
- * onMetadata
56
+ * @param {!shaka.media.MediaSourceEngine.PlayerInterface} playerInterface
57
+ * Interface for common player methods.
58
58
  * @param {?shaka.lcevc.Dec} [lcevcDec] Optional - LCEVC Decoder Object
59
- *
60
59
  */
61
- constructor(video, textDisplayer, onMetadata, lcevcDec) {
60
+ constructor(video, textDisplayer, playerInterface, lcevcDec) {
62
61
  /** @private {HTMLMediaElement} */
63
62
  this.video_ = video;
64
63
 
64
+ /** @private {?shaka.media.MediaSourceEngine.PlayerInterface} */
65
+ this.playerInterface_ = playerInterface;
66
+
65
67
  /** @private {?shaka.extern.MediaSourceConfiguration} */
66
68
  this.config_ = null;
67
69
 
@@ -87,12 +89,6 @@ shaka.media.MediaSourceEngine = class {
87
89
  /** @private {boolean} */
88
90
  this.segmentRelativeVttTiming_ = false;
89
91
 
90
- const onMetadataNoOp = (metadata, timestampOffset, segmentEnd) => {};
91
-
92
- /** @private {!function(!Array.<shaka.extern.ID3Metadata>,
93
- number, ?number)} */
94
- this.onMetadata_ = onMetadata || onMetadataNoOp;
95
-
96
92
  /** @private {?shaka.lcevc.Dec} */
97
93
  this.lcevcDec_ = lcevcDec || null;
98
94
 
@@ -316,7 +312,7 @@ shaka.media.MediaSourceEngine = class {
316
312
  'audio/mp4; codecs="mp4a.40.2"',
317
313
  'audio/mp4; codecs="ac-3"',
318
314
  'audio/mp4; codecs="ec-3"',
319
- 'audio/mp4; codecs="ac-4"',
315
+ 'audio/mp4; codecs="ac-4.02.01.01"',
320
316
  'audio/mp4; codecs="opus"',
321
317
  'audio/mp4; codecs="flac"',
322
318
  'audio/mp4; codecs="dtsc"', // DTS Digital Surround
@@ -438,6 +434,7 @@ shaka.media.MediaSourceEngine = class {
438
434
  this.lcevcDec_ = null;
439
435
 
440
436
  this.tsParser_ = null;
437
+ this.playerInterface_ = null;
441
438
  }
442
439
 
443
440
  /**
@@ -813,7 +810,8 @@ shaka.media.MediaSourceEngine = class {
813
810
  dts: reference.startTime,
814
811
  pts: reference.startTime,
815
812
  };
816
- this.onMetadata_([metadata], /* offset= */ 0, reference.endTime);
813
+ this.playerInterface_.onMetadata(
814
+ [metadata], /* offset= */ 0, reference.endTime);
817
815
  }
818
816
  } else if (mimeType.includes('/mp4') &&
819
817
  reference && reference.timestampOffset == 0 &&
@@ -855,7 +853,7 @@ shaka.media.MediaSourceEngine = class {
855
853
  }
856
854
  const metadata = tsParser.getMetadata();
857
855
  if (metadata.length) {
858
- this.onMetadata_(metadata, timestampOffset,
856
+ this.playerInterface_.onMetadata(metadata, timestampOffset,
859
857
  reference ? reference.endTime : null);
860
858
  }
861
859
  }
@@ -1719,8 +1717,11 @@ shaka.media.MediaSourceEngine = class {
1719
1717
  * @private
1720
1718
  */
1721
1719
  workAroundBrokenPlatforms_(segment, startTime, contentType, uri) {
1720
+ const Platform = shaka.util.Platform;
1721
+
1722
1722
  const isInitSegment = startTime == null;
1723
1723
  const encryptionExpected = this.expectedEncryption_[contentType];
1724
+ const keySystem = this.playerInterface_.getKeySystem();
1724
1725
 
1725
1726
  // If:
1726
1727
  // 1. the configuration tells to insert fake encryption,
@@ -1735,7 +1736,7 @@ shaka.media.MediaSourceEngine = class {
1735
1736
  if (this.config_.insertFakeEncryptionInInit &&
1736
1737
  isInitSegment &&
1737
1738
  encryptionExpected &&
1738
- shaka.util.Platform.requiresEncryptionInfoInAllInitSegments() &&
1739
+ Platform.requiresEncryptionInfoInAllInitSegments(keySystem) &&
1739
1740
  shaka.util.MimeUtils.getContainerType(
1740
1741
  this.sourceBufferTypes_[contentType]) == 'mp4') {
1741
1742
  shaka.log.debug('Forcing fake encryption information in init segment.');
@@ -2151,3 +2152,19 @@ shaka.media.MediaSourceEngine.SourceBufferMode_ = {
2151
2152
  SEQUENCE: 'sequence',
2152
2153
  SEGMENTS: 'segments',
2153
2154
  };
2155
+
2156
+
2157
+ /**
2158
+ * @typedef {{
2159
+ * getKeySystem: function():?string,
2160
+ * onMetadata: function(!Array<shaka.extern.ID3Metadata>, number, ?number)
2161
+ * }}
2162
+ *
2163
+ * @summary Player interface
2164
+ * @property {function():?string} getKeySystem
2165
+ * Gets currently used key system or null if not used.
2166
+ * @property {function(
2167
+ * !Array<shaka.extern.ID3Metadata>, number, ?number)} onMetadata
2168
+ * Callback to use when metadata arrives.
2169
+ */
2170
+ shaka.media.MediaSourceEngine.PlayerInterface;
@@ -98,7 +98,7 @@ shaka.media.PresentationTimeline = class {
98
98
  this.startTimeLocked_ = false;
99
99
 
100
100
  /** @private {?number} */
101
- this.initialProgramDateTime_ = null;
101
+ this.initialProgramDateTime_ = presentationStartTime;
102
102
  }
103
103
 
104
104
 
package/lib/player.js CHANGED
@@ -901,21 +901,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
901
901
  */
902
902
  setupLcevc_(config) {
903
903
  if (config.lcevc.enabled) {
904
- const tracks = this.getVariantTracks();
905
- if (tracks && tracks[0] && tracks[0].videoMimeType == 'video/mp2t') {
906
- const edge = shaka.util.Platform.isEdge() ||
907
- shaka.util.Platform.isLegacyEdge();
908
- if (edge) {
909
- if (!config.mediaSource.forceTransmux) {
910
- // If forceTransmux is disabled for Microsoft Edge, LCEVC data
911
- // is stripped out in case of a MPEG-2 TS container.
912
- // Hence the warning for Microsoft Edge when playing content with
913
- // MPEG-2 TS container.
914
- shaka.log.alwaysWarn('LCEVC Warning: For MPEG-2 TS decoding '+
915
- 'the config.mediaSource.forceTransmux must be enabled.');
916
- }
917
- }
918
- }
919
904
  this.closeLcevcDec_();
920
905
  this.createLcevcDec_(config.lcevc);
921
906
  } else {
@@ -1371,6 +1356,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1371
1356
  this.playhead_ = null;
1372
1357
  }
1373
1358
 
1359
+ // EME v0.1b requires the media element to clear the MediaKeys
1360
+ if (shaka.util.Platform.isMediaKeysPolyfilled('webkit') &&
1361
+ this.drmEngine_) {
1362
+ await this.drmEngine_.destroy();
1363
+ this.drmEngine_ = null;
1364
+ }
1365
+
1374
1366
  // Media source engine holds onto the media element, and in order to
1375
1367
  // detach the media keys (with drm engine), we need to break the
1376
1368
  // connection between media source engine and the media element.
@@ -2268,8 +2260,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2268
2260
  const mediaSourceEngine = this.createMediaSourceEngine(
2269
2261
  this.video_,
2270
2262
  textDisplayer,
2271
- (metadata, offset, endTime) => {
2272
- this.processTimedMetadataMediaSrc_(metadata, offset, endTime);
2263
+ {
2264
+ getKeySystem: () => this.keySystem(),
2265
+ onMetadata: (metadata, offset, endTime) => {
2266
+ this.processTimedMetadataMediaSrc_(metadata, offset, endTime);
2267
+ },
2273
2268
  },
2274
2269
  this.lcevcDec_);
2275
2270
  mediaSourceEngine.configure(this.config_.mediaSource);
@@ -3403,17 +3398,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3403
3398
  *
3404
3399
  * @param {!HTMLMediaElement} mediaElement
3405
3400
  * @param {!shaka.extern.TextDisplayer} textDisplayer
3406
- * @param {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)}
3407
- * onMetadata
3401
+ * @param {!shaka.media.MediaSourceEngine.PlayerInterface} playerInterface
3408
3402
  * @param {shaka.lcevc.Dec} lcevcDec
3409
3403
  *
3410
3404
  * @return {!shaka.media.MediaSourceEngine}
3411
3405
  */
3412
- createMediaSourceEngine(mediaElement, textDisplayer, onMetadata, lcevcDec) {
3406
+ createMediaSourceEngine(mediaElement, textDisplayer, playerInterface,
3407
+ lcevcDec) {
3413
3408
  return new shaka.media.MediaSourceEngine(
3414
3409
  mediaElement,
3415
3410
  textDisplayer,
3416
- onMetadata,
3411
+ playerInterface,
3417
3412
  lcevcDec);
3418
3413
  }
3419
3414
 
@@ -7454,7 +7449,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
7454
7449
  * @export
7455
7450
  */
7456
7451
  // eslint-disable-next-line no-useless-concat
7457
- shaka.Player.version = 'v4.9.2' + '-uncompiled'; // x-release-please-version
7452
+ shaka.Player.version = 'v4.9.4' + '-uncompiled'; // x-release-please-version
7458
7453
 
7459
7454
  // Initialize the deprecation system using the version string we just set
7460
7455
  // on the player.
@@ -76,7 +76,7 @@ shaka.polyfill.PatchedMediaKeysApple = class {
76
76
  navigator.requestMediaKeySystemAccess =
77
77
  PatchedMediaKeysApple.requestMediaKeySystemAccess;
78
78
 
79
- window.shakaMediaKeysPolyfill = true;
79
+ window.shakaMediaKeysPolyfill = PatchedMediaKeysApple.apiName_;
80
80
  }
81
81
 
82
82
  /**
@@ -115,7 +115,7 @@ shaka.polyfill.PatchedMediaKeysApple = class {
115
115
  PatchedMediaKeysApple.originalNavigatorRequestMediaKeySystemAccess = null;
116
116
  PatchedMediaKeysApple.originalHTMLMediaElementPrototypeMediaKeys = null;
117
117
 
118
- window.shakaMediaKeysPolyfill = false;
118
+ window.shakaMediaKeysPolyfill = '';
119
119
  }
120
120
 
121
121
  /**
@@ -791,3 +791,10 @@ shaka.polyfill.PatchedMediaKeysApple.MediaKeyStatusMap = class {
791
791
  goog.asserts.assert(false, 'Not used! Provided only for the compiler.');
792
792
  }
793
793
  };
794
+
795
+ /**
796
+ * API name.
797
+ *
798
+ * @private {string}
799
+ */
800
+ shaka.polyfill.PatchedMediaKeysApple.apiName_ = 'apple';
@@ -50,7 +50,7 @@ shaka.polyfill.PatchedMediaKeysNop = class {
50
50
  window.MediaKeys = PatchedMediaKeysNop.MediaKeys;
51
51
  window.MediaKeySystemAccess = PatchedMediaKeysNop.MediaKeySystemAccess;
52
52
 
53
- window.shakaMediaKeysPolyfill = true;
53
+ window.shakaMediaKeysPolyfill = PatchedMediaKeysNop.apiName_;
54
54
  }
55
55
 
56
56
  /**
@@ -136,6 +136,13 @@ shaka.polyfill.PatchedMediaKeysNop.MediaKeySystemAccess = class {
136
136
  createMediaKeys() {}
137
137
  };
138
138
 
139
+ /**
140
+ * API name.
141
+ *
142
+ * @private {string}
143
+ */
144
+ shaka.polyfill.PatchedMediaKeysNop.apiName_ = 'nop';
145
+
139
146
 
140
147
  // A low priority ensures this is the last and acts as a fallback.
141
148
  shaka.polyfill.register(shaka.polyfill.PatchedMediaKeysNop.install, -10);
@@ -73,7 +73,7 @@ shaka.polyfill.PatchedMediaKeysWebkit = class {
73
73
  window.MediaKeys = PatchedMediaKeysWebkit.MediaKeys;
74
74
  window.MediaKeySystemAccess = PatchedMediaKeysWebkit.MediaKeySystemAccess;
75
75
 
76
- window.shakaMediaKeysPolyfill = true;
76
+ window.shakaMediaKeysPolyfill = PatchedMediaKeysWebkit.apiName_;
77
77
  }
78
78
 
79
79
  /**
@@ -860,7 +860,9 @@ class extends shaka.util.FakeEventTarget {
860
860
  PatchedMediaKeysWebkit.prefixApi_('cancelKeyRequest');
861
861
  try {
862
862
  this.media_[cancelKeyRequestName](this.keySystem_, this.sessionId);
863
- } catch (exception) {}
863
+ } catch (exception) {
864
+ shaka.log.debug(`${cancelKeyRequestName} exception`, exception);
865
+ }
864
866
  }
865
867
 
866
868
  // Resolve the 'closed' promise and return it.
@@ -977,4 +979,12 @@ shaka.polyfill.PatchedMediaKeysWebkit.MediaKeyStatusMap = class {
977
979
  shaka.polyfill.PatchedMediaKeysWebkit.prefix_ = '';
978
980
 
979
981
 
982
+ /**
983
+ * API name.
984
+ *
985
+ * @private {string}
986
+ */
987
+ shaka.polyfill.PatchedMediaKeysWebkit.apiName_ = 'webkit';
988
+
989
+
980
990
  shaka.polyfill.register(shaka.polyfill.PatchedMediaKeysWebkit.install);
@@ -0,0 +1,34 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.DrmUtils');
8
+
9
+
10
+ shaka.util.DrmUtils = class {
11
+ /**
12
+ * @param {?string} keySystem
13
+ * @return {boolean}
14
+ */
15
+ static isPlayReadyKeySystem(keySystem) {
16
+ if (keySystem) {
17
+ return !!keySystem.match(/^com\.(microsoft|chromecast)\.playready/);
18
+ }
19
+
20
+ return false;
21
+ }
22
+
23
+ /**
24
+ * @param {?string} keySystem
25
+ * @return {boolean}
26
+ */
27
+ static isFairPlayKeySystem(keySystem) {
28
+ if (keySystem) {
29
+ return !!keySystem.match(/^com\.apple\.fps/);
30
+ }
31
+
32
+ return false;
33
+ }
34
+ };
@@ -7,6 +7,7 @@
7
7
  goog.provide('shaka.util.Platform');
8
8
 
9
9
  goog.require('shaka.log');
10
+ goog.require('shaka.util.DrmUtils');
10
11
  goog.require('shaka.util.Timer');
11
12
 
12
13
 
@@ -590,12 +591,15 @@ shaka.util.Platform = class {
590
591
  * around a lack of such info by inserting fake encryption information into
591
592
  * initialization segments.
592
593
  *
594
+ * @param {?string} keySystem
593
595
  * @return {boolean}
594
596
  * @see https://github.com/shaka-project/shaka-player/issues/2759
595
597
  */
596
- static requiresEncryptionInfoInAllInitSegments() {
598
+ static requiresEncryptionInfoInAllInitSegments(keySystem) {
597
599
  const Platform = shaka.util.Platform;
598
- return Platform.isTizen() || Platform.isXboxOne() || Platform.isOrange();
600
+ const isPlayReady = shaka.util.DrmUtils.isPlayReadyKeySystem(keySystem);
601
+ return Platform.isTizen() || Platform.isXboxOne() || Platform.isOrange() ||
602
+ (Platform.isEdge() && Platform.isWindows() && isPlayReady);
599
603
  }
600
604
 
601
605
  /**
@@ -644,16 +648,17 @@ shaka.util.Platform = class {
644
648
  /**
645
649
  * Returns true if MediaKeys is polyfilled
646
650
  *
651
+ * @param {string=} polyfillType
647
652
  * @return {boolean}
648
653
  */
649
- static isMediaKeysPolyfilled() {
650
- if (window.shakaMediaKeysPolyfill) {
651
- return true;
654
+ static isMediaKeysPolyfilled(polyfillType) {
655
+ if (polyfillType) {
656
+ return polyfillType === window.shakaMediaKeysPolyfill;
652
657
  }
653
-
654
- return false;
658
+ return !!window.shakaMediaKeysPolyfill;
655
659
  }
656
660
 
661
+
657
662
  /**
658
663
  * Detect the maximum resolution that the platform's hardware can handle.
659
664
  *
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.9.2",
4
+ "version": "4.9.4",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [