mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 00:01:23 +00:00
tcpserversrc: Add stats property
Like in tcpclientsrc Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/651>
This commit is contained in:
parent
47e2c4cc10
commit
e56b784171
6 changed files with 105 additions and 41 deletions
|
@ -43,18 +43,9 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* macOS and iOS have the .h files but the tcp_info struct is private API */
|
|
||||||
#if defined(HAVE_NETINET_TCP_H) && defined(HAVE_NETINET_IN_H) && defined(HAVE_SYS_SOCKET_H)
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#if defined(TCP_INFO)
|
|
||||||
#define HAVE_SOCKET_METRIC_HEADERS
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gst/gst-i18n-plugin.h>
|
#include <gst/gst-i18n-plugin.h>
|
||||||
#include "gsttcpclientsrc.h"
|
#include "gsttcpclientsrc.h"
|
||||||
|
#include "gsttcpsrcstats.h"
|
||||||
#include "gsttcp.h"
|
#include "gsttcp.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (tcpclientsrc_debug);
|
GST_DEBUG_CATEGORY_STATIC (tcpclientsrc_debug);
|
||||||
|
@ -576,36 +567,7 @@ gst_tcp_client_src_get_stats (GstTCPClientSrc * src)
|
||||||
s = gst_structure_new ("GstTCPClientSrcStats",
|
s = gst_structure_new ("GstTCPClientSrcStats",
|
||||||
"bytes-received", G_TYPE_UINT64, src->bytes_received, NULL);
|
"bytes-received", G_TYPE_UINT64, src->bytes_received, NULL);
|
||||||
|
|
||||||
#ifdef HAVE_SOCKET_METRIC_HEADERS
|
gst_tcp_stats_from_socket (s, src->socket);
|
||||||
if (src->socket) {
|
|
||||||
struct tcp_info info;
|
|
||||||
socklen_t info_len = sizeof info;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = g_socket_get_fd (src->socket);
|
|
||||||
|
|
||||||
if (getsockopt (fd, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0) {
|
|
||||||
/* this is system-specific */
|
|
||||||
#ifdef HAVE_BSD_TCP_INFO
|
|
||||||
gst_structure_set (s,
|
|
||||||
"reordering", G_TYPE_UINT, info.__tcpi_reordering,
|
|
||||||
"unacked", G_TYPE_UINT, info.__tcpi_unacked,
|
|
||||||
"sacked", G_TYPE_UINT, info.__tcpi_sacked,
|
|
||||||
"lost", G_TYPE_UINT, info.__tcpi_lost,
|
|
||||||
"retrans", G_TYPE_UINT, info.__tcpi_retrans,
|
|
||||||
"fackets", G_TYPE_UINT, info.__tcpi_fackets, NULL);
|
|
||||||
#elif defined(HAVE_LINUX_TCP_INFO)
|
|
||||||
gst_structure_set (s,
|
|
||||||
"reordering", G_TYPE_UINT, info.tcpi_reordering,
|
|
||||||
"unacked", G_TYPE_UINT, info.tcpi_unacked,
|
|
||||||
"sacked", G_TYPE_UINT, info.tcpi_sacked,
|
|
||||||
"lost", G_TYPE_UINT, info.tcpi_lost,
|
|
||||||
"retrans", G_TYPE_UINT, info.tcpi_retrans,
|
|
||||||
"fackets", G_TYPE_UINT, info.tcpi_fackets, NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include <gst/gst-i18n-plugin.h>
|
#include <gst/gst-i18n-plugin.h>
|
||||||
#include "gsttcp.h"
|
#include "gsttcp.h"
|
||||||
|
#include "gsttcpsrcstats.h"
|
||||||
#include "gsttcpserversrc.h"
|
#include "gsttcpserversrc.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (tcpserversrc_debug);
|
GST_DEBUG_CATEGORY_STATIC (tcpserversrc_debug);
|
||||||
|
@ -62,7 +63,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_HOST,
|
PROP_HOST,
|
||||||
PROP_PORT,
|
PROP_PORT,
|
||||||
PROP_CURRENT_PORT
|
PROP_CURRENT_PORT,
|
||||||
|
PROP_STATS,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gst_tcp_server_src_parent_class parent_class
|
#define gst_tcp_server_src_parent_class parent_class
|
||||||
|
@ -81,6 +83,7 @@ static void gst_tcp_server_src_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_tcp_server_src_get_property (GObject * object, guint prop_id,
|
static void gst_tcp_server_src_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
static GstStructure *gst_tcp_server_src_get_stats (GstTCPServerSrc * src);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_tcp_server_src_class_init (GstTCPServerSrcClass * klass)
|
gst_tcp_server_src_class_init (GstTCPServerSrcClass * klass)
|
||||||
|
@ -123,6 +126,30 @@ gst_tcp_server_src_class_init (GstTCPServerSrcClass * klass)
|
||||||
"The port number the socket is currently bound to", 0,
|
"The port number the socket is currently bound to", 0,
|
||||||
TCP_HIGHEST_PORT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
TCP_HIGHEST_PORT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstTCPServerSrc::stats:
|
||||||
|
*
|
||||||
|
* Sends a GstStructure with statistics. We count bytes-received in a
|
||||||
|
* platform-independent way and the rest via the tcp_info struct, if it's
|
||||||
|
* available. The OS takes care of the TCP layer for us so we can't know it
|
||||||
|
* from here.
|
||||||
|
*
|
||||||
|
* Struct members:
|
||||||
|
*
|
||||||
|
* bytes-received (uint64): Total bytes received (platform-independent)
|
||||||
|
* reordering (uint): Amount of reordering (linux-specific)
|
||||||
|
* unacked (uint): Un-acked packets (linux-specific)
|
||||||
|
* sacked (uint): Selective acked packets (linux-specific)
|
||||||
|
* lost (uint): Lost packets (linux-specific)
|
||||||
|
* retrans (uint): Retransmits (linux-specific)
|
||||||
|
* fackets (uint): Forward acknowledgement (linux-specific)
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_STATS,
|
||||||
|
g_param_spec_boxed ("stats", "Stats", "Retrieve a statistics structure",
|
||||||
|
GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
|
gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (gstelement_class,
|
gst_element_class_set_static_metadata (gstelement_class,
|
||||||
|
@ -171,6 +198,8 @@ gst_tcp_server_src_finalize (GObject * gobject)
|
||||||
g_free (src->host);
|
g_free (src->host);
|
||||||
src->host = NULL;
|
src->host = NULL;
|
||||||
|
|
||||||
|
gst_clear_structure (&src->stats);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (gobject);
|
G_OBJECT_CLASS (parent_class)->finalize (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +306,7 @@ gst_tcp_server_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
gst_buffer_unmap (*outbuf, &map);
|
gst_buffer_unmap (*outbuf, &map);
|
||||||
gst_buffer_resize (*outbuf, 0, rret);
|
gst_buffer_resize (*outbuf, 0, rret);
|
||||||
|
src->bytes_received += read;
|
||||||
|
|
||||||
GST_LOG_OBJECT (src,
|
GST_LOG_OBJECT (src,
|
||||||
"Returning buffer from _get of size %" G_GSIZE_FORMAT ", ts %"
|
"Returning buffer from _get of size %" G_GSIZE_FORMAT ", ts %"
|
||||||
|
@ -372,6 +402,9 @@ gst_tcp_server_src_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_CURRENT_PORT:
|
case PROP_CURRENT_PORT:
|
||||||
g_value_set_int (value, g_atomic_int_get (&tcpserversrc->current_port));
|
g_value_set_int (value, g_atomic_int_get (&tcpserversrc->current_port));
|
||||||
break;
|
break;
|
||||||
|
case PROP_STATS:
|
||||||
|
g_value_take_boxed (value, gst_tcp_server_src_get_stats (tcpserversrc));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -389,6 +422,9 @@ gst_tcp_server_src_start (GstBaseSrc * bsrc)
|
||||||
GResolver *resolver;
|
GResolver *resolver;
|
||||||
gint bound_port = 0;
|
gint bound_port = 0;
|
||||||
|
|
||||||
|
src->bytes_received = 0;
|
||||||
|
gst_clear_structure (&src->stats);
|
||||||
|
|
||||||
/* look up name if we need to */
|
/* look up name if we need to */
|
||||||
addr = g_inet_address_new_from_string (src->host);
|
addr = g_inet_address_new_from_string (src->host);
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
|
@ -516,6 +552,8 @@ gst_tcp_server_src_stop (GstBaseSrc * bsrc)
|
||||||
if (src->client_socket) {
|
if (src->client_socket) {
|
||||||
GST_DEBUG_OBJECT (src, "closing socket");
|
GST_DEBUG_OBJECT (src, "closing socket");
|
||||||
|
|
||||||
|
src->stats = gst_tcp_server_src_get_stats (src);
|
||||||
|
|
||||||
if (!g_socket_close (src->client_socket, &err)) {
|
if (!g_socket_close (src->client_socket, &err)) {
|
||||||
GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message);
|
GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message);
|
||||||
g_clear_error (&err);
|
g_clear_error (&err);
|
||||||
|
@ -564,3 +602,21 @@ gst_tcp_server_src_unlock_stop (GstBaseSrc * bsrc)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GstStructure *
|
||||||
|
gst_tcp_server_src_get_stats (GstTCPServerSrc * src)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
|
/* we can't get the values post stop so just return the saved ones */
|
||||||
|
if (src->stats)
|
||||||
|
return gst_structure_copy (src->stats);
|
||||||
|
|
||||||
|
s = gst_structure_new ("GstTCPServerSrcStats",
|
||||||
|
"bytes-received", G_TYPE_UINT64, src->bytes_received, NULL);
|
||||||
|
|
||||||
|
gst_tcp_stats_from_socket (s, src->client_socket);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,9 @@ struct _GstTCPServerSrc {
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GSocket *server_socket;
|
GSocket *server_socket;
|
||||||
GSocket *client_socket;
|
GSocket *client_socket;
|
||||||
|
|
||||||
|
guint64 bytes_received;
|
||||||
|
GstStructure *stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstTCPServerSrcClass {
|
struct _GstTCPServerSrcClass {
|
||||||
|
|
38
gst/tcp/gsttcpsrcstats.c
Normal file
38
gst/tcp/gsttcpsrcstats.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* macOS and iOS have the .h files but the tcp_info struct is private API */
|
||||||
|
#if defined(HAVE_NETINET_TCP_H) && defined(HAVE_NETINET_IN_H) && defined(HAVE_SYS_SOCKET_H)
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#if defined(TCP_INFO)
|
||||||
|
#define HAVE_SOCKET_METRIC_HEADERS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gsttcpsrcstats.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_tcp_stats_from_socket (GstStructure * structure, GSocket * socket)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SOCKET_METRIC_HEADERS
|
||||||
|
if (getsockopt (fd, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0) {
|
||||||
|
/* this is system-specific */
|
||||||
|
#ifdef HAVE_BSD_TCP_INFO
|
||||||
|
gst_structure_set (s,
|
||||||
|
"reordering", G_TYPE_UINT, info.__tcpi_reordering,
|
||||||
|
"unacked", G_TYPE_UINT, info.__tcpi_unacked,
|
||||||
|
"sacked", G_TYPE_UINT, info.__tcpi_sacked,
|
||||||
|
"lost", G_TYPE_UINT, info.__tcpi_lost,
|
||||||
|
"retrans", G_TYPE_UINT, info.__tcpi_retrans,
|
||||||
|
"fackets", G_TYPE_UINT, info.__tcpi_fackets, NULL);
|
||||||
|
#elif defined(HAVE_LINUX_TCP_INFO)
|
||||||
|
gst_structure_set (s,
|
||||||
|
"reordering", G_TYPE_UINT, info.tcpi_reordering,
|
||||||
|
"unacked", G_TYPE_UINT, info.tcpi_unacked,
|
||||||
|
"sacked", G_TYPE_UINT, info.tcpi_sacked,
|
||||||
|
"lost", G_TYPE_UINT, info.tcpi_lost,
|
||||||
|
"retrans", G_TYPE_UINT, info.tcpi_retrans,
|
||||||
|
"fackets", G_TYPE_UINT, info.tcpi_fackets, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
4
gst/tcp/gsttcpsrcstats.h
Normal file
4
gst/tcp/gsttcpsrcstats.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
void gst_tcp_stats_from_socket (GstStructure *structure, GSocket *socket);
|
|
@ -6,6 +6,7 @@ tcp_sources = [
|
||||||
'gsttcpclientsink.c',
|
'gsttcpclientsink.c',
|
||||||
'gsttcpserversrc.c',
|
'gsttcpserversrc.c',
|
||||||
'gsttcpserversink.c',
|
'gsttcpserversink.c',
|
||||||
|
'gsttcpsrcstats.c',
|
||||||
'gsttcpplugin.c',
|
'gsttcpplugin.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue