rtmp2: Expose connection stats as property
Save the stats before we destroy the connection, so we can still retrieve them afterwards.
This commit is contained in:
parent
f1a9a3146a
commit
02a6a794ec
@ -66,6 +66,7 @@ typedef struct
|
|||||||
gboolean async_connect;
|
gboolean async_connect;
|
||||||
guint peak_kbps;
|
guint peak_kbps;
|
||||||
guint32 chunk_size;
|
guint32 chunk_size;
|
||||||
|
GstStructure *stats;
|
||||||
|
|
||||||
/* If both self->lock and OBJECT_LOCK are needed,
|
/* If both self->lock and OBJECT_LOCK are needed,
|
||||||
* self->lock must be taken first */
|
* self->lock must be taken first */
|
||||||
@ -123,6 +124,8 @@ static void connect_task_done (GObject * object, GAsyncResult * result,
|
|||||||
static void set_pacing_rate (GstRtmp2Sink * self);
|
static void set_pacing_rate (GstRtmp2Sink * self);
|
||||||
static void set_chunk_size (GstRtmp2Sink * self);
|
static void set_chunk_size (GstRtmp2Sink * self);
|
||||||
|
|
||||||
|
static GstStructure *gst_rtmp2_sink_get_stats (GstRtmp2Sink * self);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -141,6 +144,7 @@ enum
|
|||||||
PROP_ASYNC_CONNECT,
|
PROP_ASYNC_CONNECT,
|
||||||
PROP_PEAK_KBPS,
|
PROP_PEAK_KBPS,
|
||||||
PROP_CHUNK_SIZE,
|
PROP_CHUNK_SIZE,
|
||||||
|
PROP_STATS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* pad templates */
|
/* pad templates */
|
||||||
@ -215,6 +219,10 @@ gst_rtmp2_sink_class_init (GstRtmp2SinkClass * klass)
|
|||||||
GST_RTMP_DEFAULT_CHUNK_SIZE, G_PARAM_READWRITE |
|
GST_RTMP_DEFAULT_CHUNK_SIZE, G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING));
|
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING));
|
||||||
|
|
||||||
|
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_DEBUG_CATEGORY_INIT (gst_rtmp2_sink_debug_category, "rtmp2sink", 0,
|
GST_DEBUG_CATEGORY_INIT (gst_rtmp2_sink_debug_category, "rtmp2sink", 0,
|
||||||
"debug category for rtmp2sink element");
|
"debug category for rtmp2sink element");
|
||||||
}
|
}
|
||||||
@ -429,6 +437,9 @@ gst_rtmp2_sink_get_property (GObject * object, guint property_id,
|
|||||||
g_value_set_uint (value, self->chunk_size);
|
g_value_set_uint (value, self->chunk_size);
|
||||||
GST_OBJECT_UNLOCK (self);
|
GST_OBJECT_UNLOCK (self);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STATS:
|
||||||
|
g_value_take_boxed (value, gst_rtmp2_sink_get_stats (self));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -451,6 +462,7 @@ gst_rtmp2_sink_finalize (GObject * object)
|
|||||||
g_mutex_clear (&self->lock);
|
g_mutex_clear (&self->lock);
|
||||||
g_cond_clear (&self->cond);
|
g_cond_clear (&self->cond);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->stats, gst_structure_free);
|
||||||
gst_rtmp_location_clear (&self->location);
|
gst_rtmp_location_clear (&self->location);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gst_rtmp2_sink_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gst_rtmp2_sink_parent_class)->finalize (object);
|
||||||
@ -873,6 +885,8 @@ gst_rtmp2_sink_task_func (gpointer user_data)
|
|||||||
loop = self->loop = g_main_loop_new (context, TRUE);
|
loop = self->loop = g_main_loop_new (context, TRUE);
|
||||||
connector = g_task_new (self, self->cancellable, connect_task_done, NULL);
|
connector = g_task_new (self, self->cancellable, connect_task_done, NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->stats, gst_structure_free);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (self);
|
GST_OBJECT_LOCK (self);
|
||||||
gst_rtmp_client_connect_async (&self->location, self->cancellable,
|
gst_rtmp_client_connect_async (&self->location, self->cancellable,
|
||||||
client_connect_done, connector);
|
client_connect_done, connector);
|
||||||
@ -883,6 +897,8 @@ gst_rtmp2_sink_task_func (gpointer user_data)
|
|||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
g_mutex_lock (&self->lock);
|
g_mutex_lock (&self->lock);
|
||||||
|
|
||||||
|
self->stats = gst_rtmp_connection_get_stats (self->connection);
|
||||||
|
|
||||||
g_clear_pointer (&self->loop, g_main_loop_unref);
|
g_clear_pointer (&self->loop, g_main_loop_unref);
|
||||||
g_clear_pointer (&self->connection, gst_rtmp_connection_close_and_unref);
|
g_clear_pointer (&self->connection, gst_rtmp_connection_close_and_unref);
|
||||||
g_cond_broadcast (&self->cond);
|
g_cond_broadcast (&self->cond);
|
||||||
@ -1103,3 +1119,23 @@ set_chunk_size (GstRtmp2Sink * self)
|
|||||||
gst_rtmp_connection_set_chunk_size (self->connection, chunk_size);
|
gst_rtmp_connection_set_chunk_size (self->connection, chunk_size);
|
||||||
GST_INFO_OBJECT (self, "Set chunk size to %" G_GUINT32_FORMAT, chunk_size);
|
GST_INFO_OBJECT (self, "Set chunk size to %" G_GUINT32_FORMAT, chunk_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstStructure *
|
||||||
|
gst_rtmp2_sink_get_stats (GstRtmp2Sink * self)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
|
g_mutex_lock (&self->lock);
|
||||||
|
|
||||||
|
if (self->connection) {
|
||||||
|
s = gst_rtmp_connection_get_stats (self->connection);
|
||||||
|
} else if (self->stats) {
|
||||||
|
s = gst_structure_copy (self->stats);
|
||||||
|
} else {
|
||||||
|
s = gst_rtmp_connection_get_null_stats ();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock (&self->lock);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
@ -59,6 +59,7 @@ typedef struct
|
|||||||
/* properties */
|
/* properties */
|
||||||
GstRtmpLocation location;
|
GstRtmpLocation location;
|
||||||
gboolean async_connect;
|
gboolean async_connect;
|
||||||
|
GstStructure *stats;
|
||||||
|
|
||||||
/* If both self->lock and OBJECT_LOCK are needed,
|
/* If both self->lock and OBJECT_LOCK are needed,
|
||||||
* self->lock must be taken first */
|
* self->lock must be taken first */
|
||||||
@ -112,6 +113,8 @@ static void start_play_done (GObject * object, GAsyncResult * result,
|
|||||||
static void connect_task_done (GObject * object, GAsyncResult * result,
|
static void connect_task_done (GObject * object, GAsyncResult * result,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
static GstStructure *gst_rtmp2_src_get_stats (GstRtmp2Src * self);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -128,6 +131,7 @@ enum
|
|||||||
PROP_TIMEOUT,
|
PROP_TIMEOUT,
|
||||||
PROP_TLS_VALIDATION_FLAGS,
|
PROP_TLS_VALIDATION_FLAGS,
|
||||||
PROP_ASYNC_CONNECT,
|
PROP_ASYNC_CONNECT,
|
||||||
|
PROP_STATS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* pad templates */
|
/* pad templates */
|
||||||
@ -189,6 +193,10 @@ gst_rtmp2_src_class_init (GstRtmp2SrcClass * klass)
|
|||||||
"Connect on READY, otherwise on first push", TRUE,
|
"Connect on READY, otherwise on first push", TRUE,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
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_DEBUG_CATEGORY_INIT (gst_rtmp2_src_debug_category, "rtmp2src", 0,
|
GST_DEBUG_CATEGORY_INIT (gst_rtmp2_src_debug_category, "rtmp2src", 0,
|
||||||
"debug category for rtmp2src element");
|
"debug category for rtmp2src element");
|
||||||
}
|
}
|
||||||
@ -368,6 +376,9 @@ gst_rtmp2_src_get_property (GObject * object, guint property_id,
|
|||||||
g_value_set_boolean (value, self->async_connect);
|
g_value_set_boolean (value, self->async_connect);
|
||||||
GST_OBJECT_UNLOCK (self);
|
GST_OBJECT_UNLOCK (self);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STATS:
|
||||||
|
g_value_take_boxed (value, gst_rtmp2_src_get_stats (self));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -390,6 +401,7 @@ gst_rtmp2_src_finalize (GObject * object)
|
|||||||
g_mutex_clear (&self->lock);
|
g_mutex_clear (&self->lock);
|
||||||
g_cond_clear (&self->cond);
|
g_cond_clear (&self->cond);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->stats, gst_structure_free);
|
||||||
gst_rtmp_location_clear (&self->location);
|
gst_rtmp_location_clear (&self->location);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gst_rtmp2_src_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gst_rtmp2_src_parent_class)->finalize (object);
|
||||||
@ -608,6 +620,8 @@ gst_rtmp2_src_task_func (gpointer user_data)
|
|||||||
loop = self->loop = g_main_loop_new (context, TRUE);
|
loop = self->loop = g_main_loop_new (context, TRUE);
|
||||||
connector = g_task_new (self, self->cancellable, connect_task_done, NULL);
|
connector = g_task_new (self, self->cancellable, connect_task_done, NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->stats, gst_structure_free);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (self);
|
GST_OBJECT_LOCK (self);
|
||||||
gst_rtmp_client_connect_async (&self->location, self->cancellable,
|
gst_rtmp_client_connect_async (&self->location, self->cancellable,
|
||||||
client_connect_done, connector);
|
client_connect_done, connector);
|
||||||
@ -618,6 +632,8 @@ gst_rtmp2_src_task_func (gpointer user_data)
|
|||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
g_mutex_lock (&self->lock);
|
g_mutex_lock (&self->lock);
|
||||||
|
|
||||||
|
self->stats = gst_rtmp_connection_get_stats (self->connection);
|
||||||
|
|
||||||
g_clear_pointer (&self->loop, g_main_loop_unref);
|
g_clear_pointer (&self->loop, g_main_loop_unref);
|
||||||
g_clear_pointer (&self->connection, gst_rtmp_connection_close_and_unref);
|
g_clear_pointer (&self->connection, gst_rtmp_connection_close_and_unref);
|
||||||
g_cond_broadcast (&self->cond);
|
g_cond_broadcast (&self->cond);
|
||||||
@ -841,3 +857,23 @@ connect_task_done (GObject * object, GAsyncResult * result, gpointer user_data)
|
|||||||
g_cond_broadcast (&self->cond);
|
g_cond_broadcast (&self->cond);
|
||||||
g_mutex_unlock (&self->lock);
|
g_mutex_unlock (&self->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstStructure *
|
||||||
|
gst_rtmp2_src_get_stats (GstRtmp2Src * self)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
|
g_mutex_lock (&self->lock);
|
||||||
|
|
||||||
|
if (self->connection) {
|
||||||
|
s = gst_rtmp_connection_get_stats (self->connection);
|
||||||
|
} else if (self->stats) {
|
||||||
|
s = gst_structure_copy (self->stats);
|
||||||
|
} else {
|
||||||
|
s = gst_rtmp_connection_get_null_stats ();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock (&self->lock);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user