shaka-player 4.2.9 → 4.2.11

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 (92) hide show
  1. package/.github/workflows/demo-version-index.yaml +3 -3
  2. package/.github/workflows/selenium-lab-tests.yaml +23 -1
  3. package/AUTHORS +2 -1
  4. package/CHANGELOG.md +44 -0
  5. package/CONTRIBUTORS +4 -1
  6. package/README.md +3 -0
  7. package/demo/demo.less +1 -0
  8. package/dist/controls.css +1 -1
  9. package/dist/demo.compiled.debug.js +154 -276
  10. package/dist/demo.compiled.debug.map +4 -4
  11. package/dist/demo.compiled.js +154 -276
  12. package/dist/demo.compiled.map +4 -4
  13. package/dist/demo.css +1 -1
  14. package/dist/demo.css.map +1 -1
  15. package/dist/deps.js +1 -1
  16. package/dist/locales.js +33 -33
  17. package/dist/receiver.compiled.debug.js +36 -65
  18. package/dist/receiver.compiled.debug.map +4 -4
  19. package/dist/receiver.compiled.js +36 -65
  20. package/dist/receiver.compiled.map +4 -4
  21. package/dist/shaka-player.compiled.d.ts +20 -3
  22. package/dist/shaka-player.compiled.debug.d.ts +20 -3
  23. package/dist/shaka-player.compiled.debug.externs.js +26 -12
  24. package/dist/shaka-player.compiled.debug.js +185 -180
  25. package/dist/shaka-player.compiled.debug.map +4 -4
  26. package/dist/shaka-player.compiled.externs.js +26 -12
  27. package/dist/shaka-player.compiled.js +821 -818
  28. package/dist/shaka-player.compiled.map +3 -3
  29. package/dist/shaka-player.ui.d.ts +20 -3
  30. package/dist/shaka-player.ui.debug.d.ts +20 -3
  31. package/dist/shaka-player.ui.debug.externs.js +14 -0
  32. package/dist/shaka-player.ui.debug.js +266 -261
  33. package/dist/shaka-player.ui.debug.map +3 -3
  34. package/dist/shaka-player.ui.externs.js +14 -0
  35. package/dist/shaka-player.ui.js +964 -960
  36. package/dist/shaka-player.ui.map +3 -3
  37. package/docs/tutorials/a11y.md +0 -4
  38. package/docs/tutorials/ad_monetization.md +0 -4
  39. package/docs/tutorials/basic-usage.md +0 -5
  40. package/docs/tutorials/config.md +0 -5
  41. package/docs/tutorials/debugging.md +0 -5
  42. package/docs/tutorials/drm-config.md +0 -5
  43. package/docs/tutorials/fairplay.md +2 -2
  44. package/docs/tutorials/license-server-auth.md +0 -5
  45. package/docs/tutorials/license-wrapping.md +0 -5
  46. package/docs/tutorials/network-and-buffering-config.md +0 -5
  47. package/docs/tutorials/ui-customization.md +0 -5
  48. package/docs/tutorials/ui.md +0 -7
  49. package/docs/tutorials/welcome.md +1 -6
  50. package/externs/network_information.js +7 -2
  51. package/externs/shaka/abr_manager.js +6 -0
  52. package/externs/shaka/net.js +1 -0
  53. package/externs/shaka/player.js +13 -7
  54. package/lib/abr/simple_abr_manager.js +27 -3
  55. package/lib/ads/client_side_ad_manager.js +6 -3
  56. package/lib/dash/dash_parser.js +49 -48
  57. package/lib/debug/log.js +9 -13
  58. package/lib/hls/hls_parser.js +6 -0
  59. package/lib/hls/manifest_text_parser.js +10 -1
  60. package/lib/media/drm_engine.js +9 -6
  61. package/lib/media/media_source_engine.js +17 -8
  62. package/lib/media/segment_index.js +2 -0
  63. package/lib/media/segment_reference.js +22 -0
  64. package/lib/media/streaming_engine.js +17 -7
  65. package/lib/net/http_fetch_plugin.js +79 -57
  66. package/lib/net/networking_engine.js +1 -0
  67. package/lib/player.js +26 -3
  68. package/lib/polyfill/media_capabilities.js +13 -0
  69. package/lib/text/mp4_vtt_parser.js +4 -0
  70. package/lib/text/text_engine.js +1 -0
  71. package/lib/util/manifest_parser_utils.js +1 -2
  72. package/lib/util/mime_utils.js +11 -0
  73. package/lib/util/periods.js +5 -5
  74. package/lib/util/stream_utils.js +2 -2
  75. package/maintained-branches.md +3 -4
  76. package/package.json +9 -3
  77. package/test/hls/hls_live_unit.js +3 -1
  78. package/test/media/content_workarounds_unit.js +43 -0
  79. package/test/media/drm_engine_integration.js +4 -17
  80. package/test/media/media_source_engine_unit.js +31 -0
  81. package/test/media/streaming_engine_unit.js +6 -1
  82. package/test/net/networking_engine_unit.js +6 -1
  83. package/test/player_integration.js +39 -0
  84. package/test/player_unit.js +57 -0
  85. package/test/polyfill/media_capabilities_unit.js +0 -1
  86. package/test/test/assets/text-clip-alt.vtt +63 -0
  87. package/test/test/util/fake_drm_engine.js +3 -0
  88. package/test/test/util/layout_tests.js +4 -3
  89. package/test/test/util/simple_fakes.js +6 -0
  90. package/test/test/util/test_scheme.js +9 -14
  91. package/test/text/mp4_vtt_parser_unit.js +8 -0
  92. package/test/util/mime_utils_unit.js +10 -0
@@ -238,6 +238,9 @@ shaka.media.SegmentReference = class {
238
238
  /** @type {shaka.media.SegmentReference.Status} */
239
239
  this.status = status;
240
240
 
241
+ /** @type {boolean} */
242
+ this.preload = false;
243
+
241
244
  /** @type {?shaka.extern.HlsAes128Key} */
242
245
  this.hlsAes128Key = hlsAes128Key;
243
246
 
@@ -358,6 +361,25 @@ shaka.media.SegmentReference = class {
358
361
  this.status = shaka.media.SegmentReference.Status.UNAVAILABLE;
359
362
  }
360
363
 
364
+ /**
365
+ * Mark the reference as preload.
366
+ *
367
+ * @export
368
+ */
369
+ markAsPreload() {
370
+ this.preload = true;
371
+ }
372
+
373
+ /**
374
+ * Returns true if the segment is preloaded.
375
+ *
376
+ * @return {boolean}
377
+ * @export
378
+ */
379
+ isPreload() {
380
+ return this.preload;
381
+ }
382
+
361
383
  /**
362
384
  * Offset the segment reference by a fixed amount.
363
385
  *
@@ -77,6 +77,9 @@ shaka.media.StreamingEngine = class {
77
77
  /** @private {?shaka.extern.Stream} */
78
78
  this.currentTextStream_ = null;
79
79
 
80
+ /** @private {number} */
81
+ this.textStreamSequenceId_ = 0;
82
+
80
83
  /**
81
84
  * Maps a content type, e.g., 'audio', 'video', or 'text', to a MediaState.
82
85
  *
@@ -220,6 +223,8 @@ shaka.media.StreamingEngine = class {
220
223
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
221
224
  goog.asserts.assert(!this.mediaStates_.has(ContentType.TEXT),
222
225
  'Should not call loadNewTextStream_ while streaming text!');
226
+ this.textStreamSequenceId_++;
227
+ const currentSequenceId = this.textStreamSequenceId_;
223
228
 
224
229
  try {
225
230
  // Clear MediaSource's buffered text, so that the new text stream will
@@ -242,7 +247,7 @@ shaka.media.StreamingEngine = class {
242
247
  const streamText =
243
248
  textDisplayer.isTextVisible() || this.config_.alwaysStreamText;
244
249
 
245
- if (streamText) {
250
+ if (streamText && (this.textStreamSequenceId_ == currentSequenceId)) {
246
251
  const state = this.createMediaState_(stream);
247
252
  this.mediaStates_.set(ContentType.TEXT, state);
248
253
  this.scheduleUpdate_(state, 0);
@@ -635,10 +640,15 @@ shaka.media.StreamingEngine = class {
635
640
  const mediaState = this.mediaStates_.get(type);
636
641
  const logPrefix = shaka.media.StreamingEngine.logPrefix_(mediaState);
637
642
 
638
- // Always clear the iterator since we need to start streaming from the
639
- // new time. This also happens in clearBuffer_, but if we don't clear,
640
- // we still want to reset the iterator.
641
- mediaState.segmentIterator = null;
643
+ let segment = null;
644
+ if (mediaState.segmentIterator) {
645
+ segment = mediaState.segmentIterator.current();
646
+ }
647
+ // Only reset the iterator if we seek outside the current segment.
648
+ if (!segment || segment.startTime > presentationTime ||
649
+ segment.endTime < presentationTime) {
650
+ mediaState.segmentIterator = null;
651
+ }
642
652
 
643
653
  if (!newTimeIsBuffered(type)) {
644
654
  const bufferEnd =
@@ -1559,10 +1569,10 @@ shaka.media.StreamingEngine = class {
1559
1569
  'waiting for another stream to recover...');
1560
1570
  }
1561
1571
 
1562
- // QuotaExceededError gets thrown if evication didn't help to make room
1572
+ // QuotaExceededError gets thrown if eviction didn't help to make room
1563
1573
  // for a segment. We want to wait for a while (4 seconds is just an
1564
1574
  // arbitrary number) before updating to give the playhead a chance to
1565
- // advance, so we don't immidiately throw again.
1575
+ // advance, so we don't immediately throw again.
1566
1576
  this.scheduleUpdate_(mediaState, 4);
1567
1577
  }
1568
1578
 
@@ -120,65 +120,77 @@ shaka.net.HttpFetchPlugin = class {
120
120
  // not the body yet.
121
121
  headersReceived(shaka.net.HttpFetchPlugin.headersToGenericObject_(
122
122
  response.headers));
123
- // Getting the reader in this way allows us to observe the process of
124
- // downloading the body, instead of just waiting for an opaque promise to
125
- // resolve.
126
- // We first clone the response because calling getReader locks the body
127
- // stream; if we didn't clone it here, we would be unable to get the
128
- // response's arrayBuffer later.
129
- const reader = response.clone().body.getReader();
130
-
131
- const contentLengthRaw = response.headers.get('Content-Length');
132
- const contentLength =
133
- contentLengthRaw ? parseInt(contentLengthRaw, 10) : 0;
134
-
135
- const start = (controller) => {
136
- const push = async () => {
137
- let readObj;
138
- try {
139
- readObj = await reader.read();
140
- } catch (e) {
141
- // If we abort the request, we'll get an error here. Just ignore it
142
- // since real errors will be reported when we read the buffer below.
143
- shaka.log.v1('error reading from stream', e.message);
144
- return;
145
- }
146
-
147
- if (!readObj.done) {
148
- loaded += readObj.value.byteLength;
149
- if (streamDataCallback) {
150
- await streamDataCallback(readObj.value);
123
+
124
+ // In new versions of Chromium, HEAD requests now have a response body
125
+ // that is null.
126
+ // So just don't try to download the body at all, if it's a HEAD request,
127
+ // to avoid null reference errors.
128
+ // See: https://crbug.com/1297060
129
+ if (init.method != 'HEAD') {
130
+ goog.asserts.assert(response.body,
131
+ 'non-HEAD responses should have a body');
132
+
133
+ // Getting the reader in this way allows us to observe the process of
134
+ // downloading the body, instead of just waiting for an opaque promise
135
+ // to resolve.
136
+ // We first clone the response because calling getReader locks the body
137
+ // stream; if we didn't clone it here, we would be unable to get the
138
+ // response's arrayBuffer later.
139
+ const reader = response.clone().body.getReader();
140
+
141
+ const contentLengthRaw = response.headers.get('Content-Length');
142
+ const contentLength =
143
+ contentLengthRaw ? parseInt(contentLengthRaw, 10) : 0;
144
+
145
+ const start = (controller) => {
146
+ const push = async () => {
147
+ let readObj;
148
+ try {
149
+ readObj = await reader.read();
150
+ } catch (e) {
151
+ // If we abort the request, we'll get an error here. Just ignore
152
+ // it since real errors will be reported when we read the buffer
153
+ // below.
154
+ shaka.log.v1('error reading from stream', e.message);
155
+ return;
156
+ }
157
+
158
+ if (!readObj.done) {
159
+ loaded += readObj.value.byteLength;
160
+ if (streamDataCallback) {
161
+ await streamDataCallback(readObj.value);
162
+ }
163
+ }
164
+
165
+ const currentTime = Date.now();
166
+ // If the time between last time and this time we got progress event
167
+ // is long enough, or if a whole segment is downloaded, call
168
+ // progressUpdated().
169
+ if (currentTime - lastTime > 100 || readObj.done) {
170
+ progressUpdated(currentTime - lastTime, loaded - lastLoaded,
171
+ contentLength - loaded);
172
+ lastLoaded = loaded;
173
+ lastTime = currentTime;
174
+ }
175
+
176
+ if (readObj.done) {
177
+ goog.asserts.assert(!readObj.value,
178
+ 'readObj should be unset when "done" is true.');
179
+ controller.close();
180
+ } else {
181
+ controller.enqueue(readObj.value);
182
+ push();
151
183
  }
152
- }
153
-
154
- const currentTime = Date.now();
155
- // If the time between last time and this time we got progress event
156
- // is long enough, or if a whole segment is downloaded, call
157
- // progressUpdated().
158
- if (currentTime - lastTime > 100 || readObj.done) {
159
- progressUpdated(currentTime - lastTime, loaded - lastLoaded,
160
- contentLength - loaded);
161
- lastLoaded = loaded;
162
- lastTime = currentTime;
163
- }
164
-
165
- if (readObj.done) {
166
- goog.asserts.assert(!readObj.value,
167
- 'readObj should be unset when "done" is true.');
168
- controller.close();
169
- } else {
170
- controller.enqueue(readObj.value);
171
- push();
172
- }
184
+ };
185
+ push();
173
186
  };
174
- push();
175
- };
176
- // Create a ReadableStream to use the reader. We don't need to use the
177
- // actual stream for anything, though, as we are using the response's
178
- // arrayBuffer method to get the body, so we don't store the
179
- // ReadableStream.
180
- new ReadableStream({start}); // eslint-disable-line no-new
181
- arrayBuffer = await response.arrayBuffer();
187
+ // Create a ReadableStream to use the reader. We don't need to use the
188
+ // actual stream for anything, though, as we are using the response's
189
+ // arrayBuffer method to get the body, so we don't store the
190
+ // ReadableStream.
191
+ new ReadableStream({start}); // eslint-disable-line no-new
192
+ arrayBuffer = await response.arrayBuffer();
193
+ }
182
194
  } catch (error) {
183
195
  if (abortStatus.canceled) {
184
196
  throw new shaka.util.Error(
@@ -243,6 +255,16 @@ shaka.net.HttpFetchPlugin = class {
243
255
  } else {
244
256
  return false;
245
257
  }
258
+ // Old fetch implementations hasn't body and ReadableStream implementation
259
+ // See: https://github.com/shaka-project/shaka-player/issues/5088
260
+ if (window.Response) {
261
+ const response = new Response('');
262
+ if (!response.body) {
263
+ return false;
264
+ }
265
+ } else {
266
+ return false;
267
+ }
246
268
  return !!(window.fetch && window.AbortController);
247
269
  }
248
270
  };
@@ -312,6 +312,7 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
312
312
  if (!responseAndGotProgress.gotProgress &&
313
313
  this.onProgressUpdated_ &&
314
314
  !response.fromCache &&
315
+ request.method != 'HEAD' &&
315
316
  type == shaka.net.NetworkingEngine.RequestType.SEGMENT) {
316
317
  this.onProgressUpdated_(response.timeMs, response.data.byteLength);
317
318
  }
package/lib/player.js CHANGED
@@ -806,7 +806,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
806
806
  }
807
807
 
808
808
  this.abrManagerFactory_ = null;
809
- this.abrManager_ = null;
810
809
  this.config_ = null;
811
810
  this.stats_ = null;
812
811
  this.videoContainer_ = null;
@@ -817,6 +816,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
817
816
  this.networkingEngine_ = null;
818
817
  }
819
818
 
819
+ if (this.abrManager_) {
820
+ this.abrManager_.release();
821
+ this.abrManager_ = null;
822
+ }
823
+
820
824
  // FakeEventTarget implements IReleasable
821
825
  super.release();
822
826
  }
@@ -1232,6 +1236,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1232
1236
  */
1233
1237
  shouldUseSrcEquals_(payload) {
1234
1238
  const Platform = shaka.util.Platform;
1239
+ const MimeUtils = shaka.util.MimeUtils;
1235
1240
 
1236
1241
  // If we are using a platform that does not support media source, we will
1237
1242
  // fall back to src= to handle all playback.
@@ -1286,7 +1291,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1286
1291
  // version there.
1287
1292
 
1288
1293
  // Native HLS can be preferred on any platform via this flag:
1289
- if (this.config_.streaming.preferNativeHls) {
1294
+ if (MimeUtils.isHlsType(mimeType) &&
1295
+ this.config_.streaming.preferNativeHls) {
1290
1296
  return true;
1291
1297
  }
1292
1298
 
@@ -4086,6 +4092,19 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
4086
4092
  firstVariantWithLabel.language, '', 0, label);
4087
4093
 
4088
4094
  this.chooseVariantAndSwitch_();
4095
+ } else if (this.video_ && this.video_.audioTracks) {
4096
+ const audioTracks = Array.from(this.video_.audioTracks);
4097
+
4098
+ let trackMatch = null;
4099
+
4100
+ for (const audioTrack of audioTracks) {
4101
+ if (audioTrack.label == label) {
4102
+ trackMatch = audioTrack;
4103
+ }
4104
+ }
4105
+ if (trackMatch) {
4106
+ this.switchHtml5Track_(trackMatch);
4107
+ }
4089
4108
  }
4090
4109
  }
4091
4110
 
@@ -5667,6 +5686,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
5667
5686
  error.category != shaka.util.Error.Category.NETWORK) {
5668
5687
  return false;
5669
5688
  }
5689
+ if (this.loadMode_ != shaka.Player.LoadMode.MEDIA_SOURCE) {
5690
+ return false;
5691
+ }
5692
+ goog.asserts.assert(this.manifest_, 'Should have manifest!');
5670
5693
 
5671
5694
  if (!navigator.onLine) {
5672
5695
  // Don't restrict variants if we're completely offline, or else we end up
@@ -6607,7 +6630,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6607
6630
  * @define {string} A version number taken from git at compile time.
6608
6631
  * @export
6609
6632
  */
6610
- shaka.Player.version = 'v4.2.9-uncompiled';
6633
+ shaka.Player.version = 'v4.2.11-uncompiled';
6611
6634
 
6612
6635
  // Initialize the deprecation system using the version string we just set
6613
6636
  // on the player.
@@ -115,6 +115,19 @@ shaka.polyfill.MediaCapabilities = class {
115
115
  if (shaka.util.Platform.isChromecast()) {
116
116
  isSupported =
117
117
  shaka.polyfill.MediaCapabilities.canCastDisplayType_(videoConfig);
118
+ } else if (shaka.util.Platform.isTizen()) {
119
+ let extendedType = videoConfig.contentType;
120
+ if (videoConfig.width && videoConfig.height) {
121
+ extendedType += `; width=${videoConfig.width}`;
122
+ extendedType += `; height=${videoConfig.height}`;
123
+ }
124
+ if (videoConfig.framerate) {
125
+ extendedType += `; framerate=${videoConfig.framerate}`;
126
+ }
127
+ if (videoConfig.bitrate) {
128
+ extendedType += `; bitrate=${videoConfig.bitrate}`;
129
+ }
130
+ isSupported = MediaSource.isTypeSupported(extendedType);
118
131
  } else {
119
132
  isSupported = MediaSource.isTypeSupported(videoConfig.contentType);
120
133
  }
@@ -97,6 +97,10 @@ shaka.text.Mp4VttParser = class {
97
97
  * @export
98
98
  */
99
99
  parseMedia(data, time) {
100
+ if (!data.length) {
101
+ return [];
102
+ }
103
+
100
104
  if (!this.timescale_) {
101
105
  // Missing timescale for VTT content. We should have seen the init
102
106
  // segment.
@@ -139,6 +139,7 @@ shaka.text.TextEngine = class {
139
139
  // into TextEngine and TextDisplayer.
140
140
  if (mimeType == shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE ||
141
141
  mimeType == shaka.util.MimeUtils.CEA708_CLOSED_CAPTION_MIMETYPE) {
142
+ this.parser_ = null;
142
143
  return;
143
144
  }
144
145
 
@@ -185,8 +185,7 @@ shaka.util.ManifestParserUtils.AUDIO_CODEC_REGEXPS_ = [
185
185
  /^mp4a/,
186
186
  /^[ae]c-3$/,
187
187
  /^ac-4$/,
188
- /^dts[cx]$/, // DTS Surround Sound
189
- /^[du]dts$/, // DTS Surround Sound
188
+ /^dts[cex]$/, // DTS Digital Surround (dtsc), DTS Express (dtse), DTS:X (dtsx)
190
189
  ];
191
190
 
192
191
 
@@ -196,6 +196,17 @@ shaka.util.MimeUtils = class {
196
196
  return value;
197
197
  }
198
198
 
199
+ /**
200
+ * Checks if the given MIME type is HLS MIME type.
201
+ *
202
+ * @param {string} mimeType
203
+ * @return {boolean}
204
+ */
205
+ static isHlsType(mimeType) {
206
+ return mimeType === 'application/x-mpegurl' ||
207
+ mimeType === 'application/vnd.apple.mpegurl';
208
+ }
209
+
199
210
  /**
200
211
  * Get the base and profile of a codec string. Where [0] will be the codec
201
212
  * base and [1] will be the profile.
@@ -671,11 +671,11 @@ shaka.util.PeriodCombiner = class {
671
671
  // Also checks if the segmentIndex is still valid after the async
672
672
  // operations, to make sure we stop if the active stream has changed.
673
673
  if (outputStream.segmentIndex instanceof shaka.media.MetaSegmentIndex) {
674
- for (let i = 0; i < streams.length; i++) {
674
+ for (let i = firstNewPeriodIndex; i < streams.length; i++) {
675
675
  const match = streams[i];
676
- if (match.segmentIndex && i >= firstNewPeriodIndex) {
677
- goog.asserts.assert(match.segmentIndex,
678
- 'stream should have a segmentIndex.');
676
+ goog.asserts.assert(match.segmentIndex,
677
+ 'stream should have a segmentIndex.');
678
+ if (match.segmentIndex) {
679
679
  outputStream.segmentIndex.appendSegmentIndex(match.segmentIndex);
680
680
  }
681
681
  }
@@ -728,7 +728,7 @@ shaka.util.PeriodCombiner = class {
728
728
  // in advance. concat() will add them to the output's MetaSegmentIndex.
729
729
  }
730
730
 
731
- if (!outputStream.matchedStreams) {
731
+ if (!outputStream.matchedStreams || !outputStream.matchedStreams.length) {
732
732
  // This is not a stream we can build output from, but it may become part
733
733
  // of another output based on another period's stream.
734
734
  return null;
@@ -828,7 +828,7 @@ shaka.util.StreamUtils = class {
828
828
  const video = variant.video;
829
829
  if (audio && currentVariant && currentVariant.audio) {
830
830
  if (!StreamUtils.areStreamsCompatible_(audio, currentVariant.audio)) {
831
- shaka.log.debug('Droping variant - not compatible with active audio',
831
+ shaka.log.debug('Dropping variant - not compatible with active audio',
832
832
  'active audio',
833
833
  StreamUtils.getStreamSummaryString_(currentVariant.audio),
834
834
  'variant.audio',
@@ -839,7 +839,7 @@ shaka.util.StreamUtils = class {
839
839
 
840
840
  if (video && currentVariant && currentVariant.video) {
841
841
  if (!StreamUtils.areStreamsCompatible_(video, currentVariant.video)) {
842
- shaka.log.debug('Droping variant - not compatible with active video',
842
+ shaka.log.debug('Dropping variant - not compatible with active video',
843
843
  'active video',
844
844
  StreamUtils.getStreamSummaryString_(currentVariant.video),
845
845
  'variant.video',
@@ -2,10 +2,9 @@
2
2
 
3
3
  We are currently maintaining the following branches of Shaka Player:
4
4
 
5
- - v4.1 (latest)
6
- - v4.0 (previous)
7
- - v3.3 (LTS until April 30, 2023)
8
- - v3.2 (in use by the Cast Application Framework)
5
+ - v4.3 (latest, also in use by the Cast Application Framework)
6
+ - v4.2 (previous)
7
+ - No active LTS branches at this time
9
8
 
10
9
  Other branches are no longer receiving bug fixes, and we recommend you upgrade
11
10
  to a maintained branch. For details on upgrading, please see our
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.2.9",
4
+ "version": "4.2.11",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -18,6 +18,7 @@
18
18
  "awesomplete": "^1.1.5",
19
19
  "babel-plugin-istanbul": "^6.1.1",
20
20
  "cajon": "^0.4.4",
21
+ "clean-package": "^2.2.0",
21
22
  "code-prettify": "^0.1.0",
22
23
  "color-themes-for-google-code-prettify": "^2.0.4",
23
24
  "core-js": "^3.21.1",
@@ -66,6 +67,7 @@
66
67
  "demoDeps": [
67
68
  "awesomplete/awesomplete.css",
68
69
  "awesomplete/awesomplete.min.js",
70
+ "codem-isoboxer/dist/iso_boxer.min.js",
69
71
  "dialog-polyfill/dialog-polyfill.css",
70
72
  "dialog-polyfill/dist/dialog-polyfill.js",
71
73
  "eme-encryption-scheme-polyfill/index.js",
@@ -91,12 +93,16 @@
91
93
  },
92
94
  "license": "Apache-2.0",
93
95
  "scripts": {
96
+ "prepack": "clean-package",
97
+ "postpack": "clean-package restore",
94
98
  "prepublishOnly": "python build/checkversion.py && python build/all.py --force"
95
99
  },
96
100
  "dependencies": {
97
101
  "eme-encryption-scheme-polyfill": "^2.1.1"
98
102
  },
99
- "engines": {
100
- "node": ">=14"
103
+ "clean-package": {
104
+ "remove": [
105
+ "engines"
106
+ ]
101
107
  }
102
108
  }
@@ -560,7 +560,8 @@ describe('HlsParser live', () => {
560
560
  // partialRef3
561
561
  '#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
562
562
  // preloadRef
563
- '#EXT-X-PRELOAD-HINT:TYPE=PART,URI="partial.mp4",BYTERANGE-START=210\n',
563
+ '#EXT-X-PRELOAD-HINT:TYPE=PART,URI="partial.mp4",BYTERANGE-START=210,',
564
+ 'BYTERANGE-LENGTH=210\n',
564
565
  ].join('');
565
566
 
566
567
  const partialRef = makeReference(
@@ -583,6 +584,7 @@ describe('HlsParser live', () => {
583
584
  const preloadRef = makeReference(
584
585
  'test:/partial.mp4', 6, 7.5, /* syncTime= */ null,
585
586
  /* baseUri= */ '', /* startByte= */ 210, /* endByte= */ null);
587
+ preloadRef.markAsPreload();
586
588
 
587
589
  // ref2 is not fully published yet, so it doesn't have a segment uri.
588
590
  const ref2 = makeReference(
@@ -0,0 +1,43 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ describe('ContentWorkarounds', () => {
8
+ const encryptionBoxes = {
9
+ 'encv': ['hev1', 'hvc1', 'avc1', 'avc3'],
10
+ 'enca': ['ac-3', 'ec-3', 'mp4a'],
11
+ };
12
+ for (const encryptionBox of Object.keys(encryptionBoxes)) {
13
+ for (const box of encryptionBoxes[encryptionBox]) {
14
+ it(`adds ${encryptionBox} box for ${box}`, () => {
15
+ const boxType = [];
16
+ for (const char of box) {
17
+ boxType.push(char.charCodeAt(0));
18
+ }
19
+ const unencrypted = new Uint8Array([
20
+ 0x00, 0x00, 0x00, 0x20, // size
21
+ 0x73, 0x74, 0x73, 0x64, // stsd
22
+ 0x01, // version
23
+ 0x12, 0x34, 0x56, // flags
24
+ 0x00, 0x00, 0x00, 0x01, // count
25
+ 0x00, 0x00, 0x00, 0x10, // size
26
+ ...boxType, // box type
27
+ 0x01, // version
28
+ 0x12, 0x34, 0x56, // flags
29
+ 0x00, 0x11, 0x22, 0x33, // payload
30
+ ]);
31
+
32
+ const faked =
33
+ shaka.media.ContentWorkarounds.fakeEncryption(unencrypted);
34
+ const spy = jasmine.createSpy('boxCallback');
35
+ new shaka.util.Mp4Parser()
36
+ .fullBox('stsd', shaka.util.Mp4Parser.sampleDescription)
37
+ .box(encryptionBox, /** @type {!Function} */ (spy))
38
+ .parse(faked);
39
+ expect(spy).toHaveBeenCalled();
40
+ });
41
+ }
42
+ }
43
+ });
@@ -74,19 +74,6 @@ describe('DrmEngine', () => {
74
74
  onEventSpy = jasmine.createSpy('onEvent');
75
75
 
76
76
  networkingEngine = new shaka.net.NetworkingEngine();
77
- networkingEngine.registerRequestFilter((type, request) => {
78
- if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
79
- return;
80
- }
81
-
82
- request.headers['X-AxDRM-Message'] = [
83
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lk',
84
- 'IjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6e',
85
- 'yJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiNmU1YTFkMj',
86
- 'YtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflOPv9qHnu3ZWJNZ12j',
87
- 'gkqTabmwXbDWk_47tLNE',
88
- ].join('');
89
- });
90
77
 
91
78
  const playerInterface = {
92
79
  netEngine: networkingEngine,
@@ -99,22 +86,22 @@ describe('DrmEngine', () => {
99
86
  drmEngine = new shaka.media.DrmEngine(playerInterface);
100
87
  const config = shaka.util.PlayerConfiguration.createDefault().drm;
101
88
  config.servers['com.widevine.alpha'] =
102
- 'https://drm-widevine-licensing.axtest.net/AcquireLicense';
89
+ 'https://cwip-shaka-proxy.appspot.com/specific_key?blodJidXR9eARuql0dNLWg=GX8m9XLIZNIzizrl0RTqnA';
103
90
  config.servers['com.microsoft.playready'] =
104
- 'https://drm-playready-licensing.axtest.net/AcquireLicense';
91
+ 'https://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(kid:6e5a1d26-2757-47d7-8046-eaa5d1d34b5a,contentkey:GX8m9XLIZNIzizrl0RTqnA==,sl:150)';
105
92
  drmEngine.configure(config);
106
93
 
107
94
  manifest = shaka.test.ManifestGenerator.generate((manifest) => {
108
95
  manifest.addVariant(0, (variant) => {
109
96
  variant.addVideo(1, (stream) => {
110
97
  stream.encrypted = true;
111
- stream.addDrmInfo('com.widevine.alpha');
112
98
  stream.addDrmInfo('com.microsoft.playready');
99
+ stream.addDrmInfo('com.widevine.alpha');
113
100
  });
114
101
  variant.addAudio(2, (stream) => {
115
102
  stream.encrypted = true;
116
- stream.addDrmInfo('com.widevine.alpha');
117
103
  stream.addDrmInfo('com.microsoft.playready');
104
+ stream.addDrmInfo('com.widevine.alpha');
118
105
  });
119
106
  });
120
107
  });