Repository: shaka-project/shaka-player (JavaScript)

Issue:
steaming.rebufferingGoal is being ignored after v4.6.0
<!-- NOTE: If you ignore this template, we will send it again and ask you to fill it out anyway. -->

**Have you read the [FAQ](https://bit.ly/ShakaFAQ) and checked for duplicate open issues?**
Yes.

**If the problem is related to FairPlay, have you read the tutorial?**
<!-- NOTE: https://shaka-player-demo.appspot.com/docs/api/tutorial-fairplay.html -->
N/A

**What version of Shaka Player are you using?**
<!-- NOTE:
  Only some versions of the application are maintained, if your version
  is older, first update to a newer one. See:
  https://github.com/shaka-project/shaka-player/blob/main/maintained-branches.md
--->
Nightly


**Can you reproduce the issue with our latest release version?**
Yes

**Can you reproduce the issue with the latest code from `main`?**
Yes

**Are you using the demo app or your own custom app?**
demo app

**If custom app, can you reproduce the issue using our demo app?**
N/A

**What browser and OS are you using?**
macOS Catalina v10.15.7
Chrome 120.0.6099.216（Official Build） （x86_64）

**For embedded devices (smart TVs, etc.), what model and firmware version are you using?**
N/A

**What are the manifest and license server URIs?**
<!-- NOTE:
  You can send the URIs to <shaka-player-maintainers@googlegroups.com> instead,
  but please use GitHub and the template for the rest.
  A copy of the manifest text or an attached manifest will **not** be
  enough to reproduce your issue, and we **will** ask you to send a
  URI instead.  You can copy the URI of the demo app to send us the
  exact asset, licence server, and settings you have selected there.
  If you send the URIs to email, the response time and resolution
  will be much higher.
-->

Big Buck Bunny: the Dark Truths of a Video Dev Cartoon (DASH)
https://storage.googleapis.com/shaka-demo-assets/bbb-dark-truths/dash.mpd


**What configuration are you using?  What is the output of `player.getConfiguration()`?**
<!-- NOTE:
  You can censor URLs to keep them private, but include them in the email.  You
  can also use JSON.stringify(obj, null, 2) to print nicely on platforms that
  don't print objects well in the console.  DON'T SEND '[object Object]'!
-->

The default configuration on shaka demo, with following extra configuration:
```
{
  "streaming": {
    "rebufferingGoal": 100
  }
}
```

**What did you do?**
<!-- Steps to reproduce the bug -->
1. Go to [nightly demo - CUSTOM CONTENT](https://nightly-dot-shaka-player-demo.appspot.com/demo/#audiolang=en-US;textlang=en-US;uilang=en-US;panel=CUSTOM%20CONTENT;build=uncompiled)
2. Click "+" button. and input
  * Manifest URL: https://storage.googleapis.com/shaka-demo-assets/bbb-dark-truths/dash.mpd
  * Name: Test
  * Extra config
```
{
  "streaming": {
    "rebufferingGoal": 100
  }
}
```
3. Save and play. 

**What did you expect to happen?**

By reading [this tutorial about rebufferingGoal](https://shaka-player-demo.appspot.com/docs/api/tutorial-network-and-buffering-config.html#buffering-configuration), I think shaka player should wait for the buffer reaching to 100s to start playing the video. And it actually did if I try it on version 4.5.0 or earlier.

**What actually happened?**
<!-- A clear and concise description of what the bug is -->
<!-- If applicable, you may add screenshots to help explain your problem. -->

Video is played without waiting for the rebufferingGoal being achieved.

I'm not very familiar with shaka-player's source code, after a few investigation I feel this change (https://github.com/shaka-project/shaka-player/pull/5696) might be the root cause. Also I'm not sure if it's an intentional change or a bug.


Discussion: if i'm not wrong the rebufferingGoal is only apply with manifest.dash.ignoreMinBufferTime <= true
@Iragne By reading the code([1](https://github.com/shaka-project/shaka-player/blob/main/lib/media/playhead.js#L469), [2](https://github.com/shaka-project/shaka-player/blob/07a32419d3069dbf65fda8d9c56244175f934a4a/lib/media/streaming_engine.js#L695)), I think it only happens when rebufferingGoal is less than minBufferTime. The value of `max(config.rebufferingGoal, manifest.minBufferTime)` is supposed to be respected when shaka-player handles the `play` -> `pause(for buffering)` -> `play(after has enough buffer)` thing.
Hum need more attention agree.
Thanks I clearly found the issue of the rate control and the buffering state.
I'm checking now the impact of it
here the first proposed solution but still in draft https://github.com/shaka-project/shaka-player/pull/6433



Fix (patch):
diff --git a/lib/media/play_rate_controller.js b/lib/media/play_rate_controller.js
index f0917d117c..bd3dbe1ab2 100644
--- a/lib/media/play_rate_controller.js
+++ b/lib/media/play_rate_controller.js
@@ -30,6 +30,9 @@ shaka.media.PlayRateController = class {
     /** @private {number} */
     this.rate_ = this.harness_.getRate();
 
+    /** @private {boolean} */
+    this.isBuffering_ = false;
+
     /** @private {number} */
     this.pollRate_ = 0.25;
 
@@ -50,6 +53,16 @@ shaka.media.PlayRateController = class {
     this.harness_ = null;
   }
 
+  /**
+   * Sets the buffering flag, which controls the effective playback rate.
+   *
+   * @param {boolean} isBuffering If true, forces playback rate to 0 internally.
+   */
+  setBuffering(isBuffering) {
+    this.isBuffering_ = isBuffering;
+    this.apply_();
+  }
+
   /**
    * Set the playback rate.
    *
@@ -93,11 +106,12 @@ shaka.media.PlayRateController = class {
     // Always stop the timer. We may not start it again.
     this.timer_.stop();
 
-    shaka.log.v1('Changing effective playback rate to', this.rate_);
+    const rate = this.calculateCurrentRate_();
+    shaka.log.v1('Changing effective playback rate to', rate);
 
-    if (this.rate_ >= 0) {
+    if (rate >= 0) {
       try {
-        this.applyRate_(this.rate_);
+        this.applyRate_(rate);
         return;
       } catch (e) {
         // Fall through to the next clause.
@@ -117,6 +131,17 @@ shaka.media.PlayRateController = class {
     this.applyRate_(0);
   }
 
+  /**
+   * Calculate the rate that the controller wants the media element to have
+   * based on the current state of the controller.
+   *
+   * @return {number}
+   * @private
+   */
+  calculateCurrentRate_() {
+    return this.isBuffering_ ? 0 : this.rate_;
+  }
+
   /**
    * If the new rate is different than the media element's playback rate, this
    * will change the playback rate. If the rate does not need to change, it will
diff --git a/lib/media/stall_detector.js b/lib/media/stall_detector.js
index 1dbdefa411..6b52553c82 100644
--- a/lib/media/stall_detector.js
+++ b/lib/media/stall_detector.js
@@ -180,6 +180,12 @@ shaka.media.StallDetector.MediaElementImplementation = class {
     if (this.mediaElement_.buffered.length == 0) {
       return false;
     }
+    // the playback rate is at 0, the player is not stalled but simply pausing
+    // it's buffering due to not enough buffer to respect reBufferingGoal
+    // or minbufferTime
+    if (this.mediaElement_.playbackRate == 0) {
+      return false;
+    }
 
     return shaka.media.StallDetector.MediaElementImplementation.hasContentFor_(
         this.mediaElement_.buffered,
diff --git a/lib/player.js b/lib/player.js
index fa61ef0e14..55bb4bcd20 100644
--- a/lib/player.js
+++ b/lib/player.js
@@ -5717,6 +5717,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
     const loaded = this.stats_ && this.bufferObserver_ && this.playhead_;
 
     if (loaded) {
+      this.playRateController_.setBuffering(isBuffering);
       if (this.cmcdManager_) {
         this.cmcdManager_.setBuffering(isBuffering);
       }