Fix SetPlaybackRate not to flush appsrc 69/280869/1 accepted/tizen_7.0_unified_hotfix tizen_7.0_hotfix accepted/tizen/7.0/unified/20221110.061457 accepted/tizen/7.0/unified/hotfix/20221116.105458 accepted/tizen/unified/20220908.013354 tizen_7.0_m2_release
authorJeongyoon Nam <just.nam@samsung.com>
Tue, 6 Sep 2022 05:49:35 +0000 (14:49 +0900)
committerJeongyoon Nam <just.nam@samsung.com>
Tue, 6 Sep 2022 06:21:15 +0000 (15:21 +0900)
[Version] 0.0.14
[Issue Type] Bug fix

Change-Id: Iaf2ceaa7e12c860ddeaad98d5e3da1e8274b2379

packaging/libtrackrenderer.spec
src/include_internal/trackrenderer/core/pipeline.hpp
src/include_internal/trackrenderer/trackrenderer.h
src/trackrenderer.cpp

index dbba5099fd1462dde6ed664ea1a212106e32ca47..2dffe5a41426b3b47f7ca3963492973346d4de38 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libtrackrenderer
 Summary:    new multimedia streaming player trackrenderer
-Version:    0.0.13
+Version:    0.0.14
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 674956f6faa0e69307d02ce2b265733950333dd2..ec9166c3c396b6c13dff293b4bf667a989dbd9f5 100644 (file)
@@ -453,7 +453,7 @@ class Pipeline : private boost::noncopyable {
     return true;
   }
 
-  bool FlushDownStream(T type) {
+  bool FlushDownStream(T type, gboolean reset_time) {
     GstElement* obj = mainbin_[static_cast<int>(type)];
     if (!obj) return false;
     auto pad = gstguard::make_guard(gst_element_get_static_pad(obj, "src"));
@@ -462,7 +462,7 @@ class Pipeline : private boost::noncopyable {
       TRACKRENDERER_ERROR("Fail to send flush start");
       return false;
     }
-    if (!gst_pad_send_event(peer_pad, gst_event_new_flush_stop(FALSE))) {
+    if (!gst_pad_send_event(peer_pad, gst_event_new_flush_stop(reset_time))) {
       TRACKRENDERER_ERROR("Fail to send flush stop");
       return false;
     }
@@ -536,6 +536,25 @@ class Pipeline : private boost::noncopyable {
     return gst_element_factory_list_is_type(gst_element_get_factory(obj), type);
   }
 
+  bool PushSegmentEvent(T type, uint64_t position, gdouble rate) {
+    GstElement* obj = mainbin_[static_cast<int>(type)];
+    if (!obj) return false;
+    auto pad = gstguard::make_guard(gst_element_get_static_pad(obj, "src"));
+    auto peer_pad = GST_PAD_PEER(pad.get());
+    GstSegment segment;
+    gst_segment_init(&segment, GST_FORMAT_TIME);
+    segment.rate = rate;
+    segment.start = position;
+    segment.position = position;
+    segment.time = position;
+    GstEvent* seg_event = gst_event_new_segment(&segment);
+    if (!gst_pad_send_event(peer_pad, seg_event)) {
+      TRACKRENDERER_ERROR("Fail to send segment event");
+      return false;
+    }
+    return true;
+  }
+
   ////////////////                     /////////////////
   //////////////// Utilities (Leaving) /////////////////
   ////////////////                     /////////////////
index ec14878910e8dcaab991f4db1c34eeec8679a13a..9675f774533d29623ed0439dfc1528909bfe0a73 100644 (file)
@@ -302,7 +302,8 @@ class TrackRenderer : public ResourceConflictListener,
   void SetVolume_();
   bool ActivateAudio_();
   bool DeactivateAudio_();
-  void FlushAudioDownStream_(Elements element);
+  void FlushDownStream_(Elements element, const char* key,
+                        gboolean reset_time);
   void InitConfigSetterTable_();
   bool SetAccurateSeekMode_(const boost::any& value);
   bool SetLowLatencyMode_(const boost::any& value);
index 36d44faa7c71d185707750f008f2fc57d70960ed..95b2329e0e7457e3dcc000b6b689805c4a51d99c 100644 (file)
@@ -574,7 +574,7 @@ bool TrackRenderer::Prepare() {
     return false;
   }
 
-    resource_cv_.wait(lock);
+  resource_cv_.wait(lock);
 
   if (state_ != State::kWorking) {
     TRACKRENDERER_ERROR(
@@ -842,13 +842,41 @@ bool TrackRenderer::SetPlaybackRate(double playback_rate, bool audio_mute) {
                              gint(playback_rate * 100));
     }
   }
-  if (!pipeline_->Seek(
-          playback_rate, GST_FORMAT_TIME,
-          (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
-          GST_SEEK_TYPE_SET, curtime_in_msec * GST_MSECOND, GST_SEEK_TYPE_NONE,
-          GST_CLOCK_TIME_NONE)) {
-    TRACKRENDERER_ERROR("Fail to seek ");
+
+  Elements audio_probe_element = Elements::kDecAudio;
+  Elements video_probe_element = Elements::kDecVideo;
+  Elements subtitle_probe_element = Elements::kAppSrcSubtitle;
+  Elements close_caption_probe_element = Elements::kQueueCaption;
+
+  std::map<Elements, std::pair<std::string, std::string>> probe_map = {
+      {audio_probe_element,
+       {"AUDIO_RATE_IDLE_PROBE", "AUDIO_RATE_BLOCK_PROBE"}},
+      {video_probe_element,
+       {"VIDEO_RATE_IDLE_PROBE", "VIDEO_RATE_BLOCK_PROBE"}},
+      {subtitle_probe_element,
+       {"SUBTITLE_RATE_IDLE_PROBE", "SUBTITLE_RATE_BLOCK_PROBE"}},
+      {close_caption_probe_element,
+       {"CLOSE_CAPTION_RATE_IDLE_PROBE", "CLOSE_CAPTION_RATE_BLOCK_PROBE"}}};
+
+  std::map<Elements, Elements> probe_sink_map = {
+      {audio_probe_element, Elements::kSinkAudio},
+      {video_probe_element, Elements::kSinkVideo},
+      {subtitle_probe_element, Elements::kSinkSubtitle},
+      {close_caption_probe_element, Elements::kSinkCaption}};
+
+  for (auto& kv : probe_map) {
+    const Elements& element = kv.first;
+    std::pair<std::string, std::string>& probe = kv.second;
+    pipeline_->PadAddProbe(element, (probe.second).c_str(), "src",
+                           GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, nullptr,
+                           nullptr, nullptr);
+    gboolean is_sync = FALSE;
+    pipeline_->GetProperty(probe_sink_map[element], "sync", &is_sync);
+    pipeline_->SetProperty(probe_sink_map[element], "sync", FALSE);
+    FlushDownStream_(element, (probe.first).c_str(), TRUE);
+    if (is_sync) pipeline_->SetProperty(probe_sink_map[element], "sync", TRUE);
   }
+
   if (playback_rate != kDefaultPlaybackRate) {
     TRACKRENDERER_INFO("sequential mode should be off during trickplay");
     pipeline_->SetProperty(Elements::kSinkVideo, "is-trickplay", TRUE);
@@ -857,14 +885,18 @@ bool TrackRenderer::SetPlaybackRate(double playback_rate, bool audio_mute) {
 
   pipeline_->GetProperty(Elements::kSinkVideo, "last-video-pts",
                          &last_video_pts);
-  if (last_video_pts > 0) {
-    pipeline_->SetProperty(Elements::kAppSrcVideo, "update-segment",
-                           last_video_pts);
-    pipeline_->SetProperty(Elements::kAppSrcAudio, "update-segment",
-                           last_video_pts);
-    pipeline_->SetProperty(Elements::kAppSrcSubtitle, "update-segment",
-                           last_video_pts);
+
+  TRACKRENDERER_INFO("target %" PRIu64 " ms  rate [%lf]  mute [%d]", curtime_in_msec,
+                     playback_rate, audio_mute);
+
+  for (auto& kv : probe_map) {
+    const Elements& element = kv.first;
+    std::pair<std::string, std::string>& probe = kv.second;
+    pipeline_->PushSegmentEvent(element, curtime_in_msec * GST_MSECOND,
+                                playback_rate);
+    pipeline_->PadRemoveProbe((probe.second).c_str());
   }
+
   playback_rate_ = playback_rate;
   TRACKRENDERER_LEAVE;
   return true;
@@ -2726,27 +2758,25 @@ GstPadProbeReturn TrackRenderer::GstSrcPadProbeIdleCb_(GstPad* pad,
   return GST_PAD_PROBE_DROP;
 }
 
-void TrackRenderer::FlushAudioDownStream_(Elements element) {
-  TRACKRENDERER_ENTER;
+void TrackRenderer::FlushDownStream_(Elements element, const char* key,
+                                     gboolean reset_time) {
+  TRACKRENDERER_ENTER_P(this);
   if (!pipeline_) return;
 
   Pipeline<Elements>::Pad pad;
 
-  pipeline_->PadAddProbe(element, kPadProbeAudioIdle, "src",
-                         GST_PAD_PROBE_TYPE_IDLE, GstSrcPadProbeIdleCb_, &pad,
-                         nullptr);
-
-  pipeline_->FlushDownStream(element);
+  pipeline_->PadAddProbe(element, key, "src", GST_PAD_PROBE_TYPE_IDLE,
+                         GstSrcPadProbeIdleCb_, &pad, nullptr);
 
-  {
+  if (pipeline_->FlushDownStream(element, reset_time)) {
     std::unique_lock<std::mutex> pad_block_locker(pad.m);
     if (!pad.is_idle) {
       pad.cv.wait(pad_block_locker);
-      TRACKRENDERER_INFO("pad block wait end");
+      TRACKRENDERER_INFO_P(this, "pad block wait end");
     }
   }
-  pipeline_->PadRemoveProbe(kPadProbeAudioIdle);
-  TRACKRENDERER_LEAVE;
+  pipeline_->PadRemoveProbe(key);
+  TRACKRENDERER_LEAVE_P(this);
 }
 
 bool TrackRenderer::ActivateAudio_() {
@@ -2768,7 +2798,7 @@ bool TrackRenderer::ActivateAudio_() {
                          GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
                          GstSrcPadProbeBlockCb_, nullptr, nullptr);
   pipeline_->SetProperty(Elements::kFakeSinkAudio, "async", FALSE);
-  FlushAudioDownStream_(element);
+  FlushDownStream_(element, kPadProbeAudioIdle, FALSE);
   pipeline_->BinRemove(Elements::kBinAudio, Elements::kFakeSinkAudio);
 
   auto caps = caps_builder_.Build(track, internal::IsDrmEmeElementNecessary(
@@ -2819,7 +2849,7 @@ bool TrackRenderer::DeactivateAudio_() {
                          GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
                          GstSrcPadProbeBlockCb_, nullptr, nullptr);
   pipeline_->SetProperty(Elements::kSinkAudio, "async", FALSE);
-  FlushAudioDownStream_(element);
+  FlushDownStream_(element, kPadProbeAudioIdle, FALSE);
   pipeline_->BinRemove(Elements::kBinAudio, Elements::kDecAudio,
                        Elements::kSinkAudio);
   std::string sink_name("fakesink");