support disable sync mode for low latency 35/298735/2 accepted/tizen/8.0/unified/20231005.093528 accepted/tizen/unified/20230914.100351 tizen_8.0_m2_release
authorEunhye Choi <eunhae1.choi@samsung.com>
Wed, 13 Sep 2023 05:30:18 +0000 (14:30 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Wed, 13 Sep 2023 05:36:02 +0000 (14:36 +0900)
- media data will be rendered once it is decoded
  regardless of pipeline clock
- related espp api :
  esplusplayer_set_low_latency_mode
- low_latench_mode.h file is synchronized with product

[Version] 0.0.38

Change-Id: I75b6aab3545f83016c5f81db44aa46c3b5369be1

packaging/libtrackrenderer.spec
src/include_internal/trackrenderer/core/low_latency_mode.h [new file with mode: 0644]
src/include_internal/trackrenderer/trackrenderer.h
src/trackrenderer.cpp

index 4cd5e95ec0f2c175d7a6de8d93dfd4af333894fc..eeb1b2122cab9f2e74680c6ae773d282060ba9af 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libtrackrenderer
 Summary:    new multimedia streaming player trackrenderer
-Version:    0.0.37
+Version:    0.0.38
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
diff --git a/src/include_internal/trackrenderer/core/low_latency_mode.h b/src/include_internal/trackrenderer/core/low_latency_mode.h
new file mode 100644 (file)
index 0000000..c6d15f8
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
+//
+
+#ifndef __PLUSPLAYER_TRACKRENDERER_CORE_LOW_LATENCY_MODE_H__
+#define __PLUSPLAYER_TRACKRENDERER_CORE_LOW_LATENCY_MODE_H__
+
+namespace plusplayer {
+
+namespace trackrenderer {
+
+enum LowLatencyMode {
+  kLowLatencyModeNone = 0x0000,
+  kLowLatencyModeAudio = 0x0001,
+  kLowLatencyModeVideo = 0x0010,
+  kLowLatencyModeVideoDistortionConcealment = kLowLatencyModeVideo | 0x0020,
+  kLowLatencyModeDisableAVSync = 0x0100,
+  kLowLatencyModeDisablePreroll = 0x0200,
+  kLowLatencyModeDisableVideoQuality = 0x1000,
+  kLowLatencyModeEnableGameMode =
+      kLowLatencyModeAudio | kLowLatencyModeVideo | 0x2000,
+  kLowLatencyModeEnableGameModeWithFixedResolution =
+      kLowLatencyModeEnableGameMode | 0x4000
+};
+
+}  // namespace trackrenderer
+
+}  // namespace plusplayer
+
+#endif  // __PLUSPLAYER_TRACKRENDERER_CORE_LOW_LATENCY_MODE_H__
\ No newline at end of file
index a867f4cff9f2e36f2b42e79f4025fe0ad468b2f1..2b9063ce2fc38c7abb69ac85ad1f795dcb3200f1 100644 (file)
@@ -182,21 +182,6 @@ class TrackRenderer : public ResourceConflictListener,
     kVolumeMax = 100,
   };
 
-  enum LowLatencyMode {
-    kLowLatencyModeNone = 0x0000,
-    kLowLatencyModeAudio = 0x0001,
-    kLowLatencyModeVideo = 0x0010,
-    kLowLatencyModeVideoDistortionConcealment =
-      kLowLatencyModeVideo | 0x0020,
-    kLowLatencyModeDisableAVSync = 0x0100,
-    kLowLatencyModeDisablePreroll = 0x0200,
-    kLowLatencyModeDisableVideoQuality = 0x1000,
-    kLowLatencyModeEnableGameMode =
-      kLowLatencyModeAudio | kLowLatencyModeVideo | 0x2000,
-    kLowLatencyModeEnableGameModeWithFixedResolution =
-      kLowLatencyModeEnableGameMode | 0x4000
-  };
-
   enum class SubState {
     kUnknown,
     kPaused,
index 547111d5c523386e28a1ce15568ff0394ec7647f..b34d644b5d9994ed7e7b6c67a4325ace4adc9e4f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "trackrenderer/core/gst_utils.h"
 #include "trackrenderer/core/gstobject_guard.h"
+#include "trackrenderer/core/low_latency_mode.h"
 #include "trackrenderer/core/track_util.h"
 #include "trackrenderer/core/utils/log.h"
 #include "trackrenderer/display.h"
@@ -420,10 +421,15 @@ int ToBufferTypeForSink(const DecodedVideoFrameBufferType& type) {
 }
 
 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t low_latency_mode) {
-  constexpr std::uint32_t kAVSync = 0x0100;
+  constexpr std::uint32_t kAVSync = static_cast<std::uint32_t>(kLowLatencyModeDisableAVSync);
   return (low_latency_mode & kAVSync) ? true : false;
 }
 
+inline bool IsLowLatencyModeDisablePreroll(std::uint32_t low_latency_mode) {
+  constexpr std::uint32_t kPreroll = static_cast<std::uint32_t>(kLowLatencyModeDisablePreroll);
+  return (low_latency_mode & kPreroll) ? true : false;
+}
+
 int GetVideoWidth(const GstCaps* caps) {
   GstStructure* structure = gst_caps_get_structure(caps, 0);
   if (!structure) return 0;
@@ -539,6 +545,9 @@ bool TrackRenderer::Prepare() {
     return false;
   }
 
+  if (!HasSubtitleOnly_() &&
+      !internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) &&
+      !internal::IsLowLatencyModeDisablePreroll(low_latency_mode_))
   resource_cv_.wait(lock);
 
   if (state_ != State::kWorking) {
@@ -888,6 +897,7 @@ bool TrackRenderer::SubmitPacket(const DecoderInputBufferPtr& data,
     return true;
   }
 
+  if (type >= kTrackTypeMax) return false;
   if (trackctx_[type].index == kInvalidTrackIndex  // Track is not activated.
       || data->GetIndex() != trackctx_[type].index) {
     TRACKRENDERER_DEBUG("ControlDropRate [%d] %d vs %d", type, data->GetIndex(), trackctx_[type].index);
@@ -1021,6 +1031,7 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
   auto parse_caps =
       gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseVideo));
 
+  /* create video decoder */
   GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
   if (!track->use_swdecoder &&
       !internal::GetIniValue(properties_, "use_default_video_codec_sw"))
@@ -1035,6 +1046,7 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
     return false;
   }
 
+  /* create video sink */
   DisplayType display_type;
   display_->GetDisplay(&display_type);
   const char* videosink_name = "fakesink";
@@ -1046,14 +1058,10 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
     return false;
   }
 
-  if (videosink_name &&
-      (strstr(videosink_name, "fakesink") || strstr(videosink_name, kVideoSinkName))) {
-    pipeline_->SignalConnect(Elements::kSinkVideo, "preroll-handoff",
-                              G_CALLBACK(GstPrerollDecodedVideoBufferCb_), this);
-    pipeline_->SignalConnect(Elements::kSinkVideo, "handoff",
-                              G_CALLBACK(GstDecodedVideoBufferCb_), this);
-  }
-
+  pipeline_->SignalConnect(Elements::kSinkVideo, "preroll-handoff",
+                            G_CALLBACK(GstPrerollDecodedVideoBufferCb_), this);
+  pipeline_->SignalConnect(Elements::kSinkVideo, "handoff",
+                            G_CALLBACK(GstDecodedVideoBufferCb_), this);
   pipeline_->SignalConnect(Elements::kSinkVideo, "sink", "notify::caps",
                               G_CALLBACK(GstCapsNotifyCb_), this);
 
@@ -1097,10 +1105,10 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
                              this);
     }
   }
-
+  /* setup remained video path according to video dec type */
   if (pipeline_->IsFactoryListType(Elements::kDecVideo, GST_ELEMENT_FACTORY_TYPE_HARDWARE)) {
     TRACKRENDERER_INFO("HW codec");
-    if (videosink_name && strstr(videosink_name, kVideoSinkName))
+    if (strstr(videosink_name, kVideoSinkName))
       pipeline_->SetProperty(Elements::kSinkVideo, "use-tbm", true);
   } else {
     TRACKRENDERER_INFO("SW codec");
@@ -1110,9 +1118,10 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
     pipeline_->FactoryMake(Elements::kVideoConvert, "videoconvert", NULL);
     pipeline_->SetProperty(Elements::kVideoConvert, "n-threads", 2);
 
-    if (videosink_name && strstr(videosink_name, kVideoSinkName))
+    if (strstr(videosink_name, kVideoSinkName))
       pipeline_->SetProperty(Elements::kSinkVideo, "use-tbm", false);
   }
+  GstElementLowLatency_(kTrackTypeVideo);
 
   pipeline_->BinAdd(Elements::kBinVideo, Elements::kAppSrcVideo, Elements::kDrmVideo,
               Elements::kParseVideo, Elements::kDecVideo, Elements::kCCExtractor, Elements::kVideoQueue,
@@ -1176,6 +1185,7 @@ bool TrackRenderer::CreateAudioPipeline_(const Track* track) {
 
   pipeline_->FactoryMake(Elements::kSinkAudio, kAudioSinkName, NULL);
   pipeline_->SetProperty(Elements::kSinkAudio, "provide-clock", FALSE);
+  GstElementLowLatency_(kTrackTypeAudio);
 
   pipeline_->CreateBin(Elements::kBinAudio, "audiobin");
   pipeline_->SignalConnect(Elements::kAppSrcAudio, "need-data",
@@ -1294,6 +1304,7 @@ bool TrackRenderer::CreateSubtitlePipeline_(const Track* track) {
   }
   pipeline_->SetProperty(Elements::kSinkSubtitle, "sync", TRUE, "async", FALSE,
                          "signal-handoffs", TRUE);
+  GstElementLowLatency_(kTrackTypeSubtitle);
   pipeline_->SignalConnect(Elements::kSinkSubtitle, "handoff",
                            G_CALLBACK(GstSubtitleDataHandOffCb_), this);
   TRACKRENDERER_LEAVE;
@@ -1484,6 +1495,7 @@ void TrackRenderer::GstClosedCaptionPadAddedCb_(GstElement* element,
   trackrenderer->pipeline_->SetProperty(Elements::kSinkCaption, "sync", TRUE,
                                         "async", FALSE, "signal-handoffs",
                                         TRUE);
+  trackrenderer->GstElementLowLatency_(kTrackTypeSubtitle);
   trackrenderer->pipeline_->SignalConnect(
       Elements::kSinkCaption, "handoff", G_CALLBACK(GstClosedCaptionHandOffCb_),
       userdata);
@@ -2060,6 +2072,7 @@ bool TrackRenderer::ActivateAudioPipeline(GstCaps * caps) {
     GST_APP_STREAM_TYPE_SEEKABLE);
   pipeline_->SetProperty(Elements::kAppSrcAudio, "format", GST_FORMAT_TIME);
 
+  GstElementLowLatency_(kTrackTypeAudio);
   pipeline_->BinAdd(Elements::kBinAudio,
     Elements::kParseAudio, Elements::kDecAudio,
     Elements::kAudioConvert, Elements::kAudioResample,
@@ -2100,20 +2113,21 @@ bool TrackRenderer::Activate(TrackType type, const Track& track) {
   if (state_ == State::kStopped) return false;
   if (!pipeline_) return false;
 
-  Track active_track;
-  if (!trackctx_[type].track ||
-      track_util::GetActiveTrack(trackinfo_, type, &active_track)) {
-    // Fix:: for external subtitle case, it may possible subtitle tracksource
-    // prepared after main tracksource should be allowed to set subtitle current
-    // track information in renderer trackctx_ so that it can be submitted to
-    // subtitle renderer pipeline.
+  if (!trackctx_[type].track) {
     if (type == kTrackTypeSubtitle) {
-      TRACKRENDERER_ERROR("set subtitle track information in track renderer");
+      TRACKRENDERER_ERROR("set subtitle track information");
       trackctx_[type].index = track.index;
       trackinfo_.push_back(track);
       return true;
     }
-    TRACKRENDERER_ERROR("Only valid but deactivated track can be activated.");
+
+    TRACKRENDERER_ERROR("invalid track");
+    return false;
+  }
+
+  Track active_track;
+  if (track_util::GetActiveTrack(trackinfo_, type, &active_track)) {
+    TRACKRENDERER_ERROR_P(this, "track type %d is already activated", type);
     return false;
   }
 
@@ -2183,6 +2197,8 @@ bool TrackRenderer::Activate(TrackType type, const Track& track) {
                       Elements::kDecVideo, Elements::kSinkVideo);
 
     pipeline_->SetProperty(Elements::kSinkVideo, "sync", TRUE, "async", TRUE);
+    GstElementLowLatency_(kTrackTypeVideo);
+
     pipeline_->SetAppSrcCaps(Elements::kAppSrcVideo, caps);
     pipeline_->PadRemoveProbe(kPadProbeVideoBlock);
     pipeline_->Execute(Elements::kSinkVideo, [this](GstElement* obj) noexcept {
@@ -2473,7 +2489,8 @@ void TrackRenderer::SetVolume_() {
 
 void TrackRenderer::CreateTbmBufferManager_(const Track* track) {
   TRACKRENDERER_ENTER;
-  tbm_buffer_manager_.reset(new TbmBufferManager);
+  if (tbm_buffer_manager_ == nullptr)
+    tbm_buffer_manager_.reset(new TbmBufferManager);
 }
 
 bool TrackRenderer::GetVolume(int* volume) {
@@ -2577,6 +2594,8 @@ bool TrackRenderer::SetLowLatencyMode_(const boost::any& value) {
   std::uint32_t val = boost::any_cast<std::uint32_t>(value);
   TRACKRENDERER_ERROR(" Mode [%d]", val);
   low_latency_mode_ = val;
+  if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+    unlimited_max_buffer_mode_ = true;
   return true;
 }
 
@@ -2610,19 +2629,30 @@ bool TrackRenderer::SetStartRenderingTime_(const boost::any& value) {
 }
 
 void TrackRenderer::GstElementLowLatency_(const TrackType& type) {
-  if (low_latency_mode_ == 0) return;
+  if (low_latency_mode_ ==
+      static_cast<std::uint32_t>(LowLatencyMode::kLowLatencyModeNone))
+    return;
+
   switch (type) {
     case kTrackTypeAudio:
-      if (low_latency_mode_ & kLowLatencyModeDisablePreroll) {
+      if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+        pipeline_->SetProperty(Elements::kSinkAudio, "sync", FALSE, "async", FALSE);
+      if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
         pipeline_->SetProperty(Elements::kSinkAudio, "async", FALSE);
-      }
       break;
     case kTrackTypeVideo:
-      if (low_latency_mode_ & kLowLatencyModeDisablePreroll) {
+      if (low_latency_mode_ & kLowLatencyModeDisableAVSync)
+        pipeline_->SetProperty(Elements::kSinkVideo, "sync", FALSE, "async", FALSE);
+      if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
         pipeline_->SetProperty(Elements::kSinkVideo, "async", FALSE);
-      }
       break;
     case kTrackTypeSubtitle:
+      if (low_latency_mode_ & kLowLatencyModeDisableAVSync) {
+        pipeline_->SetProperty(Elements::kSinkCaption, "sync", FALSE, "async", FALSE);
+        pipeline_->SetProperty(Elements::kSinkSubtitle, "sync", FALSE, "async", FALSE);
+      }
+      if (low_latency_mode_ & kLowLatencyModeDisablePreroll)
+        pipeline_->SetProperty(Elements::kSinkSubtitle, "async", FALSE);
       break;
     default:
       TRACKRENDERER_ERROR("wrong track type");
@@ -2756,8 +2786,8 @@ bool TrackRenderer::ActivateAudio_() {
   pipeline_->BinAdd(Elements::kBinAudio, Elements::kDecAudio,
                     Elements::kSinkAudio);
   pipeline_->SetProperty(Elements::kSinkAudio, "sync", TRUE, "async", TRUE);
-  pipeline_->SetProperty(Elements::kSinkAudio, "multiview-window-id",
-                         static_cast<int>(display_->GetSurfaceId()));
+  GstElementLowLatency_(kTrackTypeAudio);
+
   pipeline_->PadRemoveProbe(kPadProbeAudioBlock);
 
   is_audioactivated_ = true;