LAST_SIGNAL
};
-#define DEFAULT_LATENCY_MS 200
+#define DEFAULT_LATENCY_MS 200
#define DEFAULT_SDES_CNAME NULL
#define DEFAULT_SDES_NAME NULL
#define DEFAULT_SDES_EMAIL NULL
#define DEFAULT_SDES_LOCATION NULL
#define DEFAULT_SDES_TOOL NULL
#define DEFAULT_SDES_NOTE NULL
+#define DEFAULT_DO_LOST FALSE
enum
{
PROP_SDES_LOCATION,
PROP_SDES_TOOL,
PROP_SDES_NOTE,
+ PROP_DO_LOST,
PROP_LAST
};
/* for lip-sync */
guint64 clock_base;
+ guint64 clock_base_time;
gint clock_rate;
gint64 ts_offset;
gint64 prev_ts_offset;
sess->bin = rtpbin;
sess->session = session;
sess->demux = demux;
- sess->ptmap = g_hash_table_new (NULL, NULL);
+ sess->ptmap = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) gst_caps_unref);
rtpbin->sessions = g_slist_prepend (rtpbin->sessions, sess);
/* set NTP base or new session */
gst_element_set_state (sess->session, GST_STATE_NULL);
gst_element_set_state (sess->demux, GST_STATE_NULL);
+ if (sess->recv_rtp_sink != NULL)
+ gst_element_release_request_pad (sess->session, sess->recv_rtp_sink);
+ if (sess->recv_rtp_src != NULL)
+ gst_object_unref (sess->recv_rtp_src);
+ if (sess->recv_rtcp_sink != NULL)
+ gst_element_release_request_pad (sess->session, sess->recv_rtcp_sink);
+ if (sess->sync_src != NULL)
+ gst_object_unref (sess->sync_src);
+ if (sess->send_rtp_sink != NULL)
+ gst_element_release_request_pad (sess->session, sess->send_rtp_sink);
+ if (sess->send_rtp_src != NULL)
+ gst_object_unref (sess->send_rtp_src);
+ if (sess->send_rtcp_src != NULL)
+ gst_element_release_request_pad (sess->session, sess->send_rtcp_src);
+
gst_bin_remove (GST_BIN_CAST (bin), sess->session);
gst_bin_remove (GST_BIN_CAST (bin), sess->demux);
/* first look in the cache */
caps = g_hash_table_lookup (session->ptmap, GINT_TO_POINTER (pt));
- if (caps)
+ if (caps) {
+ gst_caps_ref (caps);
goto done;
+ }
bin = session->bin;
g_signal_emitv (args, gst_rtp_bin_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);
- caps = (GstCaps *) g_value_get_boxed (&ret);
+ g_value_unset (&args[0]);
+ g_value_unset (&args[1]);
+ g_value_unset (&args[2]);
+ caps = (GstCaps *) g_value_dup_boxed (&ret);
+ g_value_unset (&ret);
if (!caps)
goto no_caps;
GST_DEBUG ("caching pt %d as %" GST_PTR_FORMAT, pt, caps);
- /* store in cache */
- g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps);
+ /* store in cache, take additional ref */
+ g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt),
+ gst_caps_ref (caps));
done:
- gst_caps_ref (caps);
GST_RTP_SESSION_UNLOCK (session);
return caps;
GST_RTP_BIN_UNLOCK (bin);
}
+static void
+gst_rtp_bin_propagate_property_to_jitterbuffer (GstRtpBin * bin,
+ const gchar * name, const GValue * value)
+{
+ GSList *sessions, *streams;
+
+ GST_RTP_BIN_LOCK (bin);
+ for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) {
+ GstRtpBinSession *session = (GstRtpBinSession *) sessions->data;
+
+ GST_RTP_SESSION_LOCK (session);
+ for (streams = session->streams; streams; streams = g_slist_next (streams)) {
+ GstRtpBinStream *stream = (GstRtpBinStream *) streams->data;
+
+ g_object_set_property (G_OBJECT (stream->buffer), name, value);
+ }
+ GST_RTP_SESSION_UNLOCK (session);
+ }
+ GST_RTP_BIN_UNLOCK (bin);
+}
+
+/* get a client with the given SDES name. Must be called with RTP_BIN_LOCK */
static GstRtpBinClient *
get_client (GstRtpBin * bin, guint8 len, guint8 * data, gboolean * created)
{
static void
free_client (GstRtpBinClient * client)
{
+ g_slist_free (client->streams);
g_free (client->cname);
g_free (client);
}
GSList *walk;
/* first find or create the CNAME */
+ GST_RTP_BIN_LOCK (bin);
client = get_client (bin, len, data, &created);
/* find stream in the client */
stream->local_unix =
gst_util_uint64_scale_int (stream->local_rtp, GST_SECOND,
stream->clock_rate);
+ stream->local_unix += stream->clock_base_time;
/* calculate delta between server and receiver */
stream->unix_delta = stream->last_unix - stream->local_unix;
ostream->ssrc, ostream->ts_offset);
}
}
+ GST_RTP_BIN_UNLOCK (bin);
return;
no_clock_base:
{
GST_WARNING_OBJECT (bin, "we have no clock-base");
+ GST_RTP_BIN_UNLOCK (bin);
return;
}
no_clock_rate:
{
GST_WARNING_OBJECT (bin, "we have no clock-rate");
+ GST_RTP_BIN_UNLOCK (bin);
return;
}
}
if (type == GST_RTCP_SDES_CNAME) {
stream->clock_base = GST_BUFFER_OFFSET (buffer);
+ stream->clock_base_time = GST_BUFFER_OFFSET_END (buffer);
/* associate the stream to CNAME */
gst_rtp_bin_associate (bin, stream, len, data);
}
g_signal_connect (buffer, "request-pt-map",
(GCallback) pt_map_requested, session);
- /* configure latency */
+ /* configure latency and packet lost */
g_object_set (buffer, "latency", session->bin->latency, NULL);
+ g_object_set (buffer, "do-lost", session->bin->do_lost, NULL);
gst_bin_add (GST_BIN_CAST (session->bin), buffer);
gst_element_set_state (buffer, GST_STATE_PLAYING);
"The NOTE to put in SDES messages of this session",
DEFAULT_SDES_NOTE, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_DO_LOST,
+ g_param_spec_boolean ("do-lost", "Do Lost",
+ "Send an event downstream when a packet is lost", DEFAULT_DO_LOST,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gstelement_class->provide_clock =
GST_DEBUG_FUNCPTR (gst_rtp_bin_provide_clock);
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_bin_change_state);
rtpbin->priv = GST_RTP_BIN_GET_PRIVATE (rtpbin);
rtpbin->priv->bin_lock = g_mutex_new ();
rtpbin->provided_clock = gst_system_clock_obtain ();
+
rtpbin->latency = DEFAULT_LATENCY_MS;
+ rtpbin->do_lost = DEFAULT_DO_LOST;
/* some default SDES entries */
str = g_strdup_printf ("%s@%s", g_get_user_name (), g_get_host_name ());
GST_RTP_BIN_LOCK (rtpbin);
rtpbin->latency = g_value_get_uint (value);
GST_RTP_BIN_UNLOCK (rtpbin);
+ /* propegate the property down to the jitterbuffer */
+ gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "latency", value);
break;
case PROP_SDES_CNAME:
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_CNAME,
gst_rtp_bin_set_sdes_string (rtpbin, GST_RTCP_SDES_NOTE,
g_value_get_string (value));
break;
+ case PROP_DO_LOST:
+ GST_RTP_BIN_LOCK (rtpbin);
+ rtpbin->do_lost = g_value_get_boolean (value);
+ GST_RTP_BIN_UNLOCK (rtpbin);
+ gst_rtp_bin_propagate_property_to_jitterbuffer (rtpbin, "do-lost", value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_take_string (value, gst_rtp_bin_get_sdes_string (rtpbin,
GST_RTCP_SDES_NOTE));
break;
+ case PROP_DO_LOST:
+ GST_RTP_BIN_LOCK (rtpbin);
+ g_value_set_boolean (value, rtpbin->do_lost);
+ GST_RTP_BIN_UNLOCK (rtpbin);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
stream->clock_base = val;
else
stream->clock_base = -1;
+
+ gst_caps_unref (caps);
}
/* get pad and link */
GST_DEBUG_OBJECT (session->bin, "linking jitterbuffer");
padname = g_strdup_printf ("src_%d", ssrc);
- srcpad = gst_element_get_pad (element, padname);
+ srcpad = gst_element_get_static_pad (element, padname);
g_free (padname);
sinkpad = gst_element_get_static_pad (stream->buffer, "sink");
gst_pad_link (srcpad, sinkpad);
gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
/* get the RTCP sync pad */
GST_DEBUG_OBJECT (session->bin, "linking sync pad");
padname = g_strdup_printf ("rtcp_src_%d", ssrc);
- srcpad = gst_element_get_pad (element, padname);
+ srcpad = gst_element_get_static_pad (element, padname);
g_free (padname);
gst_pad_link (srcpad, stream->sync_pad);
gst_object_unref (srcpad);
pad_it = gst_element_iterate_pads (GST_ELEMENT (element));
name_found = TRUE;
while (gst_iterator_next (pad_it, (gpointer) & pad) == GST_ITERATOR_OK) {
- if (strcmp (gst_pad_get_name (pad), pad_name) == 0)
+ gchar *name;
+
+ name = gst_pad_get_name (pad);
+ if (strcmp (name, pad_name) == 0)
name_found = FALSE;
+ g_free (name);
}
gst_iterator_free (pad_it);
}