diff options
author | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 00:14:42 +0900 |
---|---|---|
committer | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 00:14:42 +0900 |
commit | 715f9ce62a12d128754d2cf47f90a024b537e320 (patch) | |
tree | 57fb94c81055a31938bea831641092152a03089f /gst/interleave | |
parent | dfa84b358c7cdf0535eba1fead62fc4122cc56e6 (diff) | |
download | gst-plugins-good0.10-tizen_2.0.tar.gz gst-plugins-good0.10-tizen_2.0.tar.bz2 gst-plugins-good0.10-tizen_2.0.zip |
Diffstat (limited to 'gst/interleave')
-rw-r--r-- | gst/interleave/Makefile.am | 24 | ||||
-rw-r--r-- | gst/interleave/Makefile.in | 837 | ||||
-rw-r--r-- | gst/interleave/deinterleave.c | 889 | ||||
-rw-r--r-- | gst/interleave/deinterleave.h | 75 | ||||
-rw-r--r-- | gst/interleave/interleave.c | 1306 | ||||
-rw-r--r-- | gst/interleave/interleave.h | 89 | ||||
-rw-r--r-- | gst/interleave/plugin.c | 44 | ||||
-rw-r--r-- | gst/interleave/plugin.h | 31 |
8 files changed, 3295 insertions, 0 deletions
diff --git a/gst/interleave/Makefile.am b/gst/interleave/Makefile.am new file mode 100644 index 0000000..0a2d2d8 --- /dev/null +++ b/gst/interleave/Makefile.am @@ -0,0 +1,24 @@ + +plugin_LTLIBRARIES = libgstinterleave.la + +libgstinterleave_la_SOURCES = plugin.c interleave.c deinterleave.c +libgstinterleave_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstinterleave_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_LIBS) +libgstinterleave_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstinterleave_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = plugin.h interleave.h deinterleave.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstinterleave -:SHARED libgstinterleave \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstinterleave_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstinterleave_la_CFLAGS) \ + -:LDFLAGS $(libgstinterleave_la_LDFLAGS) \ + $(libgstinterleave_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst/interleave/Makefile.in b/gst/interleave/Makefile.in new file mode 100644 index 0000000..fcd6846 --- /dev/null +++ b/gst/interleave/Makefile.in @@ -0,0 +1,837 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = gst/interleave +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ + $(top_srcdir)/common/m4/as-auto-alt.m4 \ + $(top_srcdir)/common/m4/as-compiler-flag.m4 \ + $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \ + $(top_srcdir)/common/m4/as-objc.m4 \ + $(top_srcdir)/common/m4/as-python.m4 \ + $(top_srcdir)/common/m4/as-scrub-include.m4 \ + $(top_srcdir)/common/m4/as-version.m4 \ + $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/common/m4/gst-arch.m4 \ + $(top_srcdir)/common/m4/gst-args.m4 \ + $(top_srcdir)/common/m4/gst-check.m4 \ + $(top_srcdir)/common/m4/gst-default.m4 \ + $(top_srcdir)/common/m4/gst-dowhile.m4 \ + $(top_srcdir)/common/m4/gst-error.m4 \ + $(top_srcdir)/common/m4/gst-feature.m4 \ + $(top_srcdir)/common/m4/gst-gettext.m4 \ + $(top_srcdir)/common/m4/gst-glib2.m4 \ + $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \ + $(top_srcdir)/common/m4/gst-platform.m4 \ + $(top_srcdir)/common/m4/gst-plugin-docs.m4 \ + $(top_srcdir)/common/m4/gst-plugindir.m4 \ + $(top_srcdir)/common/m4/gst-x11.m4 \ + $(top_srcdir)/common/m4/gst.m4 \ + $(top_srcdir)/common/m4/gtk-doc.m4 \ + $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \ + $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \ + $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgstinterleave_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libgstinterleave_la_OBJECTS = libgstinterleave_la-plugin.lo \ + libgstinterleave_la-interleave.lo \ + libgstinterleave_la-deinterleave.lo +libgstinterleave_la_OBJECTS = $(am_libgstinterleave_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libgstinterleave_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(libgstinterleave_la_CFLAGS) $(CFLAGS) \ + $(libgstinterleave_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libgstinterleave_la_SOURCES) +DIST_SOURCES = $(libgstinterleave_la_SOURCES) +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AALIB_CFLAGS = @AALIB_CFLAGS@ +AALIB_CONFIG = @AALIB_CONFIG@ +AALIB_LIBS = @AALIB_LIBS@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANNODEX_CFLAGS = @ANNODEX_CFLAGS@ +ANNODEX_LIBS = @ANNODEX_LIBS@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BZ2_LIBS = @BZ2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@ +CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@ +DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@ +DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@ +DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@ +DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ +DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@ +DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@ +DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DV1394_CFLAGS = @DV1394_CFLAGS@ +DV1394_LIBS = @DV1394_LIBS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +ERROR_CXXFLAGS = @ERROR_CXXFLAGS@ +ESD_CFLAGS = @ESD_CFLAGS@ +ESD_CONFIG = @ESD_CONFIG@ +ESD_LIBS = @ESD_LIBS@ +EXEEXT = @EXEEXT@ +FFLAGS = @FFLAGS@ +FGREP = @FGREP@ +FLAC_CFLAGS = @FLAC_CFLAGS@ +FLAC_LIBS = @FLAC_LIBS@ +GCONFTOOL = @GCONFTOOL@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ +GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ +GCOV = @GCOV@ +GCOV_CFLAGS = @GCOV_CFLAGS@ +GCOV_LIBS = @GCOV_LIBS@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ = @GLIB_REQ@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@ +GSTPB_PREFIX = @GSTPB_PREFIX@ +GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ +GST_BASE_CFLAGS = @GST_BASE_CFLAGS@ +GST_BASE_LIBS = @GST_BASE_LIBS@ +GST_CFLAGS = @GST_CFLAGS@ +GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@ +GST_CHECK_LIBS = @GST_CHECK_LIBS@ +GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@ +GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@ +GST_CXXFLAGS = @GST_CXXFLAGS@ +GST_GDP_CFLAGS = @GST_GDP_CFLAGS@ +GST_GDP_LIBS = @GST_GDP_LIBS@ +GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ +GST_LIBS = @GST_LIBS@ +GST_LICENSE = @GST_LICENSE@ +GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ +GST_MAJORMINOR = @GST_MAJORMINOR@ +GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@ +GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@ +GST_PACKAGE_NAME = @GST_PACKAGE_NAME@ +GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@ +GST_PLUGINS_ALL = @GST_PLUGINS_ALL@ +GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@ +GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@ +GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@ +GST_PLUGINS_DIR = @GST_PLUGINS_DIR@ +GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GST_PREFIX = @GST_PREFIX@ +GST_TOOLS_DIR = @GST_TOOLS_DIR@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_X11_CFLAGS = @GTK_X11_CFLAGS@ +GTK_X11_LIBS = @GTK_X11_LIBS@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +HAVE_AVC1394 = @HAVE_AVC1394@ +HAVE_BZ2 = @HAVE_BZ2@ +HAVE_CXX = @HAVE_CXX@ +HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@ +HAVE_GCONFTOOL = @HAVE_GCONFTOOL@ +HAVE_ROM1394 = @HAVE_ROM1394@ +HAVE_SPEEX = @HAVE_SPEEX@ +HAVE_X = @HAVE_X@ +HAVE_XSHM = @HAVE_XSHM@ +HAVE_ZLIB = @HAVE_ZLIB@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@ +JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@ +JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@ +JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@ +JACK_CFLAGS = @JACK_CFLAGS@ +JACK_LIBS = @JACK_LIBS@ +JPEG_LIBS = @JPEG_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCACA_CFLAGS = @LIBCACA_CFLAGS@ +LIBCACA_LIBS = @LIBCACA_LIBS@ +LIBDV_CFLAGS = @LIBDV_CFLAGS@ +LIBDV_LIBS = @LIBDV_LIBS@ +LIBICONV = @LIBICONV@ +LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@ +LIBIEC61883_LIBS = @LIBIEC61883_LIBS@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@ +LIBV4L2_LIBS = @LIBV4L2_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALEDIR = @LOCALEDIR@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJC_LDFLAGS = @OBJC_LDFLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +ORCC = @ORCC@ +ORCC_FLAGS = @ORCC_FLAGS@ +ORC_CFLAGS = @ORC_CFLAGS@ +ORC_LIBS = @ORC_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@ +PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGINDIR = @PLUGINDIR@ +POSUB = @POSUB@ +PROFILE_CFLAGS = @PROFILE_CFLAGS@ +PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@ +PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@ +PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@ +PULSE_1_0_LIBS = @PULSE_1_0_LIBS@ +PULSE_CFLAGS = @PULSE_CFLAGS@ +PULSE_LIBS = @PULSE_LIBS@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RAW1394_CFLAGS = @RAW1394_CFLAGS@ +RAW1394_LIBS = @RAW1394_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHOUT2_CFLAGS = @SHOUT2_CFLAGS@ +SHOUT2_LIBS = @SHOUT2_LIBS@ +SOUP_CFLAGS = @SOUP_CFLAGS@ +SOUP_LIBS = @SOUP_LIBS@ +SPEEX_CFLAGS = @SPEEX_CFLAGS@ +SPEEX_LIBS = @SPEEX_LIBS@ +STRIP = @STRIP@ +TAGLIB_CFLAGS = @TAGLIB_CFLAGS@ +TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@ +TAGLIB_LIBS = @TAGLIB_LIBS@ +USE_NLS = @USE_NLS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VALGRIND_PATH = @VALGRIND_PATH@ +VERSION = @VERSION@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +WARNING_CXXFLAGS = @WARNING_CXXFLAGS@ +WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ +WAVPACK_LIBS = @WAVPACK_LIBS@ +WIN32_LIBS = @WIN32_LIBS@ +XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@ +XDAMAGE_LIBS = @XDAMAGE_LIBS@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XSHM_LIBS = @XSHM_LIBS@ +XVIDEO_LIBS = @XVIDEO_LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +plugin_LTLIBRARIES = libgstinterleave.la +libgstinterleave_la_SOURCES = plugin.c interleave.c deinterleave.c +libgstinterleave_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstinterleave_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_LIBS) +libgstinterleave_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstinterleave_la_LIBTOOLFLAGS = --tag=disable-static +noinst_HEADERS = plugin.h interleave.h deinterleave.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/interleave/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu gst/interleave/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libgstinterleave.la: $(libgstinterleave_la_OBJECTS) $(libgstinterleave_la_DEPENDENCIES) $(EXTRA_libgstinterleave_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgstinterleave_la_LINK) -rpath $(plugindir) $(libgstinterleave_la_OBJECTS) $(libgstinterleave_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstinterleave_la-deinterleave.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstinterleave_la-interleave.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstinterleave_la-plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgstinterleave_la-plugin.lo: plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -MT libgstinterleave_la-plugin.lo -MD -MP -MF $(DEPDIR)/libgstinterleave_la-plugin.Tpo -c -o libgstinterleave_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstinterleave_la-plugin.Tpo $(DEPDIR)/libgstinterleave_la-plugin.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin.c' object='libgstinterleave_la-plugin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -c -o libgstinterleave_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c + +libgstinterleave_la-interleave.lo: interleave.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -MT libgstinterleave_la-interleave.lo -MD -MP -MF $(DEPDIR)/libgstinterleave_la-interleave.Tpo -c -o libgstinterleave_la-interleave.lo `test -f 'interleave.c' || echo '$(srcdir)/'`interleave.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstinterleave_la-interleave.Tpo $(DEPDIR)/libgstinterleave_la-interleave.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='interleave.c' object='libgstinterleave_la-interleave.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -c -o libgstinterleave_la-interleave.lo `test -f 'interleave.c' || echo '$(srcdir)/'`interleave.c + +libgstinterleave_la-deinterleave.lo: deinterleave.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -MT libgstinterleave_la-deinterleave.lo -MD -MP -MF $(DEPDIR)/libgstinterleave_la-deinterleave.Tpo -c -o libgstinterleave_la-deinterleave.lo `test -f 'deinterleave.c' || echo '$(srcdir)/'`deinterleave.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstinterleave_la-deinterleave.Tpo $(DEPDIR)/libgstinterleave_la-deinterleave.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='deinterleave.c' object='libgstinterleave_la-deinterleave.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstinterleave_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstinterleave_la_CFLAGS) $(CFLAGS) -c -o libgstinterleave_la-deinterleave.lo `test -f 'deinterleave.c' || echo '$(srcdir)/'`deinterleave.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstinterleave -:SHARED libgstinterleave \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstinterleave_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstinterleave_la_CFLAGS) \ + -:LDFLAGS $(libgstinterleave_la_LDFLAGS) \ + $(libgstinterleave_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gst/interleave/deinterleave.c b/gst/interleave/deinterleave.c new file mode 100644 index 0000000..ad88c4e --- /dev/null +++ b/gst/interleave/deinterleave.c @@ -0,0 +1,889 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * 2005 Wim Taymans <wim@fluendo.com> + * 2007 Andy Wingo <wingo at pobox.com> + * 2008 Sebastian Dröge <slomo@circular-chaos.org> + * + * deinterleave.c: deinterleave samples + * + * 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. + */ + +/* TODO: + * - handle changes in number of channels + * - handle changes in channel positions + * - better capsnego by using a buffer alloc function + * and passing downstream caps changes upstream there + */ + +/** + * SECTION:element-deinterleave + * @see_also: interleave + * + * Splits one interleaved multichannel audio stream into many mono audio streams. + * + * This element handles all raw audio formats and supports changing the input caps as long as + * all downstream elements can handle the new caps and the number of channels and the channel + * positions stay the same. This restriction will be removed in later versions by adding or + * removing some source pads as required. + * + * In most cases a queue and an audioconvert element should be added after each source pad + * before further processing of the audio data. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch filesrc location=/path/to/file.mp3 ! decodebin ! audioconvert ! "audio/x-raw-int,channels=2 ! deinterleave name=d d.src0 ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=channel1.ogg d.src1 ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=channel2.ogg + * ]| Decodes an MP3 file and encodes the left and right channel into separate + * Ogg Vorbis files. + * |[ + * gst-launch filesrc location=file.mp3 ! decodebin ! audioconvert ! "audio/x-raw-int,channels=2" ! deinterleave name=d interleave name=i ! audioconvert ! wavenc ! filesink location=test.wav d.src0 ! queue ! audioconvert ! i.sink1 d.src1 ! queue ! audioconvert ! i.sink0 + * ]| Decodes and deinterleaves a Stereo MP3 file into separate channels and + * then interleaves the channels again to a WAV file with the channel with the + * channels exchanged. + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gst/gst.h> +#include <string.h> +#include "deinterleave.h" + +GST_DEBUG_CATEGORY_STATIC (gst_deinterleave_debug); +#define GST_CAT_DEFAULT gst_deinterleave_debug + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("audio/x-raw-int, " + "rate = (int) [ 1, MAX ], " + "channels = (int) 1, " + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " + "width = (int) { 8, 16, 24, 32 }, " + "depth = (int) [ 1, 32 ], " + "signed = (boolean) { true, false }; " + "audio/x-raw-float, " + "rate = (int) [ 1, MAX ], " + "channels = (int) 1, " + "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " + "width = (int) { 32, 64 }") + ); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, MAX ], " + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " + "width = (int) { 8, 16, 24, 32 }, " + "depth = (int) [ 1, 32 ], " + "signed = (boolean) { true, false }; " + "audio/x-raw-float, " + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, MAX ], " + "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " + "width = (int) { 32, 64 }") + ); + +#define MAKE_FUNC(type) \ +static void deinterleave_##type (guint##type *out, guint##type *in, \ + guint stride, guint nframes) \ +{ \ + gint i; \ + \ + for (i = 0; i < nframes; i++) { \ + out[i] = *in; \ + in += stride; \ + } \ +} + +MAKE_FUNC (8); +MAKE_FUNC (16); +MAKE_FUNC (32); +MAKE_FUNC (64); + +static void +deinterleave_24 (guint8 * out, guint8 * in, guint stride, guint nframes) +{ + gint i; + + for (i = 0; i < nframes; i++) { + memcpy (out, in, 3); + out += 3; + in += stride * 3; + } +} + +GST_BOILERPLATE (GstDeinterleave, gst_deinterleave, GstElement, + GST_TYPE_ELEMENT); + +enum +{ + PROP_0, + PROP_KEEP_POSITIONS +}; + +static GstFlowReturn gst_deinterleave_chain (GstPad * pad, GstBuffer * buffer); + +static gboolean gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps); + +static GstCaps *gst_deinterleave_sink_getcaps (GstPad * pad); + +static gboolean gst_deinterleave_sink_activate_push (GstPad * pad, + gboolean active); +static gboolean gst_deinterleave_sink_event (GstPad * pad, GstEvent * event); + +static gboolean gst_deinterleave_src_query (GstPad * pad, GstQuery * query); + +static void gst_deinterleave_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_deinterleave_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + + +static void +gst_deinterleave_finalize (GObject * obj) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (obj); + + if (self->pos) { + g_free (self->pos); + self->pos = NULL; + } + + if (self->pending_events) { + g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref, NULL); + g_list_free (self->pending_events); + self->pending_events = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_deinterleave_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = (GstElementClass *) g_class; + + gst_element_class_set_details_simple (gstelement_class, "Audio deinterleaver", + "Filter/Converter/Audio", + "Splits one interleaved multichannel audio stream into many mono audio streams", + "Andy Wingo <wingo at pobox.com>, " + "Iain <iain@prettypeople.org>, " + "Sebastian Dröge <slomo@circular-chaos.org>"); + + gst_element_class_add_static_pad_template (gstelement_class, + &sink_template); + gst_element_class_add_static_pad_template (gstelement_class, + &src_template); +} + +static void +gst_deinterleave_class_init (GstDeinterleaveClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + GST_DEBUG_CATEGORY_INIT (gst_deinterleave_debug, "deinterleave", 0, + "deinterleave element"); + + gobject_class->finalize = gst_deinterleave_finalize; + gobject_class->set_property = gst_deinterleave_set_property; + gobject_class->get_property = gst_deinterleave_get_property; + + /** + * GstDeinterleave:keep-positions + * + * Keep positions: When enable the caps on the output buffers will + * contain the original channel positions. This can be used to correctly + * interleave the output again later but can also lead to unwanted effects + * if the output should be handled as Mono. + * + */ + g_object_class_install_property (gobject_class, PROP_KEEP_POSITIONS, + g_param_spec_boolean ("keep-positions", "Keep positions", + "Keep the original channel positions on the output buffers", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_deinterleave_init (GstDeinterleave * self, GstDeinterleaveClass * klass) +{ + self->channels = 0; + self->pos = NULL; + self->keep_positions = FALSE; + self->width = 0; + self->func = NULL; + + /* Add sink pad */ + self->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_chain_function (self->sink, + GST_DEBUG_FUNCPTR (gst_deinterleave_chain)); + gst_pad_set_setcaps_function (self->sink, + GST_DEBUG_FUNCPTR (gst_deinterleave_sink_setcaps)); + gst_pad_set_getcaps_function (self->sink, + GST_DEBUG_FUNCPTR (gst_deinterleave_sink_getcaps)); + gst_pad_set_activatepush_function (self->sink, + GST_DEBUG_FUNCPTR (gst_deinterleave_sink_activate_push)); + gst_pad_set_event_function (self->sink, + GST_DEBUG_FUNCPTR (gst_deinterleave_sink_event)); + gst_element_add_pad (GST_ELEMENT (self), self->sink); +} + +static void +gst_deinterleave_add_new_pads (GstDeinterleave * self, GstCaps * caps) +{ + GstPad *pad; + + guint i; + + for (i = 0; i < self->channels; i++) { + gchar *name = g_strdup_printf ("src%d", i); + + GstCaps *srccaps; + + GstStructure *s; + + pad = gst_pad_new_from_static_template (&src_template, name); + g_free (name); + + /* Set channel position if we know it */ + if (self->keep_positions) { + GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_NONE }; + + srccaps = gst_caps_copy (caps); + s = gst_caps_get_structure (srccaps, 0); + if (self->pos) + gst_audio_set_channel_positions (s, &self->pos[i]); + else + gst_audio_set_channel_positions (s, pos); + } else { + srccaps = caps; + } + + gst_pad_set_caps (pad, srccaps); + gst_pad_use_fixed_caps (pad); + gst_pad_set_query_function (pad, + GST_DEBUG_FUNCPTR (gst_deinterleave_src_query)); + gst_pad_set_active (pad, TRUE); + gst_element_add_pad (GST_ELEMENT (self), pad); + self->srcpads = g_list_prepend (self->srcpads, gst_object_ref (pad)); + + if (self->keep_positions) + gst_caps_unref (srccaps); + } + + gst_element_no_more_pads (GST_ELEMENT (self)); + self->srcpads = g_list_reverse (self->srcpads); +} + +static void +gst_deinterleave_set_pads_caps (GstDeinterleave * self, GstCaps * caps) +{ + GList *l; + + GstStructure *s; + + gint i; + + for (l = self->srcpads, i = 0; l; l = l->next, i++) { + GstPad *pad = GST_PAD (l->data); + + GstCaps *srccaps; + + /* Set channel position if we know it */ + if (self->keep_positions) { + GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_NONE }; + + srccaps = gst_caps_copy (caps); + s = gst_caps_get_structure (srccaps, 0); + if (self->pos) + gst_audio_set_channel_positions (s, &self->pos[i]); + else + gst_audio_set_channel_positions (s, pos); + } else { + srccaps = caps; + } + + gst_pad_set_caps (pad, srccaps); + + if (self->keep_positions) + gst_caps_unref (srccaps); + } +} + +static void +gst_deinterleave_remove_pads (GstDeinterleave * self) +{ + GList *l; + + GST_INFO_OBJECT (self, "removing pads"); + + for (l = self->srcpads; l; l = l->next) { + GstPad *pad = GST_PAD (l->data); + + gst_element_remove_pad (GST_ELEMENT_CAST (self), pad); + gst_object_unref (pad); + } + g_list_free (self->srcpads); + self->srcpads = NULL; + + gst_pad_set_caps (self->sink, NULL); + gst_caps_replace (&self->sinkcaps, NULL); +} + +static gboolean +gst_deinterleave_set_process_function (GstDeinterleave * self, GstCaps * caps) +{ + GstStructure *s; + + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (s, "width", &self->width)) + return FALSE; + + switch (self->width) { + case 8: + self->func = (GstDeinterleaveFunc) deinterleave_8; + break; + case 16: + self->func = (GstDeinterleaveFunc) deinterleave_16; + break; + case 24: + self->func = (GstDeinterleaveFunc) deinterleave_24; + break; + case 32: + self->func = (GstDeinterleaveFunc) deinterleave_32; + break; + case 64: + self->func = (GstDeinterleaveFunc) deinterleave_64; + break; + default: + return FALSE; + } + return TRUE; +} + +static gboolean +gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstDeinterleave *self; + + GstCaps *srccaps; + + GstStructure *s; + + self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps); + + if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) { + gint new_channels, i; + + GstAudioChannelPosition *pos; + + gboolean same_layout = TRUE; + + s = gst_caps_get_structure (caps, 0); + + /* We allow caps changes as long as the number of channels doesn't change + * and the channel positions stay the same. _getcaps() should've cared + * for this already but better be safe. + */ + if (!gst_structure_get_int (s, "channels", &new_channels) || + new_channels != self->channels || + !gst_deinterleave_set_process_function (self, caps)) + goto cannot_change_caps; + + /* Now check the channel positions. If we had no channel positions + * and get them or the other way around things have changed. + * If we had channel positions and get different ones things have + * changed too of course + */ + pos = gst_audio_get_channel_positions (s); + if ((pos && !self->pos) || (!pos && self->pos)) + goto cannot_change_caps; + + if (pos) { + for (i = 0; i < self->channels; i++) { + if (self->pos[i] != pos[i]) { + same_layout = FALSE; + break; + } + } + g_free (pos); + if (!same_layout) + goto cannot_change_caps; + } + + } else { + s = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (s, "channels", &self->channels)) + goto no_channels; + + if (!gst_deinterleave_set_process_function (self, caps)) + goto unsupported_caps; + + self->pos = gst_audio_get_channel_positions (s); + } + + gst_caps_replace (&self->sinkcaps, caps); + + /* Get srcpad caps */ + srccaps = gst_caps_copy (caps); + s = gst_caps_get_structure (srccaps, 0); + gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL); + gst_structure_remove_field (s, "channel-positions"); + + /* If we already have pads, update the caps otherwise + * add new pads */ + if (self->srcpads) { + gst_deinterleave_set_pads_caps (self, srccaps); + } else { + gst_deinterleave_add_new_pads (self, srccaps); + } + + gst_caps_unref (srccaps); + gst_object_unref (self); + + return TRUE; + +cannot_change_caps: + { + GST_ERROR_OBJECT (self, "can't set new caps: %" GST_PTR_FORMAT, caps); + gst_object_unref (self); + return FALSE; + } +unsupported_caps: + { + GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps); + gst_object_unref (self); + return FALSE; + } +no_channels: + { + GST_ERROR_OBJECT (self, "invalid caps"); + gst_object_unref (self); + return FALSE; + } +} + +static void +__remove_channels (GstCaps * caps) +{ + GstStructure *s; + + gint i, size; + + size = gst_caps_get_size (caps); + for (i = 0; i < size; i++) { + s = gst_caps_get_structure (caps, i); + gst_structure_remove_field (s, "channel-positions"); + gst_structure_remove_field (s, "channels"); + } +} + +static void +__set_channels (GstCaps * caps, gint channels) +{ + GstStructure *s; + + gint i, size; + + size = gst_caps_get_size (caps); + for (i = 0; i < size; i++) { + s = gst_caps_get_structure (caps, i); + if (channels > 0) + gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL); + else + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + } +} + +static GstCaps * +gst_deinterleave_sink_getcaps (GstPad * pad) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); + + GstCaps *ret; + + GList *l; + + GST_OBJECT_LOCK (self); + /* Intersect all of our pad template caps with the peer caps of the pad + * to get all formats that are possible up- and downstream. + * + * For the pad for which the caps are requested we don't remove the channel + * informations as they must be in the returned caps and incompatibilities + * will be detected here already + */ + ret = gst_caps_new_any (); + for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) { + GstPad *ourpad = GST_PAD (l->data); + + GstCaps *peercaps = NULL, *ourcaps; + + ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad)); + + if (pad == ourpad) { + if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) + __set_channels (ourcaps, self->channels); + else + __set_channels (ourcaps, 1); + } else { + __remove_channels (ourcaps); + /* Only ask for peer caps for other pads than pad + * as otherwise gst_pad_peer_get_caps() might call + * back into this function and deadlock + */ + peercaps = gst_pad_peer_get_caps (ourpad); + } + + /* If the peer exists and has caps add them to the intersection, + * otherwise assume that the peer accepts everything */ + if (peercaps) { + GstCaps *intersection; + + GstCaps *oldret = ret; + + __remove_channels (peercaps); + + intersection = gst_caps_intersect (peercaps, ourcaps); + + ret = gst_caps_intersect (ret, intersection); + gst_caps_unref (intersection); + gst_caps_unref (peercaps); + gst_caps_unref (oldret); + } else { + GstCaps *oldret = ret; + + ret = gst_caps_intersect (ret, ourcaps); + gst_caps_unref (oldret); + } + gst_caps_unref (ourcaps); + } + GST_OBJECT_UNLOCK (self); + + gst_object_unref (self); + + GST_DEBUG_OBJECT (pad, "Intersected caps to %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_deinterleave_sink_event (GstPad * pad, GstEvent * event) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); + + gboolean ret; + + GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), + GST_DEBUG_PAD_NAME (pad)); + + /* Send FLUSH_STOP, FLUSH_START and EOS immediately, no matter if + * we have src pads already or not. Queue all other events and + * push them after we have src pads + */ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_FLUSH_START: + case GST_EVENT_EOS: + ret = gst_pad_event_default (pad, event); + break; + default: + if (self->srcpads) { + ret = gst_pad_event_default (pad, event); + } else { + GST_OBJECT_LOCK (self); + self->pending_events = g_list_append (self->pending_events, event); + GST_OBJECT_UNLOCK (self); + ret = TRUE; + } + break; + } + + gst_object_unref (self); + + return ret; +} + +static gboolean +gst_deinterleave_src_query (GstPad * pad, GstQuery * query) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); + + gboolean res; + + res = gst_pad_query_default (pad, query); + + if (res && GST_QUERY_TYPE (query) == GST_QUERY_DURATION) { + GstFormat format; + + gint64 dur; + + gst_query_parse_duration (query, &format, &dur); + + /* Need to divide by the number of channels in byte format + * to get the correct value. All other formats should be fine + */ + if (format == GST_FORMAT_BYTES && dur != -1) + gst_query_set_duration (query, format, dur / self->channels); + } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_POSITION) { + GstFormat format; + + gint64 pos; + + gst_query_parse_position (query, &format, &pos); + + /* Need to divide by the number of channels in byte format + * to get the correct value. All other formats should be fine + */ + if (format == GST_FORMAT_BYTES && pos != -1) + gst_query_set_position (query, format, pos / self->channels); + } + + gst_object_unref (self); + return res; +} + +static void +gst_deinterleave_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (object); + + switch (prop_id) { + case PROP_KEEP_POSITIONS: + self->keep_positions = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_deinterleave_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (object); + + switch (prop_id) { + case PROP_KEEP_POSITIONS: + g_value_set_boolean (value, self->keep_positions); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_deinterleave_process (GstDeinterleave * self, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + + guint channels = self->channels; + + guint pads_pushed = 0, buffers_allocated = 0; + + guint nframes = GST_BUFFER_SIZE (buf) / channels / (self->width / 8); + + guint bufsize = nframes * (self->width / 8); + + guint i; + + GList *srcs; + + GstBuffer **buffers_out = g_new0 (GstBuffer *, channels); + + guint8 *in, *out; + + /* Send any pending events to all src pads */ + GST_OBJECT_LOCK (self); + if (self->pending_events) { + GList *events; + + GstEvent *event; + + GST_DEBUG_OBJECT (self, "Sending pending events to all src pads"); + + for (events = self->pending_events; events != NULL; events = events->next) { + event = GST_EVENT (events->data); + + for (srcs = self->srcpads; srcs != NULL; srcs = srcs->next) + gst_pad_push_event (GST_PAD (srcs->data), gst_event_ref (event)); + gst_event_unref (event); + } + + g_list_free (self->pending_events); + self->pending_events = NULL; + } + GST_OBJECT_UNLOCK (self); + + /* Allocate buffers */ + for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) { + GstPad *pad = (GstPad *) srcs->data; + + buffers_out[i] = NULL; + ret = + gst_pad_alloc_buffer (pad, GST_BUFFER_OFFSET_NONE, bufsize, + GST_PAD_CAPS (pad), &buffers_out[i]); + + /* Make sure we got a correct buffer. The only other case we allow + * here is an unliked pad */ + if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) + goto alloc_buffer_failed; + else if (buffers_out[i] && GST_BUFFER_SIZE (buffers_out[i]) != bufsize) + goto alloc_buffer_bad_size; + else if (buffers_out[i] && + !gst_caps_is_equal (GST_BUFFER_CAPS (buffers_out[i]), + GST_PAD_CAPS (pad))) + goto invalid_caps; + + if (buffers_out[i]) { + gst_buffer_copy_metadata (buffers_out[i], buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + buffers_allocated++; + } + } + + /* Return NOT_LINKED if no pad was linked */ + if (!buffers_allocated) { + GST_WARNING_OBJECT (self, + "Couldn't allocate any buffers because no pad was linked"); + ret = GST_FLOW_NOT_LINKED; + goto done; + } + + /* deinterleave */ + for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) { + GstPad *pad = (GstPad *) srcs->data; + + in = (guint8 *) GST_BUFFER_DATA (buf); + in += i * (self->width / 8); + if (buffers_out[i]) { + out = (guint8 *) GST_BUFFER_DATA (buffers_out[i]); + + self->func (out, in, channels, nframes); + + ret = gst_pad_push (pad, buffers_out[i]); + buffers_out[i] = NULL; + if (ret == GST_FLOW_OK) + pads_pushed++; + else if (ret == GST_FLOW_NOT_LINKED) + ret = GST_FLOW_OK; + else + goto push_failed; + } + } + + /* Return NOT_LINKED if no pad was linked */ + if (!pads_pushed) + ret = GST_FLOW_NOT_LINKED; + +done: + gst_buffer_unref (buf); + g_free (buffers_out); + return ret; + +alloc_buffer_failed: + { + GST_WARNING ("gst_pad_alloc_buffer() returned %s", gst_flow_get_name (ret)); + goto clean_buffers; + + } +alloc_buffer_bad_size: + { + GST_WARNING ("called alloc_buffer(), but didn't get requested bytes"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto clean_buffers; + } +invalid_caps: + { + GST_WARNING ("called alloc_buffer(), but didn't get requested caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto clean_buffers; + } +push_failed: + { + GST_DEBUG ("push() failed, flow = %s", gst_flow_get_name (ret)); + goto clean_buffers; + } +clean_buffers: + { + for (i = 0; i < channels; i++) { + if (buffers_out[i]) + gst_buffer_unref (buffers_out[i]); + } + gst_buffer_unref (buf); + g_free (buffers_out); + return ret; + } +} + +static GstFlowReturn +gst_deinterleave_chain (GstPad * pad, GstBuffer * buffer) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (GST_PAD_PARENT (pad)); + + GstFlowReturn ret; + + g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED); + g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED); + g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED); + + ret = gst_deinterleave_process (self, buffer); + + if (ret != GST_FLOW_OK) + GST_DEBUG_OBJECT (self, "flow return: %s", gst_flow_get_name (ret)); + + return ret; +} + +static gboolean +gst_deinterleave_sink_activate_push (GstPad * pad, gboolean active) +{ + GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); + + /* Reset everything when the pad is deactivated */ + if (!active) { + gst_deinterleave_remove_pads (self); + if (self->pos) { + g_free (self->pos); + self->pos = NULL; + } + self->channels = 0; + self->width = 0; + self->func = NULL; + + if (self->pending_events) { + g_list_foreach (self->pending_events, (GFunc) gst_mini_object_unref, + NULL); + g_list_free (self->pending_events); + self->pending_events = NULL; + } + } + + gst_object_unref (self); + + return TRUE; +} diff --git a/gst/interleave/deinterleave.h b/gst/interleave/deinterleave.h new file mode 100644 index 0000000..fe8ec75 --- /dev/null +++ b/gst/interleave/deinterleave.h @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * 2005 Wim Taymans <wim@fluendo.com> + * 2007 Andy Wingo <wingo at pobox.com> + * 2008 Sebastian Dröge <slomo@circular-chaos.org> + * + * deinterleave.c: deinterleave samples + * + * 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 __DEINTERLEAVE_H__ +#define __DEINTERLEAVE_H__ + +G_BEGIN_DECLS + +#include <gst/gst.h> +#include <gst/audio/multichannel.h> + +#define GST_TYPE_DEINTERLEAVE (gst_deinterleave_get_type()) +#define GST_DEINTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEINTERLEAVE,GstDeinterleave)) +#define GST_DEINTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEINTERLEAVE,GstDeinterleaveClass)) +#define GST_DEINTERLEAVE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_DEINTERLEAVE,GstDeinterleaveClass)) +#define GST_IS_DEINTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEINTERLEAVE)) +#define GST_IS_DEINTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEINTERLEAVE)) + +typedef struct _GstDeinterleave GstDeinterleave; +typedef struct _GstDeinterleaveClass GstDeinterleaveClass; + +typedef void (*GstDeinterleaveFunc) (gpointer out, gpointer in, guint stride, guint nframes); + +struct _GstDeinterleave +{ + GstElement element; + + /*< private > */ + GList *srcpads; + GstCaps *sinkcaps; + gint channels; + GstAudioChannelPosition *pos; + gboolean keep_positions; + + GstPad *sink; + + gint width; + GstDeinterleaveFunc func; + + GList *pending_events; +}; + +struct _GstDeinterleaveClass +{ + GstElementClass parent_class; +}; + +GType gst_deinterleave_get_type (void); + +G_END_DECLS + +#endif /* __DEINTERLEAVE_H__ */ diff --git a/gst/interleave/interleave.c b/gst/interleave/interleave.c new file mode 100644 index 0000000..bc672d1 --- /dev/null +++ b/gst/interleave/interleave.c @@ -0,0 +1,1306 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * 2005 Wim Taymans <wim@fluendo.com> + * 2007 Andy Wingo <wingo at pobox.com> + * 2008 Sebastian Dröge <slomo@circular-chaos.rg> + * + * interleave.c: interleave samples, mostly based on adder. + * + * 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. + */ + +/* TODO: + * - handle caps changes + * - handle more queries/events + */ + +/** + * SECTION:element-interleave + * @see_also: deinterleave + * + * Merges separate mono inputs into one interleaved stream. + * + * This element handles all raw floating point sample formats and all signed integer sample formats. The first + * caps on one of the sinkpads will set the caps of the output so usually an audioconvert element should be + * placed before every sinkpad of interleave. + * + * It's possible to change the number of channels while the pipeline is running by adding or removing + * some of the request pads but this will change the caps of the output buffers. Changing the input + * caps is _not_ supported yet. + * + * The channel number of every sinkpad in the out can be retrieved from the "channel" property of the pad. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch filesrc location=file.mp3 ! decodebin ! audioconvert ! "audio/x-raw-int,channels=2" ! deinterleave name=d interleave name=i ! audioconvert ! wavenc ! filesink location=test.wav d.src0 ! queue ! audioconvert ! i.sink1 d.src1 ! queue ! audioconvert ! i.sink0 + * ]| Decodes and deinterleaves a Stereo MP3 file into separate channels and + * then interleaves the channels again to a WAV file with the channel with the + * channels exchanged. + * |[ + * gst-launch interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav filesrc location=file1.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink0 filesrc location=file2.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink1 + * ]| Interleaves two Mono WAV files to a single Stereo WAV file. + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gst/gst.h> +#include <string.h> +#include "interleave.h" + +#include <gst/audio/multichannel.h> + +GST_DEBUG_CATEGORY_STATIC (gst_interleave_debug); +#define GST_CAT_DEFAULT gst_interleave_debug + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("audio/x-raw-int, " + "rate = (int) [ 1, MAX ], " + "channels = (int) 1, " + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " + "width = (int) { 8, 16, 24, 32 }, " + "depth = (int) [ 1, 32 ], " + "signed = (boolean) true; " + "audio/x-raw-float, " + "rate = (int) [ 1, MAX ], " + "channels = (int) 1, " + "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " + "width = (int) { 32, 64 }") + ); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, MAX ], " + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " + "width = (int) { 8, 16, 24, 32 }, " + "depth = (int) [ 1, 32 ], " + "signed = (boolean) true; " + "audio/x-raw-float, " + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, MAX ], " + "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " + "width = (int) { 32, 64 }") + ); + +#define MAKE_FUNC(type) \ +static void interleave_##type (guint##type *out, guint##type *in, \ + guint stride, guint nframes) \ +{ \ + gint i; \ + \ + for (i = 0; i < nframes; i++) { \ + *out = in[i]; \ + out += stride; \ + } \ +} + +MAKE_FUNC (8); +MAKE_FUNC (16); +MAKE_FUNC (32); +MAKE_FUNC (64); + +static void +interleave_24 (guint8 * out, guint8 * in, guint stride, guint nframes) +{ + gint i; + + for (i = 0; i < nframes; i++) { + memcpy (out, in, 3); + out += stride * 3; + in += 3; + } +} + +typedef struct +{ + GstPad parent; + guint channel; +} GstInterleavePad; + +enum +{ + PROP_PAD_0, + PROP_PAD_CHANNEL +}; + +static void gst_interleave_pad_class_init (GstPadClass * klass); + +#define GST_TYPE_INTERLEAVE_PAD (gst_interleave_pad_get_type()) +#define GST_INTERLEAVE_PAD(pad) (G_TYPE_CHECK_INSTANCE_CAST((pad),GST_TYPE_INTERLEAVE_PAD,GstInterleavePad)) +#define GST_INTERLEAVE_PAD_CAST(pad) ((GstInterleavePad *) pad) +#define GST_IS_INTERLEAVE_PAD(pad) (G_TYPE_CHECK_INSTANCE_TYPE((pad),GST_TYPE_INTERLEAVE_PAD)) +static GType +gst_interleave_pad_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + type = g_type_register_static_simple (GST_TYPE_PAD, + g_intern_static_string ("GstInterleavePad"), sizeof (GstPadClass), + (GClassInitFunc) gst_interleave_pad_class_init, + sizeof (GstInterleavePad), NULL, 0); + } + return type; +} + +static void +gst_interleave_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstInterleavePad *self = GST_INTERLEAVE_PAD (object); + + switch (prop_id) { + case PROP_PAD_CHANNEL: + g_value_set_uint (value, self->channel); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_interleave_pad_class_init (GstPadClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->get_property = gst_interleave_pad_get_property; + + g_object_class_install_property (gobject_class, + PROP_PAD_CHANNEL, + g_param_spec_uint ("channel", + "Channel number", + "Number of the channel of this pad in the output", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + +GST_BOILERPLATE (GstInterleave, gst_interleave, GstElement, GST_TYPE_ELEMENT); + +enum +{ + PROP_0, + PROP_CHANNEL_POSITIONS, + PROP_CHANNEL_POSITIONS_FROM_INPUT +}; + +static void gst_interleave_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_interleave_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPad *gst_interleave_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_interleave_release_pad (GstElement * element, GstPad * pad); + +static GstStateChangeReturn gst_interleave_change_state (GstElement * element, + GstStateChange transition); + +static gboolean gst_interleave_src_query (GstPad * pad, GstQuery * query); + +static gboolean gst_interleave_src_event (GstPad * pad, GstEvent * event); + +static gboolean gst_interleave_sink_event (GstPad * pad, GstEvent * event); + +static gboolean gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps); + +static GstCaps *gst_interleave_sink_getcaps (GstPad * pad); + +static GstFlowReturn gst_interleave_collected (GstCollectPads * pads, + GstInterleave * self); + +static void +gst_interleave_finalize (GObject * object) +{ + GstInterleave *self = GST_INTERLEAVE (object); + + if (self->collect) { + gst_object_unref (self->collect); + self->collect = NULL; + } + + if (self->channel_positions + && self->channel_positions != self->input_channel_positions) { + g_value_array_free (self->channel_positions); + self->channel_positions = NULL; + } + + if (self->input_channel_positions) { + g_value_array_free (self->input_channel_positions); + self->input_channel_positions = NULL; + } + + gst_caps_replace (&self->sinkcaps, NULL); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_interleave_check_channel_positions (GValueArray * positions) +{ + gint i; + guint channels; + GstAudioChannelPosition *pos; + gboolean ret; + + channels = positions->n_values; + pos = g_new (GstAudioChannelPosition, positions->n_values); + + for (i = 0; i < channels; i++) { + GValue *v = g_value_array_get_nth (positions, i); + + pos[i] = g_value_get_enum (v); + } + + ret = gst_audio_check_channel_positions (pos, channels); + g_free (pos); + + return ret; +} + +static void +gst_interleave_set_channel_positions (GstInterleave * self, GstStructure * s) +{ + GValue pos_array = { 0, }; + gint i; + + g_value_init (&pos_array, GST_TYPE_ARRAY); + + if (self->channel_positions + && self->channels == self->channel_positions->n_values + && gst_interleave_check_channel_positions (self->channel_positions)) { + GST_DEBUG_OBJECT (self, "Using provided channel positions"); + for (i = 0; i < self->channels; i++) + gst_value_array_append_value (&pos_array, + g_value_array_get_nth (self->channel_positions, i)); + } else { + GValue pos_none = { 0, }; + + GST_WARNING_OBJECT (self, "Using NONE channel positions"); + + g_value_init (&pos_none, GST_TYPE_AUDIO_CHANNEL_POSITION); + g_value_set_enum (&pos_none, GST_AUDIO_CHANNEL_POSITION_NONE); + + for (i = 0; i < self->channels; i++) + gst_value_array_append_value (&pos_array, &pos_none); + + g_value_unset (&pos_none); + } + gst_structure_set_value (s, "channel-positions", &pos_array); + g_value_unset (&pos_array); +} + +static void +gst_interleave_base_init (gpointer g_class) +{ + gst_element_class_set_details_simple (g_class, "Audio interleaver", + "Filter/Converter/Audio", + "Folds many mono channels into one interleaved audio stream", + "Andy Wingo <wingo at pobox.com>, " + "Sebastian Dröge <slomo@circular-chaos.org>"); + + gst_element_class_add_static_pad_template (g_class, &sink_template); + gst_element_class_add_static_pad_template (g_class, &src_template); +} + +static void +gst_interleave_class_init (GstInterleaveClass * klass) +{ + GstElementClass *gstelement_class; + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (gst_interleave_debug, "interleave", 0, + "interleave element"); + + /* Reference GstInterleavePad class to have the type registered from + * a threadsafe context + */ + g_type_class_ref (GST_TYPE_INTERLEAVE_PAD); + + gobject_class->finalize = gst_interleave_finalize; + gobject_class->set_property = gst_interleave_set_property; + gobject_class->get_property = gst_interleave_get_property; + + /** + * GstInterleave:channel-positions + * + * Channel positions: This property controls the channel positions + * that are used on the src caps. The number of elements should be + * the same as the number of sink pads and the array should contain + * a valid list of channel positions. The n-th element of the array + * is the position of the n-th sink pad. + * + * These channel positions will only be used if they're valid and the + * number of elements is the same as the number of channels. If this + * is not given a NONE layout will be used. + * + */ + g_object_class_install_property (gobject_class, PROP_CHANNEL_POSITIONS, + g_param_spec_value_array ("channel-positions", "Channel positions", + "Channel positions used on the output", + g_param_spec_enum ("channel-position", "Channel position", + "Channel position of the n-th input", + GST_TYPE_AUDIO_CHANNEL_POSITION, + GST_AUDIO_CHANNEL_POSITION_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS), + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstInterleave:channel-positions-from-input + * + * Channel positions from input: If this property is set to %TRUE the channel + * positions will be taken from the input caps if valid channel positions for + * the output can be constructed from them. If this is set to %TRUE setting the + * channel-positions property overwrites this property again. + * + */ + g_object_class_install_property (gobject_class, + PROP_CHANNEL_POSITIONS_FROM_INPUT, + g_param_spec_boolean ("channel-positions-from-input", + "Channel positions from input", + "Take channel positions from the input", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_interleave_request_new_pad); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_interleave_release_pad); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_interleave_change_state); +} + +static void +gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass) +{ + self->src = gst_pad_new_from_static_template (&src_template, "src"); + + gst_pad_set_query_function (self->src, + GST_DEBUG_FUNCPTR (gst_interleave_src_query)); + gst_pad_set_event_function (self->src, + GST_DEBUG_FUNCPTR (gst_interleave_src_event)); + + gst_element_add_pad (GST_ELEMENT (self), self->src); + + self->collect = gst_collect_pads_new (); + gst_collect_pads_set_function (self->collect, + (GstCollectPadsFunction) gst_interleave_collected, self); + + self->input_channel_positions = g_value_array_new (0); + self->channel_positions_from_input = TRUE; + self->channel_positions = self->input_channel_positions; +} + +static void +gst_interleave_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstInterleave *self = GST_INTERLEAVE (object); + + switch (prop_id) { + case PROP_CHANNEL_POSITIONS: + if (self->channel_positions && + self->channel_positions != self->input_channel_positions) + g_value_array_free (self->channel_positions); + + self->channel_positions = g_value_dup_boxed (value); + self->channel_positions_from_input = FALSE; + break; + case PROP_CHANNEL_POSITIONS_FROM_INPUT: + self->channel_positions_from_input = g_value_get_boolean (value); + + if (self->channel_positions_from_input) { + if (self->channel_positions && + self->channel_positions != self->input_channel_positions) + g_value_array_free (self->channel_positions); + self->channel_positions = self->input_channel_positions; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_interleave_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstInterleave *self = GST_INTERLEAVE (object); + + switch (prop_id) { + case PROP_CHANNEL_POSITIONS: + g_value_set_boxed (value, self->channel_positions); + break; + case PROP_CHANNEL_POSITIONS_FROM_INPUT: + g_value_set_boolean (value, self->channel_positions_from_input); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * req_name) +{ + GstInterleave *self = GST_INTERLEAVE (element); + GstPad *new_pad; + gchar *pad_name; + gint channels, padnumber; + GValue val = { 0, }; + + if (templ->direction != GST_PAD_SINK) + goto not_sink_pad; + +#if GLIB_CHECK_VERSION(2,29,5) + channels = g_atomic_int_add (&self->channels, 1); + padnumber = g_atomic_int_add (&self->padcounter, 1); +#else + channels = g_atomic_int_exchange_and_add (&self->channels, 1); + padnumber = g_atomic_int_exchange_and_add (&self->padcounter, 1); +#endif + + pad_name = g_strdup_printf ("sink%d", padnumber); + new_pad = GST_PAD_CAST (g_object_new (GST_TYPE_INTERLEAVE_PAD, + "name", pad_name, "direction", templ->direction, + "template", templ, NULL)); + GST_INTERLEAVE_PAD_CAST (new_pad)->channel = channels; + GST_DEBUG_OBJECT (self, "requested new pad %s", pad_name); + g_free (pad_name); + + gst_pad_set_setcaps_function (new_pad, + GST_DEBUG_FUNCPTR (gst_interleave_sink_setcaps)); + gst_pad_set_getcaps_function (new_pad, + GST_DEBUG_FUNCPTR (gst_interleave_sink_getcaps)); + + gst_collect_pads_add_pad (self->collect, new_pad, sizeof (GstCollectData)); + + /* FIXME: hacked way to override/extend the event function of + * GstCollectPads; because it sets its own event function giving the + * element no access to events */ + self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (new_pad); + gst_pad_set_event_function (new_pad, + GST_DEBUG_FUNCPTR (gst_interleave_sink_event)); + + if (!gst_element_add_pad (element, new_pad)) + goto could_not_add; + + g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION); + g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_NONE); + self->input_channel_positions = + g_value_array_append (self->input_channel_positions, &val); + g_value_unset (&val); + + /* Update the src caps if we already have them */ + if (self->sinkcaps) { + GstCaps *srccaps; + GstStructure *s; + + /* Take lock to make sure processing finishes first */ + GST_OBJECT_LOCK (self->collect); + + srccaps = gst_caps_copy (self->sinkcaps); + s = gst_caps_get_structure (srccaps, 0); + + gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL); + gst_interleave_set_channel_positions (self, s); + + gst_pad_set_caps (self->src, srccaps); + gst_caps_unref (srccaps); + + GST_OBJECT_UNLOCK (self->collect); + } + + return new_pad; + + /* errors */ +not_sink_pad: + { + g_warning ("interleave: requested new pad that is not a SINK pad\n"); + return NULL; + } +could_not_add: + { + GST_DEBUG_OBJECT (self, "could not add pad %s", GST_PAD_NAME (new_pad)); + gst_collect_pads_remove_pad (self->collect, new_pad); + gst_object_unref (new_pad); + return NULL; + } +} + +static void +gst_interleave_release_pad (GstElement * element, GstPad * pad) +{ + GstInterleave *self = GST_INTERLEAVE (element); + GList *l; + + g_return_if_fail (GST_IS_INTERLEAVE_PAD (pad)); + + /* Take lock to make sure we're not changing this when processing buffers */ + GST_OBJECT_LOCK (self->collect); + + g_atomic_int_add (&self->channels, -1); + + g_value_array_remove (self->input_channel_positions, + GST_INTERLEAVE_PAD_CAST (pad)->channel); + + /* Update channel numbers */ + GST_OBJECT_LOCK (self); + for (l = GST_ELEMENT_CAST (self)->sinkpads; l != NULL; l = l->next) { + GstInterleavePad *ipad = GST_INTERLEAVE_PAD (l->data); + + if (GST_INTERLEAVE_PAD_CAST (pad)->channel < ipad->channel) + ipad->channel--; + } + GST_OBJECT_UNLOCK (self); + + /* Update the src caps if we already have them */ + if (self->sinkcaps) { + if (self->channels > 0) { + GstCaps *srccaps; + GstStructure *s; + + srccaps = gst_caps_copy (self->sinkcaps); + s = gst_caps_get_structure (srccaps, 0); + + gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL); + gst_interleave_set_channel_positions (self, s); + + gst_pad_set_caps (self->src, srccaps); + gst_caps_unref (srccaps); + } else { + gst_caps_replace (&self->sinkcaps, NULL); + gst_pad_set_caps (self->src, NULL); + } + } + + GST_OBJECT_UNLOCK (self->collect); + + gst_collect_pads_remove_pad (self->collect, pad); + gst_element_remove_pad (element, pad); +} + +static GstStateChangeReturn +gst_interleave_change_state (GstElement * element, GstStateChange transition) +{ + GstInterleave *self; + GstStateChangeReturn ret; + + self = GST_INTERLEAVE (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + self->timestamp = 0; + self->offset = 0; + self->segment_pending = TRUE; + self->segment_position = 0; + self->segment_rate = 1.0; + gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); + gst_collect_pads_start (self->collect); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + /* Stop before calling the parent's state change function as + * GstCollectPads might take locks and we would deadlock in that + * case + */ + if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) + gst_collect_pads_stop (self->collect); + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_pad_set_caps (self->src, NULL); + gst_caps_replace (&self->sinkcaps, NULL); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static void +__remove_channels (GstCaps * caps) +{ + GstStructure *s; + gint i, size; + + size = gst_caps_get_size (caps); + for (i = 0; i < size; i++) { + s = gst_caps_get_structure (caps, i); + gst_structure_remove_field (s, "channel-positions"); + gst_structure_remove_field (s, "channels"); + } +} + +static void +__set_channels (GstCaps * caps, gint channels) +{ + GstStructure *s; + gint i, size; + + size = gst_caps_get_size (caps); + for (i = 0; i < size; i++) { + s = gst_caps_get_structure (caps, i); + if (channels > 0) + gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL); + else + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + } +} + +/* we can only accept caps that we and downstream can handle. */ +static GstCaps * +gst_interleave_sink_getcaps (GstPad * pad) +{ + GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad)); + GstCaps *result, *peercaps, *sinkcaps; + + GST_OBJECT_LOCK (self); + + /* If we already have caps on one of the sink pads return them */ + if (self->sinkcaps) { + result = gst_caps_copy (self->sinkcaps); + } else { + /* get the downstream possible caps */ + peercaps = gst_pad_peer_get_caps (self->src); + /* get the allowed caps on this sinkpad */ + sinkcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + __remove_channels (sinkcaps); + if (peercaps) { + __remove_channels (peercaps); + /* if the peer has caps, intersect */ + GST_DEBUG_OBJECT (pad, "intersecting peer and template caps"); + result = gst_caps_intersect (peercaps, sinkcaps); + gst_caps_unref (peercaps); + gst_caps_unref (sinkcaps); + } else { + /* the peer has no caps (or there is no peer), just use the allowed caps + * of this sinkpad. */ + GST_DEBUG_OBJECT (pad, "no peer caps, using sinkcaps"); + result = sinkcaps; + } + __set_channels (result, 1); + } + + GST_OBJECT_UNLOCK (self); + + gst_object_unref (self); + + GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, result); + + return result; +} + +static void +gst_interleave_set_process_function (GstInterleave * self) +{ + switch (self->width) { + case 8: + self->func = (GstInterleaveFunc) interleave_8; + break; + case 16: + self->func = (GstInterleaveFunc) interleave_16; + break; + case 24: + self->func = (GstInterleaveFunc) interleave_24; + break; + case 32: + self->func = (GstInterleaveFunc) interleave_32; + break; + case 64: + self->func = (GstInterleaveFunc) interleave_64; + break; + default: + g_assert_not_reached (); + break; + } +} + +static gboolean +gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstInterleave *self; + + g_return_val_if_fail (GST_IS_INTERLEAVE_PAD (pad), FALSE); + + self = GST_INTERLEAVE (gst_pad_get_parent (pad)); + + /* First caps that are set on a sink pad are used as output caps */ + /* TODO: handle caps changes */ + if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) { + goto cannot_change_caps; + } else { + GstCaps *srccaps; + GstStructure *s; + gboolean res; + + s = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (s, "width", &self->width)) + goto no_width; + + if (!gst_structure_get_int (s, "rate", &self->rate)) + goto no_rate; + + gst_interleave_set_process_function (self); + + if (gst_structure_has_field (s, "channel-positions")) { + const GValue *pos_array; + + pos_array = gst_structure_get_value (s, "channel-positions"); + if (GST_VALUE_HOLDS_ARRAY (pos_array) + && gst_value_array_get_size (pos_array) == 1) { + const GValue *pos = gst_value_array_get_value (pos_array, 0); + + GValue *apos = g_value_array_get_nth (self->input_channel_positions, + GST_INTERLEAVE_PAD_CAST (pad)->channel); + + g_value_set_enum (apos, g_value_get_enum (pos)); + } + } + + srccaps = gst_caps_copy (caps); + s = gst_caps_get_structure (srccaps, 0); + + gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL); + gst_interleave_set_channel_positions (self, s); + + res = gst_pad_set_caps (self->src, srccaps); + gst_caps_unref (srccaps); + + if (!res) + goto src_did_not_accept; + } + + if (!self->sinkcaps) { + GstCaps *sinkcaps = gst_caps_copy (caps); + GstStructure *s = gst_caps_get_structure (sinkcaps, 0); + + gst_structure_remove_field (s, "channel-positions"); + + gst_caps_replace (&self->sinkcaps, sinkcaps); + + gst_caps_unref (sinkcaps); + } + + gst_object_unref (self); + + return TRUE; + +cannot_change_caps: + { + GST_WARNING_OBJECT (self, "caps of %" GST_PTR_FORMAT " already set, can't " + "change", self->sinkcaps); + gst_object_unref (self); + return FALSE; + } +src_did_not_accept: + { + GST_WARNING_OBJECT (self, "src did not accept setcaps()"); + gst_object_unref (self); + return FALSE; + } +no_width: + { + GST_WARNING_OBJECT (self, "caps did not have width: %" GST_PTR_FORMAT, + caps); + gst_object_unref (self); + return FALSE; + } +no_rate: + { + GST_WARNING_OBJECT (self, "caps did not have rate: %" GST_PTR_FORMAT, caps); + gst_object_unref (self); + return FALSE; + } +} + +static gboolean +gst_interleave_sink_event (GstPad * pad, GstEvent * event) +{ + GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad)); + gboolean ret; + + GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), + GST_DEBUG_PAD_NAME (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + /* mark a pending new segment. This event is synchronized + * with the streaming thread so we can safely update the + * variable without races. It's somewhat weird because we + * assume the collectpads forwarded the FLUSH_STOP past us + * and downstream (using our source pad, the bastard!). + */ + self->segment_pending = TRUE; + break; + default: + break; + } + + /* now GstCollectPads can take care of the rest, e.g. EOS */ + ret = self->collect_event (pad, event); + + gst_object_unref (self); + return ret; +} + +static gboolean +gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query) +{ + gint64 max; + gboolean res; + GstFormat format; + GstIterator *it; + gboolean done; + + /* parse format */ + gst_query_parse_duration (query, &format, NULL); + + max = -1; + res = TRUE; + done = FALSE; + + /* Take maximum of all durations */ + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); + while (!done) { + GstIteratorResult ires; + + gpointer item; + + ires = gst_iterator_next (it, &item); + switch (ires) { + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_OK: + { + GstPad *pad = GST_PAD_CAST (item); + + gint64 duration; + + /* ask sink peer for duration */ + res &= gst_pad_query_peer_duration (pad, &format, &duration); + /* take max from all valid return values */ + if (res) { + /* valid unknown length, stop searching */ + if (duration == -1) { + max = duration; + done = TRUE; + } + /* else see if bigger than current max */ + else if (duration > max) + max = duration; + } + gst_object_unref (pad); + break; + } + case GST_ITERATOR_RESYNC: + max = -1; + res = TRUE; + gst_iterator_resync (it); + break; + default: + res = FALSE; + done = TRUE; + break; + } + } + gst_iterator_free (it); + + if (res) { + /* If in bytes format we have to multiply with the number of channels + * to get the correct results. All other formats should be fine */ + if (format == GST_FORMAT_BYTES && max != -1) + max *= self->channels; + + /* and store the max */ + GST_DEBUG_OBJECT (self, "Total duration in format %s: %" + GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max)); + gst_query_set_duration (query, format, max); + } + + return res; +} + +static gboolean +gst_interleave_src_query_latency (GstInterleave * self, GstQuery * query) +{ + GstClockTime min, max; + gboolean live; + gboolean res; + GstIterator *it; + gboolean done; + + res = TRUE; + done = FALSE; + + live = FALSE; + min = 0; + max = GST_CLOCK_TIME_NONE; + + /* Take maximum of all latency values */ + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); + while (!done) { + GstIteratorResult ires; + gpointer item; + + ires = gst_iterator_next (it, &item); + switch (ires) { + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_OK: + { + GstPad *pad = GST_PAD_CAST (item); + GstQuery *peerquery; + GstClockTime min_cur, max_cur; + gboolean live_cur; + + peerquery = gst_query_new_latency (); + + /* Ask peer for latency */ + res &= gst_pad_peer_query (pad, peerquery); + + /* take max from all valid return values */ + if (res) { + gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur); + + if (min_cur > min) + min = min_cur; + + if (max_cur != GST_CLOCK_TIME_NONE && + ((max != GST_CLOCK_TIME_NONE && max_cur > max) || + (max == GST_CLOCK_TIME_NONE))) + max = max_cur; + + live = live || live_cur; + } + + gst_query_unref (peerquery); + gst_object_unref (pad); + break; + } + case GST_ITERATOR_RESYNC: + live = FALSE; + min = 0; + max = GST_CLOCK_TIME_NONE; + res = TRUE; + gst_iterator_resync (it); + break; + default: + res = FALSE; + done = TRUE; + break; + } + } + gst_iterator_free (it); + + if (res) { + /* store the results */ + GST_DEBUG_OBJECT (self, "Calculated total latency: live %s, min %" + GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, + (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + gst_query_set_latency (query, live, min, max); + } + + return res; +} + +static gboolean +gst_interleave_src_query (GstPad * pad, GstQuery * query) +{ + GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad)); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + gst_query_parse_position (query, &format, NULL); + + switch (format) { + case GST_FORMAT_TIME: + /* FIXME, bring to stream time, might be tricky */ + gst_query_set_position (query, format, self->timestamp); + res = TRUE; + break; + case GST_FORMAT_BYTES: + gst_query_set_position (query, format, + self->offset * self->channels * self->width); + res = TRUE; + break; + case GST_FORMAT_DEFAULT: + gst_query_set_position (query, format, self->offset); + res = TRUE; + break; + default: + break; + } + break; + } + case GST_QUERY_DURATION: + res = gst_interleave_src_query_duration (self, query); + break; + case GST_QUERY_LATENCY: + res = gst_interleave_src_query_latency (self, query); + break; + default: + /* FIXME, needs a custom query handler because we have multiple + * sinkpads */ + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (self); + return res; +} + +static gboolean +forward_event_func (GstPad * pad, GValue * ret, GstEvent * event) +{ + gst_event_ref (event); + GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event)); + if (!gst_pad_push_event (pad, event)) { + g_value_set_boolean (ret, FALSE); + GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.", + event, GST_EVENT_TYPE_NAME (event)); + } else { + GST_LOG_OBJECT (pad, "Sent event %p (%s).", + event, GST_EVENT_TYPE_NAME (event)); + } + gst_object_unref (pad); + return TRUE; +} + +static gboolean +forward_event (GstInterleave * self, GstEvent * event) +{ + GstIterator *it; + GValue vret = { 0 }; + + GST_LOG_OBJECT (self, "Forwarding event %p (%s)", event, + GST_EVENT_TYPE_NAME (event)); + + g_value_init (&vret, G_TYPE_BOOLEAN); + g_value_set_boolean (&vret, TRUE); + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); + gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret, + event); + gst_iterator_free (it); + gst_event_unref (event); + + return g_value_get_boolean (&vret); +} + + +static gboolean +gst_interleave_src_event (GstPad * pad, GstEvent * event) +{ + GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad)); + gboolean result; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_QOS: + /* QoS might be tricky */ + result = FALSE; + break; + case GST_EVENT_SEEK: + { + GstSeekFlags flags; + GstSeekType curtype; + gint64 cur; + + /* parse the seek parameters */ + gst_event_parse_seek (event, &self->segment_rate, NULL, &flags, &curtype, + &cur, NULL, NULL); + + /* check if we are flushing */ + if (flags & GST_SEEK_FLAG_FLUSH) { + /* make sure we accept nothing anymore and return WRONG_STATE */ + gst_collect_pads_set_flushing (self->collect, TRUE); + + /* flushing seek, start flush downstream, the flush will be done + * when all pads received a FLUSH_STOP. */ + gst_pad_push_event (self->src, gst_event_new_flush_start ()); + } + + /* now wait for the collected to be finished and mark a new + * segment */ + GST_OBJECT_LOCK (self->collect); + if (curtype == GST_SEEK_TYPE_SET) + self->segment_position = cur; + else + self->segment_position = 0; + self->segment_pending = TRUE; + GST_OBJECT_UNLOCK (self->collect); + + result = forward_event (self, event); + break; + } + case GST_EVENT_NAVIGATION: + /* navigation is rather pointless. */ + result = FALSE; + break; + default: + /* just forward the rest for now */ + result = forward_event (self, event); + break; + } + gst_object_unref (self); + + return result; +} + +static GstFlowReturn +gst_interleave_collected (GstCollectPads * pads, GstInterleave * self) +{ + guint size; + GstBuffer *outbuf; + GstFlowReturn ret = GST_FLOW_OK; + GSList *collected; + guint nsamples; + guint ncollected = 0; + gboolean empty = TRUE; + gint width = self->width / 8; + + g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED); + g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED); + g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED); + g_return_val_if_fail (self->rate > 0, GST_FLOW_NOT_NEGOTIATED); + + size = gst_collect_pads_available (pads); + + g_return_val_if_fail (size % width == 0, GST_FLOW_ERROR); + + GST_DEBUG_OBJECT (self, "Starting to collect %u bytes from %d channels", size, + self->channels); + + nsamples = size / width; + + ret = + gst_pad_alloc_buffer (self->src, GST_BUFFER_OFFSET_NONE, + size * self->channels, GST_PAD_CAPS (self->src), &outbuf); + + if (ret != GST_FLOW_OK) { + return ret; + } else if (outbuf == NULL || GST_BUFFER_SIZE (outbuf) < size * self->channels) { + gst_buffer_unref (outbuf); + return GST_FLOW_NOT_NEGOTIATED; + } else if (!gst_caps_is_equal (GST_BUFFER_CAPS (outbuf), + GST_PAD_CAPS (self->src))) { + gst_buffer_unref (outbuf); + return GST_FLOW_NOT_NEGOTIATED; + } + + memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels); + + for (collected = pads->data; collected != NULL; collected = collected->next) { + GstCollectData *cdata; + GstBuffer *inbuf; + guint8 *outdata; + + cdata = (GstCollectData *) collected->data; + + inbuf = gst_collect_pads_take_buffer (pads, cdata, size); + if (inbuf == NULL) { + GST_DEBUG_OBJECT (cdata->pad, "No buffer available"); + goto next; + } + ncollected++; + + if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) + goto next; + + empty = FALSE; + outdata = + GST_BUFFER_DATA (outbuf) + + width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel; + + self->func (outdata, GST_BUFFER_DATA (inbuf), self->channels, nsamples); + + next: + if (inbuf) + gst_buffer_unref (inbuf); + } + + if (ncollected == 0) + goto eos; + + if (self->segment_pending) { + GstEvent *event; + + event = gst_event_new_new_segment_full (FALSE, self->segment_rate, + 1.0, GST_FORMAT_TIME, self->timestamp, -1, self->segment_position); + + gst_pad_push_event (self->src, event); + self->segment_pending = FALSE; + self->segment_position = 0; + } + + GST_BUFFER_TIMESTAMP (outbuf) = self->timestamp; + GST_BUFFER_OFFSET (outbuf) = self->offset; + + self->offset += nsamples; + self->timestamp = gst_util_uint64_scale_int (self->offset, + GST_SECOND, self->rate); + + GST_BUFFER_DURATION (outbuf) = self->timestamp - + GST_BUFFER_TIMESTAMP (outbuf); + + if (empty) + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); + + GST_LOG_OBJECT (self, "pushing outbuf, timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); + ret = gst_pad_push (self->src, outbuf); + + return ret; + +eos: + { + GST_DEBUG_OBJECT (self, "no data available, must be EOS"); + gst_buffer_unref (outbuf); + gst_pad_push_event (self->src, gst_event_new_eos ()); + return GST_FLOW_UNEXPECTED; + } +} diff --git a/gst/interleave/interleave.h b/gst/interleave/interleave.h new file mode 100644 index 0000000..fb3b274 --- /dev/null +++ b/gst/interleave/interleave.h @@ -0,0 +1,89 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * 2005 Wim Taymans <wim@fluendo.com> + * 2007 Andy Wingo <wingo at pobox.com> + * 2008 Sebastian Dröge <slomo@circular-chaos.org> + * + * interleave.c: interleave samples, mostly based on adder + * + * 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 __INTERLEAVE_H__ +#define __INTERLEAVE_H__ + +#include <gst/gst.h> +#include <gst/base/gstcollectpads.h> + +G_BEGIN_DECLS + +#define GST_TYPE_INTERLEAVE (gst_interleave_get_type()) +#define GST_INTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INTERLEAVE,GstInterleave)) +#define GST_INTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INTERLEAVE,GstInterleaveClass)) +#define GST_INTERLEAVE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_INTERLEAVE,GstInterleaveClass)) +#define GST_IS_INTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INTERLEAVE)) +#define GST_IS_INTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INTERLEAVE)) + +typedef struct _GstInterleave GstInterleave; +typedef struct _GstInterleaveClass GstInterleaveClass; + +typedef void (*GstInterleaveFunc) (gpointer out, gpointer in, guint stride, guint nframes); + +struct _GstInterleave +{ + GstElement element; + + /*< private >*/ + GstCollectPads *collect; + + gint channels; + gint padcounter; + gint rate; + gint width; + + GValueArray *channel_positions; + GValueArray *input_channel_positions; + gboolean channel_positions_from_input; + + GstCaps *sinkcaps; + + GstClockTime timestamp; + guint64 offset; + + gboolean segment_pending; + guint64 segment_position; + gdouble segment_rate; + GstSegment segment; + + GstPadEventFunction collect_event; + + GstInterleaveFunc func; + + GstPad *src; +}; + +struct _GstInterleaveClass +{ + GstElementClass parent_class; +}; + +GType gst_interleave_get_type (void); + +G_END_DECLS + +#endif /* __INTERLEAVE_H__ */ diff --git a/gst/interleave/plugin.c b/gst/interleave/plugin.c new file mode 100644 index 0000000..7017c45 --- /dev/null +++ b/gst/interleave/plugin.c @@ -0,0 +1,44 @@ +/* GStreamer interleave plugin + * Copyright (C) 2004,2007 Andy Wingo <wingo at pobox.com> + * + * plugin.c: the stubs for the interleave plugin + * + * 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 "plugin.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "interleave", + GST_RANK_NONE, gst_interleave_get_type ()) || + !gst_element_register (plugin, "deinterleave", + GST_RANK_NONE, gst_deinterleave_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "interleave", + "Audio interleaver/deinterleaver", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst/interleave/plugin.h b/gst/interleave/plugin.h new file mode 100644 index 0000000..3e96a7e --- /dev/null +++ b/gst/interleave/plugin.h @@ -0,0 +1,31 @@ +/* GStreamer interleave plugin + * Copyright (C) 2004,2007 Andy Wingo <wingo at pobox.com> + * + * plugin.h: the stubs for the interleave plugin + * + * 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_PLUGIN_INTERLEAVE_H__ +#define __GST_PLUGIN_INTERLEAVE_H__ + + +#include <gst/gst.h> +#include "interleave.h" +#include "deinterleave.h" + +#endif /* __GST_PLUGIN_INTERLEAVE_H__ */ |