rtpmux: port to 0.11

This commit is contained in:
Olivier Crête 2012-01-24 14:20:52 +01:00 committed by Tim-Philipp Müller
parent 35b6668fb6
commit f20a6b1d16
4 changed files with 292 additions and 294 deletions

View file

@ -58,35 +58,22 @@ GST_STATIC_PAD_TEMPLATE ("priority_sink_%u",
GST_STATIC_CAPS ("application/x-rtp"));
static GstPad *gst_rtp_dtmf_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name);
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static GstStateChangeReturn gst_rtp_dtmf_mux_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_rtp_dtmf_mux_accept_buffer_locked (GstRTPMux * rtp_mux,
GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer);
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * rtpbuffer);
static gboolean gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux,
GstEvent * event);
GST_BOILERPLATE (GstRTPDTMFMux, gst_rtp_dtmf_mux, GstRTPMux, GST_TYPE_RTP_MUX);
G_DEFINE_TYPE (GstRTPDTMFMux, gst_rtp_dtmf_mux, GST_TYPE_RTP_MUX);
static void
gst_rtp_dtmf_mux_init (GstRTPDTMFMux * object, GstRTPDTMFMuxClass * g_class)
gst_rtp_dtmf_mux_init (GstRTPDTMFMux * mux)
{
}
static void
gst_rtp_dtmf_mux_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&priority_sink_factory));
gst_element_class_set_details_simple (element_class, "RTP muxer",
"Codec/Muxer",
"mixes RTP DTMF streams into other RTP streams",
"Zeeshan Ali <first.last@nokia.com>");
}
static void
gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
@ -97,6 +84,14 @@ gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
gstelement_class = (GstElementClass *) klass;
gstrtpmux_class = (GstRTPMuxClass *) klass;
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&priority_sink_factory));
gst_element_class_set_metadata (gstelement_class, "RTP muxer",
"Codec/Muxer",
"mixes RTP DTMF streams into other RTP streams",
"Zeeshan Ali <first.last@nokia.com>");
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_request_new_pad);
gstelement_class->change_state =
@ -107,45 +102,46 @@ gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
static gboolean
gst_rtp_dtmf_mux_accept_buffer_locked (GstRTPMux * rtp_mux,
GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer)
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * rtpbuffer)
{
GstRTPDTMFMux *mux = GST_RTP_DTMF_MUX (rtp_mux);
GstClockTime running_ts;
running_ts = GST_BUFFER_TIMESTAMP (buffer);
running_ts = GST_BUFFER_PTS (rtpbuffer->buffer);
if (GST_CLOCK_TIME_IS_VALID (running_ts)) {
if (padpriv && padpriv->segment.format == GST_FORMAT_TIME)
running_ts = gst_segment_to_running_time (&padpriv->segment,
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
GST_FORMAT_TIME, GST_BUFFER_PTS (rtpbuffer->buffer));
if (padpriv && padpriv->priority) {
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
if (GST_BUFFER_PTS_IS_VALID (rtpbuffer->buffer)) {
if (GST_CLOCK_TIME_IS_VALID (mux->last_priority_end))
mux->last_priority_end =
MAX (running_ts + GST_BUFFER_DURATION (buffer),
MAX (running_ts + GST_BUFFER_DURATION (rtpbuffer->buffer),
mux->last_priority_end);
else
mux->last_priority_end = running_ts + GST_BUFFER_DURATION (buffer);
mux->last_priority_end = running_ts +
GST_BUFFER_DURATION (rtpbuffer->buffer);
GST_LOG_OBJECT (mux, "Got buffer %p on priority pad, "
" blocking regular pads until %" GST_TIME_FORMAT, buffer,
" blocking regular pads until %" GST_TIME_FORMAT, rtpbuffer->buffer,
GST_TIME_ARGS (mux->last_priority_end));
} else {
GST_WARNING_OBJECT (mux, "Buffer %p has an invalid duration,"
" not blocking other pad", buffer);
" not blocking other pad", rtpbuffer->buffer);
}
} else {
if (GST_CLOCK_TIME_IS_VALID (mux->last_priority_end) &&
running_ts < mux->last_priority_end) {
GST_LOG_OBJECT (mux, "Dropping buffer %p because running time"
" %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT, buffer,
" %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT, rtpbuffer->buffer,
GST_TIME_ARGS (running_ts), GST_TIME_ARGS (mux->last_priority_end));
return FALSE;
}
}
} else {
GST_LOG_OBJECT (mux, "Buffer %p has an invalid timestamp,"
" letting through", buffer);
" letting through", rtpbuffer->buffer);
}
return TRUE;
@ -154,12 +150,13 @@ gst_rtp_dtmf_mux_accept_buffer_locked (GstRTPMux * rtp_mux,
static GstPad *
gst_rtp_dtmf_mux_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * name)
const gchar * name, const GstCaps * caps)
{
GstPad *pad;
pad = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, request_new_pad,
(element, templ, name), NULL);
pad =
GST_ELEMENT_CLASS (gst_rtp_dtmf_mux_parent_class)->request_new_pad
(element, templ, name, caps);
if (pad) {
GstRTPMuxPadPrivate *padpriv;
@ -195,7 +192,8 @@ gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux, GstEvent * event)
}
}
return GST_RTP_MUX_CLASS (parent_class)->src_event (rtp_mux, event);
return GST_RTP_MUX_CLASS (gst_rtp_dtmf_mux_parent_class)->src_event (rtp_mux,
event);
}
@ -217,7 +215,9 @@ gst_rtp_dtmf_mux_change_state (GstElement * element, GstStateChange transition)
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
ret =
GST_ELEMENT_CLASS (gst_rtp_dtmf_mux_parent_class)->change_state (element,
transition);
return ret;
}

View file

@ -89,14 +89,18 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
);
static GstPad *gst_rtp_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name);
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void gst_rtp_mux_release_pad (GstElement * element, GstPad * pad);
static GstFlowReturn gst_rtp_mux_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad,
static GstFlowReturn gst_rtp_mux_chain (GstPad * pad, GstObject * parent,
GstBuffer * buffer);
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent,
GstBufferList * bufferlist);
static gboolean gst_rtp_mux_setcaps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_rtp_mux_getcaps (GstPad * pad);
static gboolean gst_rtp_mux_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux,
GstCaps * caps);
static gboolean gst_rtp_mux_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static gboolean gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent,
GstQuery * query);
static GstStateChangeReturn gst_rtp_mux_change_state (GstElement *
element, GstStateChange transition);
@ -110,22 +114,8 @@ static void gst_rtp_mux_dispose (GObject * object);
static gboolean gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux,
GstEvent * event);
GST_BOILERPLATE (GstRTPMux, gst_rtp_mux, GstElement, GST_TYPE_ELEMENT);
G_DEFINE_TYPE (GstRTPMux, gst_rtp_mux, GST_TYPE_ELEMENT);
static void
gst_rtp_mux_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (element_class, "RTP muxer",
"Codec/Muxer",
"multiplex N rtp streams into one", "Zeeshan Ali <first.last@nokia.com>");
}
static void
gst_rtp_mux_class_init (GstRTPMuxClass * klass)
@ -136,6 +126,16 @@ gst_rtp_mux_class_init (GstRTPMuxClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_metadata (gstelement_class, "RTP muxer",
"Codec/Muxer",
"multiplex N rtp streams into one", "Zeeshan Ali <first.last@nokia.com>");
gobject_class->get_property = gst_rtp_mux_get_property;
gobject_class->set_property = gst_rtp_mux_set_property;
gobject_class->dispose = gst_rtp_mux_dispose;
@ -182,24 +182,20 @@ restart:
}
}
G_OBJECT_CLASS (parent_class)->dispose (object);
G_OBJECT_CLASS (gst_rtp_mux_parent_class)->dispose (object);
}
static gboolean
gst_rtp_mux_src_event (GstPad * pad, GstEvent * event)
gst_rtp_mux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstRTPMux *rtp_mux;
GstRTPMux *rtp_mux = GST_RTP_MUX (parent);
GstRTPMuxClass *klass;
gboolean ret = FALSE;
rtp_mux = (GstRTPMux *) gst_pad_get_parent_element (pad);
g_return_val_if_fail (rtp_mux != NULL, FALSE);
klass = GST_RTP_MUX_GET_CLASS (rtp_mux);
ret = klass->src_event (rtp_mux, event);
gst_object_unref (rtp_mux);
return ret;
}
@ -207,18 +203,18 @@ static gboolean
gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux, GstEvent * event)
{
GstIterator *iter;
GstPad *sinkpad;
gboolean result = FALSE;
gboolean done = FALSE;
iter = gst_element_iterate_sink_pads (GST_ELEMENT (rtp_mux));
while (!done) {
switch (gst_iterator_next (iter, (gpointer) & sinkpad)) {
GValue item = { 0, };
switch (gst_iterator_next (iter, &item)) {
case GST_ITERATOR_OK:
gst_event_ref (event);
result |= gst_pad_push_event (sinkpad, event);
gst_object_unref (sinkpad);
result |= gst_pad_push_event (g_value_get_object (&item), event);
break;
case GST_ITERATOR_RESYNC:
gst_iterator_resync (iter);
@ -238,23 +234,26 @@ gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux, GstEvent * event)
}
static void
gst_rtp_mux_init (GstRTPMux * object, GstRTPMuxClass * g_class)
gst_rtp_mux_init (GstRTPMux * rtp_mux)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (object);
GstElementClass *klass = GST_ELEMENT_GET_CLASS (rtp_mux);
GstSegment segment;
object->srcpad =
rtp_mux->srcpad =
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
"src"), "src");
gst_pad_set_event_function (object->srcpad,
gst_pad_set_event_function (rtp_mux->srcpad,
GST_DEBUG_FUNCPTR (gst_rtp_mux_src_event));
gst_element_add_pad (GST_ELEMENT (object), object->srcpad);
gst_element_add_pad (GST_ELEMENT (rtp_mux), rtp_mux->srcpad);
object->ssrc = DEFAULT_SSRC;
object->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
object->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
gst_segment_init (&segment, GST_FORMAT_TIME);
gst_pad_push_event (rtp_mux->srcpad, gst_event_new_segment (&segment));
object->segment_pending = TRUE;
object->last_stop = GST_CLOCK_TIME_NONE;
rtp_mux->ssrc = DEFAULT_SSRC;
rtp_mux->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
rtp_mux->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
}
static void
@ -263,16 +262,16 @@ gst_rtp_mux_setup_sinkpad (GstRTPMux * rtp_mux, GstPad * sinkpad)
GstRTPMuxPadPrivate *padpriv = g_slice_new0 (GstRTPMuxPadPrivate);
/* setup some pad functions */
gst_pad_set_setcaps_function (sinkpad, gst_rtp_mux_setcaps);
gst_pad_set_getcaps_function (sinkpad, gst_rtp_mux_getcaps);
gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_rtp_mux_chain));
gst_pad_set_chain_list_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_rtp_mux_chain_list));
gst_pad_set_event_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_rtp_mux_sink_event));
gst_pad_set_query_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_rtp_mux_sink_query));
gst_segment_init (&padpriv->segment, GST_FORMAT_UNDEFINED);
gst_segment_init (&padpriv->segment, GST_FORMAT_TIME);
gst_pad_set_element_private (sinkpad, padpriv);
@ -282,7 +281,7 @@ gst_rtp_mux_setup_sinkpad (GstRTPMux * rtp_mux, GstPad * sinkpad)
static GstPad *
gst_rtp_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * req_name)
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
{
GstRTPMux *rtp_mux;
GstPad *newpad;
@ -327,7 +326,7 @@ gst_rtp_mux_release_pad (GstElement * element, GstPad * pad)
/* Put our own clock-base on the buffer */
static void
gst_rtp_mux_readjust_rtp_timestamp_locked (GstRTPMux * rtp_mux,
GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer)
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * rtpbuffer)
{
guint32 ts;
guint32 sink_ts_base = 0;
@ -335,59 +334,87 @@ gst_rtp_mux_readjust_rtp_timestamp_locked (GstRTPMux * rtp_mux,
if (padpriv && padpriv->have_clock_base)
sink_ts_base = padpriv->clock_base;
ts = gst_rtp_buffer_get_timestamp (buffer) - sink_ts_base + rtp_mux->ts_base;
ts = gst_rtp_buffer_get_timestamp (rtpbuffer) - sink_ts_base +
rtp_mux->ts_base;
GST_LOG_OBJECT (rtp_mux, "Re-adjusting RTP ts %u to %u",
gst_rtp_buffer_get_timestamp (buffer), ts);
gst_rtp_buffer_set_timestamp (buffer, ts);
gst_rtp_buffer_get_timestamp (rtpbuffer), ts);
gst_rtp_buffer_set_timestamp (rtpbuffer, ts);
}
static gboolean
process_buffer_locked (GstRTPMux * rtp_mux, GstRTPMuxPadPrivate * padpriv,
GstBuffer * buffer)
GstRTPBuffer * rtpbuffer)
{
GstRTPMuxClass *klass = GST_RTP_MUX_GET_CLASS (rtp_mux);
if (klass->accept_buffer_locked)
if (!klass->accept_buffer_locked (rtp_mux, padpriv, buffer))
if (!klass->accept_buffer_locked (rtp_mux, padpriv, rtpbuffer))
return FALSE;
rtp_mux->seqnum++;
gst_rtp_buffer_set_seq (buffer, rtp_mux->seqnum);
gst_rtp_buffer_set_seq (rtpbuffer, rtp_mux->seqnum);
gst_rtp_buffer_set_ssrc (buffer, rtp_mux->current_ssrc);
gst_rtp_mux_readjust_rtp_timestamp_locked (rtp_mux, padpriv, buffer);
gst_rtp_buffer_set_ssrc (rtpbuffer, rtp_mux->current_ssrc);
gst_rtp_mux_readjust_rtp_timestamp_locked (rtp_mux, padpriv, rtpbuffer);
GST_LOG_OBJECT (rtp_mux, "Pushing packet size %d, seq=%d, ts=%u",
GST_BUFFER_SIZE (buffer), rtp_mux->seqnum,
gst_rtp_buffer_get_timestamp (buffer));
rtpbuffer->size, rtp_mux->seqnum,
gst_rtp_buffer_get_timestamp (rtpbuffer));
if (padpriv) {
gst_buffer_set_caps (buffer, padpriv->out_caps);
if (padpriv->segment.format == GST_FORMAT_TIME)
GST_BUFFER_TIMESTAMP (buffer) =
GST_BUFFER_PTS (rtpbuffer->buffer) =
gst_segment_to_running_time (&padpriv->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (buffer));
GST_BUFFER_PTS (rtpbuffer->buffer));
}
return TRUE;
}
struct BufferListData
{
GstRTPMux *rtp_mux;
GstRTPMuxPadPrivate *padpriv;
gboolean drop;
};
static gboolean
process_list_item (GstBuffer ** buffer, guint idx, gpointer user_data)
{
struct BufferListData *bd = user_data;
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
*buffer = gst_buffer_make_writable (*buffer);
gst_rtp_buffer_map (*buffer, GST_MAP_READWRITE, &rtpbuffer);
bd->drop = !process_buffer_locked (bd->rtp_mux, bd->padpriv, &rtpbuffer);
gst_rtp_buffer_unmap (&rtpbuffer);
if (bd->drop)
return FALSE;
if (GST_BUFFER_DURATION_IS_VALID (*buffer) &&
GST_BUFFER_TIMESTAMP_IS_VALID (*buffer))
bd->rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (*buffer) +
GST_BUFFER_DURATION (*buffer);
else
bd->rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
return TRUE;
}
static GstFlowReturn
gst_rtp_mux_chain_list (GstPad * pad, GstBufferList * bufferlist)
gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent,
GstBufferList * bufferlist)
{
GstRTPMux *rtp_mux;
GstFlowReturn ret;
GstBufferListIterator *it;
GstRTPMuxPadPrivate *padpriv;
GstEvent *newseg_event = NULL;
gboolean drop = TRUE;
struct BufferListData bd;
rtp_mux = GST_RTP_MUX (gst_pad_get_parent (pad));
if (!gst_rtp_buffer_list_validate (bufferlist)) {
GST_ERROR_OBJECT (rtp_mux, "Invalid RTP buffer");
gst_object_unref (rtp_mux);
return GST_FLOW_ERROR;
}
rtp_mux = GST_RTP_MUX (parent);
GST_OBJECT_LOCK (rtp_mux);
@ -399,52 +426,15 @@ gst_rtp_mux_chain_list (GstPad * pad, GstBufferList * bufferlist)
goto out;
}
bd.rtp_mux = rtp_mux;
bd.padpriv = padpriv;
bd.drop = FALSE;
bufferlist = gst_buffer_list_make_writable (bufferlist);
it = gst_buffer_list_iterate (bufferlist);
while (gst_buffer_list_iterator_next_group (it)) {
GstBuffer *rtpbuf;
rtpbuf = gst_buffer_list_iterator_next (it);
rtpbuf = gst_buffer_make_writable (rtpbuf);
drop = !process_buffer_locked (rtp_mux, padpriv, rtpbuf);
if (drop)
break;
gst_buffer_list_iterator_take (it, rtpbuf);
do {
if (GST_BUFFER_DURATION_IS_VALID (rtpbuf) &&
GST_BUFFER_TIMESTAMP_IS_VALID (rtpbuf))
rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (rtpbuf) +
GST_BUFFER_DURATION (rtpbuf);
else
rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
gst_buffer_list_iterator_take (it, rtpbuf);
} while ((rtpbuf = gst_buffer_list_iterator_next (it)) != NULL);
}
gst_buffer_list_iterator_free (it);
if (!drop && rtp_mux->segment_pending) {
/*
* We set the start at 0, because we re-timestamps to the running time
*/
newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
GST_FORMAT_TIME, 0, -1, 0);
rtp_mux->segment_pending = FALSE;
}
gst_buffer_list_foreach (bufferlist, process_list_item, &bd);
GST_OBJECT_UNLOCK (rtp_mux);
if (newseg_event)
gst_pad_push_event (rtp_mux->srcpad, newseg_event);
if (drop) {
gst_buffer_list_unref (bufferlist);
ret = GST_FLOW_OK;
@ -454,19 +444,18 @@ gst_rtp_mux_chain_list (GstPad * pad, GstBufferList * bufferlist)
out:
gst_object_unref (rtp_mux);
return ret;
}
static GstFlowReturn
gst_rtp_mux_chain (GstPad * pad, GstBuffer * buffer)
gst_rtp_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
GstRTPMux *rtp_mux;
GstFlowReturn ret;
GstRTPMuxPadPrivate *padpriv;
GstEvent *newseg_event = NULL;
gboolean drop;
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
rtp_mux = GST_RTP_MUX (GST_OBJECT_PARENT (pad));
@ -487,19 +476,13 @@ gst_rtp_mux_chain (GstPad * pad, GstBuffer * buffer)
buffer = gst_buffer_make_writable (buffer);
drop = !process_buffer_locked (rtp_mux, padpriv, buffer);
gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtpbuffer);
drop = !process_buffer_locked (rtp_mux, padpriv, &rtpbuffer);
gst_rtp_buffer_unmap (&rtpbuffer);
if (!drop) {
if (rtp_mux->segment_pending) {
/*
* We set the start at 0, because we re-timestamps to the running time
*/
newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
GST_FORMAT_TIME, 0, -1, 0);
rtp_mux->segment_pending = FALSE;
}
if (GST_BUFFER_DURATION_IS_VALID (buffer) &&
GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (buffer) +
@ -524,19 +507,16 @@ gst_rtp_mux_chain (GstPad * pad, GstBuffer * buffer)
}
static gboolean
gst_rtp_mux_setcaps (GstPad * pad, GstCaps * caps)
gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
{
GstRTPMux *rtp_mux;
GstStructure *structure;
gboolean ret = FALSE;
GstRTPMuxPadPrivate *padpriv;
rtp_mux = GST_RTP_MUX (gst_pad_get_parent (pad));
structure = gst_caps_get_structure (caps, 0);
if (!structure)
goto out;
return FALSE;
GST_OBJECT_LOCK (rtp_mux);
padpriv = gst_pad_get_element_private (pad);
@ -572,9 +552,6 @@ gst_rtp_mux_setcaps (GstPad * pad, GstCaps * caps)
}
gst_caps_unref (caps);
out:
gst_object_unref (rtp_mux);
return ret;
}
@ -600,54 +577,47 @@ clear_caps (GstCaps * caps, gboolean only_clock_rate)
}
static gboolean
same_clock_rate_fold (gpointer item, GValue * ret, gpointer user_data)
same_clock_rate_fold (const GValue * item, GValue * ret, gpointer user_data)
{
GstPad *mypad = user_data;
GstPad *pad = item;
GstPad *pad = g_value_get_object (item);
GstCaps *peercaps;
GstCaps *othercaps;
const GstCaps *accumcaps;
GstCaps *intersect;
if (pad == mypad) {
gst_object_unref (pad);
return TRUE;
}
peercaps = gst_pad_peer_get_caps (pad);
if (!peercaps) {
gst_object_unref (pad);
return TRUE;
}
othercaps = gst_caps_intersect (peercaps,
gst_pad_get_pad_template_caps (pad));
gst_caps_unref (peercaps);
accumcaps = gst_value_get_caps (ret);
peercaps = gst_pad_peer_query_caps (pad, (GstCaps *) accumcaps);
if (!peercaps) {
g_warning ("no peercaps");
return TRUE;
}
peercaps = gst_caps_make_writable (peercaps);
clear_caps (peercaps, TRUE);
clear_caps (othercaps, TRUE);
intersect = gst_caps_intersect (accumcaps, othercaps);
intersect = gst_caps_intersect (accumcaps, peercaps);
g_value_take_boxed (ret, intersect);
gst_caps_unref (othercaps);
gst_object_unref (pad);
gst_caps_unref (peercaps);
return !gst_caps_is_empty (intersect);
}
static GstCaps *
gst_rtp_mux_getcaps (GstPad * pad)
gst_rtp_mux_getcaps (GstPad * pad, GstRTPMux * mux, GstCaps * filter)
{
GstRTPMux *mux = GST_RTP_MUX (gst_pad_get_parent (pad));
GstCaps *caps = NULL;
GstIterator *iter = NULL;
GValue v = { 0 };
GstIteratorResult res;
GstCaps *peercaps = gst_pad_peer_get_caps (mux->srcpad);
GstCaps *peercaps;
GstCaps *othercaps = NULL;
GstCaps *filtered_caps;
peercaps = gst_pad_peer_query_caps (mux->srcpad, filter);
if (peercaps) {
othercaps = gst_caps_intersect (peercaps,
@ -657,13 +627,21 @@ gst_rtp_mux_getcaps (GstPad * pad)
othercaps = gst_caps_copy (gst_pad_get_pad_template_caps (mux->srcpad));
}
clear_caps (othercaps, FALSE);
if (filter) {
filtered_caps = gst_caps_intersect (othercaps, filter);
gst_caps_unref (othercaps);
} else {
filtered_caps = othercaps;
}
filtered_caps = gst_caps_make_writable (filtered_caps);
clear_caps (filtered_caps, FALSE);
g_value_init (&v, GST_TYPE_CAPS);
iter = gst_element_iterate_sink_pads (GST_ELEMENT (mux));
do {
gst_value_set_caps (&v, othercaps);
gst_value_set_caps (&v, filtered_caps);
res = gst_iterator_fold (iter, same_clock_rate_fold, &v, pad);
} while (res == GST_ITERATOR_RESYNC);
gst_iterator_free (iter);
@ -675,13 +653,39 @@ gst_rtp_mux_getcaps (GstPad * pad)
caps = gst_caps_new_empty ();
}
if (othercaps)
gst_caps_unref (othercaps);
gst_object_unref (mux);
gst_caps_unref (filtered_caps);
return caps;
}
static gboolean
gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
GstRTPMux *mux = GST_RTP_MUX (parent);
gboolean res = FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
caps = gst_rtp_mux_getcaps (pad, mux, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
res = TRUE;
break;
}
default:
res = gst_pad_query_default (pad, parent, query);
break;
}
return res;
}
static void
gst_rtp_mux_get_property (GObject * object,
@ -737,49 +741,41 @@ gst_rtp_mux_set_property (GObject * object,
}
static gboolean
gst_rtp_mux_sink_event (GstPad * pad, GstEvent * event)
gst_rtp_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstRTPMux *mux;
gboolean ret = FALSE;
gboolean forward = TRUE;
mux = GST_RTP_MUX (gst_pad_get_parent (pad));
mux = GST_RTP_MUX (parent);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
ret = gst_rtp_mux_setcaps (pad, mux, caps);
forward = FALSE;
break;
}
case GST_EVENT_FLUSH_STOP:
{
GstRTPMuxPadPrivate *padpriv;
GST_OBJECT_LOCK (mux);
mux->last_stop = GST_CLOCK_TIME_NONE;
mux->segment_pending = TRUE;
padpriv = gst_pad_get_element_private (pad);
if (padpriv)
gst_segment_init (&padpriv->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_UNLOCK (mux);
}
break;
case GST_EVENT_NEWSEGMENT:
}
case GST_EVENT_SEGMENT:
{
gboolean update;
gdouble rate, applied_rate;
GstFormat format;
gint64 start, stop, position;
GstRTPMuxPadPrivate *padpriv;
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
&format, &start, &stop, &position);
GST_OBJECT_LOCK (mux);
padpriv = gst_pad_get_element_private (pad);
if (padpriv) {
if (format == GST_FORMAT_TIME)
gst_segment_set_newsegment_full (&padpriv->segment, update,
rate, applied_rate, format, start, stop, position);
else
gst_segment_init (&padpriv->segment, GST_FORMAT_UNDEFINED);
gst_event_copy_segment (event, &padpriv->segment);
}
GST_OBJECT_UNLOCK (mux);
gst_event_unref (event);
@ -794,40 +790,14 @@ gst_rtp_mux_sink_event (GstPad * pad, GstEvent * event)
if (forward)
ret = gst_pad_push_event (mux->srcpad, event);
gst_object_unref (mux);
return ret;
}
static void
clear_segment (gpointer data, gpointer user_data)
{
GstPad *pad = data;
GstRTPMux *mux = user_data;
GstRTPMuxPadPrivate *padpriv;
GST_OBJECT_LOCK (mux);
padpriv = gst_pad_get_element_private (pad);
if (padpriv)
gst_segment_init (&padpriv->segment, GST_FORMAT_UNDEFINED);
GST_OBJECT_UNLOCK (mux);
gst_object_unref (pad);
}
static void
gst_rtp_mux_ready_to_paused (GstRTPMux * rtp_mux)
{
GstIterator *iter;
iter = gst_element_iterate_sink_pads (GST_ELEMENT (rtp_mux));
while (gst_iterator_foreach (iter, clear_segment, rtp_mux) ==
GST_ITERATOR_RESYNC);
gst_iterator_free (iter);
GST_OBJECT_LOCK (rtp_mux);
rtp_mux->segment_pending = TRUE;
if (rtp_mux->ssrc == -1)
rtp_mux->current_ssrc = g_random_int ();
@ -871,7 +841,8 @@ gst_rtp_mux_change_state (GstElement * element, GstStateChange transition)
break;
}
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
return GST_ELEMENT_CLASS (gst_rtp_mux_parent_class)->change_state (element,
transition);
}
gboolean

View file

@ -27,6 +27,7 @@
#define __GST_RTP_MUX_H__
#include <gst/gst.h>
#include <gst/rtp/gstrtpbuffer.h>
G_BEGIN_DECLS
#define GST_TYPE_RTP_MUX (gst_rtp_mux_get_type())
@ -83,7 +84,7 @@ struct _GstRTPMuxClass
GstElementClass parent_class;
gboolean (*accept_buffer_locked) (GstRTPMux *rtp_mux,
GstRTPMuxPadPrivate * padpriv, GstBuffer * buffer);
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * buffer);
gboolean (*src_event) (GstRTPMux *rtp_mux, GstEvent *event);
};

View file

@ -38,32 +38,43 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
typedef void (*check_cb) (GstPad * pad, int i);
static GstCaps *
getcaps_func (GstPad * pad)
{
GstCaps **caps = g_object_get_data (G_OBJECT (pad), "caps");
fail_unless (caps != NULL && *caps != NULL);
return gst_caps_ref (*caps);
}
static gboolean
setcaps_func (GstPad * pad, GstCaps * caps)
query_func (GstPad * pad, GstObject * noparent, GstQuery * query)
{
GstCaps **caps2 = g_object_get_data (G_OBJECT (pad), "caps");
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
GstCaps **caps = g_object_get_data (G_OBJECT (pad), "caps");
fail_unless (caps2 != NULL && *caps2 != NULL);
fail_unless (gst_caps_is_equal (caps, *caps2));
fail_unless (caps != NULL && *caps != NULL);
gst_query_set_caps_result (query, *caps);
break;
}
default:
break;
}
return TRUE;
}
static gboolean
event_func (GstPad * pad, GstEvent * event)
event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
{
gst_event_unref (event);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
GstCaps **caps2 = g_object_get_data (G_OBJECT (pad), "caps");
gst_event_parse_caps (event, &caps);
fail_unless (caps2 != NULL && *caps2 != NULL);
fail_unless (gst_caps_is_equal (caps, *caps2));
break;
}
default:
gst_event_unref (event);
break;
}
return TRUE;
}
@ -83,7 +94,7 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
GstCaps *src2caps = NULL;
GstCaps *sinkcaps = NULL;
GstCaps *caps;
GstEvent *newsegment;
GstSegment segment;
int i;
rtpmux = gst_check_setup_element (elem_name);
@ -98,10 +109,9 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
src2 = gst_pad_new_from_static_template (&srctemplate, "src");
fail_unless (gst_pad_link (src1, reqpad1) == GST_PAD_LINK_OK);
fail_unless (gst_pad_link (src2, reqpad2) == GST_PAD_LINK_OK);
gst_pad_set_getcaps_function (src1, getcaps_func);
gst_pad_set_getcaps_function (src2, getcaps_func);
gst_pad_set_getcaps_function (sink, getcaps_func);
gst_pad_set_setcaps_function (sink, setcaps_func);
gst_pad_set_query_function (src1, query_func);
gst_pad_set_query_function (src2, query_func);
gst_pad_set_query_function (sink, query_func);
gst_pad_set_event_function (sink, event_func);
g_object_set_data (G_OBJECT (src1), "caps", &src1caps);
g_object_set_data (G_OBJECT (src2), "caps", &src2caps);
@ -114,12 +124,12 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
sinkcaps = gst_caps_new_simple ("application/x-rtp",
"clock-rate", G_TYPE_INT, 3, "ssrc", G_TYPE_UINT, 13, NULL);
caps = gst_pad_peer_get_caps (src1);
caps = gst_pad_peer_query_caps (src1, NULL);
fail_unless (gst_caps_is_empty (caps));
gst_caps_unref (caps);
gst_caps_set_simple (src2caps, "clock-rate", G_TYPE_INT, 3, NULL);
caps = gst_pad_peer_get_caps (src1);
caps = gst_pad_peer_query_caps (src1, NULL);
fail_unless (gst_caps_is_equal (caps, sinkcaps));
gst_caps_unref (caps);
@ -141,27 +151,33 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
"ssrc", G_TYPE_UINT, 66, NULL);
fail_unless (gst_pad_set_caps (src1, caps));
newsegment = gst_event_new_new_segment (FALSE, 1, GST_FORMAT_TIME, 100000,
-1, 0);
fail_unless (gst_pad_push_event (src1, newsegment));
newsegment = gst_event_new_new_segment (FALSE, 1, GST_FORMAT_TIME, 0, -1, 0);
fail_unless (gst_pad_push_event (src2, newsegment));
gst_segment_init (&segment, GST_FORMAT_TIME);
segment.start = 100000;
fail_unless (gst_pad_push_event (src1, gst_event_new_segment (&segment)));
segment.start = 0;
fail_unless (gst_pad_push_event (src2, gst_event_new_segment (&segment)));
for (i = 0; i < count; i++) {
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
GST_BUFFER_TIMESTAMP (inbuf) = i * 1000 + 100000;
GST_BUFFER_PTS (inbuf) = i * 1000 + 100000;
GST_BUFFER_DURATION (inbuf) = 1000;
gst_buffer_set_caps (inbuf, caps);
gst_rtp_buffer_set_version (inbuf, 2);
gst_rtp_buffer_set_payload_type (inbuf, 98);
gst_rtp_buffer_set_ssrc (inbuf, 44);
gst_rtp_buffer_set_timestamp (inbuf, 200 + i);
gst_rtp_buffer_set_seq (inbuf, 2000 + i);
gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer);
gst_rtp_buffer_set_version (&rtpbuffer, 2);
gst_rtp_buffer_set_payload_type (&rtpbuffer, 98);
gst_rtp_buffer_set_ssrc (&rtpbuffer, 44);
gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i);
gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i);
gst_rtp_buffer_unmap (&rtpbuffer);
fail_unless (gst_pad_push (src1, inbuf) == GST_FLOW_OK);
if (buffers)
fail_unless (GST_BUFFER_TIMESTAMP (buffers->data) == i * 1000, "%lld",
GST_BUFFER_TIMESTAMP (buffers->data));
fail_unless (GST_BUFFER_PTS (buffers->data) == i * 1000, "%lld",
GST_BUFFER_PTS (buffers->data));
cb (src2, i);
@ -195,11 +211,15 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
static void
basic_check_cb (GstPad * pad, int i)
{
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
fail_unless (buffers && g_list_length (buffers) == 1);
fail_unless (gst_rtp_buffer_get_ssrc (buffers->data) == 55);
fail_unless (gst_rtp_buffer_get_timestamp (buffers->data) ==
gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 55);
fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
200 - 57 + 1000 + i);
fail_unless (gst_rtp_buffer_get_seq (buffers->data) == 100 + 1 + i);
fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
gst_rtp_buffer_unmap (&rtpbuffer);
}
@ -225,20 +245,26 @@ lock_check_cb (GstPad * pad, int i)
if (i % 2) {
fail_unless (buffers == NULL);
} else {
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
fail_unless (buffers && g_list_length (buffers) == 1);
fail_unless (gst_rtp_buffer_get_ssrc (buffers->data) == 55);
fail_unless (gst_rtp_buffer_get_timestamp (buffers->data) ==
gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 55);
fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
200 - 57 + 1000 + i);
fail_unless (gst_rtp_buffer_get_seq (buffers->data) == 100 + 1 + i);
fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
gst_rtp_buffer_unmap (&rtpbuffer);
inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
GST_BUFFER_TIMESTAMP (inbuf) = i * 1000 + 500;
GST_BUFFER_PTS (inbuf) = i * 1000 + 500;
GST_BUFFER_DURATION (inbuf) = 1000;
gst_rtp_buffer_set_version (inbuf, 2);
gst_rtp_buffer_set_payload_type (inbuf, 98);
gst_rtp_buffer_set_ssrc (inbuf, 44);
gst_rtp_buffer_set_timestamp (inbuf, 200 + i);
gst_rtp_buffer_set_seq (inbuf, 2000 + i);
gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer);
gst_rtp_buffer_set_version (&rtpbuffer, 2);
gst_rtp_buffer_set_payload_type (&rtpbuffer, 98);
gst_rtp_buffer_set_ssrc (&rtpbuffer, 44);
gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i);
gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i);
gst_rtp_buffer_unmap (&rtpbuffer);
fail_unless (gst_pad_push (pad, inbuf) == GST_FLOW_OK);