summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilbok Lee <gilbok.lee@samsung.com>2024-03-19 15:12:48 +0900
committerGilbok Lee <gilbok.lee@samsung.com>2024-03-25 10:00:13 +0900
commit355a437f84a5b2c7446ed704e111dabc20fc7b8b (patch)
tree06d72e4a72e84dfc146ea68810a0145f89cddcdf
parente3f54017102e8b233ef9f9d1fd1b36085333bc1e (diff)
downloadmediatransporter-tizen.tar.gz
mediatransporter-tizen.tar.bz2
mediatransporter-tizen.zip
- The element isn't configured properly, mtpr_start() after mptr_stop() Change-Id: I41cbc785f44a8cb0ebdf8b3870aeb8183f2eee89
-rw-r--r--include/MediaTransporterBase.h1
-rw-r--r--include/MediaTransporterGst.h10
-rw-r--r--include/MediaTransporterReceiver.h3
-rw-r--r--packaging/capi-media-transporter.spec2
-rw-r--r--src/MediaSourceBinMediaPacket.cpp23
-rw-r--r--src/MediaTransporter.cpp2
-rw-r--r--src/MediaTransporterBase.cpp18
-rw-r--r--src/MediaTransporterGst.cpp100
-rw-r--r--src/MediaTransporterReceiver.cpp152
-rw-r--r--src/MediaTransporterReceiverRist.cpp4
-rw-r--r--src/MediaTransporterReceiverRtsp.cpp4
-rw-r--r--src/MediaTransporterReceiverSrt.cpp6
-rw-r--r--src/MediaTransporterSender.cpp2
-rw-r--r--src/MediaTransporterSenderRist.cpp2
-rw-r--r--src/MediaTransporterSenderRtsp.cpp12
-rw-r--r--src/MediaTransporterSenderSrt.cpp3
-rw-r--r--src/MediaTransporterSenderToServerRtsp.cpp2
-rw-r--r--test/mtpr_test.c6
-rw-r--r--test/mtpr_test_with_camera.c6
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()