2 * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "MediaTransporterBase.h"
18 #include "MediaTransporterException.h"
19 #include "MediaTransporterReceiverSrt.h"
20 #include "MediaTransporterGst.h"
21 #include "MediaTransporterLog.h"
22 #include "MediaTransporterUtil.h"
25 using namespace tizen_media_transporter;
26 using namespace tizen_media_transporter::param::srt;
28 static const std::map<std::string, mtprConnectionStatsProp> __receiverProp = {
29 { "packets-received", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED },
30 { "packets-received-lost", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED_LOST },
31 { "packets-received-rate-mbps", MTPR_CONNECTION_STATS_PROP_RECEIVED_RATE_MBPS },
32 { "negotiated-latency-ms", MTPR_CONNECTION_STATS_PROP_NEGOTIATED_LATENCY_MS },
33 { "bandwidth-mbps", MTPR_CONNECTION_STATS_PROP_BANDWIDTH_MPBS },
34 { "rtt-ms", MTPR_CONNECTION_STATS_PROP_RTT_MS },
35 { "bytes-received-total", MTPR_CONNECTION_STATS_PROP_BYTES_RECEIVED_TOTAL }};
37 MediaTransporterReceiverSrt::MediaTransporterReceiverSrt()
39 LOG_DEBUG("ctor: %p", this);
42 MediaTransporterReceiverSrt::~MediaTransporterReceiverSrt()
44 LOG_DEBUG("dtor: %p", this);
47 void MediaTransporterReceiverSrt::_demuxNoMorePadsCallback(GstElement *demux, gpointer userData)
49 MediaTransporterReceiverSrt* srt = static_cast<MediaTransporterReceiverSrt*>(userData);
50 std::string dotName = std::string { GST_ELEMENT_NAME(srt->_gst.pipeline) } + ".complete";
51 gst::_generateDot(srt->_gst.pipeline, dotName);
53 _noMoreStreamCallback(userData);
56 void MediaTransporterReceiverSrt::_demuxPadAddedCallback(GstElement *demux, GstPad *new_pad, gpointer userData)
58 if (GST_PAD_DIRECTION(new_pad) != GST_PAD_SRC)
61 std::string mediaType = gst::_getMimeTypeFromPad(new_pad);
63 if (!_isSupportedMediaType(mediaType))
66 LOG_INFO("new_pad[%s] media_type[%s]", GST_PAD_NAME(new_pad), mediaType.c_str());
68 auto srt = static_cast<MediaTransporterReceiverSrt*>(userData);
71 bool isAudio = _isAudioMediaType(mediaType);
72 if (srt->_audioCallback._callback && isAudio)
73 srt->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedAudioStreamCallback));
74 else if (srt->_videoCallback._callback && !isAudio)
75 srt->_buildForwardingElements(demux, new_pad, G_CALLBACK(_encodedVideoStreamCallback));
77 srt->_buildRenderingElements(demux, new_pad, isAudio);
79 _streamAddedCallback(new_pad, userData);
82 void MediaTransporterReceiverSrt::buildPipeline()
84 GstElement* src = NULL;
85 GstElement* queue = NULL;
86 GstElement* tsdemux = NULL;
90 /* create mux to sink */
92 if (_senderAddress.empty())
93 throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "address is empty");
95 src = gst::_createElement(gst::DEFAULT_ELEMENT_SRTSRC);
96 g_object_set(G_OBJECT(src),
97 "uri", util::addProtocolPrefix(_senderAddress, "srt").c_str(),
101 if (_connectionParam.mode != MTPR_CONNECTION_SRT_MODE_NONE)
102 g_object_set(G_OBJECT(src),
103 "mode", static_cast<int>(_connectionParam.mode), NULL);
105 if (_connectionParam.pbKeyLen != MTPR_CONNECTION_SRT_NO_KEY)
106 g_object_set(G_OBJECT(src),
107 "pbkeylen", static_cast<int>(_connectionParam.pbKeyLen), NULL);
109 if (!_connectionParam.passPhrase.empty())
110 g_object_set(G_OBJECT(src),
111 "passphrase", _connectionParam.passPhrase.c_str(), NULL);
113 if (!_connectionParam.streamId.empty())
114 g_object_set(G_OBJECT(src),
115 "streamid", _connectionParam.streamId.c_str(), NULL);
117 queue = gst::_createElement(gst::DEFAULT_ELEMENT_QUEUE);
119 tsdemux = gst::_createElement(gst::DEFAULT_ELEMENT_TSDEMUX);
120 g_object_set(G_OBJECT(tsdemux), "latency", 0, NULL);
122 gst_bin_add_many(GST_BIN(_gst.pipeline), src, queue, tsdemux, NULL);
124 if (!gst_element_link_many (src, queue, tsdemux, NULL))
125 throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "failed to link elements");
127 gst::_connectAndAppendSignal(&_gst.signals, G_OBJECT(tsdemux), "pad-added", G_CALLBACK(_demuxPadAddedCallback), this);
128 gst::_connectAndAppendSignal(&_gst.signals, G_OBJECT(tsdemux), "no-more-pads", G_CALLBACK(_demuxNoMorePadsCallback), this);
129 LOG_INFO("linked mux and sink");
131 } catch (const MediaTransporterException& e) {
132 LOG_ERROR("%s", e.what());
134 gst::_disconnectSignal(&_gst.signals, G_OBJECT(tsdemux));
136 gst::_destroyElementFromParent(src);
137 gst::_destroyElementFromParent(queue);
138 gst::_destroyElementFromParent(tsdemux);
144 void MediaTransporterReceiverSrt::startPipeline()
146 gst::_setPipelineState(_gst.pipeline, GST_STATE_PLAYING,
147 MediaTransporterIni::get().general().timeout);
150 void MediaTransporterReceiverSrt::stopPipeline()
152 gst::_setPipelineState(_gst.pipeline, GST_STATE_NULL,
153 MediaTransporterIni::get().general().timeout);
157 void MediaTransporterReceiverSrt::setConnection(std::string name, std::string val)
159 setConnectionParam(name, val, &_connectionParam);
162 std::string MediaTransporterReceiverSrt::getConnection(std::string name)
164 return getConnectionParam(_connectionParam, name);
167 void MediaTransporterReceiverSrt::setSenderAddress(std::string address)
169 _senderAddress = address;
172 gboolean MediaTransporterReceiverSrt::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData)
174 auto callback = static_cast<IInvokable*>(userData);
175 std::string fieldName = g_quark_to_string(fieldId);
178 !callback->invoke(fieldName, val, __receiverProp)) {
179 LOG_WARNING("stop calling stats callback");
186 void MediaTransporterReceiverSrt::foreachConnectionStats(InvokablePtr callback)
188 GstStructure* structure = nullptr;
190 g_object_get(_srtSrc, "stats", &structure, NULL);
192 gchar* str = gst_structure_to_string(structure);
193 SECURE_LOG_DEBUG("RECEIVER >>> stats : %s", str);
196 gst_structure_foreach(structure, _statsForeachCb, callback.get());