From: Torrie Fischer Date: Fri, 15 Nov 2013 14:20:14 +0000 (+0100) Subject: gstrtpsession: Implement a number of feedback packet statistics X-Git-Tag: 1.19.3~509^2~5169 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=acf74435e3a713a7d0fd685abad86e6a61eef51f;p=platform%2Fupstream%2Fgstreamer.git gstrtpsession: Implement a number of feedback packet statistics Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711693 --- diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index bb9ea5695d..02a8430727 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -218,6 +218,7 @@ enum PROP_USE_PIPELINE_CLOCK, PROP_RTCP_MIN_INTERVAL, PROP_PROBATION, + PROP_STATS, PROP_LAST }; @@ -251,6 +252,8 @@ struct _GstRtpSessionPrivate GstClockTime send_latency; gboolean use_pipeline_clock; + + guint rtx_count; }; /* callbacks to handle actions from the session manager */ @@ -305,6 +308,8 @@ static gboolean gst_rtp_session_setcaps_send_rtp (GstPad * pad, static void gst_rtp_session_clear_pt_map (GstRtpSession * rtpsession); +static GstStructure *gst_rtp_session_create_stats (GstRtpSession * rtpsession); + static guint gst_rtp_session_signals[LAST_SIGNAL] = { 0 }; static void @@ -605,6 +610,26 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass) 0, G_MAXUINT, DEFAULT_PROBATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRtpSession::stats: + * + * Various session statistics. This property returns a GstStructure + * with name application/x-rtp-session-stats with the following fields: + * + * "rtx-count" G_TYPE_UINT The number of retransmission events + * received from downstream (in receiver mode) + * "rtx-drop-count" G_TYPE_UINT The number of retransmission events + * dropped (due to bandwidth constraints) + * "sent-nack-count" G_TYPE_UINT Number of NACKs sent + * "recv-nack-count" G_TYPE_UINT Number of NACKs received + * + * Since: 1.3.1 + */ + g_object_class_install_property (gobject_class, PROP_STATS, + g_param_spec_boxed ("stats", "Statistics", + "Various statistics", GST_TYPE_STRUCTURE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_session_change_state); gstelement_class->request_new_pad = @@ -678,6 +703,8 @@ gst_rtp_session_init (GstRtpSession * rtpsession) gst_segment_init (&rtpsession->send_rtp_seg, GST_FORMAT_UNDEFINED); rtpsession->priv->thread_stopped = TRUE; + + rtpsession->priv->rtx_count = 0; } static void @@ -788,12 +815,27 @@ gst_rtp_session_get_property (GObject * object, guint prop_id, case PROP_PROBATION: g_object_get_property (G_OBJECT (priv->session), "probation", value); break; + case PROP_STATS: + g_value_take_boxed (value, gst_rtp_session_create_stats (rtpsession)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static GstStructure * +gst_rtp_session_create_stats (GstRtpSession * rtpsession) +{ + GstStructure *s; + + g_object_get (rtpsession->priv->session, "stats", &s, NULL); + gst_structure_set (s, "rtx-count", G_TYPE_UINT, rtpsession->priv->rtx_count, + NULL); + + return s; +} + static void get_current_times (GstRtpSession * rtpsession, GstClockTime * running_time, guint64 * ntpnstime) @@ -1511,6 +1553,10 @@ gst_rtp_session_event_recv_rtp_src (GstPad * pad, GstObject * parent, GstClockTime running_time; guint seqnum, delay, deadline, max_delay; + GST_RTP_SESSION_LOCK (rtpsession); + rtpsession->priv->rtx_count++; + GST_RTP_SESSION_UNLOCK (rtpsession); + if (!gst_structure_get_clock_time (s, "running-time", &running_time)) running_time = -1; if (!gst_structure_get_uint (s, "ssrc", &ssrc)) diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index c023012be7..fbd0578c55 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -86,6 +86,7 @@ enum PROP_RTCP_FEEDBACK_RETENTION_WINDOW, PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD, PROP_PROBATION, + PROP_STATS, PROP_LAST }; @@ -442,6 +443,24 @@ rtp_session_class_init (RTPSessionClass * klass) 0, G_MAXUINT, DEFAULT_PROBATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * RTPSession::stats: + * + * Various session statistics. This property returns a GstStructure + * with name application/x-rtp-session-stats with the following fields: + * + * "rtx-drop-count" G_TYPE_UINT The number of retransmission events + * dropped (due to bandwidth constraints) + * "sent-nack-count" G_TYPE_UINT Number of NACKs sent + * "recv-nack-count" G_TYPE_UINT Number of NACKs received + * + * Since: 1.3.1 + */ + g_object_class_install_property (gobject_class, PROP_STATS, + g_param_spec_boxed ("stats", "Statistics", + "Various statistics", GST_TYPE_STRUCTURE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + klass->get_source_by_ssrc = GST_DEBUG_FUNCPTR (rtp_session_get_source_by_ssrc); klass->send_rtcp = GST_DEBUG_FUNCPTR (rtp_session_send_rtcp); @@ -563,6 +582,19 @@ rtp_session_create_sources (RTPSession * sess) return res; } +static GstStructure * +rtp_session_create_stats (RTPSession * sess) +{ + GstStructure *s; + + s = gst_structure_new ("application/x-rtp-session-stats", + "rtx-drop-count", G_TYPE_UINT, sess->stats.nacks_dropped, + "sent-nack-count", G_TYPE_UINT, sess->stats.nacks_sent, + "recv-nack-count", G_TYPE_UINT, sess->stats.nacks_received, NULL); + + return s; +} + static void rtp_session_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -684,6 +716,9 @@ rtp_session_get_property (GObject * object, guint prop_id, case PROP_PROBATION: g_value_set_uint (value, sess->probation); break; + case PROP_STATS: + g_value_take_boxed (value, rtp_session_create_stats (sess)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2260,6 +2295,8 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet, GST_BUFFER_TIMESTAMP (fci_buffer) = pinfo->running_time; } + sess->stats.nacks_received++; + RTP_SESSION_UNLOCK (sess); g_signal_emit (sess, rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP], 0, type, fbtype, sender_ssrc, media_ssrc, fci_buffer); @@ -2771,6 +2808,7 @@ typedef struct gboolean is_early; gboolean may_suppress; GQueue output; + guint nacked_seqnums; } ReportData; static void @@ -3000,6 +3038,7 @@ session_nack (const gchar * key, RTPSource * source, ReportData * data) for (i = 0; i < n_nacks; i++) { GST_WRITE_UINT32_BE (fci_data, nacks[i]); fci_data += 4; + data->nacked_seqnums++; } rtp_source_clear_nacks (source); @@ -3417,6 +3456,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, data.running_time = running_time; data.num_to_report = 0; data.may_suppress = FALSE; + data.nacked_seqnums = 0; g_queue_init (&data.output); RTP_SESSION_LOCK (sess); @@ -3492,10 +3532,12 @@ done: result = sess->callbacks.send_rtcp (sess, source, buffer, output->is_bye, sess->send_rtcp_user_data); + sess->stats.nacks_sent += data.nacked_seqnums; } else { GST_DEBUG ("freeing packet callback: %p" " do_not_suppress: %d may_suppress: %d", sess->callbacks.send_rtcp, do_not_suppress, data.may_suppress); + sess->stats.nacks_dropped += data.nacked_seqnums; gst_buffer_unref (buffer); } g_object_unref (source); diff --git a/gst/rtpmanager/rtpstats.c b/gst/rtpmanager/rtpstats.c index a73e1c6b5d..4da164cfdd 100644 --- a/gst/rtpmanager/rtpstats.c +++ b/gst/rtpmanager/rtpstats.c @@ -31,6 +31,9 @@ rtp_stats_init_defaults (RTPSessionStats * stats) rtp_stats_set_bandwidths (stats, -1, -1, -1, -1); stats->min_interval = RTP_STATS_MIN_INTERVAL; stats->bye_timeout = RTP_STATS_BYE_TIMEOUT; + stats->nacks_dropped = 0; + stats->nacks_sent = 0; + stats->nacks_received = 0; } /** diff --git a/gst/rtpmanager/rtpstats.h b/gst/rtpmanager/rtpstats.h index cb9e06c7ce..1f09ffa685 100644 --- a/gst/rtpmanager/rtpstats.h +++ b/gst/rtpmanager/rtpstats.h @@ -205,6 +205,9 @@ typedef struct { guint active_sources; guint avg_rtcp_packet_size; guint bye_members; + guint nacks_dropped; + guint nacks_sent; + guint nacks_received; } RTPSessionStats; void rtp_stats_init_defaults (RTPSessionStats *stats);