Improve handling of intial seek
Change-Id: Id6554e0298fa198d6ebc0557db3cd0093f0f6d6e
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 0e3b448..49cbbe6 100644
--- a/src/third_party/starboard/rdk/shared/player/player_internal.cc
+++ b/src/third_party/starboard/rdk/shared/player/player_internal.cc
@@ -406,15 +406,9 @@
void gst_cobalt_src_setup_and_add_app_src(SbMediaType media_type,
GstElement* element,
GstElement* appsrc,
- GstCaps* caps,
GstAppSrcCallbacks* callbacks,
gpointer user_data,
gboolean inject_decryptor) {
- if (caps) {
- PrintGstCaps(caps);
- gst_app_src_set_caps(GST_APP_SRC(appsrc), caps);
- }
-
const uint32_t kAudioMaxBytes = 256 * 1024;
const uint32_t kVideoMaxBytes = 8 * 1024 * 1024;
@@ -438,8 +432,7 @@
GstElement* src_elem = appsrc;
GstElement* decryptor = inject_decryptor ? CreateDecryptorElement(nullptr) : nullptr;
GstElement* payloader = nullptr;
- if (decryptor && media_type == kSbMediaTypeVideo && !isRialtoEnabled())
- {
+ if (decryptor && media_type == kSbMediaTypeVideo && !isRialtoEnabled()) {
payloader = CreatePayloader();
}
@@ -1326,6 +1319,7 @@
void ConfigureLimitedVideo();
void SchedulePlayingStateUpdate();
void AddBufferingProbe(GstClockTime target, int ticket);
+ void HandleInititialSeek(::starboard::ScopedLock&);
SbPlayer player_;
SbWindow window_;
@@ -1525,15 +1519,6 @@
need_first_segment_ack_ = has_enough_data_;
- if (audio_codec_ != kSbMediaAudioCodecNone) {
- auto caps = CodecToGstCaps(audio_codec_, &audio_sample_info_);
- if (!caps.empty() && caps[0].c_str()) {
- GstCaps* gst_caps = gst_caps_from_string(caps[0].c_str());
- gst_caps_replace(&audio_caps_, gst_caps);
- gst_caps_unref(gst_caps);
- }
- }
-
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_));
bus_watch_id_ = gst_bus_add_watch(bus, &PlayerImpl::BusMessageCallback, this);
gst_object_unref(bus);
@@ -1869,12 +1854,12 @@
&PlayerImpl::AppSrcSeekData, nullptr};
if (self->audio_codec_ != kSbMediaAudioCodecNone) {
gst_cobalt_src_setup_and_add_app_src(kSbMediaTypeAudio,
- source, self->audio_appsrc_, self->audio_caps_,
+ source, self->audio_appsrc_,
&callbacks, self, has_drm_system);
}
if (self->video_codec_ != kSbMediaVideoCodecNone) {
gst_cobalt_src_setup_and_add_app_src(kSbMediaTypeVideo,
- source, self->video_appsrc_, self->video_caps_,
+ source, self->video_appsrc_,
&callbacks, self, has_drm_system);
}
gst_cobalt_src_all_app_srcs_added(self->source_);
@@ -2148,6 +2133,20 @@
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
}
}
+ else {
+ SB_DCHECK (sample_infos[0].type == kSbMediaTypeAudio);
+ SB_DCHECK (audio_codec_ != kSbMediaAudioCodecNone);
+ if ( audio_caps_ == nullptr ) {
+ auto caps = CodecToGstCaps(audio_codec_, &audio_sample_info_);
+ if (!caps.empty() && caps[0].c_str()) {
+ GstCaps* gst_caps = gst_caps_from_string(caps[0].c_str());
+ PrintGstCaps(gst_caps);
+ gst_app_src_set_caps(GST_APP_SRC(audio_appsrc_), gst_caps);
+ gst_caps_replace(&audio_caps_, gst_caps);
+ gst_caps_unref(gst_caps);
+ }
+ }
+ }
RecordTimestamp(sample_type, timestamp);
@@ -2323,6 +2322,71 @@
GST_STREAM_VOLUME_FORMAT_LINEAR, volume);
}
+void PlayerImpl::HandleInititialSeek(::starboard::ScopedLock& lock) {
+ mutex_.DCheckAcquired();
+ SB_DCHECK(state_ == State::kInitial || GST_STATE(pipeline_) < GST_STATE_PAUSED);
+
+ if (state_ == State::kInitial) {
+ // This is the initial seek to 0 which will trigger data pumping.
+ SB_DCHECK(seek_position_ == .0);
+ state_ = State::kInitialPreroll;
+ DispatchOnWorkerThread(
+ new PlayerStatusTask(player_status_func_, player_,
+ ticket_, context_,
+ kSbPlayerStatePrerolling));
+ seek_position_ = kSbTimeMax;
+ if (GST_STATE(pipeline_) < GST_STATE_PAUSED &&
+ GST_STATE_PENDING(pipeline_) < GST_STATE_PAUSED) {
+ mutex_.Release();
+ ChangePipelineState(GST_STATE_PAUSED);
+ mutex_.Acquire();
+ }
+ return;
+ }
+
+ // Ask for data.
+ if (state_ == State::kInitialPreroll) {
+ MediaType need_data = static_cast<MediaType>(
+ static_cast<int>(MediaType::kBoth) & ~has_enough_data_ );
+ if (need_data != MediaType::kNone)
+ DecoderNeedsData(lock, need_data);
+ }
+
+#if GST_CHECK_VERSION(1, 18, 0)
+ // It is safe to replace the segment before app writes any data.
+ bool can_change_segment = !audio_caps_ && !video_caps_ && !isRialtoEnabled();
+ if (can_change_segment) {
+ GST_INFO_OBJECT(pipeline_, "Changing initial segment.");
+ GstClockTime position = seek_position_ * kSbTimeNanosecondsPerMicrosecond;
+ GstSegment segment;
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ if ( !gst_segment_do_seek(&segment, !rate_ ? 1.0 : rate_,
+ GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
+ GST_SEEK_TYPE_SET, position,
+ GST_SEEK_TYPE_NONE, 0, nullptr) ) {
+ GST_WARNING_OBJECT(pipeline_, "Segment seek failed.");
+ }
+ else if ( !gst_base_src_new_segment(GST_BASE_SRC(audio_appsrc_), &segment) ) {
+ GST_WARNING_OBJECT(pipeline_, "Could not change audio source segment.");
+ }
+ else if ( !gst_base_src_new_segment(GST_BASE_SRC(video_appsrc_), &segment) ) {
+ GST_WARNING_OBJECT(pipeline_, "Could not change video source segment.");
+ }
+ else {
+ DispatchOnWorkerThread(new PlayerStatusTask(player_status_func_, player_, ticket_,
+ context_, kSbPlayerStatePrerolling));
+ AddBufferingProbe(position, ticket_);
+ GST_INFO("Successfully changed initial segment, position: %" GST_TIME_FORMAT ", ticket: %d", GST_TIME_ARGS(position), ticket_);
+ return;
+ }
+ }
+#endif
+
+ // Else send seek after pre-roll.
+ GST_INFO("Delaying seek.");
+ is_seek_pending_ = true;
+}
+
void PlayerImpl::Seek(SbTime seek_to_timestamp, int ticket) {
::starboard::ScopedLock lock(seek_mutex_);
gint64 current_pos_ns = GetPosition();
@@ -2357,41 +2421,14 @@
seek_position_ = seek_to_timestamp;
decoder_state_data_ = 0;
eos_data_ = 0;
-
- if (state_ == State::kInitial) {
- SB_DCHECK(seek_position_ == .0);
- // This is the initial seek to 0 which will trigger data pumping.
- state_ = State::kInitialPreroll;
- DispatchOnWorkerThread(new PlayerStatusTask(player_status_func_, player_,
- ticket_, context_,
- kSbPlayerStatePrerolling));
- seek_position_ = kSbTimeMax;
- if (GST_STATE(pipeline_) < GST_STATE_PAUSED &&
- GST_STATE_PENDING(pipeline_) < GST_STATE_PAUSED) {
- mutex_.Release();
- ChangePipelineState(GST_STATE_PAUSED);
- mutex_.Acquire();
- }
- return;
- }
-
- if (GST_STATE(pipeline_) < GST_STATE_PAUSED) {
- GST_INFO("Delaying seek.");
- if (state_ == State::kInitialPreroll) {
- if ((has_enough_data_ & static_cast<int>(MediaType::kVideo)) == 0) {
- DecoderNeedsData(lock, MediaType::kVideo);
- }
-
- if ((has_enough_data_ & static_cast<int>(MediaType::kAudio)) == 0) {
- DecoderNeedsData(lock, MediaType::kAudio);
- }
- }
- is_seek_pending_ = true;
- return;
- }
-
is_seek_pending_ = false;
+
rate = rate_;
+
+ if (state_ == State::kInitial || GST_STATE(pipeline_) < GST_STATE_PAUSED) {
+ HandleInititialSeek(lock);
+ return;
+ }
}
GST_DEBUG("Calling seek");
@@ -2467,11 +2504,6 @@
return false;
if( !!getenv("COBALT_ENABLE_INSTANT_RATE_CHANGE_SEEK") )
return true;
- auto *amlhalasink_factory = gst_element_factory_find("amlhalasink");
- if ( amlhalasink_factory ) {
- gst_object_unref(amlhalasink_factory);
- return true;
- }
return false;
})();
if (kEnableInstantRateChangeSeek) {