[1.0.30] Clean up the pipeline after mtpr_stop() 10/308410/1 accepted/tizen_8.0_unified tizen_8.0 accepted/tizen/8.0/unified/20240327.133213
authorGilbok Lee <gilbok.lee@samsung.com>
Tue, 19 Mar 2024 06:12:48 +0000 (15:12 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Mon, 25 Mar 2024 06:27:09 +0000 (15:27 +0900)
- The element isn't configured properly, mtpr_start() after mptr_stop()

Change-Id: I41cbc785f44a8cb0ebdf8b3870aeb8183f2eee89

19 files changed:
include/MediaTransporterBase.h
include/MediaTransporterGst.h
include/MediaTransporterReceiver.h
packaging/capi-media-transporter.spec
src/MediaSourceBinMediaPacket.cpp
src/MediaTransporter.cpp
src/MediaTransporterBase.cpp
src/MediaTransporterGst.cpp
src/MediaTransporterReceiver.cpp
src/MediaTransporterReceiverRist.cpp
src/MediaTransporterReceiverRtsp.cpp
src/MediaTransporterReceiverSrt.cpp
src/MediaTransporterSender.cpp
src/MediaTransporterSenderRist.cpp
src/MediaTransporterSenderRtsp.cpp
src/MediaTransporterSenderSrt.cpp
src/MediaTransporterSenderToServerRtsp.cpp
test/mtpr_test.c
test/mtpr_test_with_camera.c

index 65dd9c9..cac8cd7 100644 (file)
@@ -82,6 +82,7 @@ protected:
 private:
        void makePipeline();
        void stopInternal();
+       void clearPipeline();
 
        virtual void buildPipeline() = 0;
        virtual void startPipeline() = 0;
index cf074bf..7cbecfd 100644 (file)
@@ -92,8 +92,9 @@ GstElement*_createElement(std::string factory_name, std::string name ="");
 void _connectAndAppendSignal(GList** signals, GObject* obj, const char* sig_name, GCallback cb, gpointer user_data);
 void _disconnectSignal(GList** signals, GObject* obj);
 void _disconnectSignal(gpointer data);
-bool _addNoTargetGhostpad(GstBin* bin, GstPad** new_pad, bool is_src);
-bool _setGhostpadTarget(GstPad* ghost_pad, GstElement* target_element, bool is_src);
+bool _addNoTargetGhostpad(GstBin* bin, GstPad** new_pad, bool isSrcPad);
+bool _setGhostpadTarget(GstPad* ghost_pad, GstElement* target_element, bool isSrcPad);
+GstPad* _getGhostPadFromBin(GstBin* bin, const std::string& name, bool isSrcPad);
 unsigned int _getUnoccupiedSourceId(GHashTable* slots);
 
 void _setElementProperties(GstElement* element, std::vector<std::string> key_value_pairs);
@@ -128,14 +129,15 @@ void _destroyElementFromParent(GstElement* element);
 
 void _printCaps(GstCaps* caps, std::string prefix);
 
-GstPad* _getGhostPadFromBin(GstBin* bin);
-
 void _updateCaps(GstElement* element, const param::videoInfo& vInfo);
 void _updateEncCaps(GstElement* element, const param::videoInfo& vInfo);
 
 void _updateCaps(GstElement* element, const param::audioInfo& aInfo);
 void _updateEncCaps(GstElement* element, const param::audioInfo& aInfo);
 
+void _removeAllPads(GstElement* element, bool srcPad);
+void _removeAllElements(GstBin* bin);
+
 }; // gst
 
 } // tizen_media_transporter
index a50fc4d..46f7108 100644 (file)
@@ -59,7 +59,7 @@ public:
        void setSoundStreamInfo(sound_stream_info_h streamInfo);
 
 protected:
-       int _buildForwardingElements(GstElement* demux, GstPad* pad, GCallback callback);
+       int _buildForwardingElements(GstElement* demux, GstPad* pad, bool isAudio, GCallback callback);
        int _buildRenderingElements(GstElement* demux, GstPad* pad, bool isAudio);
 
        static void _streamAddedCallback(GstPad* pad, gpointer data);
@@ -95,4 +95,3 @@ private:
 
 #endif // __cplusplus
 #endif // __TIZEN_MEDIA_TRANSPORTER_RECEIVER_H__
-
index 787ffeb..004ca63 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-transporter
 Summary:    A Media Transporter library in Tizen Native API
-Version:    1.0.29
+Version:    1.0.30
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 9ce0978..c6ad9b1 100644 (file)
@@ -42,6 +42,9 @@ MediaSourceBinMediaPacket::MediaSourceBinMediaPacket()
 MediaSourceBinMediaPacket::~MediaSourceBinMediaPacket()
 {
        LOG_DEBUG("dtor: %p", this);
+       if (_mediaFormat)
+               media_format_unref(_mediaFormat);
+
        if (_sourceCaps)
                gst_caps_unref(_sourceCaps);
 
@@ -69,10 +72,12 @@ MediaSourceBinInfo MediaSourceBinMediaPacket::generate()
 {
        gst::GstElements elements;
 
-       if (_mediaPacketSource == nullptr)
-               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Media packet source isn't created");
-
        try {
+               _createMediaPacketSource();
+               _makeCapsFromMediaFormat(_mediaFormat);
+               g_object_set(_mediaPacketSource, "caps", _sourceCaps, nullptr);
+               gst::_printCaps(_sourceCaps, "setAppsrcCaps");
+
                elements.push_back(_mediaPacketSource);
                gst::_connectAndAppendSignal(&_signals, G_OBJECT(_mediaPacketSource), "need-data", G_CALLBACK(_needDataCallback), this);
                gst::_connectAndAppendSignal(&_signals, G_OBJECT(_mediaPacketSource), "enough-data", G_CALLBACK(_enoughDataCallback), this);
@@ -132,16 +137,10 @@ MediaSourceBinInfo MediaSourceBinMediaPacket::generate()
 
 void MediaSourceBinMediaPacket::setMediaFormat(media_format_h format)
 {
+       if (media_format_ref(format) != MEDIA_FORMAT_ERROR_NONE)
+               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to ref media_format");
+
        _mediaFormat = format;
-       try {
-               _createMediaPacketSource();
-               _makeCapsFromMediaFormat(format);
-               g_object_set(_mediaPacketSource, "caps", _sourceCaps, nullptr);
-               gst::_printCaps(_sourceCaps, "setAppsrcCaps");
-       } catch (const MediaTransporterException& e) {
-               LOG_ERROR("%s", e.what());
-               throw;
-       }
 }
 
 void MediaSourceBinMediaPacket::pushMediaPacket(media_packet_h packet)
index b9f8071..b20e4ca 100644 (file)
@@ -98,8 +98,10 @@ int mtpr_stop(mtpr_h mtpr)
        try {
                auto handle = static_cast<media_transporter_s*>(mtpr);
                assert(handle->base);
+               assert(handle->resourceManager);
 
                handle->base->stop();
+               handle->resourceManager->releaseAll();
        } catch (const MediaTransporterException& e) {
                LOG_ERROR("Failed to stop!!! : %s", e.what());
                return e.error();
index 16e6bb8..c396981 100644 (file)
@@ -99,6 +99,18 @@ void MediaTransporterBase::makePipeline()
        MTPR_FLEAVE();
 }
 
+void MediaTransporterBase::clearPipeline()
+{
+       MTPR_FENTER();
+
+       if (_gst.signals) {
+               g_list_free_full(_gst.signals, gst::_disconnectSignal);
+               _gst.signals = nullptr;
+       }
+
+       gst::_removeAllElements(GST_BIN(_gst.pipeline));
+}
+
 void MediaTransporterBase::create()
 {
        gst::_gstInit();
@@ -132,6 +144,7 @@ void MediaTransporterBase::stopInternal()
 {
        try {
                stopPipeline();
+               clearPipeline();
                _state = MTPR_STATE_IDLE;
        } catch (const MediaTransporterException& e) {
                LOG_ERROR("%s", e.what());
@@ -164,11 +177,6 @@ void MediaTransporterBase::destroy()
                        _gst.bus = NULL;
                }
 
-               if (_gst.signals) {
-                       g_list_free_full(_gst.signals, gst::_disconnectSignal);
-                       _gst.signals = NULL;
-               }
-
                if (_gst.pipeline) {
                        gst_object_unref(_gst.pipeline);
                        _gst.pipeline = NULL;
index 082bace..eb24059 100644 (file)
@@ -102,12 +102,12 @@ void gst::_disconnectSignal(gpointer data)
        g_free(sig_data);
 }
 
-bool gst::_addNoTargetGhostpad(GstBin* bin, GstPad** new_pad, bool is_src)
+bool gst::_addNoTargetGhostpad(GstBin* bin, GstPad** new_pad, bool isSrcPad)
 {
        RET_VAL_IF(!bin, false, "bin is NULL");
        RET_VAL_IF(!new_pad, false, "new_pad is NULL");
 
-       GstPad* ghost_pad = gst_ghost_pad_new_no_target(NULL, is_src ? GST_PAD_SRC : GST_PAD_SINK);
+       GstPad* ghost_pad = gst_ghost_pad_new_no_target(NULL, isSrcPad ? GST_PAD_SRC : GST_PAD_SINK);
        if (!ghost_pad) {
                LOG_ERROR("failed to gst_ghost_pad_new_no_target()");
                return false;
@@ -130,12 +130,12 @@ bool gst::_addNoTargetGhostpad(GstBin* bin, GstPad** new_pad, bool is_src)
        return true;
 }
 
-bool gst::_setGhostpadTarget(GstPad* ghost_pad, GstElement* target_element, bool is_src)
+bool gst::_setGhostpadTarget(GstPad* ghost_pad, GstElement* target_element, bool isSrcPad)
 {
        RET_VAL_IF(!ghost_pad, false, "ghost_pad is NULL");
        RET_VAL_IF(!target_element, false, "target_element is NULL");
 
-       GstPad* target_pad = gst_element_get_static_pad(target_element, is_src ? "src" : "sink");
+       GstPad* target_pad = gst_element_get_static_pad(target_element, isSrcPad ? "src" : "sink");
 
        if (!target_pad) {
                LOG_ERROR("failed to gst_element_get_static_pad() of [%s]",
@@ -157,6 +157,26 @@ bool gst::_setGhostpadTarget(GstPad* ghost_pad, GstElement* target_element, bool
        return true;
 }
 
+GstPad* gst::_getGhostPadFromBin(GstBin* bin, const std::string& name, bool isSrcPad)
+{
+       if (name.empty())
+               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Element name is empty");
+
+       GstElement* element = gst_bin_get_by_name(bin, name.c_str());
+       if (!element)
+               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to get element");
+
+       GstPad* pad = nullptr;
+
+       if (!gst::_addNoTargetGhostpad(bin, &pad, isSrcPad))
+               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to _addNoTargetGhostpad");
+
+       if (!gst::_setGhostpadTarget(pad, element, isSrcPad))
+               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to _setGhostpadTarget");
+
+       return pad;
+}
+
 void gst::_removeElementsFromBin(GstBin* bin, GstElements& elements)
 {
        for (auto element : elements)
@@ -765,24 +785,6 @@ void gst::_printCaps(GstCaps* caps, std::string prefix)
        LOG_DEBUG("%s caps[%s]", prefix.c_str(), caps_str.c_str());
 }
 
-GstPad* gst::_getGhostPadFromBin(GstBin* bin)
-{
-       GstElement* queue = gst_bin_get_by_name(bin, "srcQueue");
-       if (!queue)
-               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to get srcQueue");
-
-       GstPad* srcPad = nullptr;
-
-       if (!gst::_addNoTargetGhostpad(bin, &srcPad, true))
-               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to _addNoTargetGhostpad");
-
-       if (!gst::_setGhostpadTarget(srcPad, queue, true))
-               throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "Failed to _setGhostpadTarget");
-
-       return srcPad;
-}
-
-
 void gst::_updateCaps(GstElement* element, const param::videoInfo& vInfo)
 {
        GstCaps* oldCaps;
@@ -876,3 +878,57 @@ void gst::_updateEncCaps(GstElement* element, const param::audioInfo& aInfo)
 
        gst_caps_unref(newCaps);
 }
+
+void gst::_removeAllPads(GstElement* element, bool srcPad)
+{
+       RET_IF(!element, "input element is null");
+
+       g_auto(GValue) item = G_VALUE_INIT;
+       g_autoptr(GstIterator) it = srcPad ? gst_element_iterate_src_pads(element) : gst_element_iterate_sink_pads(element);
+       while (it) {
+               switch (gst_iterator_next (it, &item)) {
+               case GST_ITERATOR_OK:
+               {
+                       GstPad *pad = GST_PAD(g_value_get_object (&item));
+                       gst_element_remove_pad (element, pad);
+               }
+                       break;
+               case GST_ITERATOR_DONE:
+               case GST_ITERATOR_ERROR:
+                       return;
+               case GST_ITERATOR_RESYNC:
+               {
+                       gst_iterator_resync(it);
+                       break;
+               }
+       }
+       }
+}
+
+void gst::_removeAllElements(GstBin* bin)
+{
+       RET_IF(!bin, "input bin is null");
+
+       g_auto(GValue) item = G_VALUE_INIT;
+       g_autoptr(GstIterator) it = gst_bin_iterate_recurse(bin);
+       while (it) {
+               switch (gst_iterator_next (it, &item)) {
+               case GST_ITERATOR_OK:
+               {
+                       GstElement *element = GST_ELEMENT(g_value_get_object (&item));
+                       LOG_DEBUG("destroy %s element", GST_ELEMENT_NAME(element));
+                       gst::_destroyElementFromParent(element);
+                       gst_iterator_resync(it);
+               }
+                       break;
+               case GST_ITERATOR_DONE:
+               case GST_ITERATOR_ERROR:
+                       return;
+               case GST_ITERATOR_RESYNC:
+               {
+                       gst_iterator_resync(it);
+                       break;
+               }
+       }
+       }
+}
index cc768d2..902656a 100644 (file)
@@ -359,8 +359,7 @@ void MediaTransporterReceiver::_buildForwardingSink(gst::GstElements& elements,
        gst::_connectAndAppendSignal(&_gst.signals, G_OBJECT(fakesink), "handoff", callback, this);
 }
 
-// FIXME : exception handling
-int MediaTransporterReceiver::_buildForwardingElements(GstElement* demux, GstPad* pad, GCallback callback)
+int MediaTransporterReceiver::_buildForwardingElements(GstElement* demux, GstPad* pad, bool isAudio, GCallback callback)
 {
        gst::GstElements elements;
 
@@ -376,27 +375,76 @@ int MediaTransporterReceiver::_buildForwardingElements(GstElement* demux, GstPad
                                NULL);
        elements.push_back(queue);
 
-       GstElement* parser = gst::_createElementFromRegistry("Parser", gst_pad_get_current_caps(pad), NULL,
-                                                                                                               MediaTransporterIni::get().general().gstExcludedElements);
-       if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(parser)), "config-interval")) {
-               g_object_set(G_OBJECT(parser), "config-interval", -1, NULL);
-               LOG_DEBUG("[%s] set config-interval -1", GST_ELEMENT_NAME(parser) );
+    GstElement* parser = nullptr;
+       std::string demuxerName = GST_ELEMENT_NAME(demux);
+    if (demuxerName.find("decodebin") == std::string::npos)
+               parser = gst::_createElementFromRegistry("Parser", gst_pad_get_current_caps(pad), NULL,
+                                                                                               MediaTransporterIni::get().general().gstExcludedElements);
+
+       if (parser) {
+               if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(parser)), "config-interval")) {
+                       g_object_set(G_OBJECT(parser), "config-interval", -1, NULL);
+                       LOG_DEBUG("[%s] set config-interval -1", GST_ELEMENT_NAME(parser) );
+               }
+               elements.push_back(parser);
        }
-       elements.push_back(parser);
 
        _buildForwardingSink(elements, pad, callback);
 
-       gst::_addElementsToBin(GST_BIN(_gst.pipeline), elements);
+       std::string binName = isAudio ? "forwardingAudioBin" : "forwordingVideoBin";
+
+       GstBin* bin = GST_BIN(gst_bin_new(binName.c_str()));
+       if (!bin) {
+               LOG_ERROR("Failed to create bin");
+               gst::_clearElements(elements);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+       try {
+               gst::_addElementsToBin(bin, elements);
+       } catch (const MediaTransporterException& e) {
+               LOG_ERROR("%s", e.what());
+               gst::_clearElements(elements);
+               gst_object_unref(bin);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+
+       if (!gst_bin_add(GST_BIN(_gst.pipeline), GST_ELEMENT(bin))) {
+               LOG_ERROR("failed to add (%s)bin into pipeline", binName.c_str());
+               gst_object_unref(bin);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+       GstPad* sinkPad = nullptr;
+       try {
+               sinkPad = gst::_getGhostPadFromBin(bin, GST_ELEMENT_NAME(queue), false);
+               GstPadLinkReturn res = gst_pad_link(pad, sinkPad);
+               if (GST_PAD_LINK_FAILED(res)) {
+                       LOG_ERROR("failed to link pads, [%s:%s] - [%s:%s]",
+                                       GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkPad));
+                       gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+                       gst_object_unref(sinkPad);
+                       return MTPR_ERROR_INVALID_OPERATION;
+               }
+
+               gst::_linkElements(elements);
+       } catch (const MediaTransporterException& e) {
+               LOG_ERROR("%s", e.what());
+
+               gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+               gst_object_unref(sinkPad);
+               if (sinkPad)
+                       gst_object_unref(sinkPad);
 
-       if (!gst_element_link_pads(GST_ELEMENT(demux),
-                                                       GST_PAD_NAME(pad),
-                                                       GST_ELEMENT(queue),
-                                                       "sink")) {
-               LOG_ERROR("failed to link demuxer and queue");
+               return MTPR_ERROR_INVALID_OPERATION;
        }
 
-       gst::_linkElements(elements);
-       gst::_syncElementsStateWithParent(elements);
+       if (!gst_element_sync_state_with_parent(GST_ELEMENT(bin))) {
+               LOG_ERROR("failed to sync %s state with parent", binName.c_str());
+               gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
 
        return MTPR_ERROR_NONE;
 }
@@ -489,9 +537,13 @@ int MediaTransporterReceiver::_buildRenderingElements(GstElement* demux, GstPad*
                                NULL);
        elements.push_back(queue);
 
-       GstElement* parser = gst::_createElementFromRegistry("Parser", gst_pad_get_current_caps(pad), NULL,
-                                                                                                               MediaTransporterIni::get().general().gstExcludedElements);
-       GstPad* srcPad;
+       GstPad* srcPad = nullptr;
+       GstElement* parser = nullptr;
+       std::string demuxerName = GST_ELEMENT_NAME(demux);
+
+       if (demuxerName.find("decodebin") == std::string::npos)
+               parser = gst::_createElementFromRegistry("Parser", gst_pad_get_current_caps(pad), NULL,
+                                                                                                                       MediaTransporterIni::get().general().gstExcludedElements);
        if (parser) {
                if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(parser)), "config-interval")) {
                        g_object_set(G_OBJECT(parser), "config-interval", -1, NULL);
@@ -500,7 +552,7 @@ int MediaTransporterReceiver::_buildRenderingElements(GstElement* demux, GstPad*
                srcPad = gst_element_get_static_pad(parser, "src");
                elements.push_back(parser);
        } else {
-               srcPad = gst_element_get_static_pad(queue, "src");
+               srcPad = g_object_ref(pad);
        }
 
        GstCaps* caps = gst_pad_has_current_caps(srcPad) ? gst_pad_get_current_caps(srcPad)
@@ -516,17 +568,59 @@ int MediaTransporterReceiver::_buildRenderingElements(GstElement* demux, GstPad*
        else
                _buildVideoRenderingSink(elements);
 
-       gst::_addElementsToBin(GST_BIN(_gst.pipeline), elements);
+       std::string binName = isAudio ? "renderingAudioBin" : "renderingVideoBin";
+
+       GstBin* bin = GST_BIN(gst_bin_new(binName.c_str()));
+       if (!bin) {
+               LOG_ERROR("Failed to create bin");
+               gst::_clearElements(elements);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+       try {
+               gst::_addElementsToBin(bin, elements);
+       } catch (const MediaTransporterException& e) {
+               LOG_ERROR("%s", e.what());
+               gst::_clearElements(elements);
+               gst_object_unref(bin);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+       if (!gst_bin_add(GST_BIN(_gst.pipeline), GST_ELEMENT(bin))) {
+               LOG_ERROR("failed to add (%s)bin into pipeline", binName.c_str());
+               gst_object_unref(bin);
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
+
+       GstPad* sinkPad = nullptr;
+       try {
+               sinkPad = gst::_getGhostPadFromBin(bin, GST_ELEMENT_NAME(queue), false);
+               GstPadLinkReturn res = gst_pad_link(pad, sinkPad);
+               if (GST_PAD_LINK_FAILED(res)) {
+                       LOG_ERROR("failed to link pads, [%s:%s] - [%s:%s]",
+                                       GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkPad));
+                       gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+                       gst_object_unref(sinkPad);
+                       return MTPR_ERROR_INVALID_OPERATION;
+               }
+
+               gst::_linkElements(elements);
+       } catch (const MediaTransporterException& e) {
+               LOG_ERROR("%s", e.what());
+
+               gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+               gst_object_unref(sinkPad);
+               if (sinkPad)
+                       gst_object_unref(sinkPad);
 
-       if (!gst_element_link_pads(GST_ELEMENT(demux),
-                                                       GST_PAD_NAME(pad),
-                                                       GST_ELEMENT(queue),
-                                                       "sink")) {
-               LOG_ERROR("failed to link demuxer and queue");
+               return MTPR_ERROR_INVALID_OPERATION;
        }
 
-       gst::_linkElements(elements);
-       gst::_syncElementsStateWithParent(elements);
+       if (!gst_element_sync_state_with_parent(GST_ELEMENT(bin))) {
+               LOG_ERROR("failed to sync %s state with parent", binName.c_str());
+               gst_bin_remove(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
+               return MTPR_ERROR_INVALID_OPERATION;
+       }
 
        return MTPR_ERROR_NONE;
 }
@@ -585,4 +679,4 @@ bool MediaTransporterReceiver::_isSupportedMediaType(std::string mediaType)
 bool MediaTransporterReceiver::_isAudioMediaType(std::string mediaType)
 {
        return mediaType.find("audio") != std::string::npos;
-}
\ No newline at end of file
+}
index b062ceb..e30796d 100644 (file)
@@ -60,9 +60,9 @@ void MediaTransporterReceiverRist::_demuxPadAddedCallback(GstElement *demux, Gst
 
        bool isAudio = _isAudioMediaType(mediaType);
        if (rist->_audioCallback._callback && isAudio)
-               rist->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedAudioStreamCallback));
+               rist->_buildForwardingElements(demux, new_pad, isAudio, G_CALLBACK(_encodedAudioStreamCallback));
        else if (rist->_videoCallback._callback && !isAudio)
-               rist->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedVideoStreamCallback));
+               rist->_buildForwardingElements(demux, new_pad, isAudio, G_CALLBACK(_encodedVideoStreamCallback));
        else
                rist->_buildRenderingElements(demux, new_pad, isAudio);
 
index d795d43..23867f9 100644 (file)
@@ -161,9 +161,9 @@ void MediaTransporterReceiverRtsp::_decodebinPadAddedCallback(GstElement* decode
 
        bool isAudio = _isAudioMediaType(mediaType);
        if (rtsp->_audioCallback._callback && isAudio)
-               rtsp->_buildForwardingElements(decodebin, new_pad, G_CALLBACK(_encodedAudioStreamCallback));
+               rtsp->_buildForwardingElements(decodebin, new_pad, isAudio, G_CALLBACK(_encodedAudioStreamCallback));
        else if (rtsp->_videoCallback._callback && !isAudio)
-               rtsp->_buildForwardingElements(decodebin, new_pad, G_CALLBACK(_encodedVideoStreamCallback));
+               rtsp->_buildForwardingElements(decodebin, new_pad, isAudio, G_CALLBACK(_encodedVideoStreamCallback));
        else
                rtsp->_buildRenderingElements(decodebin, new_pad, isAudio);
 
index 9ac843b..ae307bb 100644 (file)
@@ -62,9 +62,9 @@ void MediaTransporterReceiverSrt::_demuxPadAddedCallback(GstElement *demux, GstP
 
        bool isAudio = _isAudioMediaType(mediaType);
        if (srt->_audioCallback._callback && isAudio)
-               srt->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedAudioStreamCallback));
+               srt->_buildForwardingElements(demux, new_pad, isAudio, G_CALLBACK(_encodedAudioStreamCallback));
        else if (srt->_videoCallback._callback && !isAudio)
-               srt->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedVideoStreamCallback));
+               srt->_buildForwardingElements(demux, new_pad, isAudio, G_CALLBACK(_encodedVideoStreamCallback));
        else
                srt->_buildRenderingElements(demux, new_pad, isAudio);
 
@@ -164,4 +164,4 @@ void MediaTransporterReceiverSrt::setSenderAddress(std::string address)
 void MediaTransporterReceiverSrt::foreachConnectionStats(InvokablePtr callback)
 {
        ConnectionStatsFactory::createReceiverSrtConnectionStats(_srtSrc, std::move(callback))->foreach();
-}
\ No newline at end of file
+}
index 01c793e..9574834 100644 (file)
@@ -73,7 +73,7 @@ void MediaTransporterSender::linkMediaSourceToMuxer(GstElement* mux)
 
                        gst_bin_add(GST_BIN(_gst.pipeline), GST_ELEMENT(bin));
 
-                       GstPad* srcPad = gst::_getGhostPadFromBin(bin);
+                       GstPad* srcPad = gst::_getGhostPadFromBin(bin, "srcQueue", true);
                        if (gst_pad_is_linked(srcPad)) {
                                LOG_ERROR("pad %s:%s is already linked", GST_DEBUG_PAD_NAME(srcPad));
                                throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "already linked");
index 4811007..d7e05e8 100644 (file)
@@ -125,10 +125,10 @@ void MediaTransporterSenderRist::startPipeline()
 
 void MediaTransporterSenderRist::stopPipeline()
 {
-       _ristSink = NULL;
        _canSendPacket = false;
        gst::_setPipelineState(_gst.pipeline, GST_STATE_NULL,
                                                        MediaTransporterIni::get().general().timeout);
+       _ristSink = nullptr;
 }
 
 void MediaTransporterSenderRist::setConnection(std::string name, std::string val)
index 0d9a432..491ffdf 100644 (file)
@@ -27,6 +27,8 @@ using namespace tizen_media_transporter;
 #define ADDR_PATH_DELIM "/"
 #define ADDR_RTSP_PREFIX "rtsp://"
 
+#define DEFAULT_RTMP2PAY_NAME "pay0"
+
 static GstRTSPFilterResult
 __clientFilter(GstRTSPServer* server, GstRTSPClient* client, gpointer userData)
 {
@@ -62,7 +64,7 @@ void MediaTransporterSenderRtsp::buildPipeline()
                g_object_set(G_OBJECT(mux), "alignment", 7, NULL);
 
                /* pay element name have to be "pay0" */
-               pay = gst::_createElement("rtpmp2tpay", "pay0");
+               pay = gst::_createElement("rtpmp2tpay", DEFAULT_RTMP2PAY_NAME);
                gst_bin_add_many(GST_BIN(_gst.pipeline), mux, pay, NULL);
                if (!gst_element_link(mux, pay)) {
                        LOG_ERROR("failed to gst_element_link()");
@@ -88,20 +90,28 @@ void MediaTransporterSenderRtsp::buildPipeline()
 
 void MediaTransporterSenderRtsp::startPipeline()
 {
+       /* _canSendPacket flag is changed to true when _clientConnectedCb() is called */
        startRtspServer();
 }
 
 void MediaTransporterSenderRtsp::stopPipeline()
 {
        _canSendPacket = false;
+
        if (_rtspPipeline) {
                GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_rtspPipeline));
                gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
                gst_object_unref(bus);
 
+               gst::_setPipelineState(_rtspPipeline, GST_STATE_NULL,
+                                                               MediaTransporterIni::get().general().timeout);
+
+               gst::_removeAllPads(GST_ELEMENT(_gst.pipeline), true);
+
                gst_object_unref(_rtspPipeline);
                _rtspPipeline = NULL;
        }
+
        stopRtspServer();
        removeIdleEventSource();
 }
index 3cc1c7d..5cc9f85 100644 (file)
@@ -205,6 +205,7 @@ void MediaTransporterSenderSrt::startPipeline()
        gst::_setPipelineState(_gst.pipeline, GST_STATE_PLAYING,
                                                MediaTransporterIni::get().general().timeout, _asyncStart);
        _canSendPacket = true;
+
        startStatsMonitoring();
 }
 
@@ -212,10 +213,10 @@ void MediaTransporterSenderSrt::stopPipeline()
 {
        stopStatsMonitoring();
 
-       _srtSink = NULL;
        _canSendPacket = false;
        gst::_setPipelineState(_gst.pipeline, GST_STATE_NULL,
                                                                MediaTransporterIni::get().general().timeout);
+       _srtSink = nullptr;
 }
 
 void MediaTransporterSenderSrt::setConnection(std::string name, std::string val)
index ebfaad9..2b14e1c 100644 (file)
@@ -108,10 +108,10 @@ void MediaTransporterSenderToServerRtsp::startPipeline()
 
 void MediaTransporterSenderToServerRtsp::stopPipeline()
 {
-       _rtspSink = NULL;
        _canSendPacket = false;
        gst::_setPipelineState(_gst.pipeline, GST_STATE_NULL,
                                                        MediaTransporterIni::get().general().timeout);
+       _rtspSink = nullptr;
 }
 
 void MediaTransporterSenderToServerRtsp::setConnection(std::string name, std::string val)
index ba8df71..d941b43 100644 (file)
@@ -1379,7 +1379,11 @@ static void interpret(char *cmd)
        }
        case CURRENT_STATUS_ADD_MEDIA_SOURCE: {
                value = atoi(cmd);
-               _mtpr_test_add_media_source((mtpr_source_type_e) value - 1);
+               if (value < 1) {
+                       reset_menu_state();
+                       break;
+               }
+               _mtpr_test_add_media_source((mtpr_source_type_e)(value - 1));
                if (value == 5) {
                        _mtpr_test_camera_packet_src_create(g_mtpr, g_video_source_id);
                        g_use_camera_for_packet = true;
index 7aba90b..6713dcb 100644 (file)
@@ -25,6 +25,7 @@ typedef struct _test_camera_packet_src_s {
        int source_id;
        camera_h camera;
        bool push_packet;
+       bool stopped;
        media_format_h format;
 } test_camera_packet_src_s;
 
@@ -104,12 +105,17 @@ void _mtpr_test_camera_packet_src_create(mtpr_h mtpr, int source_id)
 void _mtpr_test_camera_packet_src_start()
 {
        g_camera_src->push_packet = true;
+       if (g_camera_src->stopped) {
+               camera_start_preview(g_camera_src->camera);
+               g_camera_src->stopped = false;
+       }
 }
 
 void _mtrp_test_camera_packet_src_stop()
 {
        g_camera_src->push_packet = false;
        camera_stop_preview(g_camera_src->camera);
+       g_camera_src->stopped = true;
 }
 
 void _mtrp_test_camera_packet_src_destroy()