insertbin: Add bin to dynamically insert elements in a running pipeline

This element automatically links in any element added using it's
action signals. These elements must have a single source pad and a single
sink pad.
This commit is contained in:
Olivier Crête 2012-03-15 14:12:21 -04:00
parent 07a51b16eb
commit d1023646f9
18 changed files with 1661 additions and 2 deletions

2
.gitignore vendored
View file

@ -38,6 +38,8 @@ gst-plugins-bad-*.tar.*
/m4
Makefile.in
Makefile
*.gir
*.typelib
tmp-orc.c
gst*orc.h

View file

@ -9,6 +9,7 @@ GST_PLUGINS_BAD_BUILT_SOURCES := \
gst-libs/gst/baseparse/Android.mk \
gst-libs/gst/basecamerabinsrc/Android.mk \
gst-libs/gst/codecparsers/Android.mk \
gst-libs/gst/insertbin/Android.mk
gst-libs/gst/interfaces/Android.mk \
gst/h264parse/Android.mk \
gst/videoparsers/Android.mk \
@ -98,6 +99,7 @@ CONFIGURE_TARGETS += gst-plugins-bad-configure
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/baseparse/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/basecamerabinsrc/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/codecparsers/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/insertbin/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/interfaces/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/h264parse/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/audiobuffer/Android.mk

View file

@ -123,6 +123,9 @@ AG_GST_CHECK_DOWHILE_MACROS
AC_PATH_PROG(VALGRIND_PATH, valgrind, no)
AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno")
dnl check for gobject-introspection
GOBJECT_INTROSPECTION_CHECK([1.31.1])
dnl check for documentation tools
GTK_DOC_CHECK([1.12])
AG_GST_PLUGIN_DOCS([1.12])
@ -2257,6 +2260,7 @@ gst/y4m/Makefile
gst-libs/Makefile
gst-libs/gst/Makefile
gst-libs/gst/basecamerabinsrc/Makefile
gst-libs/gst/insertbin/Makefile
gst-libs/gst/interfaces/Makefile
gst-libs/gst/signalprocessor/Makefile
gst-libs/gst/codecparsers/Makefile
@ -2371,6 +2375,8 @@ pkgconfig/gstreamer-plugins-bad.pc
pkgconfig/gstreamer-plugins-bad-uninstalled.pc
pkgconfig/gstreamer-codecparsers.pc
pkgconfig/gstreamer-codecparsers-uninstalled.pc
pkgconfig/gstreamer-insertbin.pc
pkgconfig/gstreamer-insertbin-uninstalled.pc
pkgconfig/gstreamer-basevideo.pc
pkgconfig/gstreamer-basevideo-uninstalled.pc
tools/Makefile

View file

@ -56,6 +56,7 @@ GTKDOC_LIBS = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/signalprocessor/libgstsignalprocessor-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/video/libgstbasevideo-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/insertbin/libgstinsertbin-@GST_API_VERSION@.la \
$(GST_BASE_LIBS)
GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC)

View file

@ -44,6 +44,11 @@
<xi:include href="xml/gstsurfacebuffer.xml" />
<xi:include href="xml/gstsurfaceconverter.xml" />
</chapter>
<chapter id="tools">
<title>Useful elements</title>
<xi:include href="xml/gstinsertbin.xml" />
</chapter>
</part>
<part id="gstreamer-libs-hierarchy">

View file

@ -486,3 +486,27 @@ GstSurfaceConverterInterface
gst_surface_converter_get_type
gst_surface_converter_upload
</SECTION>
<SECTION>
<FILE>gstinsertbin</FILE>
<TITLE>GstInsertbin</TITLE>
GstInsertBin
GstInsertBinClass
GstInsertBinCallback
gst_insert_bin_new
gst_insert_bin_append
gst_insert_bin_prepend
gst_insert_bin_insert_after
gst_insert_bin_insert_before
gst_insert_bin_remove
<SUBSECTION Standard>
GST_INSERT_BIN
GST_INSERT_BIN_CLASS
GST_INSERT_BIN_GET_CLASS
GST_IS_INSERT_BIN
GST_IS_INSERT_BIN_CLASS
GST_TYPE_INSERT_BIN
gst_insert_bin_get_type
<SUBSECTION Private>
GstInsertBinPrivate
</SECTION>

View file

@ -2,3 +2,6 @@
#include <gst/codecparsers/gsth264parser.h>
#include <gst/codecparsers/gstmpegvideoparser.h>
#include <gst/insertbin/gstinsertbin.h>
gst_insert_bin_get_type

View file

@ -1,6 +1,8 @@
SUBDIRS = interfaces signalprocessor video basecamerabinsrc codecparsers
SUBDIRS = interfaces signalprocessor video basecamerabinsrc codecparsers \
insertbin
noinst_HEADERS = gst-i18n-plugin.h gettext.h glib-compat-private.h
DIST_SUBDIRS = interfaces signalprocessor video basecamerabinsrc codecparsers
DIST_SUBDIRS = interfaces signalprocessor video basecamerabinsrc codecparsers \
insertbin

View file

@ -0,0 +1,90 @@
lib_LTLIBRARIES = libgstinsertbin-@GST_API_VERSION@.la
libgstinsertbin_@GST_API_VERSION@_la_SOURCES = gstinsertbin.c
libgstinsertbin_@GST_API_VERSION@includedir = \
$(includedir)/gstreamer-@GST_API_VERSION@/gst/insertbin
libgstinsertbin_@GST_API_VERSION@include_HEADERS = gstinsertbin.h
libgstinsertbin_@GST_API_VERSION@_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_CFLAGS)
libgstinsertbin_@GST_API_VERSION@_la_LIBADD = \
$(GST_LIBS)
libgstinsertbin_@GST_API_VERSION@_la_LDFLAGS = \
$(GST_LIB_LDFLAGS) \
$(GST_ALL_LDFLAGS) \
$(GST_LT_LDFLAGS)
if HAVE_INTROSPECTION
BUILT_GIRSOURCES = GstInsertBin-@GST_API_VERSION@.gir
gir_headers=$(patsubst %,$(srcdir)/%, $(libgstinsertbin_@GST_API_VERSION@include_HEADERS))
gir_headers+=$(patsubst %,$(builddir)/%, $(built_headers))
gir_sources=$(patsubst %,$(srcdir)/%, $(libgstinsertbin_@GST_API_VERSION@_la_SOURCES))
gir_sources+=$(patsubst %,$(builddir)/%, $(built_sources))
GstInsertBin-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstinsertbin-@GST_API_VERSION@.la
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \
$(INTROSPECTION_SCANNER) -v --namespace GstInsertBin \
--nsversion=@GST_API_VERSION@ \
--strip-prefix=Gst \
--warn-all \
--c-include "gst/insertbin/gstinsertbin.h" \
-I$(top_srcdir)/gst-libs \
-I$(top_builddir)/gst-libs \
--add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \
--add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \
--library=libgstinsertbin-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
--include=GstBase-@GST_API_VERSION@ \
--libtool="$(top_builddir)/libtool" \
--pkg gstreamer-@GST_API_VERSION@ \
--pkg gstreamer-base-@GST_API_VERSION@ \
--pkg-export gstreamer-insertbin-@GST_API_VERSION@ \
--add-init-section="gst_init(NULL,NULL);" \
--output $@ \
$(gir_headers) \
$(gir_sources)
# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to
# install anything - we need to install inside our prefix.
girdir = $(datadir)/gir-1.0
gir_DATA = $(BUILT_GIRSOURCES)
typelibsdir = $(libdir)/girepository-1.0/
typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
%.typelib: %.gir $(INTROSPECTION_COMPILER)
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
$(INTROSPECTION_COMPILER) \
--includedir=$(srcdir) \
--includedir=$(builddir) \
--includedir=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \
--includedir=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \
$(INTROSPECTION_COMPILER_OPTS) $< -o $(@F)
CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA)
endif
Android.mk: $(BUILT_SOURCES) Makefile.am
androgenizer -:PROJECT libgstinsertbin -:STATIC libgstinsertbin-@GST_API_VERSION@ \
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libgstinsertbin_@GST_API_VERSION@_la_SOURCES) \
$(built_sources) \
-:CFLAGS $(DEFS) $(libgstinsertbin_@GST_API_VERSION@_la_CFLAGS) \
-:LDFLAGS $(libgstinsertbin_@GST_API_VERSION@_la_LDFLAGS) \
$(libgstinsertbin@GST_API_VERSION@_la_LIBADD) \
-ldl \
-:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/insertbin \
-:HEADERS $(libgstinsertbininclude_HEADERS) \
$(built_headers) \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
> $@

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,101 @@
/*
* GStreamer
*
* Copyright 2013 Collabora Ltd
* @author: Olivier Crete <olivier.crete@collabora.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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef __GST_INSERT_BIN_H__
#define __GST_INSERT_BIN_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_INSERT_BIN (gst_insert_bin_get_type())
#define GST_INSERT_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INSERT_BIN,GstInsertBin))
#define GST_IS_INSERT_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INSERT_BIN))
#define GST_INSERT_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_INSERT_BIN,GstInsertBinClass))
#define GST_IS_INSERT_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_INSERT_BIN))
#define GST_INSERT_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_INSERT_BIN,GstInsertBinClass))
typedef struct _GstInsertBin GstInsertBin;
typedef struct _GstInsertBinClass GstInsertBinClass;
typedef struct _GstInsertBinPrivate GstInsertBinPrivate;
/**
* GstInsertBinCallback:
* @insertbin: A #GstInsertBin
* @element: The #GstElement on which the operation was performed
* @success: %TRUE if the operation was successful
* @user_data: The user data passed
*
* This is the prototype of callbacks to be called when the operation completes.
* It could be called at any time, including as a re-entrant call while the
* operation is requested.
*/
typedef void (*GstInsertBinCallback) (GstInsertBin *insertbin,
GstElement *element,
gboolean success,
gpointer user_data);
/**
* GstInsertBin:
*
* The object structure.
*/
struct _GstInsertBin
{
GstBin parent;
/*< private >*/
GstInsertBinPrivate *priv;
};
/**
* GstInsertBinClass:
*
* The object class structure.
*/
struct _GstInsertBinClass
{
GstBinClass parent_class;
};
GType gst_insert_bin_get_type (void);
GstElement *gst_insert_bin_new (const gchar * name);
void gst_insert_bin_prepend (GstInsertBin * self, GstElement * element,
GstInsertBinCallback callback, gpointer user_data);
void gst_insert_bin_append (GstInsertBin * self, GstElement * element,
GstInsertBinCallback callback, gpointer user_data);
void gst_insert_bin_insert_before (GstInsertBin * self,
GstElement * element, GstElement * sibling,
GstInsertBinCallback callback, gpointer user_data);
void gst_insert_bin_insert_after (GstInsertBin * self,
GstElement * element, GstElement * sibling,
GstInsertBinCallback callback, gpointer user_data);
void gst_insert_bin_remove (GstInsertBin * self, GstElement * element,
GstInsertBinCallback callback, gpointer user_data);
G_END_DECLS
#endif /* __GST_INSERT_BIN_H__ */

View file

@ -201,6 +201,7 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
%{_libdir}/libgstphotography-%{majorminor}.so.*
%{_libdir}/libgstsignalprocessor-%{majorminor}.so.*
%{_libdir}/libgstcodecparsers-%{majorminor}.so.*
%{_libdir}/libgstinsertbin-%{majorminor}.so.*
# Plugins without external dependencies
%{_libdir}/gstreamer-%{majorminor}/libgstadpcmdec.so
%{_libdir}/gstreamer-%{majorminor}/libgstadpcmenc.so
@ -353,10 +354,12 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
%{_libdir}/libgstbasevideo-%{majorminor}.so
%{_libdir}/libgstphotography-%{majorminor}.so
%{_libdir}/libgstsignalprocessor-%{majorminor}.so
%{_libdir}/libgstinsertbin-%{majorminor}.so
%{_libdir}/libgstcodecparsers-%{majorminor}.so
%{_libdir}/libgstbasecamerabinsrc-%{majorminor}.so
%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/photography*
%{_includedir}/gstreamer-%{majorminor}/gst/codecparsers
%{_includedir}/gstreamer-%{majorminor}/gst/insertbin
%{_includedir}/gstreamer-%{majorminor}/gst/signalprocessor
%{_includedir}/gstreamer-%{majorminor}/gst/video
%{_includedir}/gstreamer-%{majorminor}/gst/basecamerabinsrc/gstbasecamerasrc.h
@ -367,6 +370,7 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
# pkg-config files
%{_libdir}/pkgconfig/gstreamer-plugins-bad-%{majorminor}.pc
%{_libdir}/pkgconfig/gstreamer-codecparsers-%{majorminor}.pc
%{_libdir}/pkgconfig/gstreamer-insertbin-%{majorminor}.pc
%{_libdir}/pkgconfig/gstreamer-basevideo-%{majorminor}.pc
%files devel-docs

View file

@ -2,11 +2,13 @@
pcverfiles = \
gstreamer-plugins-bad-@GST_API_VERSION@.pc \
gstreamer-codecparsers-@GST_API_VERSION@.pc \
gstreamer-insertbin-@GST_API_VERSION@.pc \
gstreamer-basevideo-@GST_API_VERSION@.pc
pcverfiles_uninstalled = \
gstreamer-plugins-bad-@GST_API_VERSION@-uninstalled.pc \
gstreamer-codecparsers-@GST_API_VERSION@-uninstalled.pc \
gstreamer-insertbin-@GST_API_VERSION@-uninstalled.pc \
gstreamer-basevideo-@GST_API_VERSION@-uninstalled.pc
all-local: $(pcverfiles) $(pcverfiles_uninstalled)
@ -28,6 +30,7 @@ CLEANFILES = $(pcverfiles) $(pcverfiles_uninstalled)
pcinfiles = \
gstreamer-plugins-bad.pc.in gstreamer-plugins-bad-uninstalled.pc.in \
gstreamer-codecparsers.pc.in gstreamer-codecparsers-uninstalled.pc.in \
gstreamer-insertbin.pc.in gstreamer-insertbin-uninstalled.pc.in \
gstreamer-basevideo.pc.in gstreamer-basevideo-uninstalled.pc.in
DISTCLEANFILES = $(pcinfiles:.in=)

View file

@ -0,0 +1,12 @@
prefix=
exec_prefix=
libdir=${pcfiledir}/../gst-libs/gst/insertbin
includedir=${pcfiledir}/../gst-libs
Name: GStreamer Insert Bin, Uninstalled
Description: Bin to automatically and insertally link elements, uninstalled
Requires: gstreamer-@GST_API_VERSION@
Version: @VERSION@
Libs: -L${libdir} ${libdir}/libgstinsertbin-@GST_API_VERSION@.la
Cflags: -I${includedir}

View file

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@/gstreamer-@GST_API_VERSION@
Name: GStreamer Insert Bin
Description: Bin to automatically and insertally link elements
Requires: gstreamer-@GST_API_VERSION@
Version: @VERSION@
Libs: -L${libdir} -lgstinsertbin-@GST_API_VERSION@
Cflags: -I${includedir}

View file

@ -232,6 +232,7 @@ check_PROGRAMS = \
elements/viewfinderbin \
$(check_zbar) \
$(check_orc) \
libs/insertbin \
$(EXPERIMENTAL_CHECKS)
noinst_HEADERS = elements/mxfdemux.h
@ -365,6 +366,13 @@ elements_uvch264demux_CFLAGS = -DUVCH264DEMUX_DATADIR="$(srcdir)/elements/uvch26
pipelines_streamheader_CFLAGS = $(GIO_CFLAGS) $(AM_CFLAGS)
pipelines_streamheader_LDADD = $(GIO_LIBS) $(LDADD)
libs_insertbin_LDADD = \
$(GST_PLUGINS_BAD_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD) \
$(top_builddir)/gst-libs/gst/insertbin/libgstinsertbin-@GST_API_VERSION@.la
libs_insertbin_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
EXTRA_DIST = gst-plugins-bad.supp $(uvch264_dist_data)
orc_bayer_CFLAGS = $(ORC_CFLAGS)

View file

@ -2,3 +2,4 @@
h264parser
mpegvideoparser
vc1parser
insertbin

View file

@ -0,0 +1,354 @@
/* GStreamer
*
* unit test for autoconvert element
* Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/check/gstcheck.h>
#include <gst/insertbin/gstinsertbin.h>
GstStaticPadTemplate sinkpad_template = GST_STATIC_PAD_TEMPLATE ("sink", // the name of the pad
GST_PAD_SINK, // the direction of the pad
GST_PAD_ALWAYS, // when this pad will be present
GST_STATIC_CAPS ( // the capabilities of the padtemplate
"video/test")
);
GstStaticPadTemplate srcpad_template = GST_STATIC_PAD_TEMPLATE ("src", // the name of the pad
GST_PAD_SRC, // the direction of the pad
GST_PAD_ALWAYS, // when this pad will be present
GST_STATIC_CAPS ( // the capabilities of the padtemplate
"video/test")
);
gint cb_count = 0;
GMutex mutex;
GCond cond;
GThread *push_thread = NULL;
gulong block_probe_id = 0;
gboolean is_blocked = FALSE;
static void
success_cb (GstInsertBin * insertbin, GstElement * element, gboolean success,
gpointer user_data)
{
fail_unless (g_thread_self () != push_thread);
fail_unless (success == TRUE);
fail_unless (GST_IS_ELEMENT (insertbin));
fail_unless (GST_IS_ELEMENT (element));
cb_count++;
}
static void
fail_cb (GstInsertBin * insertbin, GstElement * element, gboolean success,
gpointer user_data)
{
fail_unless (GST_IS_ELEMENT (insertbin));
fail_unless (GST_IS_ELEMENT (element));
fail_unless (success == FALSE);
cb_count++;
}
/*
* This is a macro so the line number of any error is more useful
*/
#define push_buffer(srcpad, count) \
{ \
fail_unless (cb_count == 0); \
gst_pad_push (srcpad, gst_buffer_new ()); \
fail_unless (g_list_length (buffers) == 1); \
gst_check_drop_buffers (); \
fail_unless (cb_count == (count)); \
cb_count = 0; \
}
#define check_reset_cb_count(count) \
{ \
fail_unless (cb_count == (count)); \
cb_count = 0; \
}
static gpointer
thread_push_buffer (gpointer data)
{
GstPad *pad = data;
gst_pad_push (pad, gst_buffer_new ());
return NULL;
}
static GstPadProbeReturn
got_buffer_block (GstPad * pad, GstPadProbeInfo * info, gpointer data)
{
g_mutex_lock (&mutex);
is_blocked = TRUE;
g_cond_broadcast (&cond);
g_mutex_unlock (&mutex);
return GST_PAD_PROBE_OK;
}
#define block_thread() \
{ \
fail_unless (cb_count == 0); \
fail_unless (block_probe_id == 0); \
fail_unless (is_blocked == FALSE); \
fail_unless (push_thread == NULL); \
block_probe_id = gst_pad_add_probe (sinkpad, \
GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, \
got_buffer_block, NULL, NULL); \
push_thread = g_thread_new ("push block", thread_push_buffer, srcpad); \
fail_unless (push_thread != NULL); \
g_mutex_lock (&mutex); \
while (is_blocked == FALSE) \
g_cond_wait (&cond, &mutex); \
g_mutex_unlock (&mutex); \
}
#define unblock_thread() \
{ \
fail_unless (cb_count == 0); \
fail_unless (push_thread != NULL); \
fail_unless (is_blocked == TRUE); \
fail_unless (block_probe_id != 0); \
gst_pad_remove_probe (sinkpad, block_probe_id); \
g_thread_join (push_thread); \
fail_unless (g_list_length (buffers) == 1); \
gst_check_drop_buffers (); \
block_probe_id = 0; \
push_thread = NULL; \
is_blocked = FALSE; \
}
GST_START_TEST (test_insertbin_simple)
{
GstElement *insertbin;
GstElement *elem;
GstElement *elem2;
GstElement *elem3;
GstElement *elem4;
GstPad *srcpad;
GstPad *sinkpad;
g_mutex_init (&mutex);
g_cond_init (&cond);
insertbin = gst_insert_bin_new (NULL);
fail_unless (insertbin != NULL);
ASSERT_OBJECT_REFCOUNT (insertbin, insertbin, 1);
srcpad = gst_check_setup_src_pad (insertbin, &srcpad_template);
sinkpad = gst_check_setup_sink_pad (insertbin, &sinkpad_template);
g_assert (srcpad && sinkpad);
ASSERT_CRITICAL (gst_insert_bin_append (GST_INSERT_BIN (insertbin), NULL,
NULL, NULL));
ASSERT_CRITICAL (gst_insert_bin_append (GST_INSERT_BIN (insertbin), NULL,
fail_cb, NULL));
fail_unless (cb_count == 0);
elem = gst_element_factory_make ("identity", NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
check_reset_cb_count (1);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
check_reset_cb_count (1);
fail_unless (gst_pad_set_active (srcpad, TRUE));
fail_unless (gst_pad_set_active (sinkpad, TRUE));
fail_unless (gst_element_set_state (insertbin,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
fail_unless (cb_count == 0);
fail_unless (buffers == NULL);
push_buffer (srcpad, 0);
block_thread ();
elem = gst_element_factory_make ("identity", NULL);
gst_insert_bin_prepend (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, fail_cb, NULL);
check_reset_cb_count (1);
unblock_thread ();
push_buffer (srcpad, 0);
block_thread ();
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem = gst_element_factory_make ("identity", NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem2 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem2, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem3 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem3, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem4 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_prepend (GST_INSERT_BIN (insertbin), elem4, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem3, success_cb, NULL);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem2, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem2 = gst_element_factory_make ("identity", NULL);
elem3 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_insert_after (GST_INSERT_BIN (insertbin), elem2, elem,
success_cb, NULL);
gst_insert_bin_insert_before (GST_INSERT_BIN (insertbin), elem3, elem4,
success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem3, success_cb, NULL);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem2, success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 2);
push_buffer (srcpad, 0);
block_thread ();
elem2 = gst_element_factory_make ("identity", NULL);
elem3 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_insert_before (GST_INSERT_BIN (insertbin), elem3, elem4,
success_cb, NULL);
gst_insert_bin_insert_after (GST_INSERT_BIN (insertbin), elem2, elem,
success_cb, NULL);
unblock_thread ();
push_buffer (srcpad, 2);
push_buffer (srcpad, 0);
block_thread ();
elem = gst_bin_new (NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, fail_cb, NULL);
check_reset_cb_count (1);
unblock_thread ();
block_thread ();
elem = gst_bin_new (NULL);
elem2 = gst_element_factory_make ("identity", NULL);
gst_bin_add (GST_BIN (elem), elem2);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem2, fail_cb, NULL);
check_reset_cb_count (1);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem2, fail_cb, NULL);
check_reset_cb_count (1);
unblock_thread ();
gst_object_unref (elem);
push_buffer (srcpad, 0);
block_thread ();
elem = gst_element_factory_make ("identity", NULL);
elem2 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem2, success_cb, NULL);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem2, success_cb, NULL);
check_reset_cb_count (2);
unblock_thread ();
push_buffer (srcpad, 1);
push_buffer (srcpad, 0);
block_thread ();
elem = gst_element_factory_make ("identity", NULL);
elem2 = gst_element_factory_make ("identity", NULL);
gst_insert_bin_insert_before (GST_INSERT_BIN (insertbin), elem, elem2,
fail_cb, NULL);
check_reset_cb_count (1);
unblock_thread ();
push_buffer (srcpad, 0);
gst_object_unref (elem2);
fail_unless (gst_element_set_state (insertbin,
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
gst_pad_set_active (srcpad, FALSE);
gst_pad_set_active (sinkpad, FALSE);
elem = gst_element_factory_make ("identity", NULL);
gst_insert_bin_remove (GST_INSERT_BIN (insertbin), elem, fail_cb, NULL);
check_reset_cb_count (1);
gst_insert_bin_append (GST_INSERT_BIN (insertbin), elem, success_cb, NULL);
check_reset_cb_count (1);
gst_check_teardown_sink_pad (insertbin);
gst_check_teardown_src_pad (insertbin);
gst_check_teardown_element (insertbin);
fail_unless (cb_count == 0);
g_mutex_clear (&mutex);
g_cond_clear (&cond);
}
GST_END_TEST;
static Suite *
insert_bin_suite (void)
{
Suite *s = suite_create ("insertbin");
TCase *tc_basic = tcase_create ("general");
suite_add_tcase (s, tc_basic);
tcase_add_test (tc_basic, test_insertbin_simple);
return s;
}
GST_CHECK_MAIN (insert_bin);