diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 034d652b7f..2049167101 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -455,6 +455,7 @@ create_session (GstRtpBin * rtpbin, gint id) (GCallback) on_bye_timeout, sess); g_signal_connect (sess->session, "on-timeout", (GCallback) on_timeout, sess); + /* FIXME, change state only to what's needed */ gst_bin_add (GST_BIN_CAST (rtpbin), session); gst_element_set_state (session, GST_STATE_PLAYING); gst_bin_add (GST_BIN_CAST (rtpbin), demux); diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index f141274fb5..610bd55c93 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -215,12 +215,35 @@ enum LAST_SIGNAL }; -#define DEFAULT_NTP_NS_BASE 0 +#define DEFAULT_NTP_NS_BASE 0 +#define DEFAULT_BANDWIDTH RTP_STATS_BANDWIDTH +#define DEFAULT_RTCP_FRACTION RTP_STATS_RTCP_BANDWIDTH +#define DEFAULT_SDES_CNAME NULL +#define DEFAULT_SDES_NAME NULL +#define DEFAULT_SDES_EMAIL NULL +#define DEFAULT_SDES_PHONE NULL +#define DEFAULT_SDES_LOCATION NULL +#define DEFAULT_SDES_TOOL NULL +#define DEFAULT_SDES_NOTE NULL +#define DEFAULT_NUM_SOURCES 0 +#define DEFAULT_NUM_ACTIVE_SOURCES 0 enum { PROP_0, - PROP_NTP_NS_BASE + PROP_NTP_NS_BASE, + PROP_BANDWIDTH, + PROP_RTCP_FRACTION, + PROP_SDES_CNAME, + PROP_SDES_NAME, + PROP_SDES_EMAIL, + PROP_SDES_PHONE, + PROP_SDES_LOCATION, + PROP_SDES_TOOL, + PROP_SDES_NOTE, + PROP_NUM_SOURCES, + PROP_NUM_ACTIVE_SOURCES, + PROP_LAST }; #define GST_RTP_SESSION_GET_PRIVATE(obj) \ @@ -378,7 +401,6 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass) gobject_class->set_property = gst_rtp_session_set_property; gobject_class->get_property = gst_rtp_session_get_property; - /** * GstRtpSession::request-pt-map: * @sess: the object which received the signal @@ -489,6 +511,61 @@ gst_rtp_session_class_init (GstRtpSessionClass * klass) "The NTP base time corresponding to running_time 0", 0, G_MAXUINT64, DEFAULT_NTP_NS_BASE, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_BANDWIDTH, + g_param_spec_double ("bandwidth", "Bandwidth", + "The bandwidth of the session", + 0.0, G_MAXDOUBLE, DEFAULT_BANDWIDTH, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_RTCP_FRACTION, + g_param_spec_double ("rtcp-fraction", "RTCP Fraction", + "The fraction of the bandwidth used for RTCP", + 0.0, G_MAXDOUBLE, DEFAULT_RTCP_FRACTION, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_CNAME, + g_param_spec_string ("sdes-cname", "SDES CNAME", + "The CNAME to put in SDES messages of this session", + DEFAULT_SDES_CNAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NAME, + g_param_spec_string ("sdes-name", "SDES NAME", + "The NAME to put in SDES messages of this session", + DEFAULT_SDES_NAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_EMAIL, + g_param_spec_string ("sdes-email", "SDES EMAIL", + "The EMAIL to put in SDES messages of this session", + DEFAULT_SDES_EMAIL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_PHONE, + g_param_spec_string ("sdes-phone", "SDES PHONE", + "The PHONE to put in SDES messages of this session", + DEFAULT_SDES_PHONE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_LOCATION, + g_param_spec_string ("sdes-location", "SDES LOCATION", + "The LOCATION to put in SDES messages of this session", + DEFAULT_SDES_LOCATION, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_TOOL, + g_param_spec_string ("sdes-tool", "SDES TOOL", + "The TOOL to put in SDES messages of this session", + DEFAULT_SDES_TOOL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NOTE, + g_param_spec_string ("sdes-note", "SDES NOTE", + "The NOTE to put in SDES messages of this session", + DEFAULT_SDES_NOTE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_NUM_SOURCES, + g_param_spec_uint ("num-sources", "Num Sources", + "The number of sources in the session", 0, G_MAXUINT, + DEFAULT_NUM_SOURCES, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_NUM_ACTIVE_SOURCES, + g_param_spec_uint ("num-active-sources", "Num Active Sources", + "The number of active sources in the session", 0, G_MAXUINT, + DEFAULT_NUM_ACTIVE_SOURCES, G_PARAM_READABLE)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_session_change_state); gstelement_class->request_new_pad = @@ -550,17 +627,53 @@ gst_rtp_session_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstRtpSession *rtpsession; + GstRtpSessionPrivate *priv; rtpsession = GST_RTP_SESSION (object); + priv = rtpsession->priv; switch (prop_id) { case PROP_NTP_NS_BASE: GST_OBJECT_LOCK (rtpsession); - rtpsession->priv->ntpnsbase = g_value_get_uint64 (value); + priv->ntpnsbase = g_value_get_uint64 (value); GST_DEBUG_OBJECT (rtpsession, "setting NTP base to %" GST_TIME_FORMAT, - GST_TIME_ARGS (rtpsession->priv->ntpnsbase)); + GST_TIME_ARGS (priv->ntpnsbase)); GST_OBJECT_UNLOCK (rtpsession); break; + case PROP_BANDWIDTH: + rtp_session_set_bandwidth (priv->session, g_value_get_double (value)); + break; + case PROP_RTCP_FRACTION: + rtp_session_set_rtcp_fraction (priv->session, g_value_get_double (value)); + break; + case PROP_SDES_CNAME: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_CNAME, + g_value_get_string (value)); + break; + case PROP_SDES_NAME: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_NAME, + g_value_get_string (value)); + break; + case PROP_SDES_EMAIL: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_EMAIL, + g_value_get_string (value)); + break; + case PROP_SDES_PHONE: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_PHONE, + g_value_get_string (value)); + break; + case PROP_SDES_LOCATION: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_LOC, + g_value_get_string (value)); + break; + case PROP_SDES_TOOL: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_TOOL, + g_value_get_string (value)); + break; + case PROP_SDES_NOTE: + rtp_session_set_sdes_string (priv->session, GST_RTCP_SDES_NOTE, + g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -572,15 +685,58 @@ gst_rtp_session_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstRtpSession *rtpsession; + GstRtpSessionPrivate *priv; rtpsession = GST_RTP_SESSION (object); + priv = rtpsession->priv; switch (prop_id) { case PROP_NTP_NS_BASE: GST_OBJECT_LOCK (rtpsession); - g_value_set_uint64 (value, rtpsession->priv->ntpnsbase); + g_value_set_uint64 (value, priv->ntpnsbase); GST_OBJECT_UNLOCK (rtpsession); break; + case PROP_BANDWIDTH: + g_value_set_double (value, rtp_session_get_bandwidth (priv->session)); + break; + case PROP_RTCP_FRACTION: + g_value_set_double (value, rtp_session_get_rtcp_fraction (priv->session)); + break; + case PROP_SDES_CNAME: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_CNAME)); + break; + case PROP_SDES_NAME: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_NAME)); + break; + case PROP_SDES_EMAIL: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_EMAIL)); + break; + case PROP_SDES_PHONE: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_PHONE)); + break; + case PROP_SDES_LOCATION: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_LOC)); + break; + case PROP_SDES_TOOL: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_TOOL)); + break; + case PROP_SDES_NOTE: + g_value_take_string (value, rtp_session_get_sdes_string (priv->session, + GST_RTCP_SDES_NOTE)); + break; + case PROP_NUM_SOURCES: + g_value_set_uint (value, rtp_session_get_num_sources (priv->session)); + break; + case PROP_NUM_ACTIVE_SOURCES: + g_value_set_uint (value, + rtp_session_get_num_active_sources (priv->session)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c index f3c2a2abc3..4a9ea8fda2 100644 --- a/gst/rtpmanager/rtpjitterbuffer.c +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -181,7 +181,7 @@ rtp_jitter_buffer_reset_skew (RTPJitterBuffer * jbuf) * We use a 2 second window or up to 512 data points, which is statistically big * enough to catch spikes (FIXME, detect spikes). * We also use a rather large weighting factor (125) to smoothly adapt. During - * startup, when filling the window) we use a parabolic weighting factor, the + * startup, when filling the window, we use a parabolic weighting factor, the * more the window is filled, the faster we move to the detected possible skew. * * Returns: @time adjusted with the clock skew. diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index 628147dfdb..1ded0dcc13 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -37,18 +37,42 @@ enum SIGNAL_ON_SSRC_COLLISION, SIGNAL_ON_SSRC_VALIDATED, SIGNAL_ON_SSRC_ACTIVE, + SIGNAL_ON_SSRC_SDES, SIGNAL_ON_BYE_SSRC, SIGNAL_ON_BYE_TIMEOUT, SIGNAL_ON_TIMEOUT, LAST_SIGNAL }; -#define RTP_DEFAULT_BANDWIDTH 64000.0 -#define RTP_DEFAULT_RTCP_BANDWIDTH 1000 +#define DEFAULT_INTERNAL_SOURCE NULL +#define DEFAULT_BANDWIDTH RTP_STATS_BANDWIDTH +#define DEFAULT_RTCP_FRACTION RTP_STATS_RTCP_BANDWIDTH +#define DEFAULT_SDES_CNAME NULL +#define DEFAULT_SDES_NAME NULL +#define DEFAULT_SDES_EMAIL NULL +#define DEFAULT_SDES_PHONE NULL +#define DEFAULT_SDES_LOCATION NULL +#define DEFAULT_SDES_TOOL NULL +#define DEFAULT_SDES_NOTE NULL +#define DEFAULT_NUM_SOURCES 0 +#define DEFAULT_NUM_ACTIVE_SOURCES 0 enum { - PROP_0 + PROP_0, + PROP_INTERNAL_SOURCE, + PROP_BANDWIDTH, + PROP_RTCP_FRACTION, + PROP_SDES_CNAME, + PROP_SDES_NAME, + PROP_SDES_EMAIL, + PROP_SDES_PHONE, + PROP_SDES_LOCATION, + PROP_SDES_TOOL, + PROP_SDES_NOTE, + PROP_NUM_SOURCES, + PROP_NUM_ACTIVE_SOURCES, + PROP_LAST }; /* update average packet size, we keep this scaled by 16 to keep enough @@ -121,7 +145,7 @@ rtp_session_class_init (RTPSessionClass * klass) NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); /** - * RTPSession::on-ssrc_active: + * RTPSession::on-ssrc-active: * @session: the object which received the signal * @src: the active RTPSource * @@ -132,6 +156,18 @@ rtp_session_class_init (RTPSessionClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (RTPSessionClass, on_ssrc_active), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + /** + * RTPSession::on-ssrc-sdes: + * @session: the object which received the signal + * @src: the RTPSource + * + * Notify that a new SDES was received for SSRC. + */ + rtp_session_signals[SIGNAL_ON_SSRC_SDES] = + g_signal_new ("on-ssrc-sdes", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (RTPSessionClass, on_ssrc_sdes), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + G_TYPE_OBJECT); /** * RTPSession::on-bye-ssrc: * @session: the object which received the signal @@ -169,6 +205,66 @@ rtp_session_class_init (RTPSessionClass * klass) NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + g_object_class_install_property (gobject_class, PROP_INTERNAL_SOURCE, + g_param_spec_object ("internal-source", "Internal Source", + "The internal source element of the session", + RTP_TYPE_SOURCE, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_BANDWIDTH, + g_param_spec_double ("bandwidth", "Bandwidth", + "The bandwidth of the session", + 0.0, G_MAXDOUBLE, DEFAULT_BANDWIDTH, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_RTCP_FRACTION, + g_param_spec_double ("rtcp-fraction", "RTCP Fraction", + "The fraction of the bandwidth used for RTCP", + 0.0, G_MAXDOUBLE, DEFAULT_RTCP_FRACTION, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_CNAME, + g_param_spec_string ("sdes-cname", "SDES CNAME", + "The CNAME to put in SDES messages of this session", + DEFAULT_SDES_CNAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NAME, + g_param_spec_string ("sdes-name", "SDES NAME", + "The NAME to put in SDES messages of this session", + DEFAULT_SDES_NAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_EMAIL, + g_param_spec_string ("sdes-email", "SDES EMAIL", + "The EMAIL to put in SDES messages of this session", + DEFAULT_SDES_EMAIL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_PHONE, + g_param_spec_string ("sdes-phone", "SDES PHONE", + "The PHONE to put in SDES messages of this session", + DEFAULT_SDES_PHONE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_LOCATION, + g_param_spec_string ("sdes-location", "SDES LOCATION", + "The LOCATION to put in SDES messages of this session", + DEFAULT_SDES_LOCATION, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_TOOL, + g_param_spec_string ("sdes-tool", "SDES TOOL", + "The TOOL to put in SDES messages of this session", + DEFAULT_SDES_TOOL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NOTE, + g_param_spec_string ("sdes-note", "SDES NOTE", + "The NOTE to put in SDES messages of this session", + DEFAULT_SDES_NOTE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_NUM_SOURCES, + g_param_spec_uint ("num-sources", "Num Sources", + "The number of sources in the session", 0, G_MAXUINT, + DEFAULT_NUM_SOURCES, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_NUM_ACTIVE_SOURCES, + g_param_spec_uint ("num-active-sources", "Num Active Sources", + "The number of active sources in the session", 0, G_MAXUINT, + DEFAULT_NUM_ACTIVE_SOURCES, G_PARAM_READABLE)); + GST_DEBUG_CATEGORY_INIT (rtp_session_debug, "rtpsession", 0, "RTP Session"); } @@ -176,6 +272,7 @@ static void rtp_session_init (RTPSession * sess) { gint i; + gchar *str; sess->lock = g_mutex_new (); sess->key = g_random_int (); @@ -201,10 +298,13 @@ rtp_session_init (RTPSession * sess) sess->mtu = 1400; /* some default SDES entries */ - sess->cname = - g_strdup_printf ("%s@%s", g_get_user_name (), g_get_host_name ()); - sess->name = g_strdup (g_get_real_name ()); - sess->tool = g_strdup ("GStreamer"); + str = g_strdup_printf ("%s@%s", g_get_user_name (), g_get_host_name ()); + rtp_source_set_sdes_string (sess->source, GST_RTCP_SDES_CNAME, str); + g_free (str); + + rtp_source_set_sdes_string (sess->source, GST_RTCP_SDES_NAME, + g_get_real_name ()); + rtp_source_set_sdes_string (sess->source, GST_RTCP_SDES_TOOL, "GStreamer"); sess->first_rtcp = TRUE; @@ -226,15 +326,6 @@ rtp_session_finalize (GObject * object) g_hash_table_destroy (sess->cnames); g_object_unref (sess->source); - g_free (sess->cname); - g_free (sess->name); - g_free (sess->email); - g_free (sess->phone); - g_free (sess->location); - g_free (sess->tool); - g_free (sess->note); - g_free (sess->bye_reason); - G_OBJECT_CLASS (rtp_session_parent_class)->finalize (object); } @@ -247,6 +338,40 @@ rtp_session_set_property (GObject * object, guint prop_id, sess = RTP_SESSION (object); switch (prop_id) { + case PROP_BANDWIDTH: + rtp_session_set_bandwidth (sess, g_value_get_double (value)); + break; + case PROP_RTCP_FRACTION: + rtp_session_set_rtcp_fraction (sess, g_value_get_double (value)); + break; + case PROP_SDES_CNAME: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_CNAME, + g_value_get_string (value)); + break; + case PROP_SDES_NAME: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_NAME, + g_value_get_string (value)); + break; + case PROP_SDES_EMAIL: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_EMAIL, + g_value_get_string (value)); + break; + case PROP_SDES_PHONE: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_PHONE, + g_value_get_string (value)); + break; + case PROP_SDES_LOCATION: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_LOC, + g_value_get_string (value)); + break; + case PROP_SDES_TOOL: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_TOOL, + g_value_get_string (value)); + break; + case PROP_SDES_NOTE: + rtp_session_set_sdes_string (sess, GST_RTCP_SDES_NOTE, + g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -262,6 +387,49 @@ rtp_session_get_property (GObject * object, guint prop_id, sess = RTP_SESSION (object); switch (prop_id) { + case PROP_INTERNAL_SOURCE: + g_value_take_object (value, rtp_session_get_internal_source (sess)); + break; + case PROP_BANDWIDTH: + g_value_set_double (value, rtp_session_get_bandwidth (sess)); + break; + case PROP_RTCP_FRACTION: + g_value_set_double (value, rtp_session_get_rtcp_fraction (sess)); + break; + case PROP_SDES_CNAME: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_CNAME)); + break; + case PROP_SDES_NAME: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_NAME)); + break; + case PROP_SDES_EMAIL: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_EMAIL)); + break; + case PROP_SDES_PHONE: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_PHONE)); + break; + case PROP_SDES_LOCATION: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_LOC)); + break; + case PROP_SDES_TOOL: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_TOOL)); + break; + case PROP_SDES_NOTE: + g_value_take_string (value, rtp_session_get_sdes_string (sess, + GST_RTCP_SDES_NOTE)); + break; + case PROP_NUM_SOURCES: + g_value_set_uint (value, rtp_session_get_num_sources (sess)); + break; + case PROP_NUM_ACTIVE_SOURCES: + g_value_set_uint (value, rtp_session_get_num_active_sources (sess)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -302,6 +470,14 @@ on_ssrc_active (RTPSession * sess, RTPSource * source) RTP_SESSION_LOCK (sess); } +static void +on_ssrc_sdes (RTPSession * sess, RTPSource * source) +{ + RTP_SESSION_UNLOCK (sess); + g_signal_emit (sess, rtp_session_signals[SIGNAL_ON_SSRC_SDES], 0, source); + RTP_SESSION_LOCK (sess); +} + static void on_bye_ssrc (RTPSession * sess, RTPSource * source) { @@ -378,7 +554,9 @@ rtp_session_set_bandwidth (RTPSession * sess, gdouble bandwidth) { g_return_if_fail (RTP_IS_SESSION (sess)); + RTP_SESSION_LOCK (sess); sess->stats.bandwidth = bandwidth; + RTP_SESSION_UNLOCK (sess); } /** @@ -392,13 +570,19 @@ rtp_session_set_bandwidth (RTPSession * sess, gdouble bandwidth) gdouble rtp_session_get_bandwidth (RTPSession * sess) { + gdouble result; + g_return_val_if_fail (RTP_IS_SESSION (sess), 0); - return sess->stats.bandwidth; + RTP_SESSION_LOCK (sess); + result = sess->stats.bandwidth; + RTP_SESSION_UNLOCK (sess); + + return result; } /** - * rtp_session_set_rtcp_bandwidth: + * rtp_session_set_rtcp_fraction: * @sess: an #RTPSession * @bandwidth: the RTCP bandwidth * @@ -406,15 +590,17 @@ rtp_session_get_bandwidth (RTPSession * sess) * messages. */ void -rtp_session_set_rtcp_bandwidth (RTPSession * sess, gdouble bandwidth) +rtp_session_set_rtcp_fraction (RTPSession * sess, gdouble bandwidth) { g_return_if_fail (RTP_IS_SESSION (sess)); + RTP_SESSION_LOCK (sess); sess->stats.rtcp_bandwidth = bandwidth; + RTP_SESSION_UNLOCK (sess); } /** - * rtp_session_get_rtcp_bandwidth: + * rtp_session_get_rtcp_fraction: * @sess: an #RTPSession * * Get the session bandwidth used for RTCP. @@ -422,235 +608,66 @@ rtp_session_set_rtcp_bandwidth (RTPSession * sess, gdouble bandwidth) * Returns: The bandwidth used for RTCP messages. */ gdouble -rtp_session_get_rtcp_bandwidth (RTPSession * sess) +rtp_session_get_rtcp_fraction (RTPSession * sess) { + gdouble result; + g_return_val_if_fail (RTP_IS_SESSION (sess), 0.0); - return sess->stats.rtcp_bandwidth; + RTP_SESSION_LOCK (sess); + result = sess->stats.rtcp_bandwidth; + RTP_SESSION_UNLOCK (sess); + + return result; } /** - * rtp_session_set_cname: + * rtp_session_set_sdes_string: * @sess: an #RTPSession - * @cname: a CNAME for the session + * @type: the type of the SDES item + * @item: a null-terminated string to set. * - * Set the CNAME for the session. + * Store an SDES item of @type in @sess. + * + * Returns: %FALSE if the data was unchanged @type is invalid. */ -void -rtp_session_set_cname (RTPSession * sess, const gchar * cname) +gboolean +rtp_session_set_sdes_string (RTPSession * sess, GstRTCPSDESType type, + const gchar * item) { - g_return_if_fail (RTP_IS_SESSION (sess)); + gboolean result; - g_free (sess->cname); - sess->cname = g_strdup (cname); + g_return_val_if_fail (RTP_IS_SESSION (sess), FALSE); + + RTP_SESSION_LOCK (sess); + result = rtp_source_set_sdes_string (sess->source, type, item); + RTP_SESSION_UNLOCK (sess); + + return result; } /** - * rtp_session_get_cname: + * rtp_session_get_sdes_string: * @sess: an #RTPSession + * @type: the type of the SDES item * - * Get the currently configured CNAME for the session. + * Get the SDES item of @type from @sess. * - * Returns: The CNAME. g_free after usage. + * Returns: a null-terminated copy of the SDES item or NULL when @type was not + * valid. g_free() after usage. */ gchar * -rtp_session_get_cname (RTPSession * sess) +rtp_session_get_sdes_string (RTPSession * sess, GstRTCPSDESType type) { + gchar *result; + g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - return g_strdup (sess->cname); -} + RTP_SESSION_LOCK (sess); + result = rtp_source_get_sdes_string (sess->source, type); + RTP_SESSION_UNLOCK (sess); -/** - * rtp_session_set_name: - * @sess: an #RTPSession - * @name: a NAME for the session - * - * Set the NAME for the session. - */ -void -rtp_session_set_name (RTPSession * sess, const gchar * name) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->name); - sess->name = g_strdup (name); -} - -/** - * rtp_session_get_name: - * @sess: an #RTPSession - * - * Get the currently configured NAME for the session. - * - * Returns: The NAME. g_free after usage. - */ -gchar * -rtp_session_get_name (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->name); -} - -/** - * rtp_session_set_email: - * @sess: an #RTPSession - * @email: an EMAIL for the session - * - * Set the EMAIL the session. - */ -void -rtp_session_set_email (RTPSession * sess, const gchar * email) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->email); - sess->email = g_strdup (email); -} - -/** - * rtp_session_get_email: - * @sess: an #RTPSession - * - * Get the currently configured EMAIL of the session. - * - * Returns: The EMAIL. g_free after usage. - */ -gchar * -rtp_session_get_email (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->email); -} - -/** - * rtp_session_set_phone: - * @sess: an #RTPSession - * @phone: a PHONE for the session - * - * Set the PHONE the session. - */ -void -rtp_session_set_phone (RTPSession * sess, const gchar * phone) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->phone); - sess->phone = g_strdup (phone); -} - -/** - * rtp_session_get_location: - * @sess: an #RTPSession - * - * Get the currently configured PHONE of the session. - * - * Returns: The PHONE. g_free after usage. - */ -gchar * -rtp_session_get_phone (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->phone); -} - -/** - * rtp_session_set_location: - * @sess: an #RTPSession - * @location: a LOCATION for the session - * - * Set the LOCATION the session. - */ -void -rtp_session_set_location (RTPSession * sess, const gchar * location) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->location); - sess->location = g_strdup (location); -} - -/** - * rtp_session_get_location: - * @sess: an #RTPSession - * - * Get the currently configured LOCATION of the session. - * - * Returns: The LOCATION. g_free after usage. - */ -gchar * -rtp_session_get_location (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->location); -} - -/** - * rtp_session_set_tool: - * @sess: an #RTPSession - * @tool: a TOOL for the session - * - * Set the TOOL the session. - */ -void -rtp_session_set_tool (RTPSession * sess, const gchar * tool) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->tool); - sess->tool = g_strdup (tool); -} - -/** - * rtp_session_get_tool: - * @sess: an #RTPSession - * - * Get the currently configured TOOL of the session. - * - * Returns: The TOOL. g_free after usage. - */ -gchar * -rtp_session_get_tool (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->tool); -} - -/** - * rtp_session_set_note: - * @sess: an #RTPSession - * @note: a NOTE for the session - * - * Set the NOTE the session. - */ -void -rtp_session_set_note (RTPSession * sess, const gchar * note) -{ - g_return_if_fail (RTP_IS_SESSION (sess)); - - g_free (sess->note); - sess->note = g_strdup (note); -} - -/** - * rtp_session_get_note: - * @sess: an #RTPSession - * - * Get the currently configured NOTE of the session. - * - * Returns: The NOTE. g_free after usage. - */ -gchar * -rtp_session_get_note (RTPSession * sess) -{ - g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); - - return g_strdup (sess->note); + return result; } static GstFlowReturn @@ -714,6 +731,7 @@ check_collision (RTPSession * sess, RTPSource * source, return FALSE; } +/* must be called with the session lock */ static RTPSource * obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created, RTPArrivalStats * arrival, gboolean rtp) @@ -726,6 +744,9 @@ obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created, /* make new Source in probation and insert */ source = rtp_source_new (ssrc); + /* for RTP packets we need to set the source in probation. Receiving RTCP + * packets of an SSRC, on the other hand, is a strong indication that we + * are dealing with a valid source. */ if (rtp) source->probation = RTP_DEFAULT_PROBATION; else @@ -762,6 +783,26 @@ obtain_source (RTPSession * sess, guint32 ssrc, gboolean * created, return source; } +/** + * rtp_session_get_internal_source: + * @sess: a #RTPSession + * + * Get the internal #RTPSource of @session. + * + * Returns: The internal #RTPSource. g_object_unref() after usage. + */ +RTPSource * +rtp_session_get_internal_source (RTPSession * sess) +{ + RTPSource *result; + + g_return_val_if_fail (RTP_IS_SESSION (sess), NULL); + + result = g_object_ref (sess->source); + + return result; +} + /** * rtp_session_add_source: * @sess: a #RTPSession @@ -1194,11 +1235,17 @@ rtp_session_process_sdes (RTPSession * sess, GstRTCPPacket * packet, i = 0; while (more_items) { guint32 ssrc; + gboolean changed, created; + RTPSource *source; ssrc = gst_rtcp_packet_sdes_get_ssrc (packet); GST_DEBUG ("item %d, SSRC %08x", i, ssrc); + /* find src, no probation when dealing with RTCP */ + source = obtain_source (sess, ssrc, &created, arrival, FALSE); + changed = FALSE; + more_entries = gst_rtcp_packet_sdes_first_entry (packet); j = 0; while (more_entries) { @@ -1211,9 +1258,17 @@ rtp_session_process_sdes (RTPSession * sess, GstRTCPPacket * packet, GST_DEBUG ("entry %d, type %d, len %d, data %.*s", j, type, len, len, data); + + more_entries = gst_rtcp_packet_sdes_next_entry (packet); j++; } + + if (created) + on_new_ssrc (sess, source); + if (changed) + on_ssrc_sdes (sess, source); + more_items = gst_rtcp_packet_sdes_next_item (packet); i++; } @@ -1418,7 +1473,7 @@ ignore: * rtp_session_send_rtp: * @sess: an #RTPSession * @buffer: an RTP buffer - * @ntptime: the NTP time of when this buffer was captured. + * @ntpnstime: the NTP time in nanoseconds of when this buffer was captured. * * Send the RTP buffer in the session manager. This function takes ownership of * @buffer. @@ -1426,7 +1481,7 @@ ignore: * Returns: a #GstFlowReturn. */ GstFlowReturn -rtp_session_send_rtp (RTPSession * sess, GstBuffer * buffer, guint64 ntptime) +rtp_session_send_rtp (RTPSession * sess, GstBuffer * buffer, guint64 ntpnstime) { GstFlowReturn result; RTPSource *source; @@ -1451,7 +1506,7 @@ rtp_session_send_rtp (RTPSession * sess, GstBuffer * buffer, guint64 ntptime) prevsender = RTP_SOURCE_IS_SENDER (source); /* we use our own source to send */ - result = rtp_source_send_rtp (source, buffer, ntptime); + result = rtp_source_send_rtp (source, buffer, ntpnstime); if (RTP_SOURCE_IS_SENDER (source) && !prevsender) sess->stats.sender_sources++; @@ -1755,13 +1810,18 @@ static void session_sdes (RTPSession * sess, ReportData * data) { GstRTCPPacket *packet = &data->packet; + guint8 *sdes_data; + guint sdes_len; /* add SDES packet */ gst_rtcp_buffer_add_packet (data->rtcp, GST_RTCP_TYPE_SDES, packet); gst_rtcp_packet_sdes_add_item (packet, sess->source->ssrc); - gst_rtcp_packet_sdes_add_entry (packet, GST_RTCP_SDES_CNAME, - strlen (sess->cname), (guint8 *) sess->cname); + + rtp_source_get_sdes (sess->source, GST_RTCP_SDES_CNAME, &sdes_data, + &sdes_len); + gst_rtcp_packet_sdes_add_entry (packet, GST_RTCP_SDES_CNAME, sdes_len, + sdes_data); /* other SDES items must only be added at regular intervals and only when the * user requests to since it might be a privacy problem */ diff --git a/gst/rtpmanager/rtpsession.h b/gst/rtpmanager/rtpsession.h index 359a74175f..0c99d53f64 100644 --- a/gst/rtpmanager/rtpsession.h +++ b/gst/rtpmanager/rtpsession.h @@ -162,15 +162,6 @@ struct _RTPSession { RTPSource *source; - /* info for creating reports */ - gchar *cname; - gchar *name; - gchar *email; - gchar *phone; - gchar *location; - gchar *tool; - gchar *note; - /* for sender/receiver counting */ guint32 key; guint32 mask_idx; @@ -210,6 +201,7 @@ struct _RTPSessionClass { void (*on_ssrc_collision) (RTPSession *sess, RTPSource *source); void (*on_ssrc_validated) (RTPSession *sess, RTPSource *source); void (*on_ssrc_active) (RTPSession *sess, RTPSource *source); + void (*on_ssrc_sdes) (RTPSession *sess, RTPSource *source); void (*on_bye_ssrc) (RTPSession *sess, RTPSource *source); void (*on_bye_timeout) (RTPSession *sess, RTPSource *source); void (*on_timeout) (RTPSession *sess, RTPSource *source); @@ -227,22 +219,12 @@ gdouble rtp_session_get_bandwidth (RTPSession *sess); void rtp_session_set_rtcp_fraction (RTPSession *sess, gdouble fraction); gdouble rtp_session_get_rtcp_fraction (RTPSession *sess); -void rtp_session_set_cname (RTPSession *sess, const gchar *cname); -gchar* rtp_session_get_cname (RTPSession *sess); -void rtp_session_set_name (RTPSession *sess, const gchar *name); -gchar* rtp_session_get_name (RTPSession *sess); -void rtp_session_set_email (RTPSession *sess, const gchar *email); -gchar* rtp_session_get_email (RTPSession *sess); -void rtp_session_set_phone (RTPSession *sess, const gchar *phone); -gchar* rtp_session_get_phone (RTPSession *sess); -void rtp_session_set_location (RTPSession *sess, const gchar *location); -gchar* rtp_session_get_location (RTPSession *sess); -void rtp_session_set_tool (RTPSession *sess, const gchar *tool); -gchar* rtp_session_get_tool (RTPSession *sess); -void rtp_session_set_note (RTPSession *sess, const gchar *note); -gchar* rtp_session_get_note (RTPSession *sess); +gboolean rtp_session_set_sdes_string (RTPSession *sess, GstRTCPSDESType type, + const gchar *cname); +gchar* rtp_session_get_sdes_string (RTPSession *sess, GstRTCPSDESType type); /* handling sources */ +RTPSource* rtp_session_get_internal_source (RTPSession *sess); gboolean rtp_session_add_source (RTPSession *sess, RTPSource *src); guint rtp_session_get_num_sources (RTPSession *sess); guint rtp_session_get_num_active_sources (RTPSession *sess); @@ -255,13 +237,13 @@ GstFlowReturn rtp_session_process_rtp (RTPSession *sess, GstBuffer GstFlowReturn rtp_session_process_rtcp (RTPSession *sess, GstBuffer *buffer); /* processing packets for sending */ -GstFlowReturn rtp_session_send_rtp (RTPSession *sess, GstBuffer *buffer, guint64 ntptime); +GstFlowReturn rtp_session_send_rtp (RTPSession *sess, GstBuffer *buffer, guint64 ntpnstime); /* stopping the session */ GstFlowReturn rtp_session_send_bye (RTPSession *sess, const gchar *reason); /* get interval for next RTCP interval */ -GstClockTime rtp_session_next_timeout (RTPSession *sess, GstClockTime time); -GstFlowReturn rtp_session_on_timeout (RTPSession *sess, GstClockTime time, guint64 ntpnstime); +GstClockTime rtp_session_next_timeout (RTPSession *sess, GstClockTime time); +GstFlowReturn rtp_session_on_timeout (RTPSession *sess, GstClockTime time, guint64 ntpnstime); #endif /* __RTP_SESSION_H__ */ diff --git a/gst/rtpmanager/rtpsource.c b/gst/rtpmanager/rtpsource.c index 1d7eb24a06..8374036f04 100644 --- a/gst/rtpmanager/rtpsource.c +++ b/gst/rtpmanager/rtpsource.c @@ -34,13 +34,41 @@ enum LAST_SIGNAL }; +#define DEFAULT_SSRC 0 +#define DEFAULT_IS_CSRC FALSE +#define DEFAULT_IS_VALIDATED FALSE +#define DEFAULT_IS_SENDER FALSE +#define DEFAULT_SDES_CNAME NULL +#define DEFAULT_SDES_NAME NULL +#define DEFAULT_SDES_EMAIL NULL +#define DEFAULT_SDES_PHONE NULL +#define DEFAULT_SDES_LOCATION NULL +#define DEFAULT_SDES_TOOL NULL +#define DEFAULT_SDES_NOTE NULL + enum { - PROP_0 + PROP_0, + PROP_SSRC, + PROP_IS_CSRC, + PROP_IS_VALIDATED, + PROP_IS_SENDER, + PROP_SDES_CNAME, + PROP_SDES_NAME, + PROP_SDES_EMAIL, + PROP_SDES_PHONE, + PROP_SDES_LOCATION, + PROP_SDES_TOOL, + PROP_SDES_NOTE, + PROP_LAST }; /* GObject vmethods */ static void rtp_source_finalize (GObject * object); +static void rtp_source_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void rtp_source_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); /* static guint rtp_source_signals[LAST_SIGNAL] = { 0 }; */ @@ -55,6 +83,62 @@ rtp_source_class_init (RTPSourceClass * klass) gobject_class->finalize = rtp_source_finalize; + gobject_class->set_property = rtp_source_set_property; + gobject_class->get_property = rtp_source_get_property; + + g_object_class_install_property (gobject_class, PROP_SSRC, + g_param_spec_uint ("ssrc", "SSRC", + "The SSRC of this source", 0, G_MAXUINT, + DEFAULT_SSRC, G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, PROP_IS_CSRC, + g_param_spec_boolean ("is-csrc", "Is CSRC", + "If this SSRC is acting as a contributing source", + DEFAULT_IS_CSRC, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_IS_VALIDATED, + g_param_spec_boolean ("is-validated", "Is Validated", + "If this SSRC is validated", DEFAULT_IS_VALIDATED, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_IS_SENDER, + g_param_spec_boolean ("is-sender", "Is Sender", + "If this SSRC is a sender", DEFAULT_IS_SENDER, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_SDES_CNAME, + g_param_spec_string ("sdes-cname", "SDES CNAME", + "The CNAME to put in SDES messages of this source", + DEFAULT_SDES_CNAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NAME, + g_param_spec_string ("sdes-name", "SDES NAME", + "The NAME to put in SDES messages of this source", + DEFAULT_SDES_NAME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_EMAIL, + g_param_spec_string ("sdes-email", "SDES EMAIL", + "The EMAIL to put in SDES messages of this source", + DEFAULT_SDES_EMAIL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_PHONE, + g_param_spec_string ("sdes-phone", "SDES PHONE", + "The PHONE to put in SDES messages of this source", + DEFAULT_SDES_PHONE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_LOCATION, + g_param_spec_string ("sdes-location", "SDES LOCATION", + "The LOCATION to put in SDES messages of this source", + DEFAULT_SDES_LOCATION, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_TOOL, + g_param_spec_string ("sdes-tool", "SDES TOOL", + "The TOOL to put in SDES messages of this source", + DEFAULT_SDES_TOOL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SDES_NOTE, + g_param_spec_string ("sdes-note", "SDES NOTE", + "The NOTE to put in SDES messages of this source", + DEFAULT_SDES_NOTE, G_PARAM_READWRITE)); + GST_DEBUG_CATEGORY_INIT (rtp_source_debug, "rtpsource", 0, "RTP Source"); } @@ -92,9 +176,109 @@ rtp_source_finalize (GObject * object) gst_buffer_unref (buffer); g_queue_free (src->packets); + g_free (src->bye_reason); + G_OBJECT_CLASS (rtp_source_parent_class)->finalize (object); } +static void +rtp_source_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + RTPSource *src; + + src = RTP_SOURCE (object); + + switch (prop_id) { + case PROP_SDES_CNAME: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_CNAME, + g_value_get_string (value)); + break; + case PROP_SDES_NAME: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_NAME, + g_value_get_string (value)); + break; + case PROP_SDES_EMAIL: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_EMAIL, + g_value_get_string (value)); + break; + case PROP_SDES_PHONE: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_PHONE, + g_value_get_string (value)); + break; + case PROP_SDES_LOCATION: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_LOC, + g_value_get_string (value)); + break; + case PROP_SDES_TOOL: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_TOOL, + g_value_get_string (value)); + break; + case PROP_SDES_NOTE: + rtp_source_set_sdes_string (src, GST_RTCP_SDES_NOTE, + g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +rtp_source_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + RTPSource *src; + + src = RTP_SOURCE (object); + + switch (prop_id) { + case PROP_SSRC: + g_value_set_uint (value, rtp_source_get_ssrc (src)); + break; + case PROP_IS_CSRC: + g_value_set_boolean (value, rtp_source_is_as_csrc (src)); + break; + case PROP_IS_VALIDATED: + g_value_set_boolean (value, rtp_source_is_validated (src)); + break; + case PROP_IS_SENDER: + g_value_set_boolean (value, rtp_source_is_sender (src)); + break; + case PROP_SDES_CNAME: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_CNAME)); + break; + case PROP_SDES_NAME: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_NAME)); + break; + case PROP_SDES_EMAIL: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_EMAIL)); + break; + case PROP_SDES_PHONE: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_PHONE)); + break; + case PROP_SDES_LOCATION: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_LOC)); + break; + case PROP_SDES_TOOL: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_TOOL)); + break; + case PROP_SDES_NOTE: + g_value_take_string (value, rtp_source_get_sdes_string (src, + GST_RTCP_SDES_NOTE)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + /** * rtp_source_new: * @ssrc: an SSRC @@ -114,6 +298,184 @@ rtp_source_new (guint32 ssrc) return src; } +/** + * rtp_source_set_callbacks: + * @src: an #RTPSource + * @cb: callback functions + * @user_data: user data + * + * Set the callbacks for the source. + */ +void +rtp_source_set_callbacks (RTPSource * src, RTPSourceCallbacks * cb, + gpointer user_data) +{ + g_return_if_fail (RTP_IS_SOURCE (src)); + + src->callbacks.push_rtp = cb->push_rtp; + src->callbacks.clock_rate = cb->clock_rate; + src->user_data = user_data; +} + +/** + * rtp_source_get_ssrc: + * @src: an #RTPSource + * + * Get the SSRC of @source. + * + * Returns: the SSRC of src. + */ +guint32 +rtp_source_get_ssrc (RTPSource * src) +{ + guint32 result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), 0); + + result = src->ssrc; + + return result; +} + +/** + * rtp_source_set_as_csrc: + * @src: an #RTPSource + * + * Configure @src as a CSRC, this will also validate @src. + */ +void +rtp_source_set_as_csrc (RTPSource * src) +{ + g_return_if_fail (RTP_IS_SOURCE (src)); + + src->validated = TRUE; + src->is_csrc = TRUE; +} + +/** + * rtp_source_is_as_csrc: + * @src: an #RTPSource + * + * Check if @src is a contributing source. + * + * Returns: %TRUE if @src is acting as a contributing source. + */ +gboolean +rtp_source_is_as_csrc (RTPSource * src) +{ + gboolean result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + result = src->is_csrc; + + return result; +} + +/** + * rtp_source_is_active: + * @src: an #RTPSource + * + * Check if @src is an active source. A source is active if it has been + * validated and has not yet received a BYE packet + * + * Returns: %TRUE if @src is an qactive source. + */ +gboolean +rtp_source_is_active (RTPSource * src) +{ + gboolean result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + result = RTP_SOURCE_IS_ACTIVE (src); + + return result; +} + +/** + * rtp_source_is_validated: + * @src: an #RTPSource + * + * Check if @src is a validated source. + * + * Returns: %TRUE if @src is a validated source. + */ +gboolean +rtp_source_is_validated (RTPSource * src) +{ + gboolean result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + result = src->validated; + + return result; +} + +/** + * rtp_source_is_sender: + * @src: an #RTPSource + * + * Check if @src is a sending source. + * + * Returns: %TRUE if @src is a sending source. + */ +gboolean +rtp_source_is_sender (RTPSource * src) +{ + gboolean result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + result = RTP_SOURCE_IS_SENDER (src); + + return result; +} + +/** + * rtp_source_received_bye: + * @src: an #RTPSource + * + * Check if @src has receoved a BYE packet. + * + * Returns: %TRUE if @src has received a BYE packet. + */ +gboolean +rtp_source_received_bye (RTPSource * src) +{ + gboolean result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + result = src->received_bye; + + return result; +} + + +/** + * rtp_source_get_bye_reason: + * @src: an #RTPSource + * + * Get the BYE reason for @src. Check if the source receoved a BYE message first + * with rtp_source_received_bye(). + * + * Returns: The BYE reason or NULL when no reason was given or the source did + * not receive a BYE message yet. g_fee() after usage. + */ +gchar * +rtp_source_get_bye_reason (RTPSource * src) +{ + gchar *result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), NULL); + + result = g_strdup (src->bye_reason); + + return result; +} + /** * rtp_source_update_caps: * @src: an #RTPSource @@ -153,37 +515,130 @@ rtp_source_update_caps (RTPSource * src, GstCaps * caps) } /** - * rtp_source_set_callbacks: + * rtp_source_set_sdes: * @src: an #RTPSource - * @cb: callback functions - * @user_data: user data + * @type: the type of the SDES item + * @data: the SDES data + * @len: the SDES length * - * Set the callbacks for the source. + * Store an SDES item of @type in @src. + * + * Returns: %FALSE if the SDES item was unchanged or @type is unknown. */ -void -rtp_source_set_callbacks (RTPSource * src, RTPSourceCallbacks * cb, - gpointer user_data) +gboolean +rtp_source_set_sdes (RTPSource * src, GstRTCPSDESType type, + const guint8 * data, guint len) { - g_return_if_fail (RTP_IS_SOURCE (src)); + guint8 *old; - src->callbacks.push_rtp = cb->push_rtp; - src->callbacks.clock_rate = cb->clock_rate; - src->user_data = user_data; + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + if (type < 0 || type > GST_RTCP_SDES_PRIV) + return FALSE; + + old = src->sdes[type]; + + /* lengths are the same, check if the data is the same */ + if ((src->sdes_len[type] == len)) + if (data != NULL && old != NULL && (memcmp (old, data, len) == 0)) + return FALSE; + + /* NULL data, make sure we store 0 length or if no length is given, + * take strlen */ + if (data == NULL) + len = 0; + + g_free (src->sdes[type]); + src->sdes[type] = g_memdup (data, len); + src->sdes_len[type] = len; + + return TRUE; } /** - * rtp_source_set_as_csrc: + * rtp_source_set_sdes_string: * @src: an #RTPSource + * @type: the type of the SDES item + * @data: the SDES data * - * Configure @src as a CSRC, this will validate the RTpSource. + * Store an SDES item of @type in @src. This function is similar to + * rtp_source_set_sdes() but takes a null-terminated string for convenience. + * + * Returns: %FALSE if the SDES item was unchanged or @type is unknown. */ -void -rtp_source_set_as_csrc (RTPSource * src) +gboolean +rtp_source_set_sdes_string (RTPSource * src, GstRTCPSDESType type, + const gchar * data) { - g_return_if_fail (RTP_IS_SOURCE (src)); + guint len; + gboolean result; - src->validated = TRUE; - src->is_csrc = TRUE; + if (data) + len = strlen (data); + else + len = 0; + + result = rtp_source_set_sdes (src, type, (guint8 *) data, len); + + return result; +} + +/** + * rtp_source_get_sdes: + * @src: an #RTPSource + * @type: the type of the SDES item + * @data: location to store the SDES data or NULL + * @len: location to store the SDES length or NULL + * + * Get the SDES item of @type from @src. Note that @data does not always point + * to a null-terminated string, use rtp_source_get_sdes_string() to retrieve a + * null-terminated string instead. + * + * @data remains valid until the next call to rtp_source_set_sdes(). + * + * Returns: %TRUE if @type was valid and @data and @len contain valid + * data. + */ +gboolean +rtp_source_get_sdes (RTPSource * src, GstRTCPSDESType type, guint8 ** data, + guint * len) +{ + g_return_val_if_fail (RTP_IS_SOURCE (src), FALSE); + + if (type < 0 || type > GST_RTCP_SDES_PRIV) + return FALSE; + + if (data) + *data = src->sdes[type]; + if (len) + *len = src->sdes_len[type]; + + return TRUE; +} + +/** + * rtp_source_get_sdes_string: + * @src: an #RTPSource + * @type: the type of the SDES item + * + * Get the SDES item of @type from @src. + * + * Returns: a null-terminated copy of the SDES item or NULL when @type was not + * valid. g_free() after usage. + */ +gchar * +rtp_source_get_sdes_string (RTPSource * src, GstRTCPSDESType type) +{ + gchar *result; + + g_return_val_if_fail (RTP_IS_SOURCE (src), NULL); + + if (type < 0 || type > GST_RTCP_SDES_PRIV) + return NULL; + + result = g_strndup ((const gchar *) src->sdes[type], src->sdes_len[type]); + + return result; } /** @@ -588,7 +1043,7 @@ rtp_source_send_rtp (RTPSource * src, GstBuffer * buffer, guint64 ntpnstime) * rtp_source_process_sr: * @src: an #RTPSource * @time: time of packet arrival - * @ntptime: the NTP time + * @ntptime: the NTP time in 32.32 fixed point * @rtptime: the RTP time * @packet_count: the packet count * @octet_count: the octect count @@ -684,9 +1139,9 @@ rtp_source_process_rb (RTPSource * src, GstClockTime time, guint8 fractionlost, /** * rtp_source_get_new_sr: * @src: an #RTPSource - * @time: the current time in nanoseconds since 1970 - * @ntptime: the NTP time - * @rtptime: the RTP time + * @ntpnstime: the current time in nanoseconds since 1970 + * @ntptime: the NTP time in 32.32 fixed point + * @rtptime: the RTP time corresponding to @ntptime * @packet_count: the packet count * @octet_count: the octect count * @@ -695,7 +1150,7 @@ rtp_source_process_rb (RTPSource * src, GstClockTime time, guint8 fractionlost, * Returns: %TRUE on success. */ gboolean -rtp_source_get_new_sr (RTPSource * src, GstClockTime ntpnstime, +rtp_source_get_new_sr (RTPSource * src, guint64 ntpnstime, guint64 * ntptime, guint32 * rtptime, guint32 * packet_count, guint32 * octet_count) { @@ -757,7 +1212,7 @@ rtp_source_get_new_sr (RTPSource * src, GstClockTime ntpnstime, /** * rtp_source_get_new_rb: * @src: an #RTPSource - * @time: the current time in nanoseconds since 1970 + * @ntpnstime: the current time in nanoseconds since 1970 * @fractionlost: fraction lost since last SR/RR * @packetslost: the cumululative number of packets lost * @exthighestseq: the extended last sequence number received @@ -765,12 +1220,12 @@ rtp_source_get_new_sr (RTPSource * src, GstClockTime ntpnstime, * @lsr: the last SR packet from this source * @dlsr: the delay since last SR packet * - * Get the values of the last RB report set with rtp_source_process_rb(). + * Get new values to put into a new report block from this source. * * Returns: %TRUE on success. */ gboolean -rtp_source_get_new_rb (RTPSource * src, GstClockTime time, +rtp_source_get_new_rb (RTPSource * src, guint64 ntpnstime, guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq, guint32 * jitter, guint32 * lsr, guint32 * dlsr) { @@ -816,7 +1271,7 @@ rtp_source_get_new_rb (RTPSource * src, GstClockTime time, /* LSR is middle 32 bits of the last ntptime */ LSR = (ntptime >> 16) & 0xffffffff; - diff = time - sr_time; + diff = ntpnstime - sr_time; GST_DEBUG ("last SR time diff %" GST_TIME_FORMAT, GST_TIME_ARGS (diff)); /* DLSR, delay since last SR is expressed in 1/65536 second units */ DLSR = gst_util_uint64_scale_int (diff, 65536, GST_SECOND); @@ -849,7 +1304,7 @@ rtp_source_get_new_rb (RTPSource * src, GstClockTime time, * rtp_source_get_last_sr: * @src: an #RTPSource * @time: time of packet arrival - * @ntptime: the NTP time + * @ntptime: the NTP time in 32.32 fixed point * @rtptime: the RTP time * @packet_count: the packet count * @octet_count: the octect count diff --git a/gst/rtpmanager/rtpsource.h b/gst/rtpmanager/rtpsource.h index 1952a4c245..0a744dfbb2 100644 --- a/gst/rtpmanager/rtpsource.h +++ b/gst/rtpmanager/rtpsource.h @@ -118,13 +118,9 @@ struct _RTPSource { gboolean is_csrc; gboolean is_sender; - gchar *cname; - gchar *name; - gchar *email; - gchar *phone; - gchar *location; - gchar *tool; - gchar *note; + guint8 *sdes[9]; + guint sdes_len[9]; + gboolean received_bye; gchar *bye_reason; @@ -161,38 +157,62 @@ struct _RTPSourceClass { GType rtp_source_get_type (void); /* managing lifetime of sources */ -RTPSource* rtp_source_new (guint32 ssrc); -void rtp_source_update_caps (RTPSource *src, GstCaps *caps); +RTPSource* rtp_source_new (guint32 ssrc); +void rtp_source_set_callbacks (RTPSource *src, RTPSourceCallbacks *cb, gpointer data); -void rtp_source_set_callbacks (RTPSource *src, RTPSourceCallbacks *cb, gpointer data); -void rtp_source_set_as_csrc (RTPSource *src); +/* properties */ +guint32 rtp_source_get_ssrc (RTPSource *src); -void rtp_source_set_rtp_from (RTPSource *src, GstNetAddress *address); -void rtp_source_set_rtcp_from (RTPSource *src, GstNetAddress *address); +void rtp_source_set_as_csrc (RTPSource *src); +gboolean rtp_source_is_as_csrc (RTPSource *src); + +gboolean rtp_source_is_active (RTPSource *src); +gboolean rtp_source_is_validated (RTPSource *src); +gboolean rtp_source_is_sender (RTPSource *src); + +gboolean rtp_source_received_bye (RTPSource *src); +gchar * rtp_source_get_bye_reason (RTPSource *src); + +void rtp_source_update_caps (RTPSource *src, GstCaps *caps); + +/* SDES info */ +gboolean rtp_source_set_sdes (RTPSource *src, GstRTCPSDESType type, + const guint8 *data, guint len); +gboolean rtp_source_set_sdes_string (RTPSource *src, GstRTCPSDESType type, + const gchar *data); +gboolean rtp_source_get_sdes (RTPSource *src, GstRTCPSDESType type, + guint8 **data, guint *len); +gchar* rtp_source_get_sdes_string (RTPSource *src, GstRTCPSDESType type); + +/* handling network address */ +void rtp_source_set_rtp_from (RTPSource *src, GstNetAddress *address); +void rtp_source_set_rtcp_from (RTPSource *src, GstNetAddress *address); /* handling RTP */ -GstFlowReturn rtp_source_process_rtp (RTPSource *src, GstBuffer *buffer, RTPArrivalStats *arrival); +GstFlowReturn rtp_source_process_rtp (RTPSource *src, GstBuffer *buffer, RTPArrivalStats *arrival); -GstFlowReturn rtp_source_send_rtp (RTPSource *src, GstBuffer *buffer, guint64 ntpnstime); +GstFlowReturn rtp_source_send_rtp (RTPSource *src, GstBuffer *buffer, guint64 ntpnstime); /* RTCP messages */ -void rtp_source_process_bye (RTPSource *src, const gchar *reason); -void rtp_source_process_sr (RTPSource *src, GstClockTime time, guint64 ntptime, - guint32 rtptime, guint32 packet_count, guint32 octet_count); -void rtp_source_process_rb (RTPSource *src, GstClockTime time, guint8 fractionlost, - gint32 packetslost, guint32 exthighestseq, guint32 jitter, - guint32 lsr, guint32 dlsr); +void rtp_source_process_bye (RTPSource *src, const gchar *reason); +void rtp_source_process_sr (RTPSource *src, GstClockTime time, guint64 ntptime, + guint32 rtptime, guint32 packet_count, guint32 octet_count); +void rtp_source_process_rb (RTPSource *src, GstClockTime time, guint8 fractionlost, + gint32 packetslost, guint32 exthighestseq, guint32 jitter, + guint32 lsr, guint32 dlsr); -gboolean rtp_source_get_new_sr (RTPSource *src, GstClockTime time, guint64 *ntptime, - guint32 *rtptime, guint32 *packet_count, guint32 *octet_count); -gboolean rtp_source_get_new_rb (RTPSource *src, GstClockTime time, guint8 *fractionlost, - gint32 *packetslost, guint32 *exthighestseq, guint32 *jitter, - guint32 *lsr, guint32 *dlsr); +gboolean rtp_source_get_new_sr (RTPSource *src, GstClockTime time, guint64 *ntptime, + guint32 *rtptime, guint32 *packet_count, + guint32 *octet_count); +gboolean rtp_source_get_new_rb (RTPSource *src, GstClockTime time, guint8 *fractionlost, + gint32 *packetslost, guint32 *exthighestseq, guint32 *jitter, + guint32 *lsr, guint32 *dlsr); -gboolean rtp_source_get_last_sr (RTPSource *src, GstClockTime *time, guint64 *ntptime, - guint32 *rtptime, guint32 *packet_count, guint32 *octet_count); -gboolean rtp_source_get_last_rb (RTPSource *src, guint8 *fractionlost, gint32 *packetslost, - guint32 *exthighestseq, guint32 *jitter, - guint32 *lsr, guint32 *dlsr); +gboolean rtp_source_get_last_sr (RTPSource *src, GstClockTime *time, guint64 *ntptime, + guint32 *rtptime, guint32 *packet_count, + guint32 *octet_count); +gboolean rtp_source_get_last_rb (RTPSource *src, guint8 *fractionlost, gint32 *packetslost, + guint32 *exthighestseq, guint32 *jitter, + guint32 *lsr, guint32 *dlsr); #endif /* __RTP_SOURCE_H__ */