mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
Merge branch 'master' into 0.11-fdo
Conflicts: docs/plugins/gstreamer-plugins.hierarchy gst/gstelement.c
This commit is contained in:
commit
7a62d32a07
14 changed files with 916 additions and 28 deletions
|
@ -24,6 +24,7 @@
|
|||
<xi:include href="xml/element-fdsrc.xml" />
|
||||
<xi:include href="xml/element-filesrc.xml" />
|
||||
<xi:include href="xml/element-filesink.xml" />
|
||||
<xi:include href="xml/element-funnel.xml" />
|
||||
<xi:include href="xml/element-identity.xml" />
|
||||
<xi:include href="xml/element-input-selector.xml" />
|
||||
<xi:include href="xml/element-multiqueue.xml" />
|
||||
|
|
|
@ -95,6 +95,21 @@ GST_IS_FILE_SINK_CLASS
|
|||
gst_file_sink_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-funnel</FILE>
|
||||
<TITLE>funnel</TITLE>
|
||||
GstFunnel
|
||||
<SUBSECTION Standard>
|
||||
GstFunnelClass
|
||||
GST_FUNNEL
|
||||
GST_IS_FUNNEL
|
||||
GST_TYPE_FUNNEL
|
||||
GST_FUNNEL_CLASS
|
||||
GST_IS_FUNNEL_CLASS
|
||||
<SUBSECTION Private>
|
||||
gst_funnel_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-capsfilter</FILE>
|
||||
<TITLE>capsfilter</TITLE>
|
||||
|
|
|
@ -22,6 +22,7 @@ GObject
|
|||
GstFakeSink
|
||||
GstFdSink
|
||||
GstFileSink
|
||||
GstFunnel
|
||||
GstInputSelector
|
||||
GstOutputSelector
|
||||
GstQueue
|
||||
|
|
|
@ -120,6 +120,27 @@
|
|||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>funnel</name>
|
||||
<longname>Farsight Funnel pipe fitting</longname>
|
||||
<class>Generic</class>
|
||||
<description>N-to-1 pipe fitting</description>
|
||||
<author>Olivier Crete <olivier.crete@collabora.co.uk></author>
|
||||
<pads>
|
||||
<caps>
|
||||
<name>sink%d</name>
|
||||
<direction>sink</direction>
|
||||
<presence>request</presence>
|
||||
<details>ANY</details>
|
||||
</caps>
|
||||
<caps>
|
||||
<name>src</name>
|
||||
<direction>source</direction>
|
||||
<presence>always</presence>
|
||||
<details>ANY</details>
|
||||
</caps>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>identity</name>
|
||||
<longname>Identity</longname>
|
||||
|
|
12
docs/plugins/inspect/plugin-staticelements.xml
Normal file
12
docs/plugins/inspect/plugin-staticelements.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<plugin>
|
||||
<name>staticelements</name> <description>core elements linked into the GStreamer library</description> <filename></filename> <basename></basename> <version>0.10.29.1</version> <license>LGPL</license> <source>gstreamer</source> <package>GStreamer git</package> <origin>Unknown package origin</origin> <elements>
|
||||
<element>
|
||||
<name>bin</name> <longname>Generic bin</longname> <class>Generic/Bin</class> <description>Simple container object</description> <author>Erik Walthinsen <omega@cse.ogi.edu>,Wim Taymans <wim.taymans@gmail.com></author> <pads>
|
||||
</pads>
|
||||
</element>
|
||||
<element>
|
||||
<name>pipeline</name> <longname>Pipeline object</longname> <class>Generic/Bin</class> <description>Complete pipeline object</description> <author>Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com></author> <pads>
|
||||
</pads>
|
||||
</element>
|
||||
</elements>
|
||||
</plugin>
|
|
@ -953,6 +953,51 @@ _gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
|
|||
|
||||
oclass = GST_ELEMENT_GET_CLASS (element);
|
||||
|
||||
#ifndef G_DISABLE_CHECKS
|
||||
/* Some sanity checking here */
|
||||
if (name) {
|
||||
GstPad *pad;
|
||||
|
||||
/* Is this the template name? */
|
||||
if (strstr (name, "%") || !strchr (templ->name_template, '%')) {
|
||||
g_return_val_if_fail (strcmp (name, templ->name_template) == 0, NULL);
|
||||
} else {
|
||||
const gchar *str, *data;
|
||||
gchar *endptr;
|
||||
|
||||
/* Otherwise check if it's a valid name for the name template */
|
||||
str = strchr (templ->name_template, '%');
|
||||
g_return_val_if_fail (str != NULL, NULL);
|
||||
g_return_val_if_fail (strncmp (templ->name_template, name,
|
||||
str - templ->name_template) == 0, NULL);
|
||||
g_return_val_if_fail (strlen (name) > str - templ->name_template, NULL);
|
||||
|
||||
data = name + (str - templ->name_template);
|
||||
|
||||
/* Can either be %s or %d or %u, do sanity checking for %d */
|
||||
if (*(str + 1) == 'd') {
|
||||
gint tmp;
|
||||
|
||||
/* it's an int */
|
||||
tmp = strtol (data, &endptr, 10);
|
||||
g_return_val_if_fail (tmp != G_MINLONG && tmp != G_MAXLONG
|
||||
&& *endptr == '\0', NULL);
|
||||
} else if (*(str + 1) == 'u') {
|
||||
guint tmp;
|
||||
|
||||
/* it's an int */
|
||||
tmp = strtoul (data, &endptr, 10);
|
||||
g_return_val_if_fail (tmp != G_MAXULONG && *endptr == '\0', NULL);
|
||||
}
|
||||
}
|
||||
|
||||
pad = gst_element_get_static_pad (element, name);
|
||||
if (pad)
|
||||
gst_object_unref (pad);
|
||||
g_return_val_if_fail (pad == NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (oclass->request_new_pad_full)
|
||||
newpad = (oclass->request_new_pad_full) (element, templ, name, caps);
|
||||
else if (oclass->request_new_pad)
|
||||
|
@ -1018,7 +1063,7 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
|
|||
break;
|
||||
}
|
||||
/* Because of sanity checks in gst_pad_template_new(), we know that %s
|
||||
and %d, occurring at the end of the name_template, are the only
|
||||
and %d and %u, occurring at the end of the name_template, are the only
|
||||
possibilities. */
|
||||
else if ((str = strchr (templ->name_template, '%'))
|
||||
&& strncmp (templ->name_template, name,
|
||||
|
@ -1036,6 +1081,16 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
|
|||
req_name = name;
|
||||
break;
|
||||
}
|
||||
} else if (*(str + 1) == 'u') {
|
||||
guint tmp;
|
||||
|
||||
/* it's an int */
|
||||
tmp = strtoul (data, &endptr, 10);
|
||||
if (tmp != G_MAXULONG && endptr && *endptr == '\0') {
|
||||
templ_found = TRUE;
|
||||
req_name = name;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* it's a string */
|
||||
templ_found = TRUE;
|
||||
|
@ -1322,8 +1377,8 @@ gst_element_class_get_pad_template_list (GstElementClass * element_class)
|
|||
* if none was found. No unreferencing is necessary.
|
||||
*/
|
||||
GstPadTemplate *
|
||||
gst_element_class_get_pad_template (GstElementClass * element_class,
|
||||
const gchar * name)
|
||||
gst_element_class_get_pad_template (GstElementClass *
|
||||
element_class, const gchar * name)
|
||||
{
|
||||
GList *padlist;
|
||||
|
||||
|
@ -1345,8 +1400,8 @@ gst_element_class_get_pad_template (GstElementClass * element_class,
|
|||
}
|
||||
|
||||
static GstPadTemplate *
|
||||
gst_element_class_get_request_pad_template (GstElementClass * element_class,
|
||||
const gchar * name)
|
||||
gst_element_class_get_request_pad_template (GstElementClass *
|
||||
element_class, const gchar * name)
|
||||
{
|
||||
GstPadTemplate *tmpl;
|
||||
|
||||
|
@ -1361,8 +1416,8 @@ gst_element_class_get_request_pad_template (GstElementClass * element_class,
|
|||
* The pad is random in a sense that it is the first pad that is (optionaly) linked.
|
||||
*/
|
||||
static GstPad *
|
||||
gst_element_get_random_pad (GstElement * element, gboolean need_linked,
|
||||
GstPadDirection dir)
|
||||
gst_element_get_random_pad (GstElement * element,
|
||||
gboolean need_linked, GstPadDirection dir)
|
||||
{
|
||||
GstPad *result = NULL;
|
||||
GList *pads;
|
||||
|
@ -1873,7 +1928,8 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state)
|
|||
|
||||
was_ok:
|
||||
{
|
||||
GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was already in locked state %d",
|
||||
GST_CAT_DEBUG (GST_CAT_STATES,
|
||||
"elements %s was already in locked state %d",
|
||||
GST_ELEMENT_NAME (element), old);
|
||||
GST_OBJECT_UNLOCK (element);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ libgstcoreelements_la_SOURCES = \
|
|||
gstfdsink.c \
|
||||
gstfilesink.c \
|
||||
gstfilesrc.c \
|
||||
gstfunnel.c \
|
||||
gstidentity.c \
|
||||
gstinputselector.c \
|
||||
gstoutputselector.c \
|
||||
|
@ -36,6 +37,7 @@ noinst_HEADERS = \
|
|||
gstfdsink.h \
|
||||
gstfilesink.h \
|
||||
gstfilesrc.h \
|
||||
gstfunnel.h \
|
||||
gstidentity.h \
|
||||
gstinputselector.h \
|
||||
gstoutputselector.h \
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "gstfdsink.h"
|
||||
#include "gstfilesink.h"
|
||||
#include "gstfilesrc.h"
|
||||
#include "gstfunnel.h"
|
||||
#include "gstidentity.h"
|
||||
#include "gstinputselector.h"
|
||||
#include "gstoutputselector.h"
|
||||
|
@ -61,6 +62,7 @@ static struct _elements_entry _elements[] = {
|
|||
{"fdsink", GST_RANK_NONE, gst_fd_sink_get_type},
|
||||
#endif
|
||||
{"filesrc", GST_RANK_PRIMARY, gst_file_src_get_type},
|
||||
{"funnel", GST_RANK_NONE, gst_funnel_get_type},
|
||||
{"identity", GST_RANK_NONE, gst_identity_get_type},
|
||||
{"input-selector", GST_RANK_NONE, gst_input_selector_get_type},
|
||||
{"output-selector", GST_RANK_NONE, gst_output_selector_get_type},
|
||||
|
|
456
plugins/elements/gstfunnel.c
Normal file
456
plugins/elements/gstfunnel.c
Normal file
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* GStreamer Funnel element
|
||||
*
|
||||
* Copyright 2007 Collabora Ltd.
|
||||
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
* Copyright 2007 Nokia Corp.
|
||||
*
|
||||
* gstfunnel.c: Simple Funnel element
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-funnel
|
||||
* @short_description: N-to-1 simple funnel
|
||||
*
|
||||
* Takes packets from various input sinks into one output source.
|
||||
*
|
||||
* funnel always outputs a single, open ended segment from
|
||||
* 0 with in %GST_FORMAT_TIME and outputs the buffers of the
|
||||
* different sinkpads with timestamps that are set to the
|
||||
* running time for that stream. funnel does not synchronize
|
||||
* the different input streams but simply forwards all buffers
|
||||
* immediately when they arrive.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstfunnel.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_funnel_debug);
|
||||
#define GST_CAT_DEFAULT gst_funnel_debug
|
||||
|
||||
GType gst_funnel_pad_get_type (void);
|
||||
#define GST_TYPE_FUNNEL_PAD \
|
||||
(gst_funnel_pad_get_type())
|
||||
#define GST_FUNNEL_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FUNNEL_PAD, GstFunnelPad))
|
||||
#define GST_FUNNEL_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_FUNNEL_PAD, GstFunnelPadClass))
|
||||
#define GST_IS_FUNNEL_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FUNNEL_PAD))
|
||||
#define GST_IS_FUNNEL_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_FUNNEL_PAD))
|
||||
#define GST_FUNNEL_PAD_CAST(obj) \
|
||||
((GstFunnelPad *)(obj))
|
||||
|
||||
typedef struct _GstFunnelPad GstFunnelPad;
|
||||
typedef struct _GstFunnelPadClass GstFunnelPadClass;
|
||||
|
||||
struct _GstFunnelPad
|
||||
{
|
||||
GstPad parent;
|
||||
|
||||
GstSegment segment;
|
||||
};
|
||||
|
||||
struct _GstFunnelPadClass
|
||||
{
|
||||
GstPadClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstFunnelPad, gst_funnel_pad, GST_TYPE_PAD);
|
||||
|
||||
static void
|
||||
gst_funnel_pad_class_init (GstFunnelPadClass * klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_pad_reset (GstFunnelPad * pad)
|
||||
{
|
||||
gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_pad_init (GstFunnelPad * pad)
|
||||
{
|
||||
gst_funnel_pad_reset (pad);
|
||||
}
|
||||
|
||||
static GstStaticPadTemplate funnel_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate funnel_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static void
|
||||
_do_init (GType type)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_funnel_debug, "funnel", 0, "funnel element");
|
||||
}
|
||||
|
||||
GST_BOILERPLATE_FULL (GstFunnel, gst_funnel, GstElement, GST_TYPE_ELEMENT,
|
||||
_do_init);
|
||||
|
||||
static GstStateChangeReturn gst_funnel_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
static GstPad *gst_funnel_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name);
|
||||
static void gst_funnel_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static GstFlowReturn gst_funnel_sink_buffer_alloc (GstPad * pad, guint64 offset,
|
||||
guint size, GstCaps * caps, GstBuffer ** buf);
|
||||
static gboolean gst_funnel_sink_event (GstPad * pad, GstEvent * event);
|
||||
static GstCaps *gst_funnel_sink_getcaps (GstPad * pad);
|
||||
|
||||
static gboolean gst_funnel_src_event (GstPad * pad, GstEvent * event);
|
||||
|
||||
static void
|
||||
gst_funnel_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class,
|
||||
"Farsight Funnel pipe fitting", "Generic", "N-to-1 pipe fitting",
|
||||
"Olivier Crete <olivier.crete@collabora.co.uk>");
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&funnel_sink_template));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&funnel_src_template));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_dispose (GObject * object)
|
||||
{
|
||||
GList *item;
|
||||
|
||||
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 (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_class_init (GstFunnelClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_funnel_dispose);
|
||||
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_funnel_request_new_pad);
|
||||
gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_funnel_release_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_funnel_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_init (GstFunnel * funnel, GstFunnelClass * g_class)
|
||||
{
|
||||
funnel->srcpad = gst_pad_new_from_static_template (&funnel_src_template,
|
||||
"src");
|
||||
gst_pad_set_event_function (funnel->srcpad, gst_funnel_src_event);
|
||||
gst_pad_use_fixed_caps (funnel->srcpad);
|
||||
gst_element_add_pad (GST_ELEMENT (funnel), funnel->srcpad);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_funnel_sink_buffer_alloc (GstPad * pad, guint64 offset, guint size,
|
||||
GstCaps * caps, GstBuffer ** buf)
|
||||
{
|
||||
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent_element (pad));
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
ret = gst_pad_alloc_buffer (funnel->srcpad, offset, size, caps, buf);
|
||||
|
||||
gst_object_unref (funnel);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * name)
|
||||
{
|
||||
GstPad *sinkpad;
|
||||
|
||||
GST_DEBUG_OBJECT (element, "requesting pad");
|
||||
|
||||
sinkpad = GST_PAD_CAST (g_object_new (GST_TYPE_FUNNEL_PAD,
|
||||
"name", name, "direction", templ->direction, "template", templ,
|
||||
NULL));
|
||||
|
||||
gst_pad_set_chain_function (sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_funnel_sink_chain));
|
||||
gst_pad_set_event_function (sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_funnel_sink_event));
|
||||
gst_pad_set_getcaps_function (sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_funnel_sink_getcaps));
|
||||
gst_pad_set_bufferalloc_function (sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_funnel_sink_buffer_alloc));
|
||||
|
||||
gst_pad_set_active (sinkpad, TRUE);
|
||||
|
||||
gst_element_add_pad (element, sinkpad);
|
||||
|
||||
return sinkpad;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_funnel_release_pad (GstElement * element, GstPad * pad)
|
||||
{
|
||||
GstFunnel *funnel = GST_FUNNEL (element);
|
||||
|
||||
GST_DEBUG_OBJECT (funnel, "releasing pad");
|
||||
|
||||
gst_pad_set_active (pad, FALSE);
|
||||
|
||||
gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_funnel_sink_getcaps (GstPad * pad)
|
||||
{
|
||||
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
|
||||
GstCaps *caps;
|
||||
|
||||
caps = gst_pad_peer_get_caps_reffed (funnel->srcpad);
|
||||
if (caps == NULL)
|
||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||
|
||||
gst_object_unref (funnel);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
GstFlowReturn res;
|
||||
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
|
||||
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
|
||||
GstEvent *event = NULL;
|
||||
GstClockTime newts;
|
||||
GstCaps *padcaps;
|
||||
|
||||
GST_DEBUG_OBJECT (funnel, "received buffer %p", buffer);
|
||||
|
||||
GST_OBJECT_LOCK (funnel);
|
||||
if (fpad->segment.format == GST_FORMAT_UNDEFINED) {
|
||||
GST_WARNING_OBJECT (funnel, "Got buffer without segment,"
|
||||
" setting segment [0,inf[");
|
||||
gst_segment_set_newsegment_full (&fpad->segment, FALSE, 1.0, 1.0,
|
||||
GST_FORMAT_TIME, 0, -1, 0);
|
||||
}
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
|
||||
gst_segment_set_last_stop (&fpad->segment, fpad->segment.format,
|
||||
GST_BUFFER_TIMESTAMP (buffer));
|
||||
|
||||
newts = gst_segment_to_running_time (&fpad->segment,
|
||||
fpad->segment.format, GST_BUFFER_TIMESTAMP (buffer));
|
||||
if (newts != GST_BUFFER_TIMESTAMP (buffer)) {
|
||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
||||
GST_BUFFER_TIMESTAMP (buffer) = newts;
|
||||
}
|
||||
|
||||
if (!funnel->has_segment) {
|
||||
event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
|
||||
0, -1, 0);
|
||||
funnel->has_segment = TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (funnel);
|
||||
|
||||
if (event) {
|
||||
if (!gst_pad_push_event (funnel->srcpad, event))
|
||||
GST_WARNING_OBJECT (funnel, "Could not push out newsegment event");
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
padcaps = GST_PAD_CAPS (funnel->srcpad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
if (GST_BUFFER_CAPS (buffer) && GST_BUFFER_CAPS (buffer) != padcaps) {
|
||||
if (!gst_pad_set_caps (funnel->srcpad, GST_BUFFER_CAPS (buffer))) {
|
||||
res = GST_FLOW_NOT_NEGOTIATED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
res = gst_pad_push (funnel->srcpad, buffer);
|
||||
|
||||
GST_LOG_OBJECT (funnel, "handled buffer %s", gst_flow_get_name (res));
|
||||
|
||||
out:
|
||||
gst_object_unref (funnel);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_funnel_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
|
||||
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
|
||||
gboolean forward = TRUE;
|
||||
gboolean res = TRUE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate, arate;
|
||||
GstFormat format;
|
||||
gint64 start;
|
||||
gint64 stop;
|
||||
gint64 time;
|
||||
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate,
|
||||
&format, &start, &stop, &time);
|
||||
|
||||
GST_OBJECT_LOCK (funnel);
|
||||
gst_segment_set_newsegment_full (&fpad->segment, update, rate, arate,
|
||||
format, start, stop, time);
|
||||
GST_OBJECT_UNLOCK (funnel);
|
||||
|
||||
forward = FALSE;
|
||||
gst_event_unref (event);
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
{
|
||||
GST_OBJECT_LOCK (funnel);
|
||||
gst_segment_init (&fpad->segment, GST_FORMAT_UNDEFINED);
|
||||
funnel->has_segment = FALSE;
|
||||
GST_OBJECT_UNLOCK (funnel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (forward)
|
||||
res = gst_pad_push_event (funnel->srcpad, event);
|
||||
|
||||
gst_object_unref (funnel);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_funnel_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstElement *funnel;
|
||||
GstIterator *iter;
|
||||
GstPad *sinkpad;
|
||||
gboolean result = FALSE;
|
||||
gboolean done = FALSE;
|
||||
|
||||
funnel = gst_pad_get_parent_element (pad);
|
||||
g_return_val_if_fail (funnel != NULL, FALSE);
|
||||
|
||||
iter = gst_element_iterate_sink_pads (funnel);
|
||||
|
||||
while (!done) {
|
||||
switch (gst_iterator_next (iter, (gpointer) & sinkpad)) {
|
||||
case GST_ITERATOR_OK:
|
||||
gst_event_ref (event);
|
||||
result |= gst_pad_push_event (sinkpad, event);
|
||||
gst_object_unref (sinkpad);
|
||||
break;
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (iter);
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ITERATOR_ERROR:
|
||||
GST_WARNING_OBJECT (funnel, "Error iterating sinkpads");
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gst_iterator_free (iter);
|
||||
gst_object_unref (funnel);
|
||||
gst_event_unref (event);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_pad (gpointer data, gpointer user_data)
|
||||
{
|
||||
GstPad *pad = data;
|
||||
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
gst_funnel_pad_reset (fpad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_funnel_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstFunnel *funnel = GST_FUNNEL (element);
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
{
|
||||
GstIterator *iter = gst_element_iterate_sink_pads (element);
|
||||
GstIteratorResult res;
|
||||
|
||||
do {
|
||||
res = gst_iterator_foreach (iter, reset_pad, NULL);
|
||||
} while (res == GST_ITERATOR_RESYNC);
|
||||
|
||||
gst_iterator_free (iter);
|
||||
|
||||
if (res == GST_ITERATOR_ERROR)
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
|
||||
GST_OBJECT_LOCK (funnel);
|
||||
funnel->has_segment = FALSE;
|
||||
GST_OBJECT_UNLOCK (funnel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
return ret;
|
||||
}
|
69
plugins/elements/gstfunnel.h
Normal file
69
plugins/elements/gstfunnel.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* GStreamer Funnel element
|
||||
*
|
||||
* Copyright 2007 Collabora Ltd.
|
||||
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
* Copyright 2007 Nokia Corp.
|
||||
*
|
||||
* gstfunnel.h: Simple Funnel element
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GST_FUNNEL_H__
|
||||
#define __GST_FUNNEL_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_FUNNEL \
|
||||
(gst_funnel_get_type ())
|
||||
#define GST_FUNNEL(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FUNNEL,GstFunnel))
|
||||
#define GST_FUNNEL_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FUNNEL,GstFunnelClass))
|
||||
#define GST_IS_FUNNEL(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FUNNEL))
|
||||
#define GST_IS_FUNNEL_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FUNNEL))
|
||||
|
||||
typedef struct _GstFunnel GstFunnel;
|
||||
typedef struct _GstFunnelClass GstFunnelClass;
|
||||
|
||||
/**
|
||||
* GstFunnel:
|
||||
*
|
||||
* Opaque #GstFunnel data structure.
|
||||
*/
|
||||
struct _GstFunnel {
|
||||
GstElement element;
|
||||
|
||||
/*< private >*/
|
||||
GstPad *srcpad;
|
||||
|
||||
gboolean has_segment;
|
||||
};
|
||||
|
||||
struct _GstFunnelClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_funnel_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_FUNNEL_H__ */
|
|
@ -110,6 +110,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <stdio.h>
|
||||
#include "gstmultiqueue.h"
|
||||
|
||||
/**
|
||||
|
@ -173,7 +174,7 @@ struct _GstMultiQueueItem
|
|||
guint32 posid;
|
||||
};
|
||||
|
||||
static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue);
|
||||
static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, gint id);
|
||||
static void gst_single_queue_free (GstSingleQueue * squeue);
|
||||
|
||||
static void wake_up_next_non_linked (GstMultiQueue * mq);
|
||||
|
@ -591,21 +592,20 @@ gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp,
|
|||
{
|
||||
GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
|
||||
GstSingleQueue *squeue;
|
||||
gint temp_id = -1;
|
||||
|
||||
GST_LOG_OBJECT (element, "name : %s", GST_STR_NULL (name));
|
||||
if (name) {
|
||||
sscanf (name + 4, "%d", &temp_id);
|
||||
GST_LOG_OBJECT (element, "name : %s (id %d)", GST_STR_NULL (name), temp_id);
|
||||
}
|
||||
|
||||
/* Create a new single queue, add the sink and source pad and return the sink pad */
|
||||
squeue = gst_single_queue_new (mqueue);
|
||||
|
||||
GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
|
||||
mqueue->queues = g_list_append (mqueue->queues, squeue);
|
||||
mqueue->queues_cookie++;
|
||||
GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
|
||||
squeue = gst_single_queue_new (mqueue, temp_id);
|
||||
|
||||
GST_DEBUG_OBJECT (mqueue, "Returning pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (squeue->sinkpad));
|
||||
|
||||
return squeue->sinkpad;
|
||||
return squeue ? squeue->sinkpad : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1706,15 +1706,37 @@ gst_single_queue_free (GstSingleQueue * sq)
|
|||
}
|
||||
|
||||
static GstSingleQueue *
|
||||
gst_single_queue_new (GstMultiQueue * mqueue)
|
||||
gst_single_queue_new (GstMultiQueue * mqueue, gint id)
|
||||
{
|
||||
GstSingleQueue *sq;
|
||||
gchar *tmp;
|
||||
|
||||
sq = g_new0 (GstSingleQueue, 1);
|
||||
gchar *name;
|
||||
GList *tmp;
|
||||
gint temp_id = (id == -1) ? 0 : id;
|
||||
|
||||
GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
|
||||
sq->id = mqueue->nbqueues++;
|
||||
|
||||
/* Find an unused queue ID, if possible the passed one */
|
||||
for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
|
||||
GstSingleQueue *sq2 = (GstSingleQueue *) tmp->data;
|
||||
/* This works because the IDs are sorted in ascending order */
|
||||
if (sq2->id == temp_id) {
|
||||
/* If this ID was requested by the caller return NULL,
|
||||
* otherwise just get us the next one */
|
||||
if (id == -1)
|
||||
temp_id = sq2->id + 1;
|
||||
else
|
||||
return NULL;
|
||||
} else if (sq2->id > temp_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sq = g_new0 (GstSingleQueue, 1);
|
||||
mqueue->nbqueues++;
|
||||
sq->id = temp_id;
|
||||
|
||||
mqueue->queues = g_list_insert_before (mqueue->queues, tmp, sq);
|
||||
mqueue->queues_cookie++;
|
||||
|
||||
/* copy over max_size and extra_size so we don't need to take the lock
|
||||
* any longer when checking if the queue is full. */
|
||||
|
@ -1750,9 +1772,9 @@ gst_single_queue_new (GstMultiQueue * mqueue)
|
|||
sq->sink_tainted = TRUE;
|
||||
sq->src_tainted = TRUE;
|
||||
|
||||
tmp = g_strdup_printf ("sink%d", sq->id);
|
||||
sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp);
|
||||
g_free (tmp);
|
||||
name = g_strdup_printf ("sink%d", sq->id);
|
||||
|
||||
sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, name);
|
||||
|
||||
gst_pad_set_chain_function (sq->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
|
||||
|
@ -1769,9 +1791,9 @@ gst_single_queue_new (GstMultiQueue * mqueue)
|
|||
gst_pad_set_iterate_internal_links_function (sq->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
|
||||
|
||||
tmp = g_strdup_printf ("src%d", sq->id);
|
||||
sq->srcpad = gst_pad_new_from_static_template (&srctemplate, tmp);
|
||||
g_free (tmp);
|
||||
name = g_strdup_printf ("src%d", sq->id);
|
||||
sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name);
|
||||
g_free (name);
|
||||
|
||||
gst_pad_set_activatepush_function (sq->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push));
|
||||
|
|
|
@ -83,6 +83,7 @@ REGISTRY_CHECKS = \
|
|||
elements/fdsrc \
|
||||
elements/filesink \
|
||||
elements/filesrc \
|
||||
elements/funnel \
|
||||
elements/identity \
|
||||
elements/multiqueue \
|
||||
elements/selector \
|
||||
|
|
185
tests/check/elements/funnel.c
Normal file
185
tests/check/elements/funnel.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* GStreamer unit tests for the funnel
|
||||
*
|
||||
* Copyright (C) 2008 Collabora, Nokia
|
||||
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
struct TestData
|
||||
{
|
||||
GstElement *funnel;
|
||||
GstPad *funnelsrc, *funnelsink11, *funnelsink22;
|
||||
GstPad *mysink, *mysrc1, *mysrc2;
|
||||
GstCaps *mycaps;
|
||||
};
|
||||
|
||||
static void
|
||||
setup_test_objects (struct TestData *td, GstPadChainFunction chain_func,
|
||||
GstPadBufferAllocFunction alloc_func)
|
||||
{
|
||||
td->mycaps = gst_caps_new_simple ("test/test", NULL);
|
||||
|
||||
td->funnel = gst_element_factory_make ("funnel", NULL);
|
||||
|
||||
td->funnelsrc = gst_element_get_static_pad (td->funnel, "src");
|
||||
fail_unless (td->funnelsrc != NULL);
|
||||
|
||||
td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink11");
|
||||
fail_unless (td->funnelsink11 != NULL);
|
||||
fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink11"));
|
||||
|
||||
td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink22");
|
||||
fail_unless (td->funnelsink22 != NULL);
|
||||
fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink22"));
|
||||
|
||||
fail_unless (gst_element_set_state (td->funnel, GST_STATE_PLAYING) ==
|
||||
GST_STATE_CHANGE_SUCCESS);
|
||||
|
||||
td->mysink = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_pad_set_chain_function (td->mysink, chain_func);
|
||||
gst_pad_set_bufferalloc_function (td->mysink, alloc_func);
|
||||
gst_pad_set_active (td->mysink, TRUE);
|
||||
gst_pad_set_caps (td->mysink, td->mycaps);
|
||||
|
||||
td->mysrc1 = gst_pad_new ("src1", GST_PAD_SRC);
|
||||
gst_pad_set_active (td->mysrc1, TRUE);
|
||||
gst_pad_set_caps (td->mysrc1, td->mycaps);
|
||||
|
||||
td->mysrc2 = gst_pad_new ("src2", GST_PAD_SRC);
|
||||
gst_pad_set_active (td->mysrc2, TRUE);
|
||||
gst_pad_set_caps (td->mysrc2, td->mycaps);
|
||||
|
||||
fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->funnelsrc,
|
||||
td->mysink)));
|
||||
|
||||
fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc1,
|
||||
td->funnelsink11)));
|
||||
|
||||
fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc2,
|
||||
td->funnelsink22)));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
release_test_objects (struct TestData *td)
|
||||
{
|
||||
gst_pad_set_active (td->mysink, FALSE);
|
||||
gst_pad_set_active (td->mysrc1, FALSE);
|
||||
gst_pad_set_active (td->mysrc1, FALSE);
|
||||
|
||||
gst_object_unref (td->mysink);
|
||||
gst_object_unref (td->mysrc1);
|
||||
gst_object_unref (td->mysrc2);
|
||||
|
||||
fail_unless (gst_element_set_state (td->funnel, GST_STATE_NULL) ==
|
||||
GST_STATE_CHANGE_SUCCESS);
|
||||
|
||||
gst_object_unref (td->funnelsrc);
|
||||
gst_object_unref (td->funnelsink11);
|
||||
gst_element_release_request_pad (td->funnel, td->funnelsink11);
|
||||
gst_object_unref (td->funnelsink22);
|
||||
gst_element_release_request_pad (td->funnel, td->funnelsink22);
|
||||
|
||||
gst_caps_unref (td->mycaps);
|
||||
gst_object_unref (td->funnel);
|
||||
}
|
||||
|
||||
static gint bufcount = 0;
|
||||
static gint alloccount = 0;
|
||||
|
||||
static GstFlowReturn
|
||||
chain_ok (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
bufcount++;
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
alloc_ok (GstPad * pad,
|
||||
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buffer)
|
||||
{
|
||||
alloccount++;
|
||||
|
||||
fail_unless (buffer != NULL);
|
||||
fail_unless (*buffer == NULL);
|
||||
|
||||
*buffer = gst_buffer_new_and_alloc (size);
|
||||
gst_buffer_set_caps (*buffer, caps);
|
||||
GST_BUFFER_OFFSET (*buffer) = offset;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_funnel_simple)
|
||||
{
|
||||
struct TestData td;
|
||||
GstBuffer *buf1 = NULL;
|
||||
GstBuffer *buf2 = NULL;
|
||||
|
||||
setup_test_objects (&td, chain_ok, alloc_ok);
|
||||
|
||||
bufcount = 0;
|
||||
alloccount = 0;
|
||||
|
||||
fail_unless (gst_pad_push (td.mysrc1, gst_buffer_new ()) == GST_FLOW_OK);
|
||||
fail_unless (gst_pad_push (td.mysrc2, gst_buffer_new ()) == GST_FLOW_OK);
|
||||
|
||||
fail_unless (bufcount == 2);
|
||||
|
||||
fail_unless (gst_pad_alloc_buffer (td.mysrc1, 0, 1024, td.mycaps,
|
||||
&buf1) == GST_FLOW_OK);
|
||||
fail_unless (gst_pad_alloc_buffer (td.mysrc2, 1024, 1024, td.mycaps,
|
||||
&buf2) == GST_FLOW_OK);
|
||||
|
||||
fail_unless (alloccount == 2);
|
||||
|
||||
gst_buffer_unref (buf1);
|
||||
gst_buffer_unref (buf2);
|
||||
|
||||
release_test_objects (&td);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
funnel_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("funnel");
|
||||
TCase *tc_chain;
|
||||
GLogLevelFlags fatal_mask;
|
||||
|
||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
|
||||
tc_chain = tcase_create ("funnel simple");
|
||||
tcase_add_test (tc_chain, test_funnel_simple);
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (funnel);
|
|
@ -243,6 +243,50 @@ mq_sinkpad_to_srcpad (GstElement * mq, GstPad * sink)
|
|||
return srcpad;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_request_pads_named)
|
||||
{
|
||||
GstElement *mq;
|
||||
GstPad *sink1, *sink2, *sink3, *sink4;
|
||||
|
||||
mq = gst_element_factory_make ("multiqueue", NULL);
|
||||
|
||||
sink1 = gst_element_get_request_pad (mq, "sink1");
|
||||
fail_unless (sink1 != NULL);
|
||||
fail_unless (GST_IS_PAD (sink1));
|
||||
fail_unless (GST_PAD_IS_SINK (sink1));
|
||||
fail_unless_equals_string (GST_PAD_NAME (sink1), "sink1");
|
||||
GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1));
|
||||
|
||||
sink3 = gst_element_get_request_pad (mq, "sink3");
|
||||
fail_unless (sink3 != NULL);
|
||||
fail_unless (GST_IS_PAD (sink3));
|
||||
fail_unless (GST_PAD_IS_SINK (sink3));
|
||||
fail_unless_equals_string (GST_PAD_NAME (sink3), "sink3");
|
||||
GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink3));
|
||||
|
||||
sink2 = gst_element_get_request_pad (mq, "sink2");
|
||||
fail_unless (sink2 != NULL);
|
||||
fail_unless (GST_IS_PAD (sink2));
|
||||
fail_unless (GST_PAD_IS_SINK (sink2));
|
||||
fail_unless_equals_string (GST_PAD_NAME (sink2), "sink2");
|
||||
GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink2));
|
||||
|
||||
/* This gets us the first unused id, sink0 */
|
||||
sink4 = gst_element_get_request_pad (mq, "sink%d");
|
||||
fail_unless (sink4 != NULL);
|
||||
fail_unless (GST_IS_PAD (sink4));
|
||||
fail_unless (GST_PAD_IS_SINK (sink4));
|
||||
fail_unless_equals_string (GST_PAD_NAME (sink4), "sink0");
|
||||
GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink4));
|
||||
|
||||
GST_LOG ("Cleaning up");
|
||||
gst_object_unref (sink1);
|
||||
gst_object_unref (sink2);
|
||||
gst_object_unref (mq);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static GstCaps *
|
||||
mq_dummypad_getcaps (GstPad * sinkpad)
|
||||
{
|
||||
|
@ -665,6 +709,7 @@ multiqueue_suite (void)
|
|||
tcase_add_test (tc_chain, test_simple_shutdown_while_running);
|
||||
|
||||
tcase_add_test (tc_chain, test_request_pads);
|
||||
tcase_add_test (tc_chain, test_request_pads_named);
|
||||
|
||||
tcase_add_test (tc_chain, test_output_order);
|
||||
|
||||
|
|
Loading…
Reference in a new issue