Initial support for instant rate change

Custom implementation for Amlogic

Change-Id: Ie76cc8921a9ad05de44d75b399a5640f6487619d
Signed-off-by: Eugene Mutavchi <Ievgen_Mutavchi@comcast.com>
diff --git a/src/third_party/starboard/rdk/shared/player/player_internal.cc b/src/third_party/starboard/rdk/shared/player/player_internal.cc
index 190e196..047f9b5 100644
--- a/src/third_party/starboard/rdk/shared/player/player_internal.cc
+++ b/src/third_party/starboard/rdk/shared/player/player_internal.cc
@@ -1146,7 +1146,6 @@
   MediaType min_sample_timestamp_origin_{MediaType::kNone};
   bool is_seek_pending_{false};
   double pending_rate_{.0};
-  bool is_rate_being_changed_{false};
   int has_enough_data_{static_cast<int>(MediaType::kBoth)};
   mutable int decoder_state_data_{static_cast<int>(MediaType::kNone)};
   int eos_data_{static_cast<int>(MediaType::kNone)};
@@ -1170,6 +1169,7 @@
   GstCaps* audio_caps_ { nullptr };
   GstCaps* video_caps_ { nullptr };
   SbTime buf_target_min_ts_ { kSbTimeMax };
+  bool did_instant_rate_change_ { false };
 };
 
 struct PlayerRegistry
@@ -1491,7 +1491,7 @@
             }
             if (self->state_ == State::kPrerollAfterSeek ||
                 self->state_ == State::kInitialPreroll) {
-              self->has_oob_write_pending_ |= (is_seek_pending || is_rate_pending);
+              self->has_oob_write_pending_ |= is_seek_pending;
             }
           }
 
@@ -1521,15 +1521,13 @@
         ::starboard::Mutex &mutex = self->mutex_;
         ::starboard::ScopedLock lock(mutex);
 
-        self->is_rate_being_changed_ = false;
         if (self->state_ == State::kPrerollAfterSeek ||
             self->state_ == State::kInitialPreroll) {
 
           bool is_seek_pending = self->is_seek_pending_;
-          bool is_rate_pending = self->pending_rate_ != 0.;
           bool has_pending_samples = (self->pending_samples_.empty() == false) || self->has_oob_write_pending_;
 
-          if (!is_seek_pending && !is_rate_pending && has_pending_samples) {
+          if (!is_seek_pending && has_pending_samples) {
 
             int prev_has_data = static_cast<int>(self->has_enough_data_);
             self->has_enough_data_ = static_cast<int>(MediaType::kBoth);
@@ -2001,7 +1999,7 @@
   bool keep_samples = false;
   {
     ::starboard::ScopedLock lock(mutex_);
-    keep_samples = is_seek_pending_ || pending_rate_ != .0;
+    keep_samples = is_seek_pending_;
     serial = samples_serial_[ (sample_type == kSbMediaTypeVideo ? kVideoIndex : kAudioIndex) ]++;
     if (sample_type == kSbMediaTypeVideo)
       ++total_video_frames_;
@@ -2180,48 +2178,52 @@
 bool PlayerImpl::SetRate(double rate) {
   GST_DEBUG_OBJECT(pipeline_, "===> rate %lf (rate_ %lf), TID: %d", rate, rate_,
                    SbThreadGetId());
+
   bool success = true;
-  double current_rate = 1.;
   {
     ::starboard::ScopedLock lock(mutex_);
-    current_rate = rate_;
     decoder_state_data_ = 0;
     eos_data_ = 0;
   }
+
   if (rate == .0) {
     ChangePipelineState(GST_STATE_PAUSED);
-  } else if (rate == 1. && (current_rate == 1. || current_rate == .0)) {
-    ChangePipelineState(GST_STATE_PLAYING);
   } else {
     ChangePipelineState(GST_STATE_PLAYING);
+  }
+
+  if (rate != .0 && (rate != 1. || did_instant_rate_change_)) {
     {
       ::starboard::ScopedLock lock(mutex_);
       if (is_seek_pending_) {
-        GST_DEBUG("Rate will be set when doing seek");
+        GST_DEBUG_OBJECT(pipeline_, "Rate will be set when doing seek");
         rate_ = rate;
         return true;
       }
-    }
-    if (GST_STATE(pipeline_) < GST_STATE_PAUSED) {
-      GST_DEBUG_OBJECT(pipeline_, "===> Set rate postponed");
-      ::starboard::ScopedLock lock(mutex_);
-      pending_rate_ = rate;
-      return true;
-    } else {
-      {
-        ::starboard::ScopedLock lock(mutex_);
-        is_rate_being_changed_ = true;
-        pending_rate_ = .0;
+      if (GST_STATE(pipeline_) < GST_STATE_PLAYING) {
+        GST_DEBUG_OBJECT(pipeline_, "===> Set rate postponed");
+        pending_rate_ = rate;
+        return true;
       }
+      pending_rate_ = .0;
+    }
 
-      GST_DEBUG("Calling seek (set rate)");
-      success =
-          gst_element_seek(pipeline_, rate, GST_FORMAT_TIME,
-                           static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH |
-                                                     GST_SEEK_FLAG_ACCURATE),
-                           GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
-                           GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
-      GST_DEBUG("Seek called (set rate)");
+    // TODO: instant rate change support
+    GstElement* sink = nullptr;
+    g_object_get(pipeline_, "audio-sink", &sink, nullptr);
+    if (sink && g_str_has_prefix(GST_ELEMENT_NAME(sink), "amlhalasink")) {
+      GstSegment* segment = gst_segment_new();
+      gst_segment_init(segment, GST_FORMAT_TIME);
+      segment->rate = rate;
+      segment->start = GST_CLOCK_TIME_NONE;
+      segment->position = GST_CLOCK_TIME_NONE;
+      GST_DEBUG_OBJECT(pipeline_, "===> Sending new segment %" GST_SEGMENT_FORMAT, segment);
+      success = gst_pad_send_event (GST_BASE_SINK_PAD(sink), gst_event_new_segment(segment));
+      GST_DEBUG_OBJECT(pipeline_, "===> Sent new segment, success = %s", success ? "true" : "false");
+      gst_segment_free(segment);
+      g_object_unref(sink);
+
+      did_instant_rate_change_ |= success;
     }
   }
 
@@ -2409,11 +2411,6 @@
       cached_position_ns_ = seek_pos_ns;
       seek_position_ = kSbTimeMax;
     }
-
-    if (is_rate_being_changed_ && audio_codec_ != kSbMediaAudioCodecNone) {
-      GST_WARNING("Set rate workaround kicking in.");
-      return max_sample_timestamps_[kAudioIndex];
-    }
   }
 
   if (GST_CLOCK_TIME_IS_VALID(cached_position_ns_) &&
@@ -2435,7 +2432,7 @@
   int ticket = -1;
   {
     ::starboard::ScopedLock lock(mutex_);
-    keep_samples = is_seek_pending_ || pending_rate_ != 0.;
+    keep_samples = is_seek_pending_;
     ticket = ticket_;
     local_samples.swap(pending_samples_);
   }
diff --git a/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc b/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc
index d892b71..e5d2083 100644
--- a/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc
+++ b/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc
@@ -34,11 +34,5 @@
 #include "third_party/starboard/rdk/shared/player/player_internal.h"
 
 bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate) {
-  // FIXME: remove after seemless rate change is supported
-  if (playback_rate > 0.0 && playback_rate != 1.0)
-    playback_rate = 1.0;
-  else if (playback_rate < 0.0)
-    playback_rate = 0.0;
-
   return player->player_->SetRate(playback_rate);
 }