diff --git a/gst/rtmp2/gstrtmp2sink.c b/gst/rtmp2/gstrtmp2sink.c index 162a25b7d0..f0397914ee 100644 --- a/gst/rtmp2/gstrtmp2sink.c +++ b/gst/rtmp2/gstrtmp2sink.c @@ -66,6 +66,7 @@ typedef struct gboolean async_connect; guint peak_kbps; guint32 chunk_size; + GstStructure *stats; /* If both self->lock and OBJECT_LOCK are needed, * 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_chunk_size (GstRtmp2Sink * self); +static GstStructure *gst_rtmp2_sink_get_stats (GstRtmp2Sink * self); + enum { PROP_0, @@ -141,6 +144,7 @@ enum PROP_ASYNC_CONNECT, PROP_PEAK_KBPS, PROP_CHUNK_SIZE, + PROP_STATS, }; /* pad templates */ @@ -215,6 +219,10 @@ gst_rtmp2_sink_class_init (GstRtmp2SinkClass * klass) GST_RTMP_DEFAULT_CHUNK_SIZE, G_PARAM_READWRITE | 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, "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); GST_OBJECT_UNLOCK (self); break; + case PROP_STATS: + g_value_take_boxed (value, gst_rtmp2_sink_get_stats (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -451,6 +462,7 @@ gst_rtmp2_sink_finalize (GObject * object) g_mutex_clear (&self->lock); g_cond_clear (&self->cond); + g_clear_pointer (&self->stats, gst_structure_free); gst_rtmp_location_clear (&self->location); 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); connector = g_task_new (self, self->cancellable, connect_task_done, NULL); + g_clear_pointer (&self->stats, gst_structure_free); + GST_OBJECT_LOCK (self); gst_rtmp_client_connect_async (&self->location, self->cancellable, client_connect_done, connector); @@ -883,6 +897,8 @@ gst_rtmp2_sink_task_func (gpointer user_data) g_main_loop_run (loop); 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->connection, gst_rtmp_connection_close_and_unref); 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_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; +} diff --git a/gst/rtmp2/gstrtmp2src.c b/gst/rtmp2/gstrtmp2src.c index 305edcb068..e5ba76f0da 100644 --- a/gst/rtmp2/gstrtmp2src.c +++ b/gst/rtmp2/gstrtmp2src.c @@ -59,6 +59,7 @@ typedef struct /* properties */ GstRtmpLocation location; gboolean async_connect; + GstStructure *stats; /* If both self->lock and OBJECT_LOCK are needed, * 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, gpointer user_data); +static GstStructure *gst_rtmp2_src_get_stats (GstRtmp2Src * self); + enum { PROP_0, @@ -128,6 +131,7 @@ enum PROP_TIMEOUT, PROP_TLS_VALIDATION_FLAGS, PROP_ASYNC_CONNECT, + PROP_STATS, }; /* pad templates */ @@ -189,6 +193,10 @@ gst_rtmp2_src_class_init (GstRtmp2SrcClass * klass) "Connect on READY, otherwise on first push", TRUE, 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, "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); GST_OBJECT_UNLOCK (self); break; + case PROP_STATS: + g_value_take_boxed (value, gst_rtmp2_src_get_stats (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -390,6 +401,7 @@ gst_rtmp2_src_finalize (GObject * object) g_mutex_clear (&self->lock); g_cond_clear (&self->cond); + g_clear_pointer (&self->stats, gst_structure_free); gst_rtmp_location_clear (&self->location); 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); connector = g_task_new (self, self->cancellable, connect_task_done, NULL); + g_clear_pointer (&self->stats, gst_structure_free); + GST_OBJECT_LOCK (self); gst_rtmp_client_connect_async (&self->location, self->cancellable, client_connect_done, connector); @@ -618,6 +632,8 @@ gst_rtmp2_src_task_func (gpointer user_data) g_main_loop_run (loop); 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->connection, gst_rtmp_connection_close_and_unref); 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_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; +}