namespace tizen_media_transporter {
-using VariantData = std::variant<mtprError, media_packet_h, unsigned int, mtprMediaType,
- mtprPacketSourceBufferState, std::string, const GValue*, std::map<std::string, mtprConnectionStatsProp>>;
+using VariantData = std::variant<mtprError, media_packet_h, unsigned int,
+ mtprMediaType, mtprPacketSourceBufferState,
+ mtprConnectionStatsPropInfo>;
class IInvokable
{
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
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;
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;
--- /dev/null
+/*
+* 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 <variant>
+#include <memory>
+#include <map>
+#include <glib-object.h>
+
+#include "MediaTransporter.h"
+#include "MediaTransporterCallback.h"
+#include "MediaTransporterGst.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace tizen_media_transporter {
+
+using ConnectionStatPropMap = std::map<std::string, mtprConnectionStatsProp>;
+
+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<mtprConnectionStatsPropInfo> translateGvalue(const GValue* val,
+ const ConnectionStatPropMap& propList,
+ const std::string& fieldName);
+
+ const GstElement* _element { nullptr };
+ InvokablePtr _callback;
+ ConnectionStatPropMap _prop;
+};
+
+using ForeachablePtr = std::unique_ptr<IForeachable>;
+
+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
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;
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 };
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
cb, handle, userdata);
}
-bool ConnectionStatsCallback::invoke(VariantData data1, VariantData data2, VariantData data3)
+bool ConnectionStatsCallback::invokeReturn(VariantData data)
{
- auto fieldName = std::get<std::string>(data1);
- auto val = std::get<const GValue*>(data2);
- auto propList = std::get<std::map<std::string, mtprConnectionStatsProp>>(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<bool>(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<mtprConnectionStatsPropInfo>(data);
+
+ LOG_DEBUG(">>> callback[%p], handle[%p], prop[%p], user_data[%p]",
+ _callback, _handle, &prop, _userdata);
+
+ return _callback(_handle, &prop, _userdata);
+}
--- /dev/null
+/**
+ * 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 <gio/gio.h>
+
+#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<GstElement*>(_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<std::pair<IInvokable*, ConnectionStatPropMap>*>(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<mtprConnectionStatsPropInfo> 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<bool>(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<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, &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;
+ }
+ }
+ }
+}
#include "MediaTransporterGst.h"
#include "MediaTransporterLog.h"
#include "MediaTransporterUtil.h"
+#include "MediaTransporterConnectionStats.h"
#include <cassert>
using namespace tizen_media_transporter;
using namespace tizen_media_transporter::param::srt;
-static const std::map<std::string, mtprConnectionStatsProp> __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);
_senderAddress = address;
}
-gboolean MediaTransporterReceiverSrt::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData)
-{
- auto callback = static_cast<IInvokable*>(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
#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<std::string, mtprConnectionStatsProp> __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));
_senderAddress = address;
}
-gboolean MediaTransporterSenderSrt::_statsForeachCb(GQuark fieldId, const GValue* val, gpointer userData)
-{
- auto callback = static_cast<IInvokable*>(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();
}