From fefb5b39c94aee192fd7b22661e8901a0f5f93b7 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Fri, 14 Apr 2023 19:40:16 +0900 Subject: [PATCH] [1.0.27] Add ConnectionStats abstraction Change-Id: Ie344b5e65a2d04db09214b5509b7ef6a9724a364 --- include/MediaTransporterCallback.h | 11 +- include/MediaTransporterConnectionStats.h | 97 ++++++++++++ include/MediaTransporterReceiverSrt.h | 1 - include/MediaTransporterSenderSrt.h | 1 - packaging/capi-media-transporter.spec | 2 +- src/MediaTransporterCallback.cpp | 132 +--------------- src/MediaTransporterConnectionStats.cpp | 241 ++++++++++++++++++++++++++++++ src/MediaTransporterReceiverSrt.cpp | 34 +---- src/MediaTransporterSenderSrt.cpp | 53 +------ 9 files changed, 357 insertions(+), 215 deletions(-) create mode 100644 include/MediaTransporterConnectionStats.h create mode 100644 src/MediaTransporterConnectionStats.cpp diff --git a/include/MediaTransporterCallback.h b/include/MediaTransporterCallback.h index 420a87d..41d72e7 100644 --- a/include/MediaTransporterCallback.h +++ b/include/MediaTransporterCallback.h @@ -32,8 +32,9 @@ extern "C" { namespace tizen_media_transporter { -using VariantData = std::variant>; +using VariantData = std::variant; class IInvokable { @@ -43,7 +44,7 @@ public: virtual void invoke() = 0; virtual void invoke(VariantData data) = 0; virtual void invoke(VariantData data1, VariantData data2) = 0; - virtual bool invoke(VariantData data1, VariantData data2, VariantData data3) = 0; + virtual bool invokeReturn(VariantData data) = 0; }; class AbstractCallback : public IInvokable @@ -56,7 +57,7 @@ public: void invoke() override {} void invoke(VariantData data) override {} void invoke(VariantData data1, VariantData data2) override {} - bool invoke(VariantData data1, VariantData data2, VariantData data3) override { return TRUE; } + bool invokeReturn(VariantData data) override { return false; } protected: void* _handle; @@ -142,7 +143,7 @@ public: ConnectionStatsCallback(void* handle, mtprConnectionStatsCallback cb, void* userdata); virtual ~ConnectionStatsCallback() = default; - bool invoke(VariantData data1, VariantData data2, VariantData data3) override; + bool invokeReturn(VariantData data) override; private: mtprConnectionStatsCallback _callback; diff --git a/include/MediaTransporterConnectionStats.h b/include/MediaTransporterConnectionStats.h new file mode 100644 index 0000000..39b07bd --- /dev/null +++ b/include/MediaTransporterConnectionStats.h @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __TIZEN_MEDIA_TRANSPORTER_CONNECTION_STATS_H__ +#define __TIZEN_MEDIA_TRANSPORTER_CONNECTION_STATS_H__ + +#include +#include +#include +#include + +#include "MediaTransporter.h" +#include "MediaTransporterCallback.h" +#include "MediaTransporterGst.h" + +#ifdef __cplusplus +extern "C" { +#endif + +namespace tizen_media_transporter { + +using ConnectionStatPropMap = std::map; + +class IForeachable +{ +public: + virtual ~IForeachable() = default; + + virtual void foreach() = 0; +}; + +class AbstractConnectionStats : public IForeachable +{ +public: + AbstractConnectionStats(const GstElement* element, InvokablePtr callback, const ConnectionStatPropMap& prop) + : _element(element), _callback(std::move(callback)), _prop(prop) {} + virtual ~AbstractConnectionStats() = default; + +protected: + const GstStructure* stats(); + + static gboolean _statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData); + static std::optional translateGvalue(const GValue* val, + const ConnectionStatPropMap& propList, + const std::string& fieldName); + + const GstElement* _element { nullptr }; + InvokablePtr _callback; + ConnectionStatPropMap _prop; +}; + +using ForeachablePtr = std::unique_ptr; + +struct ConnectionStatsFactory +{ + static ForeachablePtr createReceiverSrtConnectionStats(const GstElement* element, InvokablePtr callback); + static ForeachablePtr createSenderSrtConnectionStats(const GstElement* element, InvokablePtr callback); +}; + +class ReceiverSrtConnectionStats : public AbstractConnectionStats +{ +public: + ReceiverSrtConnectionStats(const GstElement* element, InvokablePtr callback); + virtual ~ReceiverSrtConnectionStats() = default; + + void foreach() override; +}; + +class SenderSrtConnectionStats : public AbstractConnectionStats +{ +public: + SenderSrtConnectionStats(const GstElement* element, InvokablePtr callback); + virtual ~SenderSrtConnectionStats() = default; + + void foreach() override; +}; + +} // namespace + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_MEDIA_TRANSPORTER_CONNECTION_STATS_H__ */ \ No newline at end of file diff --git a/include/MediaTransporterReceiverSrt.h b/include/MediaTransporterReceiverSrt.h index a0d1d3a..741e5c8 100644 --- a/include/MediaTransporterReceiverSrt.h +++ b/include/MediaTransporterReceiverSrt.h @@ -51,7 +51,6 @@ public: private: static void _demuxPadAddedCallback(GstElement* demux, GstPad* new_pad, gpointer userData); static void _demuxNoMorePadsCallback(GstElement* demux, gpointer userData); - static gboolean _statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData); param::srt::connectionParam _connectionParam; std::string _senderAddress; diff --git a/include/MediaTransporterSenderSrt.h b/include/MediaTransporterSenderSrt.h index bf9e32e..78d0d9f 100644 --- a/include/MediaTransporterSenderSrt.h +++ b/include/MediaTransporterSenderSrt.h @@ -54,7 +54,6 @@ private: void stopStatsMonitoring(); static gpointer _statsMonitorThread(gpointer userData); static gpointer _updateStats(gpointer userData); - static gboolean _statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData); struct stats { gint64 packetsSent { 0 }; diff --git a/packaging/capi-media-transporter.spec b/packaging/capi-media-transporter.spec index 3cf03e4..0d5a0bc 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.26 +Version: 1.0.27 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/MediaTransporterCallback.cpp b/src/MediaTransporterCallback.cpp index aea26ae..fadb499 100644 --- a/src/MediaTransporterCallback.cpp +++ b/src/MediaTransporterCallback.cpp @@ -144,128 +144,12 @@ ConnectionStatsCallback::ConnectionStatsCallback(void* handle, mtprConnectionSta cb, handle, userdata); } -bool ConnectionStatsCallback::invoke(VariantData data1, VariantData data2, VariantData data3) +bool ConnectionStatsCallback::invokeReturn(VariantData data) { - auto fieldName = std::get(data1); - auto val = std::get(data2); - auto propList = std::get>(data3); - g_autofree gchar* addr = NULL; - - if (propList.find(fieldName) == propList.end()) { - LOG_DEBUG("not supported [%s]", fieldName.c_str()); - return true; - } - - mtprConnectionStatsProp prop = propList.at(fieldName); - - switch (G_VALUE_TYPE(val)) { - case G_TYPE_BOOLEAN: { - gboolean result = g_value_get_boolean(val); - LOG_DEBUG("field[%s] GType[%s] value[%u]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_BOOL, .v_bool = static_cast(result) - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_INT: { - gint result = g_value_get_int(val); - LOG_DEBUG("field[%s] GType[%s] value[%d]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_INT, .v_int = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_UINT: { - guint result = g_value_get_uint(val); - LOG_DEBUG("field[%s] GType[%s] value[%u]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_UINT, .v_uint = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_INT64: { - gint64 result = g_value_get_int64(val); - LOG_DEBUG("field[%s] GType[%s] value[%" G_GINT64_FORMAT "]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_INT64, .v_int64 = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_UINT64: { - guint64 result = g_value_get_uint64(val); - LOG_DEBUG("field[%s] GType[%s] value[%" G_GUINT64_FORMAT "]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_UINT64, .v_uint64 = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_FLOAT: { - gfloat result = g_value_get_float(val); - LOG_DEBUG("field[%s] GType[%s] value[%f]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_FLOAT, .v_float = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_DOUBLE: { - gdouble result = g_value_get_double(val); - LOG_DEBUG("field[%s] GType[%s] value[%f]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_DOUBLE, .v_double = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - case G_TYPE_STRING: { - const gchar *result = g_value_get_string(val); - LOG_DEBUG("field[%s] GType[%s] value[%s]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_STRING, .v_string = result - }; - - return _callback(_handle, &propInfo, _userdata); - } - default: - if (G_VALUE_TYPE(val) == G_TYPE_SOCKET_ADDRESS) { /* non-constexpr : g_socket_address_get_type() */ - addr = g_inet_address_to_string - (g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(g_value_get_object(val)))); - LOG_DEBUG("field[%s] GType[%s] value[%s]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), addr); - - mtprConnectionStatsPropInfo propInfo { - fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_STRING, .v_string = addr - }; - - return _callback(_handle, &propInfo, _userdata); - } - - LOG_ERROR("invalid type, field[%s] GType[%s]", - fieldName.c_str(), g_type_name(G_VALUE_TYPE(val))); - - break; - } - - return true; -} \ No newline at end of file + auto prop = std::get(data); + + LOG_DEBUG(">>> callback[%p], handle[%p], prop[%p], user_data[%p]", + _callback, _handle, &prop, _userdata); + + return _callback(_handle, &prop, _userdata); +} diff --git a/src/MediaTransporterConnectionStats.cpp b/src/MediaTransporterConnectionStats.cpp new file mode 100644 index 0000000..46964ca --- /dev/null +++ b/src/MediaTransporterConnectionStats.cpp @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "MediaTransporterConnectionStats.h" +#include "MediaTransporterLog.h" + +using namespace tizen_media_transporter; + +// AbstractConnectionStats +const GstStructure* AbstractConnectionStats::stats() +{ + const GstStructure* structure = nullptr; + g_object_get(const_cast(_element), "stats", &structure, NULL); + + gchar* str = gst_structure_to_string(structure); + SECURE_LOG_DEBUG(">>> stats : %s", str); + g_free(str); + + return structure; +} + +gboolean AbstractConnectionStats::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData) +{ + std::string fieldName = g_quark_to_string(fieldId); + + auto [ callback, prop ] = *(static_cast*>(userData)); + + auto propInfo = translateGvalue(val, prop, fieldName); + + if (propInfo.has_value()) { + if (!callback || !callback->invokeReturn(propInfo.value())) { + LOG_WARNING("stop calling stats callback"); + return FALSE; + } + } + + return TRUE; +} + +std::optional AbstractConnectionStats::translateGvalue(const GValue* val, + const ConnectionStatPropMap& propList, + const std::string& fieldName) +{ + g_autofree gchar* addr = NULL; + + if (propList.find(fieldName) == propList.end()) { + LOG_DEBUG("not supported [%s]", fieldName.c_str()); + return std::nullopt; + } + + mtprConnectionStatsProp prop = propList.at(fieldName); + + switch (G_VALUE_TYPE(val)) { + case G_TYPE_BOOLEAN: { + gboolean result = g_value_get_boolean(val); + LOG_DEBUG("field[%s] GType[%s] value[%u]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_BOOL, .v_bool = static_cast(result) + }; + } + case G_TYPE_INT: { + gint result = g_value_get_int(val); + LOG_DEBUG("field[%s] GType[%s] value[%d]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_INT, .v_int = result + }; + + } + case G_TYPE_UINT: { + guint result = g_value_get_uint(val); + LOG_DEBUG("field[%s] GType[%s] value[%u]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_UINT, .v_uint = result + }; + } + case G_TYPE_INT64: { + gint64 result = g_value_get_int64(val); + LOG_DEBUG("field[%s] GType[%s] value[%" G_GINT64_FORMAT "]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_INT64, .v_int64 = result + }; + } + case G_TYPE_UINT64: { + guint64 result = g_value_get_uint64(val); + LOG_DEBUG("field[%s] GType[%s] value[%" G_GUINT64_FORMAT "]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_UINT64, .v_uint64 = result + }; + } + case G_TYPE_FLOAT: { + gfloat result = g_value_get_float(val); + LOG_DEBUG("field[%s] GType[%s] value[%f]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_FLOAT, .v_float = result + }; + } + case G_TYPE_DOUBLE: { + gdouble result = g_value_get_double(val); + LOG_DEBUG("field[%s] GType[%s] value[%f]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_DOUBLE, .v_double = result + }; + } + case G_TYPE_STRING: { + const gchar *result = g_value_get_string(val); + LOG_DEBUG("field[%s] GType[%s] value[%s]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), result); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_STRING, .v_string = result + }; + } + default: + if (G_VALUE_TYPE(val) == G_TYPE_SOCKET_ADDRESS) { /* non-constexpr : g_socket_address_get_type() */ + addr = g_inet_address_to_string + (g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(g_value_get_object(val)))); + LOG_DEBUG("field[%s] GType[%s] value[%s]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val)), addr); + + return mtprConnectionStatsPropInfo { + fieldName.c_str(), prop, MTPR_CONNECTION_STATS_PROP_TYPE_STRING, .v_string = addr + }; + } + + LOG_ERROR("invalid type, field[%s] GType[%s]", + fieldName.c_str(), g_type_name(G_VALUE_TYPE(val))); + + return std::nullopt; + } +} + +// ConnectionStatsFactory +ForeachablePtr ConnectionStatsFactory::createReceiverSrtConnectionStats(const GstElement* element, InvokablePtr callback) +{ + return ForeachablePtr(new ReceiverSrtConnectionStats(element, std::move(callback))); +} + +ForeachablePtr ConnectionStatsFactory::createSenderSrtConnectionStats(const GstElement* element, InvokablePtr callback) +{ + return ForeachablePtr(new SenderSrtConnectionStats(element, std::move(callback))); +} + +// ReceiverSrtConnectionStats +ReceiverSrtConnectionStats::ReceiverSrtConnectionStats(const GstElement* element, InvokablePtr callback) + : AbstractConnectionStats(element, std::move(callback), { + { "packets-received", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED }, + { "packets-received-lost", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED_LOST }, + { "packets-received-rate-mbps", MTPR_CONNECTION_STATS_PROP_RECEIVED_RATE_MBPS }, + { "negotiated-latency-ms", MTPR_CONNECTION_STATS_PROP_NEGOTIATED_LATENCY_MS }, + { "bandwidth-mbps", MTPR_CONNECTION_STATS_PROP_BANDWIDTH_MPBS }, + { "rtt-ms", MTPR_CONNECTION_STATS_PROP_RTT_MS }, + { "bytes-received-total", MTPR_CONNECTION_STATS_PROP_BYTES_RECEIVED_TOTAL } + }) +{ +} + +void ReceiverSrtConnectionStats::foreach() +{ + const GstStructure* structure = stats(); + auto userdata = std::make_pair(_callback.get(), _prop); + + gst_structure_foreach(structure, _statsForeachCb, &userdata); +} + +// SenderSrtConnectionStats +SenderSrtConnectionStats::SenderSrtConnectionStats(const GstElement* element, InvokablePtr callback) + : AbstractConnectionStats(element, std::move(callback), { + { "packets-sent", MTPR_CONNECTION_STATS_PROP_PACKET_SENT }, + { "packets-sent-lost", MTPR_CONNECTION_STATS_PROP_PACKET_SENT_LOST }, + { "send-rate-mbps", MTPR_CONNECTION_STATS_PROP_SEND_RATE_MPBS }, + { "negotiated-latency-ms", MTPR_CONNECTION_STATS_PROP_NEGOTIATED_LATENCY_MS }, + { "bandwidth-mbps", MTPR_CONNECTION_STATS_PROP_BANDWIDTH_MPBS }, + { "rtt-ms", MTPR_CONNECTION_STATS_PROP_RTT_MS }, + { "caller-address", MTPR_CONNECTION_STATS_PROP_CALLER_ADDRESS }, + { "bytes-sent-total", MTPR_CONNECTION_STATS_PROP_BYTES_SENT_TOTAL } + }) +{ +} + +void SenderSrtConnectionStats::foreach() +{ + const GstStructure* structure = stats(); + auto userdata = std::make_pair(_callback.get(), _prop); + gboolean ret = FALSE; + + if (gst_structure_has_field(structure, "callers")) { + auto callers = static_cast(g_value_get_boxed( + gst_structure_get_value(structure, "callers") + )); + + LOG_DEBUG("SENDER >>> num of callers : %d", callers->n_values); + for (int i = 0; i < (int)callers->n_values; i++) { + const GstStructure* callerStats = (GstStructure *)g_value_get_boxed(&callers->values[i]); + + LOG_DEBUG("SENDER >>> caller idx : %d", i); + ret = gst_structure_foreach(callerStats, _statsForeachCb, &userdata); + if (!ret) + break; + } + } + + if (ret && gst_structure_has_field(structure, "bytes-sent-total")) { + auto propInfo = translateGvalue(gst_structure_get_value(structure, "bytes-sent-total"), + _prop, "bytes-sent-total"); + if (propInfo.has_value()) { + if (!_callback || !_callback->invokeReturn(propInfo.value())) { + LOG_WARNING("stop calling stats callback"); + return; + } + } + } +} diff --git a/src/MediaTransporterReceiverSrt.cpp b/src/MediaTransporterReceiverSrt.cpp index 5b61a0c..9ac843b 100644 --- a/src/MediaTransporterReceiverSrt.cpp +++ b/src/MediaTransporterReceiverSrt.cpp @@ -20,20 +20,12 @@ #include "MediaTransporterGst.h" #include "MediaTransporterLog.h" #include "MediaTransporterUtil.h" +#include "MediaTransporterConnectionStats.h" #include using namespace tizen_media_transporter; using namespace tizen_media_transporter::param::srt; -static const std::map __receiverProp = { - { "packets-received", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED }, - { "packets-received-lost", MTPR_CONNECTION_STATS_PROP_PACKET_RECEIVED_LOST }, - { "packets-received-rate-mbps", MTPR_CONNECTION_STATS_PROP_RECEIVED_RATE_MBPS }, - { "negotiated-latency-ms", MTPR_CONNECTION_STATS_PROP_NEGOTIATED_LATENCY_MS }, - { "bandwidth-mbps", MTPR_CONNECTION_STATS_PROP_BANDWIDTH_MPBS }, - { "rtt-ms", MTPR_CONNECTION_STATS_PROP_RTT_MS }, - { "bytes-received-total", MTPR_CONNECTION_STATS_PROP_BYTES_RECEIVED_TOTAL }}; - MediaTransporterReceiverSrt::MediaTransporterReceiverSrt() { LOG_DEBUG("ctor: %p", this); @@ -169,29 +161,7 @@ void MediaTransporterReceiverSrt::setSenderAddress(std::string address) _senderAddress = address; } -gboolean MediaTransporterReceiverSrt::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData) -{ - auto callback = static_cast(userData); - std::string fieldName = g_quark_to_string(fieldId); - - if (!callback || - !callback->invoke(fieldName, val, __receiverProp)) { - LOG_WARNING("stop calling stats callback"); - return FALSE; - } - - return TRUE; -} - void MediaTransporterReceiverSrt::foreachConnectionStats(InvokablePtr callback) { - GstStructure* structure = nullptr; - - g_object_get(_srtSrc, "stats", &structure, NULL); - - gchar* str = gst_structure_to_string(structure); - SECURE_LOG_DEBUG("RECEIVER >>> stats : %s", str); - g_free(str); - - gst_structure_foreach(structure, _statsForeachCb, callback.get()); + ConnectionStatsFactory::createReceiverSrtConnectionStats(_srtSrc, std::move(callback))->foreach(); } \ No newline at end of file diff --git a/src/MediaTransporterSenderSrt.cpp b/src/MediaTransporterSenderSrt.cpp index e595073..80c815c 100644 --- a/src/MediaTransporterSenderSrt.cpp +++ b/src/MediaTransporterSenderSrt.cpp @@ -22,22 +22,13 @@ #include "MediaTransporterLog.h" #include "MediaTransporterUtil.h" #include "MediaTransporterParseIni.h" +#include "MediaTransporterConnectionStats.h" using namespace tizen_media_transporter; using namespace tizen_media_transporter::param::srt; constexpr unsigned int STATS_UPDATE_INTERVAL = 1000; -static const std::map __senderProp = { - { "packets-sent", MTPR_CONNECTION_STATS_PROP_PACKET_SENT }, - { "packets-sent-lost", MTPR_CONNECTION_STATS_PROP_PACKET_SENT_LOST }, - { "send-rate-mbps", MTPR_CONNECTION_STATS_PROP_SEND_RATE_MPBS }, - { "negotiated-latency-ms", MTPR_CONNECTION_STATS_PROP_NEGOTIATED_LATENCY_MS }, - { "bandwidth-mbps", MTPR_CONNECTION_STATS_PROP_BANDWIDTH_MPBS }, - { "rtt-ms", MTPR_CONNECTION_STATS_PROP_RTT_MS }, - { "caller-address", MTPR_CONNECTION_STATS_PROP_CALLER_ADDRESS }, - { "bytes-sent-total", MTPR_CONNECTION_STATS_PROP_BYTES_SENT_TOTAL }}; - static void __callerAddedCb(GstElement* element, gint socket, GSocketAddress* address, gpointer userData) { g_autofree gchar* ip_addr = g_inet_address_to_string(g_inet_socket_address_get_address((GInetSocketAddress*)address)); @@ -240,47 +231,7 @@ void MediaTransporterSenderSrt::setSenderAddress(std::string address) _senderAddress = address; } -gboolean MediaTransporterSenderSrt::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData) -{ - auto callback = static_cast(userData); - std::string fieldName = g_quark_to_string(fieldId); - - if (!callback || - !callback->invoke(fieldName, val, __senderProp)) { - LOG_WARNING("stop calling stats callback"); - return FALSE; - } - - return TRUE; -} - void MediaTransporterSenderSrt::foreachConnectionStats(InvokablePtr callback) { - const GstStructure* structure = NULL; - - g_object_get(_srtSink, "stats", &structure, NULL); - gchar* str = gst_structure_to_string(structure); - SECURE_LOG_DEBUG("SENDER >>> stats : %s", str); - g_free(str); - - gboolean ret = FALSE; - - if (gst_structure_has_field(structure, "callers")) { - GValueArray* callers = (GValueArray *)g_value_get_boxed(gst_structure_get_value(structure, "callers")); - - LOG_DEBUG("SENDER >>> num of callers : %d", callers->n_values); - for (int i = 0; i < (int)callers->n_values; i++) { - const GstStructure* callerStats = (GstStructure *)g_value_get_boxed(&callers->values[i]); - - LOG_DEBUG("SENDER >>> caller idx : %d", i); - ret = gst_structure_foreach(callerStats, _statsForeachCb, callback.get()); - if (!ret) - break; - } - } - - if (ret && gst_structure_has_field(structure, "bytes-sent-total")) - callback->invoke("bytes-sent-total", - gst_structure_get_value(structure, "bytes-sent-total"), __senderProp); - + ConnectionStatsFactory::createSenderSrtConnectionStats(_srtSink, std::move(callback))->foreach(); } -- 2.7.4