Improve handling of intial seek Change-Id: Id6554e0298fa198d6ebc0557db3cd0093f0f6d6e 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 813a361..6a6ff4a 100644 --- a/src/third_party/starboard/rdk/shared/player/player_internal.cc +++ b/src/third_party/starboard/rdk/shared/player/player_internal.cc
@@ -397,15 +397,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; @@ -1266,6 +1260,7 @@ void ConfigureLimitedVideo(); void SchedulePlayingStateUpdate(); void AddBufferingProbe(GstClockTime target, int ticket); + void HandleInititialSeek(::starboard::ScopedLock&); SbPlayer player_; SbWindow window_; @@ -1479,15 +1474,6 @@ need_first_segment_ack_ = has_enough_data_; - if (audio_codec_ != kSbMediaAudioCodecNone) { - auto caps = CodecToGstCaps(audio_codec_, &audio_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); @@ -1832,12 +1818,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_); @@ -2116,6 +2102,25 @@ } } else if (sample_infos[0].type == kSbMediaTypeAudio) { + SB_DCHECK (sample_infos[0].type == kSbMediaTypeAudio); + SB_DCHECK (audio_codec_ != kSbMediaAudioCodecNone); + + if ( audio_caps_ == nullptr ) { +#if SB_API_VERSION >= 15 + const auto& audio_info = sample_infos[0].audio_sample_info.stream_info; +#else + const auto& audio_info = sample_infos[0].audio_sample_info; +#endif + auto caps = CodecToGstCaps(audio_codec_, &audio_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); + } + } + #if SB_API_VERSION >= 15 const auto& info = sample_infos[0].audio_sample_info; if (info.discarded_duration_from_front || info.discarded_duration_from_back) { @@ -2320,6 +2325,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(); @@ -2354,41 +2424,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");