diff --git a/configure.ac b/configure.ac index a88a170183..9c669f69dc 100644 --- a/configure.ac +++ b/configure.ac @@ -316,7 +316,7 @@ GST_PLUGINS_NONPORTED=" adpcmdec adpcmenc aiff asfmux \ hdvparse hls id3tag inter interlace ivfparse jpegformat jp2kdecimator \ kate liveadder legacyresample librfb mpegdemux mpegtsmux \ mpegpsmux mve mxf mythtv nsf nuvdemux \ - patchdetect pnm rawparse real removesilence rtpmux rtpvp8 scaletempo \ + patchdetect pnm rawparse real removesilence rtpvp8 scaletempo \ sdi segmentclip siren speed subenc stereo tta videofilters \ videomaxrate videomeasure videosignal vmnc \ decklink fbdev linsys shm vcd \ diff --git a/gst/rtpmux/Makefile.am b/gst/rtpmux/Makefile.am index d28d44d77f..39476487b3 100644 --- a/gst/rtpmux/Makefile.am +++ b/gst/rtpmux/Makefile.am @@ -2,8 +2,7 @@ plugin_LTLIBRARIES = libgstrtpmux.la libgstrtpmux_la_SOURCES = gstrtpmuxer.c gstrtpmux.c gstrtpdtmfmux.c -libgstrtpmux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ - -DEXTERN_BUF -DRTP_SUPPORT +libgstrtpmux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) libgstrtpmux_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ $(GST_BASE_LIBS) $(GST_LIBS) libgstrtpmux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) @@ -22,5 +21,5 @@ Android.mk: Makefile.am $(BUILT_SOURCES) $(libgstrtpmux_la_LIBADD) \ -ldl \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.11' \ > $@ \ No newline at end of file diff --git a/gst/rtpmux/gstrtpdtmfmux.c b/gst/rtpmux/gstrtpdtmfmux.c index 5e6d041459..b320dd9681 100644 --- a/gst/rtpmux/gstrtpdtmfmux.c +++ b/gst/rtpmux/gstrtpdtmfmux.c @@ -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 "); -} 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 "); + 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; } diff --git a/gst/rtpmux/gstrtpmux.c b/gst/rtpmux/gstrtpmux.c index 6bc9a4dc77..59f7dbe048 100644 --- a/gst/rtpmux/gstrtpmux.c +++ b/gst/rtpmux/gstrtpmux.c @@ -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 "); -} 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 "); + 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 diff --git a/gst/rtpmux/gstrtpmux.h b/gst/rtpmux/gstrtpmux.h index 7bfea60c0b..c7e39bc2c9 100644 --- a/gst/rtpmux/gstrtpmux.h +++ b/gst/rtpmux/gstrtpmux.h @@ -27,6 +27,7 @@ #define __GST_RTP_MUX_H__ #include +#include 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); }; diff --git a/tests/check/elements/rtpmux.c b/tests/check/elements/rtpmux.c index 133ee6dafe..1228e5b8fd 100644 --- a/tests/check/elements/rtpmux.c +++ b/tests/check/elements/rtpmux.c @@ -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);