cleanup duplicated code about decoder creation 59/300459/4
authorEunhye Choi <eunhae1.choi@samsung.com>
Wed, 25 Oct 2023 08:41:41 +0000 (17:41 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Thu, 26 Oct 2023 03:21:09 +0000 (12:21 +0900)
- add CreateDecoder to cleanup duplicated code
- add ElementRemove to cleanup resource in case of error

[Version] 0.0.45

Change-Id: I78c4130312738a667313f89e4396eec259ba5d50

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

index 105c4250ed03880f6f5ab77b44d1ec1a52399c31..314d689bb215c7b65265743e9d7a44e87d1b20cf 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libtrackrenderer
 Summary:    new multimedia streaming player trackrenderer
-Version:    0.0.44
+Version:    0.0.45
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 76ac9bd752e3a0b9e745804675ed115aa91d0d10..d5355cde2678f2a8276afa5e949805f07b421b47 100644 (file)
@@ -135,7 +135,7 @@ class Pipeline : private boost::noncopyable {
     return Set_(element, obj);
   }
 
-  bool FactoryMake(const T element, GstCaps *caps, GstElementFactoryListType type, const char* nickname) {
+  bool FactoryMake(const T element, const GstCaps *caps, GstElementFactoryListType type, const char* nickname) {
     GList *filtered = NULL;
     GstElement* obj = nullptr;
     bool use_hw = (type & GST_ELEMENT_FACTORY_TYPE_HARDWARE);
@@ -368,6 +368,22 @@ class Pipeline : private boost::noncopyable {
     }
   }
 
+  // ElementRemove
+  // description : remove element for error handling
+  void ElementRemove(T element) {
+    GstElement* obj = mainbin_[static_cast<int>(element)];
+    if (!obj) return;
+    gst_util::SetGstStateToNull(obj);
+
+    GstElement* parent = GST_ELEMENT_CAST(gst_element_get_parent(obj));
+    if (parent)
+      gst_bin_remove(GST_BIN(parent), obj);
+    else
+      gst_object_unref(GST_OBJECT(obj));
+
+    Unset_(element);
+  }
+
   bool BinAddSimple(T dst, T src) {
     GstElement* bin = mainbin_[static_cast<int>(dst)];
     GstElement* obj = mainbin_[static_cast<int>(src)];
index 7db2b723f06b59da16349d86e47ddb2c36b68381..f44a34c23e8b95b2e28299df2a0759759c06e651 100644 (file)
@@ -292,6 +292,7 @@ class TrackRenderer : public ResourceConflictListener,
   bool GetResource_();
   bool CreatePipeline_();
   void CreateAppSrc_(TrackType type, const GstCaps * caps);
+  bool CreateDecoder_(const Track* track, const GstCaps* caps);
   bool CreateVideoPipeline_(const Track* track);
   bool CreateAudioPipeline_(const Track* track);
   bool CreateRawAudioPipeline_(const Track* track);
index 8cdda7d089173d166e698634c15cae22b833d684..dc365c6c0d156686ef516378c5442bcc55e0b665 100644 (file)
@@ -912,6 +912,7 @@ bool TrackRenderer::SubmitPacket(const DecoderInputBufferPtr& data,
   }
 
   if (data->IsEos()) {
+    TRACKRENDERER_DEBUG("submit EOS type:%d", type);
     pipeline_->SignalEmitByName(element, "end-of-stream");
     submitstate = SubmitStatus::kSuccess;
     return true;
@@ -1028,6 +1029,38 @@ void TrackRenderer::CreateAppSrc_(TrackType type, const GstCaps* caps) {
   TRACKRENDERER_LEAVE;
 }
 
+bool TrackRenderer::CreateDecoder_(const Track* track, const GstCaps* caps) {
+  TRACKRENDERER_ENTER;
+  if (!track || !caps) {
+    TRACKRENDERER_ERROR("Invalid input, track[%p] caps[%p]", track, caps);
+    return false;
+  }
+
+  GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
+  if (!track->use_swdecoder)
+    factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
+
+  Elements element;
+  if (track->type == kTrackTypeVideo) {
+    element = Elements::kDecVideo;
+    if (internal::GetIniValue(properties_, "use_default_video_codec_sw"))
+      factory_type &= ~GST_ELEMENT_FACTORY_TYPE_HARDWARE;
+  } else if (track->type == kTrackTypeAudio) {
+    element = Elements::kDecAudio;
+  } else {
+    TRACKRENDERER_ERROR("Invalid track type %d", track->type);
+    return false;
+  }
+
+  if (!pipeline_->FactoryMake(element, caps, factory_type, NULL)) {
+    TRACKRENDERER_ERROR("Failed to make decoder");
+    return false;
+  }
+
+  TRACKRENDERER_LEAVE;
+  return true;
+}
+
 void TrackRenderer::GstCapsNotifyCb_(GstPad* pad, GParamSpec* unused, gpointer userdata)
 {
   TRACKRENDERER_ENTER;
@@ -1066,27 +1099,21 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
                                           drm_property_, track->mimetype));
     if (!pipeline_->FactoryMake(Elements::kParseVideo, (GstCaps*)caps_for_parser.GetCaps_(),
                           GST_ELEMENT_FACTORY_TYPE_PARSER, NULL))
-      TRACKRENDERER_ERROR("fail to make parser");
+      TRACKRENDERER_ERROR("Failed to make parser");
   } else {
     if (!pipeline_->FactoryMake(Elements::kParseVideo, (GstCaps*)caps.GetCaps_(),
                             GST_ELEMENT_FACTORY_TYPE_PARSER, NULL))
-      TRACKRENDERER_ERROR("fail to make parser");
+      TRACKRENDERER_ERROR("Failed to make parser");
   }
 
   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"))
-    factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
-
-  if (!pipeline_->FactoryMake(Elements::kDecVideo,
-                          static_cast<GstCaps*>(parse_caps ? parse_caps.get() : caps.GetCaps_()),
-                          factory_type, NULL)) {
+  if (!CreateDecoder_(track, parse_caps ? static_cast<GstCaps*>(parse_caps.get()) : caps.GetCaps_())) {
+    TRACKRENDERER_ERROR("Failed to make video decoder");
+    pipeline_->ElementRemove(Elements::kAppSrcVideo);
+    pipeline_->ElementRemove(Elements::kParseVideo);
     const ErrorType err = ErrorType::kNotSupportedVideoCodec;
-    TRACKRENDERER_ERROR("fail to make decoder");
     eventlistener_->OnError(err);
     return false;
   }
@@ -1098,8 +1125,9 @@ bool TrackRenderer::CreateVideoPipeline_(const Track* track) {
   if (internal::IsDisplayNeeded(display_type))
     videosink_name = kVideoSinkName;
 
+  /* FIXME: created elements have to be released in case of error */
   if (!pipeline_->FactoryMake(Elements::kSinkVideo, videosink_name, NULL)) {
-    TRACKRENDERER_ERROR("fail to make video sink(%s)", videosink_name);
+    TRACKRENDERER_ERROR("Failed to make video sink(%s)", videosink_name);
     return false;
   }
 
@@ -1203,15 +1231,11 @@ bool TrackRenderer::CreateAudioPipeline_(const Track* track) {
   auto parse_caps =
       gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseAudio));
 
-  GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
-  if (!track->use_swdecoder)
-    factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
-
-  if (!pipeline_->FactoryMake(Elements::kDecAudio,
-                              static_cast<GstCaps*>(parse_caps ? parse_caps.get() : caps.GetCaps_()),
-                              factory_type, NULL)) {
+  if (!CreateDecoder_(track, parse_caps ? static_cast<GstCaps*>(parse_caps.get()) : caps.GetCaps_())) {
+    TRACKRENDERER_ERROR("Failed to make audio decoder");
+    pipeline_->ElementRemove(Elements::kAppSrcAudio);
+    pipeline_->ElementRemove(Elements::kParseAudio);
     const ErrorType err = ErrorType::kNotSupportedAudioCodec;
-    TRACKRENDERER_ERROR("fail to make decoder");
     eventlistener_->OnError(err);
     return false;
   }
@@ -2049,24 +2073,24 @@ bool TrackRenderer::ActivateAudioPipeline(GstCaps * caps) {
 
   Track track;
   if (!track_util::GetActiveTrack(trackinfo_, kTrackTypeAudio, &track)) {
+    pipeline_->ElementRemove(Elements::kParseAudio);
     TRACKRENDERER_ERROR("Failed to find active audio track.");
     return false;
   }
-  GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
-  if (!track.use_swdecoder)
-    factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
 
   auto parse_caps =
     gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseAudio));
   auto parse_caps_str = gstguard::make_guard(gst_caps_to_string(parse_caps.get()));
   TRACKRENDERER_INFO("parse caps %s", parse_caps_str.get());
 
-  if (!pipeline_->FactoryMake(Elements::kDecAudio, (GstCaps*)parse_caps.get(),
-    factory_type, NULL)) {
+  if (!CreateDecoder_(&track, static_cast<GstCaps*>(parse_caps.get()))) {
+    TRACKRENDERER_ERROR("Failed to make audio decoder");
+    pipeline_->ElementRemove(Elements::kParseAudio);
     const ErrorType err = ErrorType::kNotSupportedAudioCodec;
     eventlistener_->OnError(err);
     return false;
   }
+
   pipeline_->FactoryMake(Elements::kAudioConvert, "audioconvert", nullptr);
   pipeline_->FactoryMake(Elements::kAudioResample, "audioresample", nullptr);
   pipeline_->FactoryMake(Elements::kSinkAudio, kAudioSinkName, nullptr);
@@ -2175,13 +2199,9 @@ bool TrackRenderer::Activate(TrackType type, const Track& track) {
     auto parse_caps =
         gstguard::make_guard(pipeline_->GetSrcPadCaps(Elements::kParseVideo));
 
-    GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
-    if (!track.use_swdecoder &&
-        !internal::GetIniValue(properties_, "use_default_video_codec_sw"))
-      factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
-
-    if (!pipeline_->FactoryMake(Elements::kDecVideo,
-                                (GstCaps*)parse_caps.get(), factory_type, NULL)) {
+    if (!CreateDecoder_(&track, static_cast<GstCaps*>(parse_caps.get()))) {
+      TRACKRENDERER_ERROR("Failed to make video decoder");
+      pipeline_->ElementRemove(Elements::kParseVideo);
       const ErrorType err = ErrorType::kNotSupportedVideoCodec;
       eventlistener_->OnError(err);
       return false;
@@ -2232,8 +2252,8 @@ bool TrackRenderer::Activate(TrackType type, const Track& track) {
     auto new_caps_str = gstguard::make_guard(gst_caps_to_string(new_caps.GetCaps_()));
     TRACKRENDERER_INFO("new caps %s", new_caps_str.get());
 
-    gboolean caps_changed = !gst_caps_is_equal (new_caps.GetCaps_(), current_caps.get());
-    if (caps_changed) { // caps is different
+    gboolean caps_changed = !gst_caps_is_equal(new_caps.GetCaps_(), current_caps.get());
+    if (caps_changed) {
       TRACKRENDERER_INFO("Caps is changed");
       pipeline_->PadAddProbe(Elements::kAppSrcAudio, kPadProbeCapsEvent, "src",
                                (GstPadProbeType)(GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM),
@@ -2862,12 +2882,11 @@ bool TrackRenderer::ActivateAudio_() {
   auto caps = caps_builder_.Build(track, internal::IsDrmEmeElementNecessary(
                                               drm_property_, track.mimetype));
 
-  GstElementFactoryListType factory_type = GST_ELEMENT_FACTORY_TYPE_DECODER;
-  if (!track.use_swdecoder)
-    factory_type |= GST_ELEMENT_FACTORY_TYPE_HARDWARE;
+  if (!CreateDecoder_(&track, caps.GetCaps_())) {
+    TRACKRENDERER_ERROR("Failed to make audio decoder");
+    return false;
+  }
 
-  pipeline_->FactoryMake(Elements::kDecAudio, (GstCaps*)caps.GetCaps_(),
-                          factory_type, NULL);
   pipeline_->FactoryMake(Elements::kSinkAudio, kAudioSinkName, NULL);
   if (volume_ != kVolumeNone) {
     SetVolume_();