shaka-player 4.6.11 → 4.6.13

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 (52) hide show
  1. package/AUTHORS +1 -0
  2. package/CHANGELOG.md +29 -0
  3. package/CONTRIBUTORS +1 -0
  4. package/README.md +14 -12
  5. package/demo/common/assets.js +3 -1
  6. package/dist/controls.css +1 -1
  7. package/dist/controls.css.map +1 -1
  8. package/dist/demo.compiled.debug.js +5 -5
  9. package/dist/demo.compiled.debug.map +1 -1
  10. package/dist/demo.compiled.js +5 -5
  11. package/dist/demo.compiled.map +1 -1
  12. package/dist/deps.js +1 -1
  13. package/dist/locales.js +33 -33
  14. package/dist/receiver.compiled.debug.js +5 -5
  15. package/dist/receiver.compiled.debug.map +1 -1
  16. package/dist/receiver.compiled.js +5 -5
  17. package/dist/receiver.compiled.map +1 -1
  18. package/dist/shaka-player.compiled.debug.js +265 -265
  19. package/dist/shaka-player.compiled.debug.map +2 -2
  20. package/dist/shaka-player.compiled.js +1127 -1122
  21. package/dist/shaka-player.compiled.map +3 -3
  22. package/dist/shaka-player.ui.d.ts +1 -1
  23. package/dist/shaka-player.ui.debug.d.ts +1 -1
  24. package/dist/shaka-player.ui.debug.js +207 -217
  25. package/dist/shaka-player.ui.debug.map +4 -4
  26. package/dist/shaka-player.ui.js +1191 -1193
  27. package/dist/shaka-player.ui.map +4 -4
  28. package/docs/tutorials/ui-customization.md +0 -13
  29. package/lib/dash/dash_parser.js +1 -1
  30. package/lib/media/content_workarounds.js +24 -0
  31. package/lib/mss/mss_parser.js +2 -0
  32. package/lib/player.js +12 -2
  33. package/lib/polyfill/media_capabilities.js +14 -1
  34. package/lib/transmuxer/aac_transmuxer.js +2 -0
  35. package/lib/transmuxer/ac3_transmuxer.js +2 -0
  36. package/lib/transmuxer/ec3_transmuxer.js +2 -0
  37. package/lib/transmuxer/h264.js +28 -1
  38. package/lib/transmuxer/h265.js +25 -5
  39. package/lib/transmuxer/mp3_transmuxer.js +2 -0
  40. package/lib/transmuxer/ts_transmuxer.js +12 -0
  41. package/lib/util/cmcd_manager.js +13 -0
  42. package/lib/util/manifest_parser_utils.js +2 -0
  43. package/lib/util/mp4_generator.js +31 -2
  44. package/lib/util/stream_utils.js +2 -10
  45. package/package.json +1 -1
  46. package/test/dash/dash_parser_live_unit.js +19 -0
  47. package/test/player_integration.js +46 -40
  48. package/test/util/stream_utils_unit.js +2 -8
  49. package/ui/externs/ui.js +1 -10
  50. package/ui/less/range_elements.less +0 -33
  51. package/ui/seek_bar.js +0 -212
  52. package/ui/ui.js +0 -2
@@ -188,19 +188,6 @@ const config = {
188
188
  ui.configure(config);
189
189
  ```
190
190
 
191
- If you've chosen to display chapters, you can specify the color for the chapter markers on
192
- the timeline and the text color of the chapter titles that popup on hover:
193
- ```js
194
- const config = {
195
- displayChapters: true,
196
- seekBarColors: {
197
- chapterMarks: 'rgb(27, 27, 27)',
198
- chapterLabels: 'rgb(255, 255, 255)'
199
- }
200
- }
201
- ui.configure(config);
202
- ```
203
-
204
191
  #### Configuring playback, fast forward and rewind rates
205
192
  The rate in which the player can play, fast forward and rewind content can be configured using the `playbackRates`, `fastForwardRates` and `rewindRates` options.
206
193
 
@@ -1640,7 +1640,7 @@ shaka.dash.DashParser = class {
1640
1640
  // An attribute which is present and set to 0 should still result in
1641
1641
  // periodic updates. For more, see:
1642
1642
  // https://github.com/Dash-Industry-Forum/Guidelines-TimingModel/issues/48
1643
- if (this.updatePeriod_ <= 0) {
1643
+ if (this.updatePeriod_ < 0) {
1644
1644
  return;
1645
1645
  }
1646
1646
 
@@ -69,6 +69,30 @@ shaka.media.ContentWorkarounds = class {
69
69
  })
70
70
  .fullBox('encv', onEncryptionMetadataBox)
71
71
  .fullBox('enca', onEncryptionMetadataBox)
72
+ .fullBox('dvav', (box) => {
73
+ boxesToModify.push({
74
+ box,
75
+ newType: ContentWorkarounds.BOX_TYPE_ENCV_,
76
+ });
77
+ })
78
+ .fullBox('dva1', (box) => {
79
+ boxesToModify.push({
80
+ box,
81
+ newType: ContentWorkarounds.BOX_TYPE_ENCV_,
82
+ });
83
+ })
84
+ .fullBox('dvh1', (box) => {
85
+ boxesToModify.push({
86
+ box,
87
+ newType: ContentWorkarounds.BOX_TYPE_ENCV_,
88
+ });
89
+ })
90
+ .fullBox('dvhe', (box) => {
91
+ boxesToModify.push({
92
+ box,
93
+ newType: ContentWorkarounds.BOX_TYPE_ENCV_,
94
+ });
95
+ })
72
96
  .fullBox('hev1', (box) => {
73
97
  boxesToModify.push({
74
98
  box,
@@ -661,6 +661,8 @@ shaka.mss.MssParser = class {
661
661
  videoNalus: videoNalus,
662
662
  audioConfig: new Uint8Array([]),
663
663
  videoConfig: new Uint8Array([]),
664
+ hSpacing: 0,
665
+ vSpacing: 0,
664
666
  data: null, // Data is not necessary for init segement.
665
667
  stream: stream,
666
668
  };
package/lib/player.js CHANGED
@@ -715,6 +715,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
715
715
 
716
716
  if (shaka.Player.adManagerFactory_) {
717
717
  this.adManager_ = shaka.Player.adManagerFactory_();
718
+ this.adManager_.configure(this.config_.ads);
718
719
  }
719
720
 
720
721
  // If the browser comes back online after being offline, then try to play
@@ -1778,8 +1779,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1778
1779
 
1779
1780
  this.drmEngine_.configure(this.config_.drm);
1780
1781
 
1782
+ const tracksChanged = shaka.util.StreamUtils.applyRestrictions(
1783
+ this.manifest_.variants, this.config_.restrictions, this.maxHwRes_);
1784
+ if (tracksChanged && this.streamingEngine_) {
1785
+ this.onTracksChanged_();
1786
+ }
1787
+
1788
+ const playableVariants = shaka.util.StreamUtils.getPlayableVariants(
1789
+ this.manifest_.variants);
1790
+
1781
1791
  await this.drmEngine_.initForPlayback(
1782
- this.manifest_.variants,
1792
+ playableVariants,
1783
1793
  this.manifest_.offlineSessionIds);
1784
1794
 
1785
1795
  await this.drmEngine_.attach(this.video_);
@@ -6827,7 +6837,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6827
6837
  * @export
6828
6838
  */
6829
6839
  // eslint-disable-next-line no-useless-concat
6830
- shaka.Player.version = 'v4.6.11' + '-uncompiled'; // x-release-please-version
6840
+ shaka.Player.version = 'v4.6.13' + '-uncompiled'; // x-release-please-version
6831
6841
 
6832
6842
  // Initialize the deprecation system using the version string we just set
6833
6843
  // on the player.
@@ -191,10 +191,23 @@ shaka.polyfill.MediaCapabilities = class {
191
191
  const videoCapabilities = [];
192
192
 
193
193
  if (mediaCapkeySystemConfig.audio) {
194
- const capability = {
194
+ let capability = {
195
195
  robustness: mediaCapkeySystemConfig.audio.robustness || '',
196
196
  contentType: mediaDecodingConfig.audio.contentType,
197
197
  };
198
+
199
+ // Some Tizen devices seem to misreport AC-3 support, but correctly
200
+ // report EC-3 support. So query EC-3 as a fallback for AC-3.
201
+ // See https://github.com/shaka-project/shaka-player/issues/2989 for
202
+ // details.
203
+ if (shaka.util.Platform.isTizen() &&
204
+ mediaDecodingConfig.audio.contentType.includes('codecs="ac-3"')) {
205
+ capability = {
206
+ robustness: capability.robustness,
207
+ contentType: 'audio/mp4; codecs="ec-3"',
208
+ };
209
+ }
210
+
198
211
  audioCapabilities.push(capability);
199
212
  }
200
213
 
@@ -195,6 +195,8 @@ shaka.transmuxer.AacTransmuxer = class {
195
195
  videoNalus: [],
196
196
  audioConfig: new Uint8Array([]),
197
197
  videoConfig: new Uint8Array([]),
198
+ hSpacing: 0,
199
+ vSpacing: 0,
198
200
  data: {
199
201
  sequenceNumber: this.frameIndex_,
200
202
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -184,6 +184,8 @@ shaka.transmuxer.Ac3Transmuxer = class {
184
184
  videoNalus: [],
185
185
  audioConfig: audioConfig,
186
186
  videoConfig: new Uint8Array([]),
187
+ hSpacing: 0,
188
+ vSpacing: 0,
187
189
  data: {
188
190
  sequenceNumber: this.frameIndex_,
189
191
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -184,6 +184,8 @@ shaka.transmuxer.Ec3Transmuxer = class {
184
184
  videoNalus: [],
185
185
  audioConfig: audioConfig,
186
186
  videoConfig: new Uint8Array([]),
187
+ hSpacing: 0,
188
+ vSpacing: 0,
187
189
  data: {
188
190
  sequenceNumber: this.frameIndex_,
189
191
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -20,7 +20,8 @@ shaka.transmuxer.H264 = class {
20
20
  * describes the properties of upcoming video frames.
21
21
  *
22
22
  * @param {!Array.<shaka.extern.VideoNalu>} nalus
23
- * @return {?{height: number, width: number, videoConfig: !Uint8Array}}
23
+ * @return {?{height: number, width: number, videoConfig: !Uint8Array,
24
+ * hSpacing: number, vSpacing: number}}
24
25
  */
25
26
  static parseInfo(nalus) {
26
27
  const H264 = shaka.transmuxer.H264;
@@ -129,6 +130,30 @@ shaka.transmuxer.H264 = class {
129
130
  frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();
130
131
  }
131
132
 
133
+ let hSpacing = 1;
134
+ let vSpacing = 1;
135
+
136
+ // vui_parameters_present_flag
137
+ if (expGolombDecoder.readBoolean()) {
138
+ // aspect_ratio_info_present_flag
139
+ if (expGolombDecoder.readBoolean()) {
140
+ const aspectRatioIdc = expGolombDecoder.readUnsignedByte();
141
+ const hSpacingTable = [
142
+ 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2,
143
+ ];
144
+ const vSpacingTable = [
145
+ 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1,
146
+ ];
147
+ if (aspectRatioIdc > 0 && aspectRatioIdc < 16) {
148
+ hSpacing = hSpacingTable[aspectRatioIdc - 1];
149
+ vSpacing = vSpacingTable[aspectRatioIdc - 1];
150
+ } else if (aspectRatioIdc === 255) {
151
+ hSpacing = expGolombDecoder.readBits(16);
152
+ vSpacing = expGolombDecoder.readBits(16);
153
+ }
154
+ }
155
+ }
156
+
132
157
  const height = ((2 - frameMbsOnlyFlag) *
133
158
  (picHeightInMapUnitsMinus1 + 1) * 16) - (frameCropTopOffset * 2) -
134
159
  (frameCropBottomOffset * 2);
@@ -165,6 +190,8 @@ shaka.transmuxer.H264 = class {
165
190
  height,
166
191
  width,
167
192
  videoConfig,
193
+ hSpacing,
194
+ vSpacing,
168
195
  };
169
196
  }
170
197
 
@@ -20,7 +20,8 @@ shaka.transmuxer.H265 = class {
20
20
  * describes the properties of upcoming video frames.
21
21
  *
22
22
  * @param {!Array.<shaka.extern.VideoNalu>} nalus
23
- * @return {?{height: number, width: number, videoConfig: !Uint8Array}}
23
+ * @return {?{height: number, width: number, videoConfig: !Uint8Array,
24
+ * hSpacing: number, vSpacing: number}}
24
25
  */
25
26
  static parseInfo(nalus) {
26
27
  const H265 = shaka.transmuxer.H265;
@@ -87,6 +88,8 @@ shaka.transmuxer.H265 = class {
87
88
  height: spsConfiguration.height,
88
89
  width: spsConfiguration.width,
89
90
  videoConfig,
91
+ hSpacing: spsConfiguration.sarWidth,
92
+ vSpacing: spsConfiguration.sarHeight,
90
93
  };
91
94
  }
92
95
 
@@ -298,6 +301,8 @@ shaka.transmuxer.H265 = class {
298
301
  }
299
302
  }
300
303
  let defaultDisplayWindowFlag = false; // for calc offset
304
+ let sarWidth = 1;
305
+ let sarHeight = 1;
301
306
  let minSpatialSegmentationIdc = 0; // for hvcC
302
307
  gb.readBoolean(); // sps_temporal_mvp_enabled_flag
303
308
  gb.readBoolean(); // strong_intra_smoothing_enabled_flag
@@ -306,9 +311,18 @@ shaka.transmuxer.H265 = class {
306
311
  const aspectRatioInfoPresentFlag = gb.readBoolean();
307
312
  if (aspectRatioInfoPresentFlag) {
308
313
  const aspectRatioIdc = gb.readUnsignedByte();
309
- if (aspectRatioIdc === 255) {
310
- gb.readBits(16); // sar_width
311
- gb.readBits(16); // sar_height
314
+ const sarWidthTable = [
315
+ 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2,
316
+ ];
317
+ const sarHeightTable = [
318
+ 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1,
319
+ ];
320
+ if (aspectRatioIdc > 0 && aspectRatioIdc < 16) {
321
+ sarWidth = sarWidthTable[aspectRatioIdc - 1];
322
+ sarHeight = sarHeightTable[aspectRatioIdc - 1];
323
+ } else if (aspectRatioIdc === 255) {
324
+ sarWidth = gb.readBits(16);
325
+ sarHeight = gb.readBits(16);
312
326
  }
313
327
  }
314
328
  const overscanInfoPresentFlag = gb.readBoolean();
@@ -459,6 +473,8 @@ shaka.transmuxer.H265 = class {
459
473
  bitDepthChromaMinus8,
460
474
  width: codecWidth,
461
475
  height: codecHeight,
476
+ sarWidth: sarWidth,
477
+ sarHeight: sarHeight,
462
478
  };
463
479
  }
464
480
 
@@ -773,7 +789,9 @@ shaka.transmuxer.H265.VPSConfiguration;
773
789
  * bitDepthLumaMinus8: number,
774
790
  * bitDepthChromaMinus8: number,
775
791
  * width: number,
776
- * height: number
792
+ * height: number,
793
+ * sarWidth: number,
794
+ * sarHeight: number
777
795
  * }}
778
796
  *
779
797
  * @property {number} generalProfileSpace
@@ -797,6 +815,8 @@ shaka.transmuxer.H265.VPSConfiguration;
797
815
  * @property {number} bitDepthChromaMinus8
798
816
  * @property {number} width
799
817
  * @property {number} height
818
+ * @property {number} sarWidth
819
+ * @property {number} sarHeight
800
820
  */
801
821
  shaka.transmuxer.H265.SPSConfiguration;
802
822
 
@@ -176,6 +176,8 @@ shaka.transmuxer.Mp3Transmuxer = class {
176
176
  videoNalus: [],
177
177
  audioConfig: new Uint8Array([]),
178
178
  videoConfig: new Uint8Array([]),
179
+ hSpacing: 0,
180
+ vSpacing: 0,
179
181
  data: {
180
182
  sequenceNumber: this.frameIndex_,
181
183
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -409,6 +409,8 @@ shaka.transmuxer.TsTransmuxer = class {
409
409
  videoNalus: [],
410
410
  audioConfig: new Uint8Array([]),
411
411
  videoConfig: new Uint8Array([]),
412
+ hSpacing: 0,
413
+ vSpacing: 0,
412
414
  data: {
413
415
  sequenceNumber: this.frameIndex_,
414
416
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -500,6 +502,8 @@ shaka.transmuxer.TsTransmuxer = class {
500
502
  videoNalus: [],
501
503
  audioConfig: audioConfig,
502
504
  videoConfig: new Uint8Array([]),
505
+ hSpacing: 0,
506
+ vSpacing: 0,
503
507
  data: {
504
508
  sequenceNumber: this.frameIndex_,
505
509
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -591,6 +595,8 @@ shaka.transmuxer.TsTransmuxer = class {
591
595
  videoNalus: [],
592
596
  audioConfig: audioConfig,
593
597
  videoConfig: new Uint8Array([]),
598
+ hSpacing: 0,
599
+ vSpacing: 0,
594
600
  data: {
595
601
  sequenceNumber: this.frameIndex_,
596
602
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -677,6 +683,8 @@ shaka.transmuxer.TsTransmuxer = class {
677
683
  videoNalus: [],
678
684
  audioConfig: new Uint8Array([]),
679
685
  videoConfig: new Uint8Array([]),
686
+ hSpacing: 0,
687
+ vSpacing: 0,
680
688
  data: {
681
689
  sequenceNumber: this.frameIndex_,
682
690
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -769,6 +777,8 @@ shaka.transmuxer.TsTransmuxer = class {
769
777
  videoNalus: [],
770
778
  audioConfig: new Uint8Array([]),
771
779
  videoConfig: info.videoConfig,
780
+ hSpacing: info.hSpacing,
781
+ vSpacing: info.vSpacing,
772
782
  data: {
773
783
  sequenceNumber: this.frameIndex_,
774
784
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -861,6 +871,8 @@ shaka.transmuxer.TsTransmuxer = class {
861
871
  videoNalus: [],
862
872
  audioConfig: new Uint8Array([]),
863
873
  videoConfig: info.videoConfig,
874
+ hSpacing: info.hSpacing,
875
+ vSpacing: info.vSpacing,
864
876
  data: {
865
877
  sequenceNumber: this.frameIndex_,
866
878
  baseMediaDecodeTime: baseMediaDecodeTime,
@@ -65,6 +65,9 @@ shaka.util.CmcdManager = class {
65
65
  */
66
66
  configure(config) {
67
67
  this.config_ = config;
68
+ if (this.config_.sessionId && this.config_.sessionId != this.sid_) {
69
+ this.sid_ = '';
70
+ }
68
71
  }
69
72
 
70
73
  /**
@@ -407,6 +410,15 @@ shaka.util.CmcdManager = class {
407
410
  */
408
411
  getObjectTypeFromMimeType_(mimeType) {
409
412
  switch (mimeType.toLowerCase()) {
413
+ case 'audio/mp4':
414
+ case 'audio/webm':
415
+ case 'audio/ogg':
416
+ case 'audio/mpeg':
417
+ case 'audio/aac':
418
+ case 'audio/flac':
419
+ case 'audio/wav':
420
+ return shaka.util.CmcdManager.ObjectType.AUDIO;
421
+
410
422
  case 'video/webm':
411
423
  case 'video/mp4':
412
424
  case 'video/mpeg':
@@ -417,6 +429,7 @@ shaka.util.CmcdManager = class {
417
429
  case 'application/vnd.apple.mpegurl':
418
430
  case 'application/dash+xml':
419
431
  case 'video/vnd.mpeg.dash.mpd':
432
+ case 'application/vnd.ms-sstr+xml':
420
433
  return shaka.util.CmcdManager.ObjectType.MANIFEST;
421
434
 
422
435
  default:
@@ -179,6 +179,8 @@ shaka.util.ManifestParserUtils.VIDEO_CODEC_REGEXPS_ = [
179
179
  /^avc/,
180
180
  /^hev/,
181
181
  /^hvc/,
182
+ /^vvc/,
183
+ /^vvi/,
182
184
  /^vp0?[89]/,
183
185
  /^av01/,
184
186
  /^dvh/,
@@ -371,12 +371,13 @@ shaka.util.Mp4Generator = class {
371
371
  ]);
372
372
 
373
373
  let boxName = 'avc1';
374
+ const paspBox = this.pasp_(streamInfo);
374
375
  let sinfBox = new Uint8Array([]);
375
376
  if (streamInfo.encrypted) {
376
377
  sinfBox = this.sinf_(streamInfo);
377
378
  boxName = 'encv';
378
379
  }
379
- return Mp4Generator.box(boxName, avc1Bytes, avcCBox, sinfBox);
380
+ return Mp4Generator.box(boxName, avc1Bytes, avcCBox, paspBox, sinfBox);
380
381
  }
381
382
 
382
383
  /**
@@ -500,12 +501,34 @@ shaka.util.Mp4Generator = class {
500
501
  ]);
501
502
 
502
503
  let boxName = 'hvc1';
504
+ const paspBox = this.pasp_(streamInfo);
503
505
  let sinfBox = new Uint8Array([]);
504
506
  if (streamInfo.encrypted) {
505
507
  sinfBox = this.sinf_(streamInfo);
506
508
  boxName = 'encv';
507
509
  }
508
- return Mp4Generator.box(boxName, hvc1Bytes, hvcCBox, sinfBox);
510
+ return Mp4Generator.box(boxName, hvc1Bytes, hvcCBox, paspBox, sinfBox);
511
+ }
512
+
513
+ /**
514
+ * Generate a PASP box
515
+ *
516
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
517
+ * @return {!Uint8Array}
518
+ * @private
519
+ */
520
+ pasp_(streamInfo) {
521
+ if (!streamInfo.hSpacing && !streamInfo.vSpacing) {
522
+ return new Uint8Array([]);
523
+ }
524
+ const Mp4Generator = shaka.util.Mp4Generator;
525
+ const hSpacing = streamInfo.hSpacing;
526
+ const vSpacing = streamInfo.vSpacing;
527
+ const bytes = new Uint8Array([
528
+ ...this.breakNumberIntoBytes_(hSpacing, 4), // hSpacing
529
+ ...this.breakNumberIntoBytes_(vSpacing, 4), // vSpacing
530
+ ]);
531
+ return Mp4Generator.box('pasp', bytes);
509
532
  }
510
533
 
511
534
  /**
@@ -1301,6 +1324,8 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]);
1301
1324
  * videoNalus: !Array.<string>,
1302
1325
  * audioConfig: !Uint8Array,
1303
1326
  * videoConfig: !Uint8Array,
1327
+ * hSpacing: number,
1328
+ * vSpacing: number,
1304
1329
  * data: ?shaka.util.Mp4Generator.Data,
1305
1330
  * stream: !shaka.extern.Stream
1306
1331
  * }}
@@ -1325,6 +1350,10 @@ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]);
1325
1350
  * The stream's audio config.
1326
1351
  * @property {!Uint8Array} videoConfig
1327
1352
  * The stream's video config.
1353
+ * @property {number} hSpacing
1354
+ * The stream's video horizontal spacing of pixels.
1355
+ * @property {number} vSpacing
1356
+ * The stream's video vertial spacing of pixels.
1328
1357
  * @property {?shaka.util.Mp4Generator.Data} data
1329
1358
  * The stream's data.
1330
1359
  * @property {!shaka.extern.Stream} stream
@@ -161,7 +161,7 @@ shaka.util.StreamUtils = class {
161
161
  const currentCodec =
162
162
  MimeUtils.getNormalizedCodec(stream.codecs);
163
163
  if (previousCodec == currentCodec) {
164
- if (stream.bandwidth < previousStream.bandwidth) {
164
+ if (stream.bandwidth > previousStream.bandwidth) {
165
165
  validVideoStreams.push(stream);
166
166
  validVideoIds.push(stream.id);
167
167
  }
@@ -848,15 +848,7 @@ shaka.util.StreamUtils = class {
848
848
  return 'opus';
849
849
  }
850
850
 
851
- // Some Tizen devices seem to misreport AC-3 support, but correctly
852
- // report EC-3 support. So query EC-3 as a fallback for AC-3.
853
- // See https://github.com/shaka-project/shaka-player/issues/2989 for
854
- // details.
855
- if (shaka.util.Platform.isTizen()) {
856
- return codecs.toLowerCase() == 'ac-3' ? 'ec-3' : codecs;
857
- } else {
858
- return codecs;
859
- }
851
+ return codecs;
860
852
  }
861
853
 
862
854
 
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.6.11",
4
+ "version": "4.6.13",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -642,6 +642,25 @@ describe('DashParser Live', () => {
642
642
  expect(updateTick).toHaveBeenCalledTimes(1);
643
643
  });
644
644
 
645
+ it('still updates when @minimumUpdatePeriod is zero', async () => {
646
+ const lines = [
647
+ '<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2" />',
648
+ ];
649
+ // updateTime parameter sets @minimumUpdatePeriod in the manifest.
650
+ const manifestText = makeSimpleLiveManifestText(lines, /* updateTime= */ 0);
651
+
652
+ /** @type {!jasmine.Spy} */
653
+ const tickAfter = updateTickSpy();
654
+ Date.now = () => 0;
655
+
656
+ fakeNetEngine.setResponseText('dummy://foo', manifestText);
657
+ await parser.start('dummy://foo', playerInterface);
658
+
659
+ expect(tickAfter).toHaveBeenCalledTimes(1);
660
+ const delay = tickAfter.calls.mostRecent().args[0];
661
+ expect(delay).toBe(0);
662
+ });
663
+
645
664
  it('uses @minimumUpdatePeriod', async () => {
646
665
  const lines = [
647
666
  '<SegmentTemplate startNumber="1" media="s$Number$.mp4" duration="2" />',
@@ -61,6 +61,46 @@ describe('Player', () => {
61
61
  document.body.removeChild(video);
62
62
  });
63
63
 
64
+ describe('seek range', () => {
65
+ // Regression test for Issue #3675.
66
+ it('has a reasonable seek range after going from live to VOD', async () => {
67
+ const netEngine = player.getNetworkingEngine();
68
+ const startTime = Date.now();
69
+ netEngine.registerRequestFilter((type, request) => {
70
+ if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
71
+ return;
72
+ }
73
+ // Simulate a live stream by providing different manifests over time.
74
+ const time = (Date.now() - startTime) / 1000;
75
+ const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
76
+ request.uris = [
77
+ '/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
78
+ ];
79
+ console.log('getting manifest', request.uris);
80
+ });
81
+
82
+ // Play the stream.
83
+ await player.load('/base/test/test/assets/3675/dash_0.mpd');
84
+ await video.play();
85
+
86
+ // Wait for the stream to be over.
87
+ eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
88
+ /** @type {shaka.test.Waiter} */
89
+ const waiter = new shaka.test.Waiter(eventManager)
90
+ .setPlayer(player)
91
+ .timeoutAfter(40)
92
+ .failOnTimeout(true);
93
+ await waiter.waitForEnd(video);
94
+
95
+ // The stream should have transitioned to VOD by now.
96
+ expect(player.isLive()).toBe(false);
97
+
98
+ // Check that the final seek range is as expected.
99
+ const seekRange = player.seekRange();
100
+ expect(seekRange.end).toBeCloseTo(14);
101
+ });
102
+ });
103
+
64
104
  describe('attach', () => {
65
105
  beforeEach(async () => {
66
106
  // To test attach, we want to construct a player without a video element
@@ -908,46 +948,6 @@ describe('Player', () => {
908
948
  });
909
949
  });
910
950
 
911
- describe('seek range', () => {
912
- // Regression test for Issue #3675.
913
- it('has a reasonable seek range after going from live to VOD', async () => {
914
- const netEngine = player.getNetworkingEngine();
915
- const startTime = Date.now();
916
- netEngine.registerRequestFilter((type, request) => {
917
- if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
918
- return;
919
- }
920
- // Simulate a live stream by providing different manifests over time.
921
- const time = (Date.now() - startTime) / 1000;
922
- const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
923
- request.uris = [
924
- '/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
925
- ];
926
- console.log('getting manifest', request.uris);
927
- });
928
-
929
- // Play the stream.
930
- await player.load('/base/test/test/assets/3675/dash_0.mpd');
931
- await video.play();
932
-
933
- // Wait for the stream to be over.
934
- eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
935
- /** @type {shaka.test.Waiter} */
936
- const waiter = new shaka.test.Waiter(eventManager)
937
- .setPlayer(player)
938
- .timeoutAfter(40)
939
- .failOnTimeout(true);
940
- await waiter.waitForEnd(video);
941
-
942
- // The stream should have transitioned to VOD by now.
943
- expect(player.isLive()).toBe(false);
944
-
945
- // Check that the final seek range is as expected.
946
- const seekRange = player.seekRange();
947
- expect(seekRange.end).toBeCloseTo(14);
948
- });
949
- });
950
-
951
951
  describe('buffering', () => {
952
952
  const startBuffering = jasmine.objectContaining({buffering: true});
953
953
  const endBuffering = jasmine.objectContaining({buffering: false});
@@ -1012,6 +1012,9 @@ describe('Player', () => {
1012
1012
  });
1013
1013
 
1014
1014
  it('buffers ahead of the playhead', async () => {
1015
+ if (window.ManagedMediaSource) {
1016
+ pending('ManagedMediaSource has buffer control signals.');
1017
+ }
1015
1018
  player.configure('streaming.bufferingGoal', 10);
1016
1019
 
1017
1020
  await player.load('test:sintel_long_compiled');
@@ -1036,6 +1039,9 @@ describe('Player', () => {
1036
1039
  });
1037
1040
 
1038
1041
  it('clears buffer behind playhead', async () => {
1042
+ if (window.ManagedMediaSource) {
1043
+ pending('ManagedMediaSource has buffer control signals.');
1044
+ }
1039
1045
  player.configure('streaming.bufferingGoal', 30);
1040
1046
  player.configure('streaming.bufferBehind', 30);
1041
1047
 
@@ -826,12 +826,6 @@ describe('StreamUtils', () => {
826
826
  stream.size(20, 20);
827
827
  });
828
828
  });
829
- manifest.addVariant(6, (variant) => {
830
- variant.addVideo(7, (stream) => {
831
- stream.bandwidth = 600000;
832
- stream.size(20, 20);
833
- });
834
- });
835
829
  });
836
830
 
837
831
  shaka.util.StreamUtils.chooseCodecsAndFilterManifest(manifest,
@@ -839,8 +833,8 @@ describe('StreamUtils', () => {
839
833
  /* preferredAudioCodecs= */[],
840
834
  /* preferredDecodingAttributes= */[]);
841
835
 
842
- expect(manifest.variants.length).toBe(2);
843
- expect(manifest.variants.every((v) => [300000, 500000].includes(
836
+ expect(manifest.variants.length).toBe(3);
837
+ expect(manifest.variants.every((v) => [300000, 400000, 500000].includes(
844
838
  v.video.bandwidth))).toBeTruthy();
845
839
  });
846
840