mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
rtpmux: remove rtpmux plugin, moved to -good
Move rtpmux and rtpdtmfmux into rtpmanager plugin in -good. https://bugzilla.gnome.org/show_bug.cgi?id=629117
This commit is contained in:
parent
7ab936fa7e
commit
02ab609c11
19 changed files with 0 additions and 1824 deletions
|
@ -56,7 +56,6 @@ GST_PLUGINS_BAD_BUILT_SOURCES := \
|
|||
gst/sdi/Android.mk \
|
||||
gst/festival/Android.mk \
|
||||
gst/y4m/Android.mk \
|
||||
gst/rtpmux/Android.mk \
|
||||
gst/pcapparse/Android.mk \
|
||||
gst/nuvdemux/Android.mk \
|
||||
gst/colorspace/Android.mk \
|
||||
|
@ -148,7 +147,6 @@ CONFIGURE_TARGETS += gst-plugins-bad-configure
|
|||
-include $(GST_PLUGINS_BAD_TOP)/gst/sdi/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/festival/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/y4m/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/rtpmux/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/pcapparse/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/nuvdemux/Android.mk
|
||||
-include $(GST_PLUGINS_BAD_TOP)/gst/colorspace/Android.mk
|
||||
|
|
|
@ -377,7 +377,6 @@ AG_GST_CHECK_PLUGIN(pnm)
|
|||
AG_GST_CHECK_PLUGIN(rawparse)
|
||||
AG_GST_CHECK_PLUGIN(real)
|
||||
AG_GST_CHECK_PLUGIN(removesilence)
|
||||
AG_GST_CHECK_PLUGIN(rtpmux)
|
||||
AG_GST_CHECK_PLUGIN(sdi)
|
||||
AG_GST_CHECK_PLUGIN(sdp)
|
||||
AG_GST_CHECK_PLUGIN(segmentclip)
|
||||
|
@ -2120,7 +2119,6 @@ gst/pnm/Makefile
|
|||
gst/rawparse/Makefile
|
||||
gst/real/Makefile
|
||||
gst/removesilence/Makefile
|
||||
gst/rtpmux/Makefile
|
||||
gst/sdi/Makefile
|
||||
gst/sdp/Makefile
|
||||
gst/segmentclip/Makefile
|
||||
|
|
|
@ -164,8 +164,6 @@ EXTRA_HFILES = \
|
|||
$(top_srcdir)/gst/pcapparse/gstpcapparse.h \
|
||||
$(top_srcdir)/gst/rawparse/gstaudioparse.h \
|
||||
$(top_srcdir)/gst/rawparse/gstvideoparse.h \
|
||||
$(top_srcdir)/gst/rtpmux/gstrtpmux.h \
|
||||
$(top_srcdir)/gst/rtpmux/gstrtpdtmfmux.h \
|
||||
$(top_srcdir)/gst/sdp/gstsdpdemux.h \
|
||||
$(top_srcdir)/gst/speed/gstspeed.h \
|
||||
$(top_srcdir)/gst/stereo/gststereo.h \
|
||||
|
|
|
@ -71,10 +71,7 @@
|
|||
<xi:include href="xml/element-pyramidsegment.xml" />
|
||||
<xi:include href="xml/element-rtmpsink.xml" />
|
||||
<xi:include href="xml/element-rtmpsrc.xml" />
|
||||
<xi:include href="xml/element-rtpmux.xml" />
|
||||
<xi:include href="xml/element-rtpdtmfsrc.xml" />
|
||||
<xi:include href="xml/element-rtpdtmfmux.xml" />
|
||||
<xi:include href="xml/element-rtpmux.xml" />
|
||||
<xi:include href="xml/element-shmsink.xml" />
|
||||
<xi:include href="xml/element-shmsrc.xml" />
|
||||
<xi:include href="xml/element-sdpdemux.xml" />
|
||||
|
@ -135,7 +132,6 @@
|
|||
<xi:include href="xml/plugin-pcapparse.xml" />
|
||||
<xi:include href="xml/plugin-rawparse.xml" />
|
||||
<xi:include href="xml/plugin-rtmp.xml" />
|
||||
<xi:include href="xml/plugin-rtpmux.xml" />
|
||||
<xi:include href="xml/plugin-sdp.xml" />
|
||||
<xi:include href="xml/plugin-shm.xml" />
|
||||
<xi:include href="xml/plugin-soundtouch.xml" />
|
||||
|
|
|
@ -1187,21 +1187,6 @@ GST_RTP_DTMF_DEPAY_CLASS
|
|||
gst_rtp_dtmf_depay_plugin_init
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-rtpdtmfmux</FILE>
|
||||
<TITLE>rtpdtmfmux</TITLE>
|
||||
GstRTPDTMFMux
|
||||
<SUBSECTION Standard>
|
||||
GST_IS_RTP_DTMF_MUX
|
||||
GST_IS_RTP_DTMF_MUX_CLASS
|
||||
GST_TYPE_RTP_DTMF_MUX
|
||||
GstRTPDTMFMuxClass
|
||||
GST_RTP_DTMF_MUX
|
||||
GST_RTP_DTMF_MUX_CLASS
|
||||
gst_rtp_dtmf_mux_get_type
|
||||
gst_rtp_dtmf_mux_plugin_init
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-rtpdtmfsrc</FILE>
|
||||
<TITLE>rtpdtmfsrc</TITLE>
|
||||
|
@ -1222,22 +1207,6 @@ GstRTPDTMFSrcEvent
|
|||
GstRTPDTMFEventType
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-rtpmux</FILE>
|
||||
<TITLE>rtpmux</TITLE>
|
||||
GstRTPMux
|
||||
<SUBSECTION Standard>
|
||||
GST_IS_RTP_MUX
|
||||
GST_IS_RTP_MUX_CLASS
|
||||
GST_RTP_MUX
|
||||
GST_RTP_MUX_CLASS
|
||||
GST_RTP_MUX_GET_CLASS
|
||||
GST_TYPE_RTP_MUX
|
||||
GstRTPMuxClass
|
||||
gst_rtp_mux_get_type
|
||||
gst_rtp_mux_plugin_init
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-sdlaudiosink</FILE>
|
||||
<TITLE>sdlaudiosink</TITLE>
|
||||
|
|
|
@ -23653,46 +23653,6 @@
|
|||
<DEFAULT>60</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstRTPMux::seqnum</NAME>
|
||||
<TYPE>guint</TYPE>
|
||||
<RANGE></RANGE>
|
||||
<FLAGS>r</FLAGS>
|
||||
<NICK>Sequence number</NICK>
|
||||
<BLURB>The RTP sequence number of the last processed packet.</BLURB>
|
||||
<DEFAULT>0</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstRTPMux::seqnum-offset</NAME>
|
||||
<TYPE>gint</TYPE>
|
||||
<RANGE>>= G_MAXULONG</RANGE>
|
||||
<FLAGS>rw</FLAGS>
|
||||
<NICK>Sequence number Offset</NICK>
|
||||
<BLURB>Offset to add to all outgoing seqnum (-1 = random).</BLURB>
|
||||
<DEFAULT>-1</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstRTPMux::ssrc</NAME>
|
||||
<TYPE>guint</TYPE>
|
||||
<RANGE></RANGE>
|
||||
<FLAGS>rw</FLAGS>
|
||||
<NICK>SSRC</NICK>
|
||||
<BLURB>The SSRC of the packets (-1 == random).</BLURB>
|
||||
<DEFAULT>4294967295</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstRTPMux::timestamp-offset</NAME>
|
||||
<TYPE>gint</TYPE>
|
||||
<RANGE>>= G_MAXULONG</RANGE>
|
||||
<FLAGS>rw</FLAGS>
|
||||
<NICK>Timestamp Offset</NICK>
|
||||
<BLURB>Offset to add to all outgoing timestamps (-1 = random).</BLURB>
|
||||
<DEFAULT>-1</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstAutoConvert::factories</NAME>
|
||||
<TYPE>gpointer</TYPE>
|
||||
|
|
|
@ -208,8 +208,6 @@ GObject
|
|||
GstRtpAsfPay
|
||||
GstRtpOPUSPay
|
||||
GstRtpVP8Pay
|
||||
GstRTPMux
|
||||
GstRTPDTMFMux
|
||||
GstRawParse
|
||||
GstAudioParse
|
||||
GstVideoParse
|
||||
|
|
|
@ -184,22 +184,6 @@ GstCameraBin *gstcamerabin
|
|||
GstCameraBin *gstcamerabin
|
||||
</SIGNAL>
|
||||
|
||||
<SIGNAL>
|
||||
<NAME>GstRTPDTMFMux::locking</NAME>
|
||||
<RETURNS>void</RETURNS>
|
||||
<FLAGS>l</FLAGS>
|
||||
GstRTPDTMFMux *gstrtpdtmfmux
|
||||
GstPad *arg1
|
||||
</SIGNAL>
|
||||
|
||||
<SIGNAL>
|
||||
<NAME>GstRTPDTMFMux::unlocked</NAME>
|
||||
<RETURNS>void</RETURNS>
|
||||
<FLAGS>l</FLAGS>
|
||||
GstRTPDTMFMux *gstrtpdtmfmux
|
||||
GstPad *arg1
|
||||
</SIGNAL>
|
||||
|
||||
<SIGNAL>
|
||||
<NAME>GstRtpBin::clear-pt-map</NAME>
|
||||
<RETURNS>void</RETURNS>
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
<plugin>
|
||||
<name>rtpmux</name>
|
||||
<description>RTP Muxer plugins</description>
|
||||
<filename>../../gst/rtpmux/.libs/libgstrtpmux.so</filename>
|
||||
<basename>libgstrtpmux.so</basename>
|
||||
<version>1.1.0.1</version>
|
||||
<license>LGPL</license>
|
||||
<source>gst-plugins-bad</source>
|
||||
<package>GStreamer Bad Plug-ins git</package>
|
||||
<origin>Unknown package origin</origin>
|
||||
<elements>
|
||||
<element>
|
||||
<name>rtpdtmfmux</name>
|
||||
<longname>RTP muxer</longname>
|
||||
<class>Codec/Muxer</class>
|
||||
<description>mixes RTP DTMF streams into other RTP streams</description>
|
||||
<author>Zeeshan Ali <first.last@nokia.com></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>priority_sink_%u</name>
|
||||
<direction>sink</direction>
|
||||
<presence>request</presence>
|
||||
<details>application/x-rtp</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>sink_%u</name>
|
||||
<direction>sink</direction>
|
||||
<presence>request</presence>
|
||||
<details>application/x-rtp</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>application/x-rtp</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>rtpmux</name>
|
||||
<longname>RTP muxer</longname>
|
||||
<class>Codec/Muxer</class>
|
||||
<description>multiplex N rtp streams into one</description>
|
||||
<author>Zeeshan Ali <first.last@nokia.com></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink_%u</name>
|
||||
<direction>sink</direction>
|
||||
<presence>request</presence>
|
||||
<details>application/x-rtp</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>application/x-rtp</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
</elements>
|
||||
</plugin>
|
|
@ -230,7 +230,6 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
|
|||
%{_libdir}/gstreamer-%{majorminor}/libgstpcapparse.so
|
||||
%{_libdir}/gstreamer-%{majorminor}/libgstpnm.so
|
||||
# %{_libdir}/gstreamer-%{majorminor}/libgstrfbsrc.so
|
||||
%{_libdir}/gstreamer-%{majorminor}/libgstrtpmux.so
|
||||
%{_libdir}/gstreamer-%{majorminor}/libgstsegmentclip.so
|
||||
%{_libdir}/gstreamer-%{majorminor}/libgstrawparse.so
|
||||
%{_libdir}/gstreamer-%{majorminor}/libgstshm.so
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
plugin_LTLIBRARIES = libgstrtpmux.la
|
||||
|
||||
libgstrtpmux_la_SOURCES = gstrtpmuxer.c gstrtpmux.c gstrtpdtmfmux.c
|
||||
|
||||
libgstrtpmux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
libgstrtpmux_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_API_VERSION@ \
|
||||
$(GST_BASE_LIBS) $(GST_LIBS)
|
||||
libgstrtpmux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstrtpmux_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstrtpmux.h gstrtpdtmfmux.h
|
||||
|
||||
Android.mk: Makefile.am $(BUILT_SOURCES)
|
||||
androgenizer \
|
||||
-:PROJECT libgstrtpmux -:SHARED libgstrtpmux \
|
||||
-:TAGS eng debug \
|
||||
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
|
||||
-:SOURCES $(libgstrtpmux_la_SOURCES) \
|
||||
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtpmux_la_CFLAGS) \
|
||||
-:LDFLAGS $(libgstrtpmux_la_LDFLAGS) \
|
||||
$(libgstrtpmux_la_LIBADD) \
|
||||
-ldl \
|
||||
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
|
||||
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-@GST_API_VERSION@' \
|
||||
> $@
|
|
@ -1,233 +0,0 @@
|
|||
/* RTP DTMF muxer element for GStreamer
|
||||
*
|
||||
* gstrtpdtmfmux.c:
|
||||
*
|
||||
* Copyright (C) <2007-2010> Nokia Corporation.
|
||||
* Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||
* Copyright (C) <2007-2010> Collabora Ltd
|
||||
* Contact: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000,2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-rtpdtmfmux
|
||||
* @see_also: rtpdtmfsrc, dtmfsrc, rtpmux
|
||||
*
|
||||
* The RTP "DTMF" Muxer muxes multiple RTP streams into a valid RTP
|
||||
* stream. It does exactly what it's parent (#rtpmux) does, except
|
||||
* that it prevent buffers coming over a regular sink_%%u pad from going through
|
||||
* for the duration of buffers that came in a priority_sink_%%u pad.
|
||||
*
|
||||
* This is especially useful if a discontinuous source like dtmfsrc or
|
||||
* rtpdtmfsrc are connected to the priority sink pads. This way, the generated
|
||||
* DTMF signal can replace the recorded audio while the tone is being sent.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gstrtpdtmfmux.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_mux_debug);
|
||||
#define GST_CAT_DEFAULT gst_rtp_dtmf_mux_debug
|
||||
|
||||
static GstStaticPadTemplate priority_sink_factory =
|
||||
GST_STATIC_PAD_TEMPLATE ("priority_sink_%u",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("application/x-rtp"));
|
||||
|
||||
static GstPad *gst_rtp_dtmf_mux_request_new_pad (GstElement * element,
|
||||
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, GstRTPBuffer * rtpbuffer);
|
||||
static gboolean gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux,
|
||||
GstEvent * event);
|
||||
|
||||
G_DEFINE_TYPE (GstRTPDTMFMux, gst_rtp_dtmf_mux, GST_TYPE_RTP_MUX);
|
||||
|
||||
static void
|
||||
gst_rtp_dtmf_mux_init (GstRTPDTMFMux * mux)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_rtp_dtmf_mux_class_init (GstRTPDTMFMuxClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class;
|
||||
GstRTPMuxClass *gstrtpmux_class;
|
||||
|
||||
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_static_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 =
|
||||
GST_DEBUG_FUNCPTR (gst_rtp_dtmf_mux_change_state);
|
||||
gstrtpmux_class->accept_buffer_locked = gst_rtp_dtmf_mux_accept_buffer_locked;
|
||||
gstrtpmux_class->src_event = gst_rtp_dtmf_mux_src_event;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_dtmf_mux_accept_buffer_locked (GstRTPMux * rtp_mux,
|
||||
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * rtpbuffer)
|
||||
{
|
||||
GstRTPDTMFMux *mux = GST_RTP_DTMF_MUX (rtp_mux);
|
||||
GstClockTime running_ts;
|
||||
|
||||
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_PTS (rtpbuffer->buffer));
|
||||
|
||||
if (padpriv && padpriv->priority) {
|
||||
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 (rtpbuffer->buffer),
|
||||
mux->last_priority_end);
|
||||
else
|
||||
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, rtpbuffer->buffer,
|
||||
GST_TIME_ARGS (mux->last_priority_end));
|
||||
} else {
|
||||
GST_WARNING_OBJECT (mux, "Buffer %p has an invalid duration,"
|
||||
" 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, 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", rtpbuffer->buffer);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GstPad *
|
||||
gst_rtp_dtmf_mux_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * name, const GstCaps * caps)
|
||||
{
|
||||
GstPad *pad;
|
||||
|
||||
pad =
|
||||
GST_ELEMENT_CLASS (gst_rtp_dtmf_mux_parent_class)->request_new_pad
|
||||
(element, templ, name, caps);
|
||||
|
||||
if (pad) {
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
|
||||
GST_OBJECT_LOCK (element);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
|
||||
if (gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
|
||||
"priority_sink_%u") == gst_pad_get_pad_template (pad))
|
||||
padpriv->priority = TRUE;
|
||||
GST_OBJECT_UNLOCK (element);
|
||||
}
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_dtmf_mux_src_event (GstRTPMux * rtp_mux, GstEvent * event)
|
||||
{
|
||||
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) {
|
||||
const GstStructure *s = gst_event_get_structure (event);
|
||||
|
||||
if (s && gst_structure_has_name (s, "dtmf-event")) {
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
if (GST_CLOCK_TIME_IS_VALID (rtp_mux->last_stop)) {
|
||||
event = (GstEvent *)
|
||||
gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (event));
|
||||
s = gst_event_get_structure (event);
|
||||
gst_structure_set ((GstStructure *) s,
|
||||
"last-stop", G_TYPE_UINT64, rtp_mux->last_stop, NULL);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
}
|
||||
}
|
||||
|
||||
return GST_RTP_MUX_CLASS (gst_rtp_dtmf_mux_parent_class)->src_event (rtp_mux,
|
||||
event);
|
||||
}
|
||||
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_rtp_dtmf_mux_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstStateChangeReturn ret;
|
||||
GstRTPDTMFMux *mux = GST_RTP_DTMF_MUX (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
{
|
||||
GST_OBJECT_LOCK (mux);
|
||||
mux->last_priority_end = GST_CLOCK_TIME_NONE;
|
||||
GST_OBJECT_UNLOCK (mux);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret =
|
||||
GST_ELEMENT_CLASS (gst_rtp_dtmf_mux_parent_class)->change_state (element,
|
||||
transition);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_rtp_dtmf_mux_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_mux_debug, "rtpdtmfmux", 0,
|
||||
"rtp dtmf muxer");
|
||||
|
||||
return gst_element_register (plugin, "rtpdtmfmux", GST_RANK_NONE,
|
||||
GST_TYPE_RTP_DTMF_MUX);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/* RTP muxer element for GStreamer
|
||||
*
|
||||
* gstrtpdtmfmux.h:
|
||||
*
|
||||
* Copyright (C) <2007> Nokia Corporation.
|
||||
* Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000,2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_RTP_DTMF_MUX_H__
|
||||
#define __GST_RTP_DTMF_MUX_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstrtpmux.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GST_TYPE_RTP_DTMF_MUX (gst_rtp_dtmf_mux_get_type())
|
||||
#define GST_RTP_DTMF_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DTMF_MUX, GstRTPDTMFMux))
|
||||
#define GST_RTP_DTMF_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DTMF_MUX, GstRTPDTMFMux))
|
||||
#define GST_IS_RTP_DTMF_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DTMF_MUX))
|
||||
#define GST_IS_RTP_DTMF_MUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DTMF_MUX))
|
||||
typedef struct _GstRTPDTMFMux GstRTPDTMFMux;
|
||||
typedef struct _GstRTPDTMFMuxClass GstRTPDTMFMuxClass;
|
||||
|
||||
/**
|
||||
* GstRTPDTMFMux:
|
||||
*
|
||||
* The opaque #GstRTPDTMFMux structure.
|
||||
*/
|
||||
struct _GstRTPDTMFMux
|
||||
{
|
||||
GstRTPMux mux;
|
||||
|
||||
/* Protected by object lock */
|
||||
GstClockTime last_priority_end;
|
||||
};
|
||||
|
||||
struct _GstRTPDTMFMuxClass
|
||||
{
|
||||
GstRTPMuxClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*locking) (GstElement * element, GstPad * pad);
|
||||
void (*unlocked) (GstElement * element, GstPad * pad);
|
||||
};
|
||||
|
||||
GType gst_rtp_dtmf_mux_get_type (void);
|
||||
gboolean gst_rtp_dtmf_mux_plugin_init (GstPlugin * plugin);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_RTP_DTMF_MUX_H__ */
|
|
@ -1,879 +0,0 @@
|
|||
/* RTP muxer element for GStreamer
|
||||
*
|
||||
* gstrtpmux.c:
|
||||
*
|
||||
* Copyright (C) <2007-2010> Nokia Corporation.
|
||||
* Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||
* Copyright (C) <2007-2010> Collabora Ltd
|
||||
* Contact: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000,2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-rtpmux
|
||||
* @see_also: rtpdtmfmux
|
||||
*
|
||||
* The rtp muxer takes multiple RTP streams having the same clock-rate and
|
||||
* muxes into a single stream with a single SSRC.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example pipelines</title>
|
||||
* |[
|
||||
* gst-launch rtpmux name=mux ! udpsink host=127.0.0.1 port=8888 \
|
||||
* alsasrc ! alawenc ! rtppcmapay ! \
|
||||
* application/x-rtp, payload=8, rate=8000 ! mux.sink_0 \
|
||||
* audiotestsrc is-live=1 ! \
|
||||
* mulawenc ! rtppcmupay ! \
|
||||
* application/x-rtp, payload=0, rate=8000 ! mux.sink_1
|
||||
* ]|
|
||||
* In this example, an audio stream is captured from ALSA and another is
|
||||
* generated, both are encoded into different payload types and muxed together
|
||||
* so they can be sent on the same port.
|
||||
* </refsect2>
|
||||
*
|
||||
* Last reviewed on 2010-09-30 (0.10.21)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gstrtpmux.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_rtp_mux_debug);
|
||||
#define GST_CAT_DEFAULT gst_rtp_mux_debug
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
PROP_TIMESTAMP_OFFSET,
|
||||
PROP_SEQNUM_OFFSET,
|
||||
PROP_SEQNUM,
|
||||
PROP_SSRC
|
||||
};
|
||||
|
||||
#define DEFAULT_TIMESTAMP_OFFSET -1
|
||||
#define DEFAULT_SEQNUM_OFFSET -1
|
||||
#define DEFAULT_SSRC -1
|
||||
|
||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("application/x-rtp")
|
||||
);
|
||||
|
||||
static GstPad *gst_rtp_mux_request_new_pad (GstElement * element,
|
||||
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, 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, 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);
|
||||
|
||||
static void gst_rtp_mux_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_rtp_mux_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_rtp_mux_dispose (GObject * object);
|
||||
|
||||
static gboolean gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux,
|
||||
GstEvent * event);
|
||||
|
||||
G_DEFINE_TYPE (GstRTPMux, gst_rtp_mux, GST_TYPE_ELEMENT);
|
||||
|
||||
|
||||
static void
|
||||
gst_rtp_mux_class_init (GstRTPMuxClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
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_static_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;
|
||||
|
||||
klass->src_event = gst_rtp_mux_src_event_real;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset",
|
||||
"Timestamp Offset",
|
||||
"Offset to add to all outgoing timestamps (-1 = random)", -1,
|
||||
G_MAXINT, DEFAULT_TIMESTAMP_OFFSET,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
|
||||
g_param_spec_int ("seqnum-offset", "Sequence number Offset",
|
||||
"Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXINT,
|
||||
DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
|
||||
g_param_spec_uint ("seqnum", "Sequence number",
|
||||
"The RTP sequence number of the last processed packet",
|
||||
0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
|
||||
g_param_spec_uint ("ssrc", "SSRC",
|
||||
"The SSRC of the packets (-1 == random)",
|
||||
0, G_MAXUINT, DEFAULT_SSRC,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_rtp_mux_request_new_pad);
|
||||
gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_rtp_mux_release_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rtp_mux_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_mux_dispose (GObject * object)
|
||||
{
|
||||
GstRTPMux *rtp_mux = GST_RTP_MUX (object);
|
||||
GList *item;
|
||||
|
||||
g_clear_object (&rtp_mux->last_pad);
|
||||
|
||||
restart:
|
||||
for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) {
|
||||
GstPad *pad = GST_PAD (item->data);
|
||||
if (GST_PAD_IS_SINK (pad)) {
|
||||
gst_element_release_request_pad (GST_ELEMENT (object), pad);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gst_rtp_mux_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_mux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
GstRTPMux *rtp_mux = GST_RTP_MUX (parent);
|
||||
GstRTPMuxClass *klass;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
klass = GST_RTP_MUX_GET_CLASS (rtp_mux);
|
||||
|
||||
ret = klass->src_event (rtp_mux, event);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux, GstEvent * event)
|
||||
{
|
||||
GstIterator *iter;
|
||||
gboolean result = FALSE;
|
||||
gboolean done = FALSE;
|
||||
|
||||
iter = gst_element_iterate_sink_pads (GST_ELEMENT (rtp_mux));
|
||||
|
||||
while (!done) {
|
||||
GValue item = { 0, };
|
||||
|
||||
switch (gst_iterator_next (iter, &item)) {
|
||||
case GST_ITERATOR_OK:
|
||||
gst_event_ref (event);
|
||||
result |= gst_pad_push_event (g_value_get_object (&item), event);
|
||||
g_value_reset (&item);
|
||||
break;
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (iter);
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ITERATOR_ERROR:
|
||||
GST_WARNING_OBJECT (rtp_mux, "Error iterating sinkpads");
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gst_iterator_free (iter);
|
||||
gst_event_unref (event);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_mux_init (GstRTPMux * rtp_mux)
|
||||
{
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (rtp_mux);
|
||||
|
||||
rtp_mux->srcpad =
|
||||
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
|
||||
"src"), "src");
|
||||
gst_pad_set_event_function (rtp_mux->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_rtp_mux_src_event));
|
||||
gst_element_add_pad (GST_ELEMENT (rtp_mux), rtp_mux->srcpad);
|
||||
|
||||
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
|
||||
gst_rtp_mux_setup_sinkpad (GstRTPMux * rtp_mux, GstPad * sinkpad)
|
||||
{
|
||||
GstRTPMuxPadPrivate *padpriv = g_slice_new0 (GstRTPMuxPadPrivate);
|
||||
|
||||
/* setup some pad functions */
|
||||
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_pad_set_element_private (sinkpad, padpriv);
|
||||
|
||||
gst_pad_set_active (sinkpad, TRUE);
|
||||
gst_element_add_pad (GST_ELEMENT (rtp_mux), sinkpad);
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_rtp_mux_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
GstPad *newpad;
|
||||
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_RTP_MUX (element), NULL);
|
||||
|
||||
rtp_mux = GST_RTP_MUX (element);
|
||||
|
||||
if (templ->direction != GST_PAD_SINK) {
|
||||
GST_WARNING_OBJECT (rtp_mux, "request pad that is not a SINK pad");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newpad = gst_pad_new_from_template (templ, req_name);
|
||||
if (newpad)
|
||||
gst_rtp_mux_setup_sinkpad (rtp_mux, newpad);
|
||||
else
|
||||
GST_WARNING_OBJECT (rtp_mux, "failed to create request pad");
|
||||
|
||||
return newpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_mux_release_pad (GstElement * element, GstPad * pad)
|
||||
{
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
|
||||
GST_OBJECT_LOCK (element);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
gst_pad_set_element_private (pad, NULL);
|
||||
GST_OBJECT_UNLOCK (element);
|
||||
|
||||
gst_element_remove_pad (element, pad);
|
||||
|
||||
if (padpriv) {
|
||||
g_slice_free (GstRTPMuxPadPrivate, padpriv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Put our own clock-base on the buffer */
|
||||
static void
|
||||
gst_rtp_mux_readjust_rtp_timestamp_locked (GstRTPMux * rtp_mux,
|
||||
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * rtpbuffer)
|
||||
{
|
||||
guint32 ts;
|
||||
guint32 sink_ts_base = 0;
|
||||
|
||||
if (padpriv && padpriv->have_clock_base)
|
||||
sink_ts_base = padpriv->clock_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 (rtpbuffer), ts);
|
||||
gst_rtp_buffer_set_timestamp (rtpbuffer, ts);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_buffer_locked (GstRTPMux * rtp_mux, GstRTPMuxPadPrivate * padpriv,
|
||||
GstRTPBuffer * rtpbuffer)
|
||||
{
|
||||
GstRTPMuxClass *klass = GST_RTP_MUX_GET_CLASS (rtp_mux);
|
||||
|
||||
if (klass->accept_buffer_locked)
|
||||
if (!klass->accept_buffer_locked (rtp_mux, padpriv, rtpbuffer))
|
||||
return FALSE;
|
||||
|
||||
rtp_mux->seqnum++;
|
||||
gst_rtp_buffer_set_seq (rtpbuffer, rtp_mux->seqnum);
|
||||
|
||||
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 %" G_GSIZE_FORMAT ", seq=%d, ts=%u",
|
||||
rtpbuffer->map[0].size, rtp_mux->seqnum,
|
||||
gst_rtp_buffer_get_timestamp (rtpbuffer));
|
||||
|
||||
if (padpriv) {
|
||||
if (padpriv->segment.format == GST_FORMAT_TIME)
|
||||
GST_BUFFER_PTS (rtpbuffer->buffer) =
|
||||
gst_segment_to_running_time (&padpriv->segment, GST_FORMAT_TIME,
|
||||
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, GstObject * parent,
|
||||
GstBufferList * bufferlist)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
GstFlowReturn ret;
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
gboolean drop = TRUE;
|
||||
struct BufferListData bd;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (parent);
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
if (!padpriv) {
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
gst_buffer_list_unref (bufferlist);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bd.rtp_mux = rtp_mux;
|
||||
bd.padpriv = padpriv;
|
||||
bd.drop = FALSE;
|
||||
|
||||
bufferlist = gst_buffer_list_make_writable (bufferlist);
|
||||
gst_buffer_list_foreach (bufferlist, process_list_item, &bd);
|
||||
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
if (drop) {
|
||||
gst_buffer_list_unref (bufferlist);
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
ret = gst_pad_push_list (rtp_mux->srcpad, bufferlist);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
resend_events (GstPad * pad, GstEvent ** event, gpointer user_data)
|
||||
{
|
||||
GstRTPMux *rtp_mux = user_data;
|
||||
|
||||
if (GST_EVENT_TYPE (*event) == GST_EVENT_CAPS) {
|
||||
GstCaps *caps;
|
||||
|
||||
gst_event_parse_caps (*event, &caps);
|
||||
gst_rtp_mux_setcaps (pad, rtp_mux, caps);
|
||||
} else {
|
||||
gst_pad_push_event (rtp_mux->srcpad, gst_event_ref (*event));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtp_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
GstFlowReturn ret;
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
gboolean drop;
|
||||
gboolean changed = FALSE;
|
||||
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (GST_OBJECT_PARENT (pad));
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
|
||||
if (!padpriv) {
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
|
||||
buffer = gst_buffer_make_writable (buffer);
|
||||
|
||||
if (!gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtpbuffer)) {
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
gst_buffer_unref (buffer);
|
||||
GST_ERROR_OBJECT (rtp_mux, "Invalid RTP buffer");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
drop = !process_buffer_locked (rtp_mux, padpriv, &rtpbuffer);
|
||||
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
|
||||
if (!drop) {
|
||||
if (pad != rtp_mux->last_pad) {
|
||||
changed = TRUE;
|
||||
g_clear_object (&rtp_mux->last_pad);
|
||||
rtp_mux->last_pad = g_object_ref (pad);
|
||||
}
|
||||
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buffer) &&
|
||||
GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
|
||||
rtp_mux->last_stop = GST_BUFFER_TIMESTAMP (buffer) +
|
||||
GST_BUFFER_DURATION (buffer);
|
||||
else
|
||||
rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
if (changed)
|
||||
gst_pad_sticky_events_foreach (pad, resend_events, rtp_mux);
|
||||
|
||||
if (drop) {
|
||||
gst_buffer_unref (buffer);
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
ret = gst_pad_push (rtp_mux->srcpad, buffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
|
||||
{
|
||||
GstStructure *structure;
|
||||
gboolean ret = FALSE;
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!structure)
|
||||
return FALSE;
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
if (padpriv &&
|
||||
gst_structure_get_uint (structure, "clock-base", &padpriv->clock_base)) {
|
||||
padpriv->have_clock_base = TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
caps = gst_caps_copy (caps);
|
||||
|
||||
gst_caps_set_simple (caps,
|
||||
"clock-base", G_TYPE_UINT, rtp_mux->ts_base,
|
||||
"seqnum-base", G_TYPE_UINT, rtp_mux->seqnum_base, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (rtp_mux,
|
||||
"setting caps %" GST_PTR_FORMAT " on src pad..", caps);
|
||||
ret = gst_pad_set_caps (rtp_mux->srcpad, caps);
|
||||
|
||||
if (rtp_mux->ssrc == -1) {
|
||||
if (gst_structure_has_field_typed (structure, "ssrc", G_TYPE_UINT)) {
|
||||
rtp_mux->current_ssrc = g_value_get_uint
|
||||
(gst_structure_get_value (structure, "ssrc"));
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_caps (GstCaps * caps, gboolean only_clock_rate)
|
||||
{
|
||||
gint i, j;
|
||||
|
||||
/* Lets only match on the clock-rate */
|
||||
for (i = 0; i < gst_caps_get_size (caps); i++) {
|
||||
GstStructure *s = gst_caps_get_structure (caps, i);
|
||||
|
||||
for (j = 0; j < gst_structure_n_fields (s); j++) {
|
||||
const gchar *name = gst_structure_nth_field_name (s, j);
|
||||
|
||||
if (strcmp (name, "clock-rate") && (only_clock_rate ||
|
||||
(strcmp (name, "ssrc")))) {
|
||||
gst_structure_remove_field (s, name);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
same_clock_rate_fold (const GValue * item, GValue * ret, gpointer user_data)
|
||||
{
|
||||
GstPad *mypad = user_data;
|
||||
GstPad *pad = g_value_get_object (item);
|
||||
GstCaps *peercaps;
|
||||
GstCaps *accumcaps;
|
||||
GstCaps *intersect;
|
||||
|
||||
if (pad == mypad)
|
||||
return TRUE;
|
||||
|
||||
accumcaps = g_value_get_boxed (ret);
|
||||
peercaps = gst_pad_peer_query_caps (pad, accumcaps);
|
||||
if (!peercaps) {
|
||||
g_warning ("no peercaps");
|
||||
return TRUE;
|
||||
}
|
||||
peercaps = gst_caps_make_writable (peercaps);
|
||||
clear_caps (peercaps, TRUE);
|
||||
|
||||
intersect = gst_caps_intersect (accumcaps, peercaps);
|
||||
|
||||
g_value_take_boxed (ret, intersect);
|
||||
gst_caps_unref (peercaps);
|
||||
|
||||
return !gst_caps_is_empty (intersect);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_rtp_mux_getcaps (GstPad * pad, GstRTPMux * mux, GstCaps * filter)
|
||||
{
|
||||
GstCaps *caps = NULL;
|
||||
GstIterator *iter = NULL;
|
||||
GValue v = { 0 };
|
||||
GstIteratorResult res;
|
||||
GstCaps *peercaps;
|
||||
GstCaps *othercaps = NULL;
|
||||
GstCaps *filtered_caps;
|
||||
|
||||
peercaps = gst_pad_peer_query_caps (mux->srcpad, filter);
|
||||
|
||||
if (peercaps) {
|
||||
othercaps = gst_caps_intersect (peercaps,
|
||||
gst_pad_get_pad_template_caps (pad));
|
||||
gst_caps_unref (peercaps);
|
||||
} else {
|
||||
othercaps = gst_caps_copy (gst_pad_get_pad_template_caps (mux->srcpad));
|
||||
}
|
||||
|
||||
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, filtered_caps);
|
||||
res = gst_iterator_fold (iter, same_clock_rate_fold, &v, pad);
|
||||
gst_iterator_resync (iter);
|
||||
} while (res == GST_ITERATOR_RESYNC);
|
||||
gst_iterator_free (iter);
|
||||
|
||||
caps = (GstCaps *) gst_value_get_caps (&v);
|
||||
|
||||
if (res == GST_ITERATOR_ERROR) {
|
||||
gst_caps_unref (caps);
|
||||
caps = gst_caps_new_empty ();
|
||||
}
|
||||
|
||||
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,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TIMESTAMP_OFFSET:
|
||||
g_value_set_int (value, rtp_mux->ts_offset);
|
||||
break;
|
||||
case PROP_SEQNUM_OFFSET:
|
||||
g_value_set_int (value, rtp_mux->seqnum_offset);
|
||||
break;
|
||||
case PROP_SEQNUM:
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
g_value_set_uint (value, rtp_mux->seqnum);
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
break;
|
||||
case PROP_SSRC:
|
||||
g_value_set_uint (value, rtp_mux->ssrc);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_mux_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TIMESTAMP_OFFSET:
|
||||
rtp_mux->ts_offset = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SEQNUM_OFFSET:
|
||||
rtp_mux->seqnum_offset = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SSRC:
|
||||
rtp_mux->ssrc = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtp_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
GstRTPMux *mux = GST_RTP_MUX (parent);
|
||||
gboolean is_pad;
|
||||
gboolean ret;
|
||||
|
||||
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);
|
||||
gst_event_unref (event);
|
||||
return ret;
|
||||
}
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
{
|
||||
GST_OBJECT_LOCK (mux);
|
||||
mux->last_stop = GST_CLOCK_TIME_NONE;
|
||||
GST_OBJECT_UNLOCK (mux);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_SEGMENT:
|
||||
{
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
|
||||
GST_OBJECT_LOCK (mux);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
|
||||
if (padpriv) {
|
||||
gst_event_copy_segment (event, &padpriv->segment);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (mux);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (mux);
|
||||
is_pad = (pad == mux->last_pad);
|
||||
GST_OBJECT_UNLOCK (mux);
|
||||
|
||||
if (is_pad) {
|
||||
return gst_pad_push_event (mux->srcpad, event);
|
||||
} else {
|
||||
gst_event_unref (event);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_mux_ready_to_paused (GstRTPMux * rtp_mux)
|
||||
{
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
|
||||
g_clear_object (&rtp_mux->last_pad);
|
||||
|
||||
if (rtp_mux->ssrc == -1)
|
||||
rtp_mux->current_ssrc = g_random_int ();
|
||||
else
|
||||
rtp_mux->current_ssrc = rtp_mux->ssrc;
|
||||
|
||||
if (rtp_mux->seqnum_offset == -1)
|
||||
rtp_mux->seqnum_base = g_random_int_range (0, G_MAXUINT16);
|
||||
else
|
||||
rtp_mux->seqnum_base = rtp_mux->seqnum_offset;
|
||||
rtp_mux->seqnum = rtp_mux->seqnum_base;
|
||||
|
||||
if (rtp_mux->ts_offset == -1)
|
||||
rtp_mux->ts_base = g_random_int ();
|
||||
else
|
||||
rtp_mux->ts_base = rtp_mux->ts_offset;
|
||||
|
||||
rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
|
||||
|
||||
GST_DEBUG_OBJECT (rtp_mux, "set clock-base to %u", rtp_mux->ts_base);
|
||||
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_rtp_mux_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstRTPMux *rtp_mux;
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_rtp_mux_ready_to_paused (rtp_mux);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS (gst_rtp_mux_parent_class)->change_state (element,
|
||||
transition);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
g_clear_object (&rtp_mux->last_pad);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_rtp_mux_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_rtp_mux_debug, "rtpmux", 0, "rtp muxer");
|
||||
|
||||
return gst_element_register (plugin, "rtpmux", GST_RANK_NONE,
|
||||
GST_TYPE_RTP_MUX);
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/* RTP muxer element for GStreamer
|
||||
*
|
||||
* gstrtpmux.h:
|
||||
*
|
||||
* Copyright (C) <2007> Nokia Corporation.
|
||||
* Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000,2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_RTP_MUX_H__
|
||||
#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())
|
||||
#define GST_RTP_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MUX, GstRTPMux))
|
||||
#define GST_RTP_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MUX, GstRTPMuxClass))
|
||||
#define GST_RTP_MUX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTP_MUX, GstRTPMuxClass))
|
||||
#define GST_IS_RTP_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MUX))
|
||||
#define GST_IS_RTP_MUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MUX))
|
||||
typedef struct _GstRTPMux GstRTPMux;
|
||||
typedef struct _GstRTPMuxClass GstRTPMuxClass;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean have_clock_base;
|
||||
guint clock_base;
|
||||
|
||||
GstSegment segment;
|
||||
|
||||
gboolean priority;
|
||||
} GstRTPMuxPadPrivate;
|
||||
|
||||
|
||||
/**
|
||||
* GstRTPMux:
|
||||
*
|
||||
* The opaque #GstRTPMux structure.
|
||||
*/
|
||||
struct _GstRTPMux
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
/* pad */
|
||||
GstPad *srcpad;
|
||||
|
||||
guint32 ts_base;
|
||||
guint16 seqnum_base;
|
||||
|
||||
gint32 ts_offset;
|
||||
gint16 seqnum_offset;
|
||||
guint16 seqnum; /* protected by object lock */
|
||||
guint ssrc;
|
||||
guint current_ssrc;
|
||||
|
||||
GstPad *last_pad; /* protected by object lock */
|
||||
|
||||
GstClockTime last_stop;
|
||||
};
|
||||
|
||||
struct _GstRTPMuxClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
|
||||
gboolean (*accept_buffer_locked) (GstRTPMux *rtp_mux,
|
||||
GstRTPMuxPadPrivate * padpriv, GstRTPBuffer * buffer);
|
||||
|
||||
gboolean (*src_event) (GstRTPMux *rtp_mux, GstEvent *event);
|
||||
};
|
||||
|
||||
|
||||
GType gst_rtp_mux_get_type (void);
|
||||
gboolean gst_rtp_mux_plugin_init (GstPlugin * plugin);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_RTP_MUX_H__ */
|
|
@ -1,48 +0,0 @@
|
|||
/* GStreamer RTP Muxer Plugins
|
||||
*
|
||||
* gstrtpdtmf.c:
|
||||
*
|
||||
* Copyright (C) <2007> Nokia Corporation.
|
||||
* Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000,2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstrtpmux.h"
|
||||
#include "gstrtpdtmfmux.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
if (!gst_rtp_mux_plugin_init (plugin))
|
||||
return FALSE;
|
||||
if (!gst_rtp_dtmf_mux_plugin_init (plugin))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
rtpmux,
|
||||
"RTP Muxer plugins",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
|
@ -224,7 +224,6 @@ check_PROGRAMS = \
|
|||
elements/id3mux \
|
||||
pipelines/mxf \
|
||||
$(check_mimic) \
|
||||
elements/rtpmux \
|
||||
libs/mpegvideoparser \
|
||||
libs/h264parser \
|
||||
$(check_uvch264) \
|
||||
|
@ -349,9 +348,6 @@ elements_timidity_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
|||
elements_kate_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||
elements_kate_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
elements_rtpmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||
elements_rtpmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-$(GST_API_VERSION) $(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
elements_assrender_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||
elements_assrender_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) -lgstapp-$(GST_API_VERSION) $(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
|
|
1
tests/check/elements/.gitignore
vendored
1
tests/check/elements/.gitignore
vendored
|
@ -40,7 +40,6 @@ opus
|
|||
rganalysis
|
||||
rglimiter
|
||||
rgvolume
|
||||
rtpmux
|
||||
schroenc
|
||||
spectrum
|
||||
timidity
|
||||
|
|
|
@ -1,311 +0,0 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* unit test for rtpmux elements
|
||||
*
|
||||
* Copyright 2009 Collabora Ltd.
|
||||
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
* Copyright 2009 Nokia Corp.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp"));
|
||||
|
||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp"));
|
||||
|
||||
typedef void (*check_cb) (GstPad * pad, int i);
|
||||
|
||||
static gboolean
|
||||
query_func (GstPad * pad, GstObject * noparent, GstQuery * query)
|
||||
{
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CAPS:
|
||||
{
|
||||
GstCaps **caps = g_object_get_data (G_OBJECT (pad), "caps");
|
||||
|
||||
fail_unless (caps != NULL && *caps != NULL);
|
||||
gst_query_set_caps_result (query, *caps);
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_ACCEPT_CAPS:
|
||||
gst_query_set_accept_caps_result (query, TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_func (GstPad * pad, GstObject * noparent, GstEvent * 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_fixed (caps));
|
||||
fail_unless (gst_caps_is_fixed (*caps2));
|
||||
fail_unless (gst_caps_is_equal_fixed (caps, *caps2));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gst_event_unref (event);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic (const gchar * elem_name, const gchar * sink2, int count,
|
||||
check_cb cb)
|
||||
{
|
||||
GstElement *rtpmux = NULL;
|
||||
GstPad *reqpad1 = NULL;
|
||||
GstPad *reqpad2 = NULL;
|
||||
GstPad *src1 = NULL;
|
||||
GstPad *src2 = NULL;
|
||||
GstPad *sink = NULL;
|
||||
GstBuffer *inbuf = NULL;
|
||||
GstCaps *src1caps = NULL;
|
||||
GstCaps *src2caps = NULL;
|
||||
GstCaps *sinkcaps = NULL;
|
||||
GstCaps *caps;
|
||||
GstSegment segment;
|
||||
int i;
|
||||
|
||||
rtpmux = gst_check_setup_element (elem_name);
|
||||
|
||||
reqpad1 = gst_element_get_request_pad (rtpmux, "sink_1");
|
||||
fail_unless (reqpad1 != NULL);
|
||||
reqpad2 = gst_element_get_request_pad (rtpmux, sink2);
|
||||
fail_unless (reqpad2 != NULL);
|
||||
sink = gst_check_setup_sink_pad_by_name (rtpmux, &sinktemplate, "src");
|
||||
|
||||
src1 = gst_pad_new_from_static_template (&srctemplate, "src");
|
||||
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_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);
|
||||
g_object_set_data (G_OBJECT (sink), "caps", &sinkcaps);
|
||||
|
||||
src1caps = gst_caps_new_simple ("application/x-rtp",
|
||||
"clock-rate", G_TYPE_INT, 1, "ssrc", G_TYPE_UINT, 11, NULL);
|
||||
src2caps = gst_caps_new_simple ("application/x-rtp",
|
||||
"clock-rate", G_TYPE_INT, 2, "ssrc", G_TYPE_UINT, 12, NULL);
|
||||
sinkcaps = gst_caps_new_simple ("application/x-rtp",
|
||||
"clock-rate", G_TYPE_INT, 3, "ssrc", G_TYPE_UINT, 13, NULL);
|
||||
|
||||
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_query_caps (src1, NULL);
|
||||
fail_unless (gst_caps_is_equal (caps, sinkcaps));
|
||||
gst_caps_unref (caps);
|
||||
|
||||
g_object_set (rtpmux, "seqnum-offset", 100, "timestamp-offset", 1000,
|
||||
"ssrc", 55, NULL);
|
||||
|
||||
fail_unless (gst_element_set_state (rtpmux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
gst_pad_set_active (sink, TRUE);
|
||||
gst_pad_set_active (src1, TRUE);
|
||||
gst_pad_set_active (src2, TRUE);
|
||||
|
||||
gst_caps_set_simple (sinkcaps,
|
||||
"payload", G_TYPE_INT, 98, "seqnum-base", G_TYPE_UINT, 100,
|
||||
"clock-base", G_TYPE_UINT, 1000, "ssrc", G_TYPE_UINT, 66, NULL);
|
||||
caps = gst_caps_new_simple ("application/x-rtp",
|
||||
"payload", G_TYPE_INT, 98, "clock-rate", G_TYPE_INT, 3,
|
||||
"seqnum-base", G_TYPE_UINT, 56, "clock-base", G_TYPE_UINT, 57,
|
||||
"ssrc", G_TYPE_UINT, 66, NULL);
|
||||
fail_unless (gst_pad_set_caps (src1, caps));
|
||||
|
||||
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_PTS (inbuf) = i * 1000 + 100000;
|
||||
GST_BUFFER_DURATION (inbuf) = 1000;
|
||||
|
||||
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_PTS (buffers->data) == i * 1000, "%lld",
|
||||
GST_BUFFER_PTS (buffers->data));
|
||||
|
||||
cb (src2, i);
|
||||
|
||||
g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
|
||||
g_list_free (buffers);
|
||||
buffers = NULL;
|
||||
}
|
||||
|
||||
|
||||
gst_pad_set_active (sink, FALSE);
|
||||
gst_pad_set_active (src1, FALSE);
|
||||
gst_pad_set_active (src2, FALSE);
|
||||
fail_unless (gst_element_set_state (rtpmux,
|
||||
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||
gst_check_teardown_pad_by_name (rtpmux, "src");
|
||||
gst_object_unref (reqpad1);
|
||||
gst_object_unref (reqpad2);
|
||||
gst_check_teardown_pad_by_name (rtpmux, "sink_1");
|
||||
gst_check_teardown_pad_by_name (rtpmux, sink2);
|
||||
gst_element_release_request_pad (rtpmux, reqpad1);
|
||||
gst_element_release_request_pad (rtpmux, reqpad2);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
gst_caps_replace (&src1caps, NULL);
|
||||
gst_caps_replace (&src2caps, NULL);
|
||||
gst_caps_replace (&sinkcaps, NULL);
|
||||
|
||||
gst_check_teardown_element (rtpmux);
|
||||
}
|
||||
|
||||
static void
|
||||
basic_check_cb (GstPad * pad, int i)
|
||||
{
|
||||
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
|
||||
fail_unless (buffers && g_list_length (buffers) == 1);
|
||||
|
||||
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 (&rtpbuffer) == 100 + 1 + i);
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
}
|
||||
|
||||
|
||||
GST_START_TEST (test_rtpmux_basic)
|
||||
{
|
||||
test_basic ("rtpmux", "sink_2", 10, basic_check_cb);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtpdtmfmux_basic)
|
||||
{
|
||||
test_basic ("rtpdtmfmux", "sink_2", 10, basic_check_cb);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
lock_check_cb (GstPad * pad, int i)
|
||||
{
|
||||
GstBuffer *inbuf;
|
||||
|
||||
if (i % 2) {
|
||||
fail_unless (buffers == NULL);
|
||||
} else {
|
||||
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
|
||||
|
||||
fail_unless (buffers && g_list_length (buffers) == 1);
|
||||
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 (&rtpbuffer) == 100 + 1 + i);
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
|
||||
inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
|
||||
GST_BUFFER_PTS (inbuf) = i * 1000 + 500;
|
||||
GST_BUFFER_DURATION (inbuf) = 1000;
|
||||
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);
|
||||
|
||||
|
||||
g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
|
||||
g_list_free (buffers);
|
||||
buffers = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GST_START_TEST (test_rtpdtmfmux_lock)
|
||||
{
|
||||
test_basic ("rtpdtmfmux", "priority_sink_2", 10, lock_check_cb);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtpmux_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("rtpmux");
|
||||
TCase *tc_chain;
|
||||
|
||||
tc_chain = tcase_create ("rtpmux_basic");
|
||||
tcase_add_test (tc_chain, test_rtpmux_basic);
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
tc_chain = tcase_create ("rtpdtmfmux_basic");
|
||||
tcase_add_test (tc_chain, test_rtpdtmfmux_basic);
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
tc_chain = tcase_create ("rtpdtmfmux_lock");
|
||||
tcase_add_test (tc_chain, test_rtpdtmfmux_lock);
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (rtpmux)
|
Loading…
Reference in a new issue