diff options
author | Gilbok Lee <gilbok.lee@samsung.com> | 2024-03-19 15:12:48 +0900 |
---|---|---|
committer | Gilbok Lee <gilbok.lee@samsung.com> | 2024-03-25 10:00:13 +0900 |
commit | 355a437f84a5b2c7446ed704e111dabc20fc7b8b (patch) | |
tree | 06d72e4a72e84dfc146ea68810a0145f89cddcdf | |
parent | e3f54017102e8b233ef9f9d1fd1b36085333bc1e (diff) | |
download | mediatransporter-tizen.tar.gz mediatransporter-tizen.tar.bz2 mediatransporter-tizen.zip |
[1.0.30] Clean up the pipeline after mtpr_stop()accepted/tizen/unified/x/20240401.142318accepted/tizen/unified/20240326.105036tizenaccepted/tizen_unified_xaccepted/tizen_unified
- The element isn't configured properly, mtpr_start() after mptr_stop()
Change-Id: I41cbc785f44a8cb0ebdf8b3870aeb8183f2eee89
-rw-r--r-- | include/MediaTransporterBase.h | 1 | ||||
-rw-r--r-- | include/MediaTransporterGst.h | 10 | ||||
-rw-r--r-- | include/MediaTransporterReceiver.h | 3 | ||||
-rw-r--r-- | packaging/capi-media-transporter.spec | 2 | ||||
-rw-r--r-- | src/MediaSourceBinMediaPacket.cpp | 23 | ||||
-rw-r--r-- | src/MediaTransporter.cpp | 2 | ||||
-rw-r--r-- | src/MediaTransporterBase.cpp | 18 | ||||
-rw-r--r-- | src/MediaTransporterGst.cpp | 100 | ||||
-rw-r--r-- | src/MediaTransporterReceiver.cpp | 152 | ||||
-rw-r--r-- | src/MediaTransporterReceiverRist.cpp | 4 | ||||
-rw-r--r-- | src/MediaTransporterReceiverRtsp.cpp | 4 | ||||
-rw-r--r-- | src/MediaTransporterReceiverSrt.cpp | 6 | ||||
-rw-r--r-- | src/MediaTransporterSender.cpp | 2 | ||||
-rw-r--r-- | src/MediaTransporterSenderRist.cpp | 2 | ||||
-rw-r--r-- | src/MediaTransporterSenderRtsp.cpp | 12 | ||||
-rw-r--r-- | src/MediaTransporterSenderSrt.cpp | 3 | ||||
-rw-r--r-- | src/MediaTransporterSenderToServerRtsp.cpp | 2 | ||||
-rw-r--r-- | test/mtpr_test.c | 6 | ||||
-rw-r--r-- | test/mtpr_test_with_camera.c | 6 |
19 files changed, 270 insertions, 88 deletions
diff --git a/include/MediaTransporterBase.h b/include/MediaTransporterBase.h index 65dd9c9..cac8cd7 100644 --- a/include/MediaTransporterBase.h +++ b/include/MediaTransporterBase.h @@ -82,6 +82,7 @@ protected: private: void makePipeline(); void stopInternal(); + void clearPipeline(); virtual void buildPipeline() = 0; virtual void startPipeline() = 0; diff --git a/include/MediaTransporterGst.h b/include/MediaTransporterGst.h index cf074bf..7cbecfd 100644 --- a/include/MediaTransporterGst.h +++ b/include/MediaTransporterGst.h @@ -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 diff --git a/include/MediaTransporterReceiver.h b/include/MediaTransporterReceiver.h index a50fc4d..46f7108 100644 --- a/include/MediaTransporterReceiver.h +++ b/include/MediaTransporterReceiver.h @@ -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__ - diff --git a/packaging/capi-media-transporter.spec b/packaging/capi-media-transporter.spec index 787ffeb..004ca63 100644 --- a/packaging/capi-media-transporter.spec +++ b/packaging/capi-media-transporter.spec @@ -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 diff --git a/src/MediaSourceBinMediaPacket.cpp b/src/MediaSourceBinMediaPacket.cpp index 9ce0978..c6ad9b1 100644 --- a/src/MediaSourceBinMediaPacket.cpp +++ b/src/MediaSourceBinMediaPacket.cpp @@ -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) diff --git a/src/MediaTransporter.cpp b/src/MediaTransporter.cpp index b9f8071..b20e4ca 100644 --- a/src/MediaTransporter.cpp +++ b/src/MediaTransporter.cpp @@ -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(); diff --git a/src/MediaTransporterBase.cpp b/src/MediaTransporterBase.cpp index 16e6bb8..c396981 100644 --- a/src/MediaTransporterBase.cpp +++ b/src/MediaTransporterBase.cpp @@ -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; diff --git a/src/MediaTransporterGst.cpp b/src/MediaTransporterGst.cpp index 082bace..eb24059 100644 --- a/src/MediaTransporterGst.cpp +++ b/src/MediaTransporterGst.cpp @@ -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; + } + } + } +} diff --git a/src/MediaTransporterReceiver.cpp b/src/MediaTransporterReceiver.cpp index cc768d2..902656a 100644 --- a/src/MediaTransporterReceiver.cpp +++ b/src/MediaTransporterReceiver.cpp @@ -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 +} diff --git a/src/MediaTransporterReceiverRist.cpp b/src/MediaTransporterReceiverRist.cpp index b062ceb..e30796d 100644 --- a/src/MediaTransporterReceiverRist.cpp +++ b/src/MediaTransporterReceiverRist.cpp @@ -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); diff --git a/src/MediaTransporterReceiverRtsp.cpp b/src/MediaTransporterReceiverRtsp.cpp index d795d43..23867f9 100644 --- a/src/MediaTransporterReceiverRtsp.cpp +++ b/src/MediaTransporterReceiverRtsp.cpp @@ -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); diff --git a/src/MediaTransporterReceiverSrt.cpp b/src/MediaTransporterReceiverSrt.cpp index 9ac843b..ae307bb 100644 --- a/src/MediaTransporterReceiverSrt.cpp +++ b/src/MediaTransporterReceiverSrt.cpp @@ -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 +} diff --git a/src/MediaTransporterSender.cpp b/src/MediaTransporterSender.cpp index 01c793e..9574834 100644 --- a/src/MediaTransporterSender.cpp +++ b/src/MediaTransporterSender.cpp @@ -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"); diff --git a/src/MediaTransporterSenderRist.cpp b/src/MediaTransporterSenderRist.cpp index 4811007..d7e05e8 100644 --- a/src/MediaTransporterSenderRist.cpp +++ b/src/MediaTransporterSenderRist.cpp @@ -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) diff --git a/src/MediaTransporterSenderRtsp.cpp b/src/MediaTransporterSenderRtsp.cpp index 0d9a432..491ffdf 100644 --- a/src/MediaTransporterSenderRtsp.cpp +++ b/src/MediaTransporterSenderRtsp.cpp @@ -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(); } diff --git a/src/MediaTransporterSenderSrt.cpp b/src/MediaTransporterSenderSrt.cpp index 3cc1c7d..5cc9f85 100644 --- a/src/MediaTransporterSenderSrt.cpp +++ b/src/MediaTransporterSenderSrt.cpp @@ -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) diff --git a/src/MediaTransporterSenderToServerRtsp.cpp b/src/MediaTransporterSenderToServerRtsp.cpp index ebfaad9..2b14e1c 100644 --- a/src/MediaTransporterSenderToServerRtsp.cpp +++ b/src/MediaTransporterSenderToServerRtsp.cpp @@ -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) diff --git a/test/mtpr_test.c b/test/mtpr_test.c index ba8df71..d941b43 100644 --- a/test/mtpr_test.c +++ b/test/mtpr_test.c @@ -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; diff --git a/test/mtpr_test_with_camera.c b/test/mtpr_test_with_camera.c index 7aba90b..6713dcb 100644 --- a/test/mtpr_test_with_camera.c +++ b/test/mtpr_test_with_camera.c @@ -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() |