shaka-player 4.8.0 → 4.8.1

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.
@@ -30,6 +30,7 @@ goog.require('shaka.util.MimeUtils');
30
30
  goog.require('shaka.util.Networking');
31
31
  goog.require('shaka.util.OperationManager');
32
32
  goog.require('shaka.util.PeriodCombiner');
33
+ goog.require('shaka.util.PlayerConfiguration');
33
34
  goog.require('shaka.util.StringUtils');
34
35
  goog.require('shaka.util.Timer');
35
36
  goog.require('shaka.util.TXml');
@@ -338,7 +339,9 @@ shaka.dash.DashParser = class {
338
339
  async parseManifest_(data, finalManifestUri) {
339
340
  let manifestData = data;
340
341
  const manifestPreprocessor = this.config_.dash.manifestPreprocessor;
341
- if (manifestPreprocessor) {
342
+ const defaultManifestPreprocessor =
343
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
344
+ if (manifestPreprocessor != defaultManifestPreprocessor) {
342
345
  shaka.Deprecate.deprecateFeature(5,
343
346
  'manifest.dash.manifestPreprocessor configuration',
344
347
  'Please Use manifest.dash.manifestPreprocessorTXml instead.');
@@ -364,7 +367,9 @@ shaka.dash.DashParser = class {
364
367
  }
365
368
  const manifestPreprocessorTXml =
366
369
  this.config_.dash.manifestPreprocessorTXml;
367
- if (manifestPreprocessorTXml) {
370
+ const defaultManifestPreprocessorTXml =
371
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml;
372
+ if (manifestPreprocessorTXml != defaultManifestPreprocessorTXml) {
368
373
  manifestPreprocessorTXml(mpd);
369
374
  }
370
375
 
@@ -2074,8 +2079,9 @@ shaka.dash.DashParser = class {
2074
2079
  * @private
2075
2080
  */
2076
2081
  async requestForTiming_(getBaseUris, uri, method) {
2082
+ const uris = [shaka.util.StringUtils.htmlUnescape(uri)];
2077
2083
  const requestUris =
2078
- shaka.util.ManifestParserUtils.resolveUris(getBaseUris(), [uri]);
2084
+ shaka.util.ManifestParserUtils.resolveUris(getBaseUris(), uris);
2079
2085
  const request = shaka.net.NetworkingEngine.makeRequest(
2080
2086
  requestUris, this.config_.retryParameters);
2081
2087
  request.method = method;
@@ -701,7 +701,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
701
701
  */
702
702
  appendTemplateInfo(info, periodStart, periodEnd, shouldFit,
703
703
  initSegmentReference) {
704
- this.initSegmentReference_ = initSegmentReference;
704
+ this.updateInitSegmentReference(initSegmentReference);
705
705
  if (!this.templateInfo_) {
706
706
  this.templateInfo_ = info;
707
707
  this.periodStart_ = periodStart;
@@ -732,6 +732,24 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
732
732
  }
733
733
  }
734
734
 
735
+ /**
736
+ * Updates the init segment reference and propagates the update to all
737
+ * references.
738
+ * @param {shaka.media.InitSegmentReference} initSegmentReference
739
+ */
740
+ updateInitSegmentReference(initSegmentReference) {
741
+ if (this.initSegmentReference_ === initSegmentReference) {
742
+ return;
743
+ }
744
+
745
+ this.initSegmentReference_ = initSegmentReference;
746
+ for (const reference of this.references) {
747
+ if (reference) {
748
+ reference.updateInitSegmentReference(initSegmentReference);
749
+ }
750
+ }
751
+ }
752
+
735
753
  /**
736
754
  *
737
755
  * @param {number} time
@@ -436,10 +436,11 @@ shaka.media.SegmentIndex = class {
436
436
  *
437
437
  * @param {number} time
438
438
  * @param {boolean=} allowNonIndepedent
439
+ * @param {boolean=} reverse
439
440
  * @return {?shaka.media.SegmentIterator}
440
441
  * @export
441
442
  */
442
- getIteratorForTime(time, allowNonIndepedent = false) {
443
+ getIteratorForTime(time, allowNonIndepedent = false, reverse = false) {
443
444
  let index = this.find(time);
444
445
  if (index == null) {
445
446
  return null;
@@ -476,7 +477,8 @@ shaka.media.SegmentIndex = class {
476
477
  }
477
478
  }
478
479
  }
479
- return new shaka.media.SegmentIterator(this, index, partialSegmentIndex);
480
+ return new shaka.media.SegmentIterator(
481
+ this, index, partialSegmentIndex, reverse);
480
482
  }
481
483
 
482
484
  /**
@@ -552,8 +554,9 @@ shaka.media.SegmentIterator = class {
552
554
  * @param {shaka.media.SegmentIndex} segmentIndex
553
555
  * @param {number} index
554
556
  * @param {number} partialSegmentIndex
557
+ * @param {boolean} reverse
555
558
  */
556
- constructor(segmentIndex, index, partialSegmentIndex) {
559
+ constructor(segmentIndex, index, partialSegmentIndex, reverse) {
557
560
  /** @private {shaka.media.SegmentIndex} */
558
561
  this.segmentIndex_ = segmentIndex;
559
562
 
@@ -562,6 +565,17 @@ shaka.media.SegmentIterator = class {
562
565
 
563
566
  /** @private {number} */
564
567
  this.currentPartialPosition_ = partialSegmentIndex;
568
+
569
+ /** @private {boolean} */
570
+ this.reverse = reverse;
571
+ }
572
+
573
+ /**
574
+ * @param {boolean} reverse
575
+ * @export
576
+ */
577
+ setReverse(reverse) {
578
+ this.reverse = reverse;
565
579
  }
566
580
 
567
581
  /**
@@ -606,25 +620,47 @@ shaka.media.SegmentIterator = class {
606
620
  next() {
607
621
  const ref = this.segmentIndex_.get(this.currentPosition_);
608
622
 
609
- if (ref && ref.hasPartialSegments()) {
610
- // If the regular segment contains partial segments, move to the next
611
- // partial SegmentReference.
612
- this.currentPartialPosition_++;
613
- // If the current regular segment has been published completely, and
614
- // we've reached the end of its partial segments list, move to the next
615
- // regular segment.
616
- // If the Partial Segments list is still on the fly, do not move to
617
- // the next regular segment.
618
- if (ref.hasAllPartialSegments() &&
619
- this.currentPartialPosition_ == ref.partialReferences.length) {
623
+ if (!this.reverse) {
624
+ if (ref && ref.hasPartialSegments()) {
625
+ // If the regular segment contains partial segments, move to the next
626
+ // partial SegmentReference.
627
+ this.currentPartialPosition_++;
628
+ // If the current regular segment has been published completely, and
629
+ // we've reached the end of its partial segments list, move to the next
630
+ // regular segment.
631
+ // If the Partial Segments list is still on the fly, do not move to
632
+ // the next regular segment.
633
+ if (ref.hasAllPartialSegments() &&
634
+ this.currentPartialPosition_ == ref.partialReferences.length) {
635
+ this.currentPosition_++;
636
+ this.currentPartialPosition_ = 0;
637
+ }
638
+ } else {
639
+ // If the regular segment doesn't contain partial segments, move to the
640
+ // next regular segment.
620
641
  this.currentPosition_++;
621
642
  this.currentPartialPosition_ = 0;
622
643
  }
623
644
  } else {
624
- // If the regular segment doesn't contain partial segments, move to the
625
- // next regular segment.
626
- this.currentPosition_++;
627
- this.currentPartialPosition_ = 0;
645
+ if (ref && ref.hasPartialSegments()) {
646
+ // If the regular segment contains partial segments, move to the
647
+ // previous partial SegmentReference.
648
+ this.currentPartialPosition_--;
649
+ if (this.currentPartialPosition_ < 0) {
650
+ this.currentPosition_--;
651
+ const prevRef = this.segmentIndex_.get(this.currentPosition_);
652
+ if (prevRef && prevRef.hasPartialSegments()) {
653
+ this.currentPartialPosition_ = prevRef.partialReferences.length - 1;
654
+ } else {
655
+ this.currentPartialPosition_ = 0;
656
+ }
657
+ }
658
+ } else {
659
+ // If the regular segment doesn't contain partial segments, move to the
660
+ // previous regular segment.
661
+ this.currentPosition_--;
662
+ this.currentPartialPosition_ = 0;
663
+ }
628
664
  }
629
665
 
630
666
  const res = this.current();
@@ -621,6 +621,18 @@ shaka.media.SegmentReference = class {
621
621
  getSegmentData() {
622
622
  return this.segmentData;
623
623
  }
624
+
625
+ /**
626
+ * Updates the init segment reference and propagates the update to all partial
627
+ * references.
628
+ * @param {shaka.media.InitSegmentReference} initSegmentReference
629
+ */
630
+ updateInitSegmentReference(initSegmentReference) {
631
+ this.initSegmentReference = initSegmentReference;
632
+ for (const partialReference of this.partialReferences) {
633
+ partialReference.updateInitSegmentReference(initSegmentReference);
634
+ }
635
+ }
624
636
  };
625
637
 
626
638
 
@@ -360,6 +360,8 @@ shaka.media.StreamingEngine = class {
360
360
  setTrickPlay(on) {
361
361
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
362
362
 
363
+ this.updateSegmentIteratorReverse_();
364
+
363
365
  const mediaState = this.mediaStates_.get(ContentType.VIDEO);
364
366
  if (!mediaState) {
365
367
  return;
@@ -1422,8 +1424,10 @@ shaka.media.StreamingEngine = class {
1422
1424
  shaka.log.v1(
1423
1425
  logPrefix, 'looking up segment from new stream endTime:', time);
1424
1426
 
1427
+ const reverse = this.playerInterface_.getPlaybackRate() < 0;
1425
1428
  mediaState.segmentIterator =
1426
- mediaState.stream.segmentIndex.getIteratorForTime(time);
1429
+ mediaState.stream.segmentIndex.getIteratorForTime(
1430
+ time, /* allowNonIndepedent= */ false, reverse);
1427
1431
  const ref = mediaState.segmentIterator &&
1428
1432
  mediaState.segmentIterator.next().value;
1429
1433
  if (ref == null) {
@@ -1443,10 +1447,12 @@ shaka.media.StreamingEngine = class {
1443
1447
  'lookupTime:', lookupTime,
1444
1448
  'presentationTime:', presentationTime);
1445
1449
 
1450
+ const reverse = this.playerInterface_.getPlaybackRate() < 0;
1446
1451
  let ref = null;
1447
1452
  if (inaccurateTolerance) {
1448
1453
  mediaState.segmentIterator =
1449
- mediaState.stream.segmentIndex.getIteratorForTime(lookupTime);
1454
+ mediaState.stream.segmentIndex.getIteratorForTime(
1455
+ lookupTime, /* allowNonIndepedent= */ false, reverse);
1450
1456
  ref = mediaState.segmentIterator &&
1451
1457
  mediaState.segmentIterator.next().value;
1452
1458
  }
@@ -1454,7 +1460,8 @@ shaka.media.StreamingEngine = class {
1454
1460
  // If we can't find a valid segment with the drifted time, look for a
1455
1461
  // segment with the presentation time.
1456
1462
  mediaState.segmentIterator =
1457
- mediaState.stream.segmentIndex.getIteratorForTime(presentationTime);
1463
+ mediaState.stream.segmentIndex.getIteratorForTime(
1464
+ presentationTime, /* allowNonIndepedent= */ false, reverse);
1458
1465
  ref = mediaState.segmentIterator &&
1459
1466
  mediaState.segmentIterator.next().value;
1460
1467
  }
@@ -2752,6 +2759,29 @@ shaka.media.StreamingEngine = class {
2752
2759
  }
2753
2760
  }
2754
2761
 
2762
+ /**
2763
+ * Update the segment iterator direction.
2764
+ *
2765
+ * @private
2766
+ */
2767
+ updateSegmentIteratorReverse_() {
2768
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
2769
+
2770
+ const reverse = this.playerInterface_.getPlaybackRate() < 0;
2771
+ const videoState = this.mediaStates_.get(ContentType.VIDEO);
2772
+ if (videoState && videoState.segmentIterator) {
2773
+ videoState.segmentIterator.setReverse(reverse);
2774
+ }
2775
+ const audioState = this.mediaStates_.get(ContentType.AUDIO);
2776
+ if (audioState && audioState.segmentIterator) {
2777
+ audioState.segmentIterator.setReverse(reverse);
2778
+ }
2779
+ const textState = this.mediaStates_.get(ContentType.TEXT);
2780
+ if (textState && textState.segmentIterator) {
2781
+ textState.segmentIterator.setReverse(reverse);
2782
+ }
2783
+ }
2784
+
2755
2785
  /**
2756
2786
  * @param {shaka.media.StreamingEngine.MediaState_} mediaState
2757
2787
  * @return {string} A log prefix of the form ($CONTENT_TYPE:$STREAM_ID), e.g.,
@@ -2768,6 +2798,7 @@ shaka.media.StreamingEngine = class {
2768
2798
  * @typedef {{
2769
2799
  * getPresentationTime: function():number,
2770
2800
  * getBandwidthEstimate: function():number,
2801
+ * getPlaybackRate: function():number,
2771
2802
  * mediaSourceEngine: !shaka.media.MediaSourceEngine,
2772
2803
  * netEngine: shaka.net.NetworkingEngine,
2773
2804
  * onError: function(!shaka.util.Error),
@@ -2787,6 +2818,8 @@ shaka.media.StreamingEngine = class {
2787
2818
  * viewer is seeing on screen right now.
2788
2819
  * @property {function():number} getBandwidthEstimate
2789
2820
  * Get the estimated bandwidth in bits per second.
2821
+ * @property {function():number} getPlaybackRate
2822
+ * Get the playback rate
2790
2823
  * @property {!shaka.media.MediaSourceEngine} mediaSourceEngine
2791
2824
  * The MediaSourceEngine. The caller retains ownership.
2792
2825
  * @property {shaka.net.NetworkingEngine} netEngine
@@ -23,6 +23,7 @@ goog.require('shaka.util.ManifestParserUtils');
23
23
  goog.require('shaka.util.MimeUtils');
24
24
  goog.require('shaka.util.Mp4Generator');
25
25
  goog.require('shaka.util.OperationManager');
26
+ goog.require('shaka.util.PlayerConfiguration');
26
27
  goog.require('shaka.util.Timer');
27
28
  goog.require('shaka.util.TXml');
28
29
  goog.require('shaka.util.XmlUtils');
@@ -282,7 +283,9 @@ shaka.mss.MssParser = class {
282
283
  parseManifest_(data, finalManifestUri) {
283
284
  let manifestData = data;
284
285
  const manifestPreprocessor = this.config_.mss.manifestPreprocessor;
285
- if (manifestPreprocessor) {
286
+ const defaultManifestPreprocessor =
287
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
288
+ if (manifestPreprocessor != defaultManifestPreprocessor) {
286
289
  shaka.Deprecate.deprecateFeature(5,
287
290
  'manifest.mss.manifestPreprocessor configuration',
288
291
  'Please Use manifest.mss.manifestPreprocessorTXml instead.');
@@ -307,7 +310,9 @@ shaka.mss.MssParser = class {
307
310
  finalManifestUri);
308
311
  }
309
312
  const manifestPreprocessorTXml = this.config_.mss.manifestPreprocessorTXml;
310
- if (manifestPreprocessorTXml) {
313
+ const defaultManifestPreprocessorTXml =
314
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml;
315
+ if (manifestPreprocessorTXml != defaultManifestPreprocessorTXml) {
311
316
  manifestPreprocessorTXml(mss);
312
317
  }
313
318
  this.processManifest_(mss, finalManifestUri);
package/lib/player.js CHANGED
@@ -3246,6 +3246,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3246
3246
  const playerInterface = {
3247
3247
  getPresentationTime: () => this.playhead_ ? this.playhead_.getTime() : 0,
3248
3248
  getBandwidthEstimate: () => this.abrManager_.getBandwidthEstimate(),
3249
+ getPlaybackRate: () => this.getPlaybackRate(),
3249
3250
  mediaSourceEngine: this.mediaSourceEngine_,
3250
3251
  netEngine: this.networkingEngine_,
3251
3252
  onError: (error) => this.onError_(error),
@@ -7181,7 +7182,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
7181
7182
  * @export
7182
7183
  */
7183
7184
  // eslint-disable-next-line no-useless-concat
7184
- shaka.Player.version = 'v4.8.0' + '-uncompiled'; // x-release-please-version
7185
+ shaka.Player.version = 'v4.8.1' + '-uncompiled'; // x-release-please-version
7185
7186
 
7186
7187
  // Initialize the deprecation system using the version string we just set
7187
7188
  // on the player.
@@ -187,12 +187,12 @@ shaka.util.CmcdManager = class {
187
187
 
188
188
  const stream = context.stream;
189
189
  if (stream) {
190
+ const playbackRate = this.playerInterface_.getPlaybackRate();
190
191
  if (isMedia) {
191
192
  data.bl = this.getBufferLength_(stream.type);
192
193
  if (data.ot !== ObjectType.TIMED_TEXT) {
193
194
  const remainingBufferLength =
194
195
  this.getRemainingBufferLength_(stream.type);
195
- const playbackRate = this.playerInterface_.getPlaybackRate();
196
196
  if (playbackRate) {
197
197
  data.dl = remainingBufferLength / Math.abs(playbackRate);
198
198
  } else {
@@ -206,8 +206,9 @@ shaka.util.CmcdManager = class {
206
206
  }
207
207
 
208
208
  if (stream.segmentIndex && segment) {
209
+ const reverse = playbackRate < 0;
209
210
  const iterator = stream.segmentIndex.getIteratorForTime(
210
- segment.endTime, /* allowNonIndepedent= */ true);
211
+ segment.endTime, /* allowNonIndepedent= */ true, reverse);
211
212
  if (iterator) {
212
213
  const nextSegment = iterator.next().value;
213
214
  if (nextSegment && nextSegment != segment) {
@@ -141,16 +141,10 @@ shaka.util.PlayerConfiguration = class {
141
141
  'urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95':
142
142
  'com.microsoft.playready',
143
143
  },
144
- manifestPreprocessor: (element) => {
145
- return shaka.util.ConfigUtils.referenceParametersAndReturn(
146
- [element],
147
- element);
148
- },
149
- manifestPreprocessorTXml: (element) => {
150
- return shaka.util.ConfigUtils.referenceParametersAndReturn(
151
- [element],
152
- element);
153
- },
144
+ manifestPreprocessor:
145
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
146
+ manifestPreprocessorTXml:
147
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
154
148
  sequenceMode: false,
155
149
  enableAudioGroups: false,
156
150
  multiTypeVariantsAllowed,
@@ -174,16 +168,10 @@ shaka.util.PlayerConfiguration = class {
174
168
  allowLowLatencyByteRangeOptimization: true,
175
169
  },
176
170
  mss: {
177
- manifestPreprocessor: (element) => {
178
- return shaka.util.ConfigUtils.referenceParametersAndReturn(
179
- [element],
180
- element);
181
- },
182
- manifestPreprocessorTXml: (element) => {
183
- return shaka.util.ConfigUtils.referenceParametersAndReturn(
184
- [element],
185
- element);
186
- },
171
+ manifestPreprocessor:
172
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
173
+ manifestPreprocessorTXml:
174
+ shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
187
175
  sequenceMode: false,
188
176
  keySystemsBySystemId: {
189
177
  '9a04f079-9840-4286-ab92-e65be0885f95':
@@ -615,4 +603,24 @@ shaka.util.PlayerConfiguration = class {
615
603
 
616
604
  return selectedTracks;
617
605
  }
606
+
607
+ /**
608
+ * @param {!Element} element
609
+ * @return {!Element}
610
+ */
611
+ static defaultManifestPreprocessor(element) {
612
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
613
+ [element],
614
+ element);
615
+ }
616
+
617
+ /**
618
+ * @param {!shaka.extern.xml.Node} element
619
+ * @return {!shaka.extern.xml.Node}
620
+ */
621
+ static defaultManifestPreprocessorTXml(element) {
622
+ return shaka.util.ConfigUtils.referenceParametersAndReturn(
623
+ [element],
624
+ element);
625
+ }
618
626
  };
@@ -983,8 +983,12 @@ shaka.util.StreamUtils = class {
983
983
  // currently don't support 'fLaC', while 'flac' is supported by most
984
984
  // major browsers.
985
985
  // See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
986
- if (codecs === 'fLaC' && !shaka.util.Platform.isSafari()) {
987
- return 'flac';
986
+ if (codecs.toLowerCase() == 'flac') {
987
+ if (!shaka.util.Platform.isSafari()) {
988
+ return 'flac';
989
+ } else {
990
+ return 'fLaC';
991
+ }
988
992
  }
989
993
 
990
994
  // The same is true for 'Opus'.
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.8.0",
4
+ "version": "4.8.1",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [