diff options
author | Olivier Naudan <o-naudan@ti.com> | 2012-04-13 09:08:41 -0400 |
---|---|---|
committer | Olivier Naudan <o-naudan@ti.com> | 2012-04-13 09:08:41 -0400 |
commit | 54399760aad93cb3ec36162ced7649c8cd8286db (patch) | |
tree | 3b6047cba24cc1323720e162b5906e3fe8abdfc4 /plugins | |
parent | beb43201c942afa12dfc4225218b61fcd6e90923 (diff) |
Imported Upstream version 0.11.90upstream/0.11.90
Diffstat (limited to 'plugins')
39 files changed, 3211 insertions, 3285 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 6fc0a1b..17233d2 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,6 +1,6 @@ -SUBDIRS = elements indexers +SUBDIRS = elements -DIST_SUBDIRS = elements indexers +DIST_SUBDIRS = elements Android.mk: Makefile.am androgenizer -:PROJECT gstreamer \ diff --git a/plugins/Makefile.in b/plugins/Makefile.in index 7d091f3..539c2ed 100644 --- a/plugins/Makefile.in +++ b/plugins/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 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. @@ -15,6 +15,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -77,11 +94,11 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ SOURCES = DIST_SOURCES = @@ -92,6 +109,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -178,10 +200,12 @@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_LIBS = @GCOV_LIBS@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ -GLIB_ONLY_CFLAGS = @GLIB_ONLY_CFLAGS@ -GLIB_ONLY_LIBS = @GLIB_ONLY_LIBS@ GLIB_PREFIX = @GLIB_PREFIX@ GLIB_REQ = @GLIB_REQ@ GMP_LIBS = @GMP_LIBS@ @@ -194,10 +218,10 @@ GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ GST_CURRENT = @GST_CURRENT@ GST_DISABLE_ALLOC_TRACE_DEFINE = @GST_DISABLE_ALLOC_TRACE_DEFINE@ GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ -GST_DISABLE_NET_DEFINE = @GST_DISABLE_NET_DEFINE@ GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ @@ -211,7 +235,6 @@ GST_LIBVERSION = @GST_LIBVERSION@ GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ GST_LICENSE = @GST_LICENSE@ GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ -GST_MAJORMINOR = @GST_MAJORMINOR@ GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ GST_OBJ_LIBS = @GST_OBJ_LIBS@ @@ -228,6 +251,10 @@ GST_PRINTF_EXTENSION_SEGMENT_FORMAT_DEFINE = @GST_PRINTF_EXTENSION_SEGMENT_FORMA GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ GST_REVISION = @GST_REVISION@ GST_USING_PRINTF_EXTENSION_DEFINE = @GST_USING_PRINTF_EXTENSION_DEFINE@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ GTKDOC_CHECK = @GTKDOC_CHECK@ HAVE_DOCBOOK2HTML = @HAVE_DOCBOOK2HTML@ HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ @@ -243,7 +270,6 @@ HAVE_PS2PDF = @HAVE_PS2PDF@ HAVE_XMLLINT = @HAVE_XMLLINT@ HOST_CPU = @HOST_CPU@ HTML_DIR = @HTML_DIR@ -INET_ATON_LIBS = @INET_ATON_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -276,6 +302,7 @@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ @@ -331,6 +358,7 @@ 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@ @@ -364,7 +392,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -385,8 +412,8 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = elements indexers -DIST_SUBDIRS = elements indexers +SUBDIRS = elements +DIST_SUBDIRS = elements all: all-recursive .SUFFIXES: @@ -594,13 +621,10 @@ distdir: $(DISTFILES) done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ @@ -635,10 +659,15 @@ install-am: all-am installcheck: installcheck-recursive install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + 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: diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am index f743cf2..d451a1f 100644 --- a/plugins/elements/Makefile.am +++ b/plugins/elements/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstcoreelements.la -libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la +libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la libgstcoreelements_la_SOURCES = \ gstcapsfilter.c \ gstelements.c \ @@ -15,6 +15,7 @@ libgstcoreelements_la_SOURCES = \ gstidentity.c \ gstinputselector.c \ gstoutputselector.c \ + gstdataqueue.c \ gstmultiqueue.c \ gstqueue.c \ gstqueue2.c \ @@ -24,7 +25,7 @@ libgstcoreelements_la_SOURCES = \ libgstcoreelements_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstcoreelements_la_LIBADD = \ - $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ $(GST_OBJ_LIBS) libgstcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstcoreelements_la_LIBTOOLFLAGS = --tag=disable-static @@ -41,6 +42,7 @@ noinst_HEADERS = \ gstidentity.h \ gstinputselector.h \ gstoutputselector.h \ + gstdataqueue.h \ gstmultiqueue.h \ gstqueue.h \ gstqueue2.h \ @@ -67,5 +69,5 @@ Android.mk: Makefile.am -:LDFLAGS $(libgstcoreelements_la_LDFLAGS) \ $(libgstcoreelements_la_LIBADD) \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_MAJORMINOR@ \ + LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_API_VERSION@ \ > $@ diff --git a/plugins/elements/Makefile.in b/plugins/elements/Makefile.in index 149fd45..2cc34f1 100644 --- a/plugins/elements/Makefile.in +++ b/plugins/elements/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 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. @@ -17,6 +17,23 @@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -101,6 +118,12 @@ am__nobase_list = $(am__nobase_strip_setup); \ 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 = @@ -117,6 +140,7 @@ am_libgstcoreelements_la_OBJECTS = \ libgstcoreelements_la-gstidentity.lo \ libgstcoreelements_la-gstinputselector.lo \ libgstcoreelements_la-gstoutputselector.lo \ + libgstcoreelements_la-gstdataqueue.lo \ libgstcoreelements_la-gstmultiqueue.lo \ libgstcoreelements_la-gstqueue.lo \ libgstcoreelements_la-gstqueue2.lo \ @@ -124,8 +148,8 @@ am_libgstcoreelements_la_OBJECTS = \ libgstcoreelements_la-gsttypefindelement.lo \ libgstcoreelements_la-gstvalve.lo libgstcoreelements_la_OBJECTS = $(am_libgstcoreelements_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent libgstcoreelements_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ @@ -141,24 +165,29 @@ 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_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +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_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +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_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +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_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libgstcoreelements_la_SOURCES) DIST_SOURCES = $(libgstcoreelements_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags @@ -216,10 +245,12 @@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_LIBS = @GCOV_LIBS@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LDFLAGS = @GIO_LDFLAGS@ +GIO_LIBS = @GIO_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ -GLIB_ONLY_CFLAGS = @GLIB_ONLY_CFLAGS@ -GLIB_ONLY_LIBS = @GLIB_ONLY_LIBS@ GLIB_PREFIX = @GLIB_PREFIX@ GLIB_REQ = @GLIB_REQ@ GMP_LIBS = @GMP_LIBS@ @@ -232,10 +263,10 @@ GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ GST_ALL_LIBS = @GST_ALL_LIBS@ +GST_API_VERSION = @GST_API_VERSION@ GST_CURRENT = @GST_CURRENT@ GST_DISABLE_ALLOC_TRACE_DEFINE = @GST_DISABLE_ALLOC_TRACE_DEFINE@ GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ -GST_DISABLE_NET_DEFINE = @GST_DISABLE_NET_DEFINE@ GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ @@ -249,7 +280,6 @@ GST_LIBVERSION = @GST_LIBVERSION@ GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ GST_LICENSE = @GST_LICENSE@ GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ -GST_MAJORMINOR = @GST_MAJORMINOR@ GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ GST_OBJ_LIBS = @GST_OBJ_LIBS@ @@ -266,6 +296,10 @@ GST_PRINTF_EXTENSION_SEGMENT_FORMAT_DEFINE = @GST_PRINTF_EXTENSION_SEGMENT_FORMA GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ GST_REVISION = @GST_REVISION@ GST_USING_PRINTF_EXTENSION_DEFINE = @GST_USING_PRINTF_EXTENSION_DEFINE@ +GST_VERSION_MAJOR = @GST_VERSION_MAJOR@ +GST_VERSION_MICRO = @GST_VERSION_MICRO@ +GST_VERSION_MINOR = @GST_VERSION_MINOR@ +GST_VERSION_NANO = @GST_VERSION_NANO@ GTKDOC_CHECK = @GTKDOC_CHECK@ HAVE_DOCBOOK2HTML = @HAVE_DOCBOOK2HTML@ HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ @@ -281,7 +315,6 @@ HAVE_PS2PDF = @HAVE_PS2PDF@ HAVE_XMLLINT = @HAVE_XMLLINT@ HOST_CPU = @HOST_CPU@ HTML_DIR = @HTML_DIR@ -INET_ATON_LIBS = @INET_ATON_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -314,6 +347,7 @@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ @@ -369,6 +403,7 @@ 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@ @@ -402,7 +437,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -424,7 +458,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugin_LTLIBRARIES = libgstcoreelements.la -libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la +libgstcoreelements_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la libgstcoreelements_la_SOURCES = \ gstcapsfilter.c \ gstelements.c \ @@ -438,6 +472,7 @@ libgstcoreelements_la_SOURCES = \ gstidentity.c \ gstinputselector.c \ gstoutputselector.c \ + gstdataqueue.c \ gstmultiqueue.c \ gstqueue.c \ gstqueue2.c \ @@ -447,7 +482,7 @@ libgstcoreelements_la_SOURCES = \ libgstcoreelements_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstcoreelements_la_LIBADD = \ - $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \ + $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ $(GST_OBJ_LIBS) libgstcoreelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) @@ -464,6 +499,7 @@ noinst_HEADERS = \ gstidentity.h \ gstinputselector.h \ gstoutputselector.h \ + gstdataqueue.h \ gstmultiqueue.h \ gstqueue.h \ gstqueue2.h \ @@ -511,7 +547,6 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(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 \ @@ -519,6 +554,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) '$(DESTDIR)$(plugindir)' || exit 1; \ 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)"; \ } @@ -540,7 +577,7 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libgstcoreelements.la: $(libgstcoreelements_la_OBJECTS) $(libgstcoreelements_la_DEPENDENCIES) +libgstcoreelements.la: $(libgstcoreelements_la_OBJECTS) $(libgstcoreelements_la_DEPENDENCIES) $(EXTRA_libgstcoreelements_la_DEPENDENCIES) $(AM_V_CCLD)$(libgstcoreelements_la_LINK) -rpath $(plugindir) $(libgstcoreelements_la_OBJECTS) $(libgstcoreelements_la_LIBADD) $(LIBS) mostlyclean-compile: @@ -550,6 +587,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstdataqueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstelements.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfakesink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreelements_la-gstfakesrc.Plo@am__quote@ @@ -571,170 +609,156 @@ distclean-compile: .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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@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@ $(COMPILE) -c $< +@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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@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@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@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@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgstcoreelements_la-gstcapsfilter.lo: gstcapsfilter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstcapsfilter.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Tpo -c -o libgstcoreelements_la-gstcapsfilter.lo `test -f 'gstcapsfilter.c' || echo '$(srcdir)/'`gstcapsfilter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Tpo $(DEPDIR)/libgstcoreelements_la-gstcapsfilter.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstcapsfilter.c' object='libgstcoreelements_la-gstcapsfilter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstcapsfilter.c' object='libgstcoreelements_la-gstcapsfilter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstcapsfilter.lo `test -f 'gstcapsfilter.c' || echo '$(srcdir)/'`gstcapsfilter.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstcapsfilter.lo `test -f 'gstcapsfilter.c' || echo '$(srcdir)/'`gstcapsfilter.c libgstcoreelements_la-gstelements.lo: gstelements.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstelements.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstelements.Tpo -c -o libgstcoreelements_la-gstelements.lo `test -f 'gstelements.c' || echo '$(srcdir)/'`gstelements.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstelements.Tpo $(DEPDIR)/libgstcoreelements_la-gstelements.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstelements.c' object='libgstcoreelements_la-gstelements.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstelements.c' object='libgstcoreelements_la-gstelements.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstelements.lo `test -f 'gstelements.c' || echo '$(srcdir)/'`gstelements.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstelements.lo `test -f 'gstelements.c' || echo '$(srcdir)/'`gstelements.c libgstcoreelements_la-gstfakesrc.lo: gstfakesrc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfakesrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Tpo -c -o libgstcoreelements_la-gstfakesrc.lo `test -f 'gstfakesrc.c' || echo '$(srcdir)/'`gstfakesrc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfakesrc.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfakesrc.c' object='libgstcoreelements_la-gstfakesrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfakesrc.c' object='libgstcoreelements_la-gstfakesrc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesrc.lo `test -f 'gstfakesrc.c' || echo '$(srcdir)/'`gstfakesrc.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesrc.lo `test -f 'gstfakesrc.c' || echo '$(srcdir)/'`gstfakesrc.c libgstcoreelements_la-gstfakesink.lo: gstfakesink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfakesink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfakesink.Tpo -c -o libgstcoreelements_la-gstfakesink.lo `test -f 'gstfakesink.c' || echo '$(srcdir)/'`gstfakesink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfakesink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfakesink.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfakesink.c' object='libgstcoreelements_la-gstfakesink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfakesink.c' object='libgstcoreelements_la-gstfakesink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesink.lo `test -f 'gstfakesink.c' || echo '$(srcdir)/'`gstfakesink.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfakesink.lo `test -f 'gstfakesink.c' || echo '$(srcdir)/'`gstfakesink.c libgstcoreelements_la-gstfdsrc.lo: gstfdsrc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfdsrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Tpo -c -o libgstcoreelements_la-gstfdsrc.lo `test -f 'gstfdsrc.c' || echo '$(srcdir)/'`gstfdsrc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfdsrc.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfdsrc.c' object='libgstcoreelements_la-gstfdsrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfdsrc.c' object='libgstcoreelements_la-gstfdsrc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsrc.lo `test -f 'gstfdsrc.c' || echo '$(srcdir)/'`gstfdsrc.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsrc.lo `test -f 'gstfdsrc.c' || echo '$(srcdir)/'`gstfdsrc.c libgstcoreelements_la-gstfdsink.lo: gstfdsink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfdsink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfdsink.Tpo -c -o libgstcoreelements_la-gstfdsink.lo `test -f 'gstfdsink.c' || echo '$(srcdir)/'`gstfdsink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfdsink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfdsink.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfdsink.c' object='libgstcoreelements_la-gstfdsink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfdsink.c' object='libgstcoreelements_la-gstfdsink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsink.lo `test -f 'gstfdsink.c' || echo '$(srcdir)/'`gstfdsink.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfdsink.lo `test -f 'gstfdsink.c' || echo '$(srcdir)/'`gstfdsink.c libgstcoreelements_la-gstfilesink.lo: gstfilesink.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfilesink.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfilesink.Tpo -c -o libgstcoreelements_la-gstfilesink.lo `test -f 'gstfilesink.c' || echo '$(srcdir)/'`gstfilesink.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfilesink.Tpo $(DEPDIR)/libgstcoreelements_la-gstfilesink.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfilesink.c' object='libgstcoreelements_la-gstfilesink.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfilesink.c' object='libgstcoreelements_la-gstfilesink.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesink.lo `test -f 'gstfilesink.c' || echo '$(srcdir)/'`gstfilesink.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesink.lo `test -f 'gstfilesink.c' || echo '$(srcdir)/'`gstfilesink.c libgstcoreelements_la-gstfilesrc.lo: gstfilesrc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfilesrc.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Tpo -c -o libgstcoreelements_la-gstfilesrc.lo `test -f 'gstfilesrc.c' || echo '$(srcdir)/'`gstfilesrc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Tpo $(DEPDIR)/libgstcoreelements_la-gstfilesrc.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfilesrc.c' object='libgstcoreelements_la-gstfilesrc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfilesrc.c' object='libgstcoreelements_la-gstfilesrc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesrc.lo `test -f 'gstfilesrc.c' || echo '$(srcdir)/'`gstfilesrc.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfilesrc.lo `test -f 'gstfilesrc.c' || echo '$(srcdir)/'`gstfilesrc.c libgstcoreelements_la-gstfunnel.lo: gstfunnel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstfunnel.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstfunnel.Tpo -c -o libgstcoreelements_la-gstfunnel.lo `test -f 'gstfunnel.c' || echo '$(srcdir)/'`gstfunnel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstfunnel.Tpo $(DEPDIR)/libgstcoreelements_la-gstfunnel.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstfunnel.c' object='libgstcoreelements_la-gstfunnel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstfunnel.c' object='libgstcoreelements_la-gstfunnel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfunnel.lo `test -f 'gstfunnel.c' || echo '$(srcdir)/'`gstfunnel.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstfunnel.lo `test -f 'gstfunnel.c' || echo '$(srcdir)/'`gstfunnel.c libgstcoreelements_la-gstidentity.lo: gstidentity.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstidentity.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstidentity.Tpo -c -o libgstcoreelements_la-gstidentity.lo `test -f 'gstidentity.c' || echo '$(srcdir)/'`gstidentity.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstidentity.Tpo $(DEPDIR)/libgstcoreelements_la-gstidentity.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstidentity.c' object='libgstcoreelements_la-gstidentity.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstidentity.c' object='libgstcoreelements_la-gstidentity.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstidentity.lo `test -f 'gstidentity.c' || echo '$(srcdir)/'`gstidentity.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstidentity.lo `test -f 'gstidentity.c' || echo '$(srcdir)/'`gstidentity.c libgstcoreelements_la-gstinputselector.lo: gstinputselector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstinputselector.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstinputselector.Tpo -c -o libgstcoreelements_la-gstinputselector.lo `test -f 'gstinputselector.c' || echo '$(srcdir)/'`gstinputselector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstinputselector.Tpo $(DEPDIR)/libgstcoreelements_la-gstinputselector.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstinputselector.c' object='libgstcoreelements_la-gstinputselector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstinputselector.c' object='libgstcoreelements_la-gstinputselector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstinputselector.lo `test -f 'gstinputselector.c' || echo '$(srcdir)/'`gstinputselector.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstinputselector.lo `test -f 'gstinputselector.c' || echo '$(srcdir)/'`gstinputselector.c libgstcoreelements_la-gstoutputselector.lo: gstoutputselector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstoutputselector.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Tpo -c -o libgstcoreelements_la-gstoutputselector.lo `test -f 'gstoutputselector.c' || echo '$(srcdir)/'`gstoutputselector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Tpo $(DEPDIR)/libgstcoreelements_la-gstoutputselector.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstoutputselector.c' object='libgstcoreelements_la-gstoutputselector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstoutputselector.c' object='libgstcoreelements_la-gstoutputselector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstoutputselector.lo `test -f 'gstoutputselector.c' || echo '$(srcdir)/'`gstoutputselector.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstoutputselector.lo `test -f 'gstoutputselector.c' || echo '$(srcdir)/'`gstoutputselector.c + +libgstcoreelements_la-gstdataqueue.lo: gstdataqueue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstdataqueue.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstdataqueue.Tpo -c -o libgstcoreelements_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstdataqueue.Tpo $(DEPDIR)/libgstcoreelements_la-gstdataqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdataqueue.c' object='libgstcoreelements_la-gstdataqueue.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 $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c libgstcoreelements_la-gstmultiqueue.lo: gstmultiqueue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstmultiqueue.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Tpo -c -o libgstcoreelements_la-gstmultiqueue.lo `test -f 'gstmultiqueue.c' || echo '$(srcdir)/'`gstmultiqueue.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Tpo $(DEPDIR)/libgstcoreelements_la-gstmultiqueue.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstmultiqueue.c' object='libgstcoreelements_la-gstmultiqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstmultiqueue.c' object='libgstcoreelements_la-gstmultiqueue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstmultiqueue.lo `test -f 'gstmultiqueue.c' || echo '$(srcdir)/'`gstmultiqueue.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstmultiqueue.lo `test -f 'gstmultiqueue.c' || echo '$(srcdir)/'`gstmultiqueue.c libgstcoreelements_la-gstqueue.lo: gstqueue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstqueue.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstqueue.Tpo -c -o libgstcoreelements_la-gstqueue.lo `test -f 'gstqueue.c' || echo '$(srcdir)/'`gstqueue.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstqueue.Tpo $(DEPDIR)/libgstcoreelements_la-gstqueue.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstqueue.c' object='libgstcoreelements_la-gstqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueue.c' object='libgstcoreelements_la-gstqueue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue.lo `test -f 'gstqueue.c' || echo '$(srcdir)/'`gstqueue.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue.lo `test -f 'gstqueue.c' || echo '$(srcdir)/'`gstqueue.c libgstcoreelements_la-gstqueue2.lo: gstqueue2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstqueue2.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstqueue2.Tpo -c -o libgstcoreelements_la-gstqueue2.lo `test -f 'gstqueue2.c' || echo '$(srcdir)/'`gstqueue2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstqueue2.Tpo $(DEPDIR)/libgstcoreelements_la-gstqueue2.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstqueue2.c' object='libgstcoreelements_la-gstqueue2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueue2.c' object='libgstcoreelements_la-gstqueue2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue2.lo `test -f 'gstqueue2.c' || echo '$(srcdir)/'`gstqueue2.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstqueue2.lo `test -f 'gstqueue2.c' || echo '$(srcdir)/'`gstqueue2.c libgstcoreelements_la-gsttee.lo: gsttee.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gsttee.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gsttee.Tpo -c -o libgstcoreelements_la-gsttee.lo `test -f 'gsttee.c' || echo '$(srcdir)/'`gsttee.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gsttee.Tpo $(DEPDIR)/libgstcoreelements_la-gsttee.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsttee.c' object='libgstcoreelements_la-gsttee.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttee.c' object='libgstcoreelements_la-gsttee.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttee.lo `test -f 'gsttee.c' || echo '$(srcdir)/'`gsttee.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttee.lo `test -f 'gsttee.c' || echo '$(srcdir)/'`gsttee.c libgstcoreelements_la-gsttypefindelement.lo: gsttypefindelement.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gsttypefindelement.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Tpo -c -o libgstcoreelements_la-gsttypefindelement.lo `test -f 'gsttypefindelement.c' || echo '$(srcdir)/'`gsttypefindelement.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Tpo $(DEPDIR)/libgstcoreelements_la-gsttypefindelement.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsttypefindelement.c' object='libgstcoreelements_la-gsttypefindelement.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gsttypefindelement.c' object='libgstcoreelements_la-gsttypefindelement.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttypefindelement.lo `test -f 'gsttypefindelement.c' || echo '$(srcdir)/'`gsttypefindelement.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gsttypefindelement.lo `test -f 'gsttypefindelement.c' || echo '$(srcdir)/'`gsttypefindelement.c libgstcoreelements_la-gstvalve.lo: gstvalve.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -MT libgstcoreelements_la-gstvalve.lo -MD -MP -MF $(DEPDIR)/libgstcoreelements_la-gstvalve.Tpo -c -o libgstcoreelements_la-gstvalve.lo `test -f 'gstvalve.c' || echo '$(srcdir)/'`gstvalve.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreelements_la-gstvalve.Tpo $(DEPDIR)/libgstcoreelements_la-gstvalve.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstvalve.c' object='libgstcoreelements_la-gstvalve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstvalve.c' object='libgstcoreelements_la-gstvalve.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstvalve.lo `test -f 'gstvalve.c' || echo '$(srcdir)/'`gstvalve.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreelements_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreelements_la_CFLAGS) $(CFLAGS) -c -o libgstcoreelements_la-gstvalve.lo `test -f 'gstvalve.c' || echo '$(srcdir)/'`gstvalve.c mostlyclean-libtool: -rm -f *.lo @@ -841,10 +865,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + 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: @@ -958,7 +987,7 @@ Android.mk: Makefile.am -:LDFLAGS $(libgstcoreelements_la_LDFLAGS) \ $(libgstcoreelements_la_LIBADD) \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_MAJORMINOR@ \ + LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_API_VERSION@ \ > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/plugins/elements/gstcapsfilter.c b/plugins/elements/gstcapsfilter.c index 16278dc..971cb7f 100644 --- a/plugins/elements/gstcapsfilter.c +++ b/plugins/elements/gstcapsfilter.c @@ -104,7 +104,7 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstelement_class = GST_ELEMENT_CLASS (klass); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "CapsFilter", "Generic", "Pass data without modification, limiting formats", @@ -131,14 +131,6 @@ gst_capsfilter_init (GstCapsFilter * filter) filter->filter_caps = gst_caps_new_any (); } -static gboolean -copy_func (GQuark field_id, const GValue * value, GstStructure * dest) -{ - gst_structure_id_set_value (dest, field_id, value); - - return TRUE; -} - static void gst_capsfilter_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -148,7 +140,7 @@ gst_capsfilter_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_FILTER_CAPS:{ GstCaps *new_caps; - GstCaps *old_caps, *suggest, *nego; + GstCaps *old_caps; const GstCaps *new_caps_val = gst_value_get_caps (value); if (new_caps_val == NULL) { @@ -167,51 +159,7 @@ gst_capsfilter_set_property (GObject * object, guint prop_id, GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps); - /* filter the currently negotiated format against the new caps */ - nego = gst_pad_get_current_caps (GST_BASE_TRANSFORM_SINK_PAD (object)); - if (nego) { - GST_DEBUG_OBJECT (capsfilter, "we had negotiated caps %" GST_PTR_FORMAT, - nego); - - if (G_UNLIKELY (gst_caps_is_any (new_caps))) { - GST_DEBUG_OBJECT (capsfilter, "not settings any suggestion"); - - suggest = NULL; - } else { - GstStructure *s1, *s2; - - /* first check if the name is the same */ - s1 = gst_caps_get_structure (nego, 0); - s2 = gst_caps_get_structure (new_caps, 0); - - if (gst_structure_get_name_id (s1) == gst_structure_get_name_id (s2)) { - /* same name, copy all fields from the new caps into the previously - * negotiated caps */ - suggest = gst_caps_copy (nego); - s1 = gst_caps_get_structure (suggest, 0); - gst_structure_foreach (s2, (GstStructureForeachFunc) copy_func, s1); - GST_DEBUG_OBJECT (capsfilter, "copied structure fields"); - } else { - GST_DEBUG_OBJECT (capsfilter, "different structure names"); - /* different names, we can only suggest the complete caps */ - suggest = gst_caps_copy (new_caps); - } - } - gst_caps_unref (nego); - } else { - GST_DEBUG_OBJECT (capsfilter, "no negotiated caps"); - /* Suggest the new caps, we can't just rely on _get_caps as this may - * already be called at this point even though no buffer has been - * pushed yet */ - suggest = gst_caps_copy (new_caps); - } - - GST_DEBUG_OBJECT (capsfilter, "suggesting new caps %" GST_PTR_FORMAT, - suggest); - gst_base_transform_suggest (GST_BASE_TRANSFORM (object), suggest, 0); - if (suggest) - gst_caps_unref (suggest); - + gst_base_transform_reconfigure_sink (GST_BASE_TRANSFORM (object)); break; } default: @@ -296,9 +244,13 @@ gst_capsfilter_accept_caps (GstBaseTransform * base, if (ret) { /* if we can intersect, see if the other end also accepts */ if (direction == GST_PAD_SRC) - ret = gst_pad_peer_accept_caps (GST_BASE_TRANSFORM_SINK_PAD (base), caps); + ret = + gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SINK_PAD (base), + caps); else - ret = gst_pad_peer_accept_caps (GST_BASE_TRANSFORM_SRC_PAD (base), caps); + ret = + gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SRC_PAD (base), + caps); GST_DEBUG_OBJECT (capsfilter, "peer accept: %d", ret); } @@ -346,8 +298,7 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input, g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); } - out_caps = gst_caps_make_writable (out_caps); - gst_caps_do_simplify (out_caps); + out_caps = gst_caps_simplify (out_caps); if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) { GST_DEBUG_OBJECT (trans, "Have fixed output caps %" @@ -355,6 +306,7 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input, if (!gst_pad_has_current_caps (trans->srcpad)) gst_pad_push_event (trans->srcpad, gst_event_new_caps (out_caps)); + gst_caps_unref (out_caps); } else { gchar *caps_str = gst_caps_to_string (out_caps); diff --git a/plugins/elements/gstdataqueue.c b/plugins/elements/gstdataqueue.c new file mode 100644 index 0000000..c1b8820 --- /dev/null +++ b/plugins/elements/gstdataqueue.c @@ -0,0 +1,661 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey <edward@fluendo.com> + * + * gstdataqueue.c: + * + * 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. + */ + +/** + * SECTION:gstdataqueue + * @short_description: Threadsafe queueing object + * + * #GstDataQueue is an object that handles threadsafe queueing of objects. It + * also provides size-related functionality. This object should be used for + * any #GstElement that wishes to provide some sort of queueing functionality. + * + * Since: 0.10.11 + */ + +#include <gst/gst.h> +#include "string.h" +#include "gstdataqueue.h" +#include "gst/glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (data_queue_debug); +#define GST_CAT_DEFAULT (data_queue_debug) +GST_DEBUG_CATEGORY_STATIC (data_queue_dataflow); + + +/* Queue signals and args */ +enum +{ + SIGNAL_EMPTY, + SIGNAL_FULL, + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_CUR_LEVEL_VISIBLE, + ARG_CUR_LEVEL_BYTES, + ARG_CUR_LEVEL_TIME + /* FILL ME */ +}; + +#define GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ + GST_CAT_LOG (data_queue_dataflow, \ + "locking qlock from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (&q->qlock); \ + GST_CAT_LOG (data_queue_dataflow, \ + "locked qlock from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define GST_DATA_QUEUE_MUTEX_LOCK_CHECK(q, label) G_STMT_START { \ + GST_DATA_QUEUE_MUTEX_LOCK (q); \ + if (q->flushing) \ + goto label; \ + } G_STMT_END + +#define GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ + GST_CAT_LOG (data_queue_dataflow, \ + "unlocking qlock from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (&q->qlock); \ +} G_STMT_END + +#define STATUS(q, msg) \ + GST_CAT_LOG (data_queue_dataflow, \ + "queue:%p " msg ": %u visible items, %u " \ + "bytes, %"G_GUINT64_FORMAT \ + " ns, %u elements", \ + queue, \ + q->cur_level.visible, \ + q->cur_level.bytes, \ + q->cur_level.time, \ + q->queue->length) + +static void gst_data_queue_finalize (GObject * object); + +static void gst_data_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_data_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GObjectClass *parent_class = NULL; +static guint gst_data_queue_signals[LAST_SIGNAL] = { 0 }; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0, \ + "data queue object"); \ + GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0, \ + "dataflow inside the data queue object"); \ +} + + +G_DEFINE_TYPE_WITH_CODE (GstDataQueue, gst_data_queue, G_TYPE_OBJECT, _do_init); + +static void +gst_data_queue_class_init (GstDataQueueClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_data_queue_set_property; + gobject_class->get_property = gst_data_queue_get_property; + + /* signals */ + /** + * GstDataQueue::empty: + * @queue: the queue instance + * + * Reports that the queue became empty (empty). + * A queue is empty if the total amount of visible items inside it (num-visible, time, + * size) is lower than the boundary values which can be set through the GObject + * properties. + */ + gst_data_queue_signals[SIGNAL_EMPTY] = + g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstDataQueueClass, empty), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GstDataQueue::full: + * @queue: the queue instance + * + * Reports that the queue became full (full). + * A queue is full if the total amount of data inside it (num-visible, time, + * size) is higher than the boundary values which can be set through the GObject + * properties. + */ + gst_data_queue_signals[SIGNAL_FULL] = + g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GstDataQueueClass, full), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* properties */ + g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_BYTES, + g_param_spec_uint ("current-level-bytes", "Current level (kB)", + "Current amount of data in the queue (bytes)", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_VISIBLE, + g_param_spec_uint ("current-level-visible", + "Current level (visible items)", + "Current number of visible items in the queue", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_TIME, + g_param_spec_uint64 ("current-level-time", "Current level (ns)", + "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_data_queue_finalize; +} + +static void +gst_data_queue_init (GstDataQueue * queue) +{ + queue->cur_level.visible = 0; /* no content */ + queue->cur_level.bytes = 0; /* no content */ + queue->cur_level.time = 0; /* no content */ + + queue->checkfull = NULL; + + g_mutex_init (&queue->qlock); + g_cond_init (&queue->item_add); + g_cond_init (&queue->item_del); + queue->queue = g_queue_new (); + + GST_DEBUG ("initialized queue's not_empty & not_full conditions"); +} + +/** + * gst_data_queue_new_full: + * @checkfull: the callback used to tell if the element considers the queue full + * or not. + * @fullcallback: the callback which will be called when the queue is considered full. + * @emptycallback: the callback which will be called when the queue is considered empty. + * @checkdata: a #gpointer that will be given in the @checkfull callback. + * + * Creates a new #GstDataQueue. The difference with @gst_data_queue_new is that it will + * not emit the 'full' and 'empty' signals, but instead calling directly @fullcallback + * or @emptycallback. + * + * Returns: a new #GstDataQueue. + * + * Since: 0.10.26 + */ + +GstDataQueue * +gst_data_queue_new_full (GstDataQueueCheckFullFunction checkfull, + GstDataQueueFullCallback fullcallback, + GstDataQueueEmptyCallback emptycallback, gpointer checkdata) +{ + GstDataQueue *ret; + + g_return_val_if_fail (checkfull != NULL, NULL); + + ret = g_object_newv (GST_TYPE_DATA_QUEUE, 0, NULL); + ret->checkfull = checkfull; + ret->checkdata = checkdata; + ret->fullcallback = fullcallback; + ret->emptycallback = emptycallback; + + return ret; +} + +/** + * gst_data_queue_new: + * @checkfull: the callback used to tell if the element considers the queue full + * or not. + * @checkdata: a #gpointer that will be given in the @checkfull callback. + * + * Returns: a new #GstDataQueue. + */ + +GstDataQueue * +gst_data_queue_new (GstDataQueueCheckFullFunction checkfull, gpointer checkdata) +{ + return gst_data_queue_new_full (checkfull, NULL, NULL, checkdata); +} + +static void +gst_data_queue_cleanup (GstDataQueue * queue) +{ + while (!g_queue_is_empty (queue->queue)) { + GstDataQueueItem *item = g_queue_pop_head (queue->queue); + + /* Just call the destroy notify on the item */ + item->destroy (item); + } + queue->cur_level.visible = 0; + queue->cur_level.bytes = 0; + queue->cur_level.time = 0; +} + +/* called only once, as opposed to dispose */ +static void +gst_data_queue_finalize (GObject * object) +{ + GstDataQueue *queue = GST_DATA_QUEUE (object); + + GST_DEBUG ("finalizing queue"); + + gst_data_queue_cleanup (queue); + g_queue_free (queue->queue); + + GST_DEBUG ("free mutex"); + g_mutex_clear (&queue->qlock); + GST_DEBUG ("done free mutex"); + + g_cond_clear (&queue->item_add); + g_cond_clear (&queue->item_del); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static inline void +gst_data_queue_locked_flush (GstDataQueue * queue) +{ + STATUS (queue, "before flushing"); + gst_data_queue_cleanup (queue); + STATUS (queue, "after flushing"); + /* we deleted something... */ + if (queue->waiting_del) + g_cond_signal (&queue->item_del); +} + +static inline gboolean +gst_data_queue_locked_is_empty (GstDataQueue * queue) +{ + return (queue->queue->length == 0); +} + +static inline gboolean +gst_data_queue_locked_is_full (GstDataQueue * queue) +{ + return queue->checkfull (queue, queue->cur_level.visible, + queue->cur_level.bytes, queue->cur_level.time, queue->checkdata); +} + +/** + * gst_data_queue_flush: + * @queue: a #GstDataQueue. + * + * Flushes all the contents of the @queue. Any call to #gst_data_queue_push and + * #gst_data_queue_pop will be released. + * MT safe. + * + * Since: 0.10.11 + */ +void +gst_data_queue_flush (GstDataQueue * queue) +{ + GST_DEBUG ("queue:%p", queue); + GST_DATA_QUEUE_MUTEX_LOCK (queue); + gst_data_queue_locked_flush (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +/** + * gst_data_queue_is_empty: + * @queue: a #GstDataQueue. + * + * Queries if there are any items in the @queue. + * MT safe. + * + * Returns: #TRUE if @queue is empty. + * + * Since: 0.10.11 + */ +gboolean +gst_data_queue_is_empty (GstDataQueue * queue) +{ + gboolean res; + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + res = gst_data_queue_locked_is_empty (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return res; +} + +/** + * gst_data_queue_is_full: + * @queue: a #GstDataQueue. + * + * Queries if @queue is full. This check will be done using the + * #GstDataQueueCheckFullFunction registered with @queue. + * MT safe. + * + * Returns: #TRUE if @queue is full. + * + * Since: 0.10.11 + */ +gboolean +gst_data_queue_is_full (GstDataQueue * queue) +{ + gboolean res; + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + res = gst_data_queue_locked_is_full (queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return res; +} + +/** + * gst_data_queue_set_flushing: + * @queue: a #GstDataQueue. + * @flushing: a #gboolean stating if the queue will be flushing or not. + * + * Sets the queue to flushing state if @flushing is #TRUE. If set to flushing + * state, any incoming data on the @queue will be discarded. Any call currently + * blocking on #gst_data_queue_push or #gst_data_queue_pop will return straight + * away with a return value of #FALSE. While the @queue is in flushing state, + * all calls to those two functions will return #FALSE. + * + * MT Safe. + * + * Since: 0.10.11 + */ +void +gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing) +{ + GST_DEBUG ("queue:%p , flushing:%d", queue, flushing); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + queue->flushing = flushing; + if (flushing) { + /* release push/pop functions */ + if (queue->waiting_add) + g_cond_signal (&queue->item_add); + if (queue->waiting_del) + g_cond_signal (&queue->item_del); + } + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +/** + * gst_data_queue_push: + * @queue: a #GstDataQueue. + * @item: a #GstDataQueueItem. + * + * Pushes a #GstDataQueueItem (or a structure that begins with the same fields) + * on the @queue. If the @queue is full, the call will block until space is + * available, OR the @queue is set to flushing state. + * MT safe. + * + * Note that this function has slightly different semantics than gst_pad_push() + * and gst_pad_push_event(): this function only takes ownership of @item and + * the #GstMiniObject contained in @item if the push was successful. If FALSE + * is returned, the caller is responsible for freeing @item and its contents. + * + * Returns: #TRUE if the @item was successfully pushed on the @queue. + * + * Since: 0.10.11 + */ +gboolean +gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item) +{ + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before pushing"); + + /* We ALWAYS need to check for queue fillness */ + if (gst_data_queue_locked_is_full (queue)) { + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + if (G_LIKELY (queue->fullcallback)) + queue->fullcallback (queue, queue->checkdata); + else + g_signal_emit (queue, gst_data_queue_signals[SIGNAL_FULL], 0); + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + /* signal might have removed some items */ + while (gst_data_queue_locked_is_full (queue)) { + queue->waiting_del = TRUE; + g_cond_wait (&queue->item_del, &queue->qlock); + queue->waiting_del = FALSE; + if (queue->flushing) + goto flushing; + } + } + + g_queue_push_tail (queue->queue, item); + + if (item->visible) + queue->cur_level.visible++; + queue->cur_level.bytes += item->size; + queue->cur_level.time += item->duration; + + STATUS (queue, "after pushing"); + if (queue->waiting_add) + g_cond_signal (&queue->item_add); + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +/** + * gst_data_queue_pop: + * @queue: a #GstDataQueue. + * @item: pointer to store the returned #GstDataQueueItem. + * + * Retrieves the first @item available on the @queue. If the queue is currently + * empty, the call will block until at least one item is available, OR the + * @queue is set to the flushing state. + * MT safe. + * + * Returns: #TRUE if an @item was successfully retrieved from the @queue. + * + * Since: 0.10.11 + */ +gboolean +gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item) +{ + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + g_return_val_if_fail (item != NULL, FALSE); + + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + STATUS (queue, "before popping"); + + if (gst_data_queue_locked_is_empty (queue)) { + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + if (G_LIKELY (queue->emptycallback)) + queue->emptycallback (queue, queue->checkdata); + else + g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0); + GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); + + while (gst_data_queue_locked_is_empty (queue)) { + queue->waiting_add = TRUE; + g_cond_wait (&queue->item_add, &queue->qlock); + queue->waiting_add = FALSE; + if (queue->flushing) + goto flushing; + } + } + + /* Get the item from the GQueue */ + *item = g_queue_pop_head (queue->queue); + + /* update current level counter */ + if ((*item)->visible) + queue->cur_level.visible--; + queue->cur_level.bytes -= (*item)->size; + queue->cur_level.time -= (*item)->duration; + + STATUS (queue, "after popping"); + if (queue->waiting_del) + g_cond_signal (&queue->item_del); + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + return TRUE; + + /* ERRORS */ +flushing: + { + GST_DEBUG ("queue:%p, we are flushing", queue); + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +/** + * gst_data_queue_drop_head: + * @queue: The #GstDataQueue to drop an item from. + * @type: The #GType of the item to drop. + * + * Pop and unref the head-most #GstMiniObject with the given #GType. + * + * Returns: TRUE if an element was removed. + * + * Since: 0.10.11 + */ +gboolean +gst_data_queue_drop_head (GstDataQueue * queue, GType type) +{ + gboolean res = FALSE; + GList *item; + GstDataQueueItem *leak = NULL; + + g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); + + GST_DEBUG ("queue:%p", queue); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + for (item = g_queue_peek_head_link (queue->queue); item; item = item->next) { + GstDataQueueItem *tmp = (GstDataQueueItem *) item->data; + + if (G_TYPE_CHECK_INSTANCE_TYPE (tmp->object, type)) { + leak = tmp; + break; + } + } + + if (!leak) + goto done; + + g_queue_delete_link (queue->queue, item); + + if (leak->visible) + queue->cur_level.visible--; + queue->cur_level.bytes -= leak->size; + queue->cur_level.time -= leak->duration; + + leak->destroy (leak); + + res = TRUE; + +done: + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); + + GST_DEBUG ("queue:%p , res:%d", queue, res); + + return res; +} + +/** + * gst_data_queue_limits_changed: + * @queue: The #GstDataQueue + * + * Inform the queue that the limits for the fullness check have changed and that + * any blocking gst_data_queue_push() should be unblocked to recheck the limts. + * + * Since: 0.10.11 + */ +void +gst_data_queue_limits_changed (GstDataQueue * queue) +{ + g_return_if_fail (GST_IS_DATA_QUEUE (queue)); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + if (queue->waiting_del) { + GST_DEBUG ("signal del"); + g_cond_signal (&queue->item_del); + } + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} + +/** + * gst_data_queue_get_level: + * @queue: The #GstDataQueue + * @level: the location to store the result + * + * Get the current level of the queue. + * + * Since: 0.10.11 + */ +void +gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level) +{ + memcpy (level, (&queue->cur_level), sizeof (GstDataQueueSize)); +} + +static void +gst_data_queue_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_data_queue_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstDataQueue *queue = GST_DATA_QUEUE (object); + + GST_DATA_QUEUE_MUTEX_LOCK (queue); + + switch (prop_id) { + case ARG_CUR_LEVEL_BYTES: + g_value_set_uint (value, queue->cur_level.bytes); + break; + case ARG_CUR_LEVEL_VISIBLE: + g_value_set_uint (value, queue->cur_level.visible); + break; + case ARG_CUR_LEVEL_TIME: + g_value_set_uint64 (value, queue->cur_level.time); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_DATA_QUEUE_MUTEX_UNLOCK (queue); +} diff --git a/plugins/elements/gstdataqueue.h b/plugins/elements/gstdataqueue.h new file mode 100644 index 0000000..36f4be7 --- /dev/null +++ b/plugins/elements/gstdataqueue.h @@ -0,0 +1,180 @@ +/* GStreamer + * Copyright (C) 2006 Edward Hervey <edward@fluendo.com> + * + * gstdataqueue.h: + * + * 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_DATA_QUEUE_H__ +#define __GST_DATA_QUEUE_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS +#define GST_TYPE_DATA_QUEUE \ + (gst_data_queue_get_type()) +#define GST_DATA_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DATA_QUEUE,GstDataQueue)) +#define GST_DATA_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DATA_QUEUE,GstDataQueueClass)) +#define GST_IS_DATA_QUEUE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DATA_QUEUE)) +#define GST_IS_DATA_QUEUE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DATA_QUEUE)) +typedef struct _GstDataQueue GstDataQueue; +typedef struct _GstDataQueueClass GstDataQueueClass; +typedef struct _GstDataQueueSize GstDataQueueSize; +typedef struct _GstDataQueueItem GstDataQueueItem; + +/** + * GstDataQueueItem: + * @object: the #GstMiniObject to queue. + * @size: the size in bytes of the miniobject. + * @duration: the duration in #GstClockTime of the miniobject. Can not be + * #GST_CLOCK_TIME_NONE. + * @visible: #TRUE if @object should be considered as a visible object. + * @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem. + * This function should also drop the reference to @object the owner of the + * #GstDataQueueItem is assumed to hold. + * + * Structure used by #GstDataQueue. You can supply a different structure, as + * long as the top of the structure is identical to this structure. + * + * Since: 0.10.11 + */ + +struct _GstDataQueueItem +{ + GstMiniObject *object; + guint size; + guint64 duration; + gboolean visible; + + /* user supplied destroy function */ + GDestroyNotify destroy; +}; + +/** + * GstDataQueueSize: + * @visible: number of buffers + * @bytes: number of bytes + * @time: amount of time + * + * Structure describing the size of a queue. + * + * Since: 0.10.11 + */ +struct _GstDataQueueSize +{ + guint visible; + guint bytes; + guint64 time; +}; + +/** + * GstDataQueueCheckFullFunction: + * @queue: a #GstDataQueue. + * @visible: The number of visible items currently in the queue. + * @bytes: The amount of bytes currently in the queue. + * @time: The accumulated duration of the items currently in the queue. + * @checkdata: The #gpointer registered when the #GstDataQueue was created. + * + * The prototype of the function used to inform the queue that it should be + * considered as full. + * + * Returns: #TRUE if the queue should be considered full. + * + * Since: 0.10.11 + */ +typedef gboolean (*GstDataQueueCheckFullFunction) (GstDataQueue * queue, + guint visible, guint bytes, guint64 time, gpointer checkdata); + +typedef void (*GstDataQueueFullCallback) (GstDataQueue * queue, gpointer checkdata); +typedef void (*GstDataQueueEmptyCallback) (GstDataQueue * queue, gpointer checkdata); + +/** + * GstDataQueue: + * @object: the parent structure + * + * Opaque #GstDataQueue structure. + * + * Since: 0.10.11 + */ +struct _GstDataQueue +{ + GObject object; + + /*< private >*/ + /* the queue of data we're keeping our grubby hands on */ + GQueue *queue; + + GstDataQueueSize cur_level; /* size of the queue */ + GstDataQueueCheckFullFunction checkfull; /* Callback to check if the queue is full */ + gpointer *checkdata; + + GMutex qlock; /* lock for queue (vs object lock) */ + gboolean waiting_add; + GCond item_add; /* signals buffers now available for reading */ + gboolean waiting_del; + GCond item_del; /* signals space now available for writing */ + gboolean flushing; /* indicates whether conditions where signalled because + * of external flushing */ + GstDataQueueFullCallback fullcallback; + GstDataQueueEmptyCallback emptycallback; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstDataQueueClass +{ + GObjectClass parent_class; + + /* signals */ + void (*empty) (GstDataQueue * queue); + void (*full) (GstDataQueue * queue); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_data_queue_get_type (void); + +GstDataQueue * gst_data_queue_new (GstDataQueueCheckFullFunction checkfull, + gpointer checkdata) G_GNUC_MALLOC; + +GstDataQueue * gst_data_queue_new_full (GstDataQueueCheckFullFunction checkfull, + GstDataQueueFullCallback fullcallback, + GstDataQueueEmptyCallback emptycallback, + gpointer checkdata) G_GNUC_MALLOC; + +gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item); +gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item); + +void gst_data_queue_flush (GstDataQueue * queue); +void gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing); + +gboolean gst_data_queue_drop_head (GstDataQueue * queue, GType type); + +gboolean gst_data_queue_is_full (GstDataQueue * queue); +gboolean gst_data_queue_is_empty (GstDataQueue * queue); + +void gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize *level); +void gst_data_queue_limits_changed (GstDataQueue * queue); + +G_END_DECLS + +#endif /* __GST_DATA_QUEUE_H__ */ diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index 8d00729..00594b5 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -93,6 +93,6 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "coreelements", + coreelements, "standard GStreamer elements", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index f4e6a5c..363fde9 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -38,7 +38,6 @@ #endif #include "gstfakesink.h" -#include <gst/gstmarshal.h> #include <string.h> static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", @@ -61,7 +60,7 @@ enum #define DEFAULT_SYNC FALSE #define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE -#define DEFAULT_SILENT FALSE +#define DEFAULT_SILENT TRUE #define DEFAULT_DUMP FALSE #define DEFAULT_SIGNAL_HANDOFFS FALSE #define DEFAULT_LAST_MESSAGE NULL @@ -131,40 +130,13 @@ static GstFlowReturn gst_fake_sink_preroll (GstBaseSink * bsink, static GstFlowReturn gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buffer); static gboolean gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event); +static gboolean gst_fake_sink_query (GstBaseSink * bsink, GstQuery * query); static guint gst_fake_sink_signals[LAST_SIGNAL] = { 0 }; static GParamSpec *pspec_last_message = NULL; static void -marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value, - guint n_param_values, const GValue * param_values, gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj, - gpointer arg1, gpointer arg2, gpointer data2); - register marshalfunc_VOID__MINIOBJECT_OBJECT callback; - register GCClosure *cc = (GCClosure *) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } else { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = - (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data : - cc->callback); - - callback (data1, g_value_get_boxed (param_values + 1), - g_value_get_object (param_values + 2), data2); -} - -static void gst_fake_sink_class_init (GstFakeSinkClass * klass) { GObjectClass *gobject_class; @@ -225,8 +197,8 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass) gst_fake_sink_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL, - marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, - GST_TYPE_BUFFER, GST_TYPE_PAD); + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); /** * GstFakeSink::preroll-handoff: @@ -241,10 +213,10 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass) gst_fake_sink_signals[SIGNAL_PREROLL_HANDOFF] = g_signal_new ("preroll-handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSinkClass, preroll_handoff), - NULL, NULL, marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, - GST_TYPE_BUFFER, GST_TYPE_PAD); + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Fake Sink", "Sink", "Black hole for data", @@ -260,6 +232,7 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass) gstbase_sink_class->event = GST_DEBUG_FUNCPTR (gst_fake_sink_event); gstbase_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_fake_sink_preroll); gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_fake_sink_render); + gstbase_sink_class->query = GST_DEBUG_FUNCPTR (gst_fake_sink_query); } static void @@ -271,9 +244,6 @@ gst_fake_sink_init (GstFakeSink * fakesink) fakesink->state_error = DEFAULT_STATE_ERROR; fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; fakesink->num_buffers = DEFAULT_NUM_BUFFERS; -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_init (&fakesink->notify_lock); -#endif gst_base_sink_set_sync (GST_BASE_SINK (fakesink), DEFAULT_SYNC); } @@ -281,12 +251,6 @@ gst_fake_sink_init (GstFakeSink * fakesink) static void gst_fake_sink_finalize (GObject * obj) { -#if !GLIB_CHECK_VERSION(2,26,0) - GstFakeSink *sink = GST_FAKE_SINK (obj); - - g_static_rec_mutex_free (&sink->notify_lock); -#endif - G_OBJECT_CLASS (parent_class)->finalize (obj); } @@ -370,19 +334,7 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value, static void gst_fake_sink_notify_last_message (GstFakeSink * sink) { - /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent - * g_object_notify() on the same object might lead to crashes, see - * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups. - * So we really don't want to do a g_object_notify() here for out-of-band - * events with the streaming thread possibly also doing a g_object_notify() - * for an in-band buffer or event. This is fixed in GLib >= 2.26 */ -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_lock (&sink->notify_lock); - g_object_notify ((GObject *) sink, "last-message"); - g_static_rec_mutex_unlock (&sink->notify_lock); -#else g_object_notify_by_pspec ((GObject *) sink, pspec_last_message); -#endif } static gboolean @@ -392,6 +344,7 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) if (!sink->silent) { const GstStructure *s; + const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (sink); @@ -405,10 +358,13 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) structure = gst_message_get_structure (msg); sstr = gst_structure_to_string (structure); sink->last_message = - g_strdup_printf ("message ******* M (type: %d, %s) %p", + g_strdup_printf ("message ******* (%s:%s) M (type: %d, %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), GST_MESSAGE_TYPE (msg), sstr, msg); gst_message_unref (msg); } else { + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); + if ((s = gst_event_get_structure (event))) { sstr = gst_structure_to_string (s); } else { @@ -416,8 +372,9 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) } sink->last_message = - g_strdup_printf ("event ******* E (type: %d, %s) %p", - GST_EVENT_TYPE (event), sstr, event); + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + tstr, GST_EVENT_TYPE (event), sstr, event); } g_free (sstr); GST_OBJECT_UNLOCK (sink); @@ -425,11 +382,7 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) gst_fake_sink_notify_last_message (sink); } - if (GST_BASE_SINK_CLASS (parent_class)->event) { - return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); - } else { - return TRUE; - } + return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); } static GstFlowReturn @@ -460,7 +413,7 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer) eos: { GST_DEBUG_OBJECT (sink, "we are EOS"); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } } @@ -476,17 +429,24 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) sink->num_buffers_left--; if (!sink->silent) { - gchar ts_str[64], dur_str[64]; + gchar dts_str[64], pts_str[64], dur_str[64]; gchar flag_str[100]; GST_OBJECT_LOCK (sink); g_free (sink->last_message); - if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { - g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DTS (buf))); } else { - g_strlcpy (ts_str, "none", sizeof (ts_str)); + g_strlcpy (dts_str, "none", sizeof (dts_str)); + } + + if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } else { + g_strlcpy (pts_str, "none", sizeof (pts_str)); } if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { @@ -497,15 +457,14 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) } { - const char *flag_list[12] = { - "ro", "media4", "", "", - "preroll", "discont", "incaps", "gap", - "delta_unit", "media1", "media2", "media3" + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" }; int i; char *end = flag_str; end[0] = '\0'; - for (i = 0; i < 12; i++) { + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { strcpy (end, flag_list[i]); end += strlen (end); @@ -517,12 +476,13 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) } sink->last_message = - g_strdup_printf ("chain ******* < (%5" G_GSIZE_FORMAT - " bytes, timestamp: %s" ", duration: %s, offset: %" G_GINT64_FORMAT - ", offset_end: %" G_GINT64_FORMAT ", flags: %d %s) %p", - gst_buffer_get_size (buf), ts_str, dur_str, GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, - flag_str, buf); + g_strdup_printf ("chain ******* (%s:%s) (%u bytes, dts: %s, pts: %s" + ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" + G_GINT64_FORMAT ", flags: %d %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + (guint) gst_buffer_get_size (buf), dts_str, pts_str, + dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf); GST_OBJECT_UNLOCK (sink); gst_fake_sink_notify_last_message (sink); @@ -532,12 +492,11 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) bsink->sinkpad); if (sink->dump) { - guint8 *data; - gsize size; + GstMapInfo info; - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); - gst_util_dump_mem (data, size); - gst_buffer_unmap (buf, data, size); + gst_buffer_map (buf, &info, GST_MAP_READ); + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); } if (sink->num_buffers_left == 0) goto eos; @@ -548,8 +507,31 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) eos: { GST_DEBUG_OBJECT (sink, "we are EOS"); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; + } +} + +static gboolean +gst_fake_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + /* we don't supporting seeking */ + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + gst_query_set_seeking (query, fmt, FALSE, 0, -1); + ret = TRUE; + break; + } + default: + ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; } + + return ret; } static GstStateChangeReturn diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h index b1165af..2db98b9 100644 --- a/plugins/elements/gstfakesink.h +++ b/plugins/elements/gstfakesink.h @@ -82,9 +82,6 @@ struct _GstFakeSink { gchar *last_message; gint num_buffers; gint num_buffers_left; -#if !GLIB_CHECK_VERSION(2,26,0) - GStaticRecMutex notify_lock; -#endif }; struct _GstFakeSinkClass { diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index df46d18..c9b2c45 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -52,7 +52,6 @@ #include <string.h> #include "gstfakesrc.h" -#include <gst/gstmarshal.h> static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -81,7 +80,7 @@ enum #define DEFAULT_PATTERN NULL #define DEFAULT_EOS FALSE #define DEFAULT_SIGNAL_HANDOFFS FALSE -#define DEFAULT_SILENT FALSE +#define DEFAULT_SILENT TRUE #define DEFAULT_DUMP FALSE #define DEFAULT_PARENTSIZE 4096*10 #define DEFAULT_CAN_ACTIVATE_PULL TRUE @@ -227,34 +226,6 @@ static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 }; static GParamSpec *pspec_last_message = NULL; static void -marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value, - guint n_param_values, const GValue * param_values, gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj, - gpointer arg1, gpointer arg2, gpointer data2); - register marshalfunc_VOID__MINIOBJECT_OBJECT callback; - register GCClosure *cc = (GCClosure *) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } else { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = - (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data : - cc->callback); - - callback (data1, g_value_get_boxed (param_values + 1), - g_value_get_object (param_values + 2), data2); -} - -static void gst_fake_src_class_init (GstFakeSrcClass * klass) { GObjectClass *gobject_class; @@ -363,10 +334,10 @@ gst_fake_src_class_init (GstFakeSrcClass * klass) gst_fake_src_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL, - marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER, - GST_TYPE_PAD); + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Fake Source", "Source", "Push empty (no data) buffers around", @@ -429,27 +400,27 @@ gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event) if (!src->silent) { const GstStructure *s; + const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (src); g_free (src->last_message); + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); + if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); src->last_message = - g_strdup_printf ("event ******* E (type: %d, %s) %p", - GST_EVENT_TYPE (event), sstr, event); + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), + tstr, GST_EVENT_TYPE (event), sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (src); -#if !GLIB_CHECK_VERSION(2,26,0) - g_object_notify ((GObject *) src, "last-message"); -#else g_object_notify_by_pspec ((GObject *) src, pspec_last_message); -#endif } return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); @@ -460,7 +431,7 @@ gst_fake_src_alloc_parent (GstFakeSrc * src) { GstBuffer *buf; - buf = gst_buffer_new_allocate (NULL, src->parentsize, 0); + buf = gst_buffer_new_allocate (NULL, src->parentsize, NULL); src->parent = buf; src->parentoffset = 0; @@ -526,11 +497,13 @@ gst_fake_src_set_property (GObject * object, guint prop_id, src->dump = g_value_get_boolean (value); break; case PROP_CAN_ACTIVATE_PUSH: - g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED)); + g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, + GST_BASE_SRC_FLAG_STARTED)); GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value); break; case PROP_CAN_ACTIVATE_PULL: - g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED)); + g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, + GST_BASE_SRC_FLAG_STARTED)); src->can_activate_pull = g_value_get_boolean (value); break; case PROP_IS_LIVE: @@ -686,8 +659,8 @@ gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size) if (do_prepare) gst_fake_src_prepare_buffer (src, data, size); - gst_buffer_take_memory (buf, -1, - gst_memory_new_wrapped (0, data, g_free, size, 0, size)); + gst_buffer_append_memory (buf, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); } return buf; @@ -720,7 +693,7 @@ gst_fake_src_create_buffer (GstFakeSrc * src, gsize * bufsize) GstBuffer *buf; gsize size = gst_fake_src_get_size (src); gboolean dump = src->dump; - guint8 *data; + GstMapInfo info; *bufsize = size; @@ -747,9 +720,9 @@ gst_fake_src_create_buffer (GstFakeSrc * src, gsize * bufsize) /* try again (this will allocate a new parent) */ return gst_fake_src_create_buffer (src, bufsize); } - data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE); - gst_fake_src_prepare_buffer (src, data, size); - gst_buffer_unmap (buf, data, size); + gst_buffer_map (buf, &info, GST_MAP_WRITE); + gst_fake_src_prepare_buffer (src, info.data, info.size); + gst_buffer_unmap (buf, &info); break; default: g_warning ("fakesrc: dunno how to allocate buffers !"); @@ -757,9 +730,9 @@ gst_fake_src_create_buffer (GstFakeSrc * src, gsize * bufsize) break; } if (dump) { - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); - gst_util_dump_mem (data, size); - gst_buffer_unmap (buf, data, size); + gst_buffer_map (buf, &info, GST_MAP_READ); + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); } return buf; @@ -775,12 +748,16 @@ gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, /* sync on the timestamp of the buffer if requested. */ if (src->sync) { - GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + GstClockTime timestamp, duration; + + /* first sync on DTS, else use PTS */ + timestamp = GST_BUFFER_DTS (buffer); + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + timestamp = GST_BUFFER_PTS (buffer); if (GST_CLOCK_TIME_IS_VALID (timestamp)) { /* get duration to calculate end time */ - GstClockTime duration = GST_BUFFER_DURATION (buffer); - + duration = GST_BUFFER_DURATION (buffer); if (GST_CLOCK_TIME_IS_VALID (duration)) { *end = timestamp + duration; } @@ -827,21 +804,28 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, time = GST_CLOCK_TIME_NONE; } - GST_BUFFER_TIMESTAMP (buf) = time; + GST_BUFFER_DTS (buf) = time; + GST_BUFFER_PTS (buf) = time; if (!src->silent) { - gchar ts_str[64], dur_str[64]; + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar flag_str[100]; GST_OBJECT_LOCK (src); g_free (src->last_message); - if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { - g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_DTS (buf))); } else { - g_strlcpy (ts_str, "none", sizeof (ts_str)); + g_strlcpy (dts_str, "none", sizeof (dts_str)); + } + if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { + g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + } else { + g_strlcpy (pts_str, "none", sizeof (pts_str)); } - if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); @@ -849,19 +833,36 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, g_strlcpy (dur_str, "none", sizeof (dur_str)); } + { + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" + }; + int i; + char *end = flag_str; + end[0] = '\0'; + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { + if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { + strcpy (end, flag_list[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + } + src->last_message = - g_strdup_printf ("get ******* > (%5d bytes, timestamp: %s" + g_strdup_printf ("create ******* (%s:%s) (%u bytes, dts: %s, pts:%s" ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" - G_GINT64_FORMAT ", flags: %d) %p", (gint) size, ts_str, - dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), - GST_MINI_OBJECT_CAST (buf)->flags, buf); + G_GINT64_FORMAT ", flags: %d %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size, + dts_str, pts_str, dur_str, GST_BUFFER_OFFSET (buf), + GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, + flag_str, buf); GST_OBJECT_UNLOCK (src); -#if !GLIB_CHECK_VERSION(2,26,0) - g_object_notify ((GObject *) src, "last-message"); -#else g_object_notify_by_pspec ((GObject *) src, pspec_last_message); -#endif } if (src->signal_handoffs) { diff --git a/plugins/elements/gstfdsink.c b/plugins/elements/gstfdsink.c index 01edb3f..7852561 100644 --- a/plugins/elements/gstfdsink.c +++ b/plugins/elements/gstfdsink.c @@ -106,7 +106,7 @@ static void gst_fd_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_fd_sink_dispose (GObject * obj); -static gboolean gst_fd_sink_query (GstPad * pad, GstQuery * query); +static gboolean gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query); static GstFlowReturn gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer); static gboolean gst_fd_sink_start (GstBaseSink * basesink); @@ -132,7 +132,7 @@ gst_fd_sink_class_init (GstFdSinkClass * klass) gobject_class->get_property = gst_fd_sink_get_property; gobject_class->dispose = gst_fd_sink_dispose; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Filedescriptor Sink", "Sink/File", "Write data to a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>"); @@ -145,6 +145,7 @@ gst_fd_sink_class_init (GstFdSinkClass * klass) gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock); gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop); gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event); + gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_fd_sink_query); g_object_class_install_property (gobject_class, ARG_FD, g_param_spec_int ("fd", "fd", "An open file descriptor to write to", @@ -154,11 +155,6 @@ gst_fd_sink_class_init (GstFdSinkClass * klass) static void gst_fd_sink_init (GstFdSink * fdsink) { - GstPad *pad; - - pad = GST_BASE_SINK_PAD (fdsink); - gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_fd_sink_query)); - fdsink->fd = 1; fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd); fdsink->bytes_written = 0; @@ -179,44 +175,67 @@ gst_fd_sink_dispose (GObject * obj) } static gboolean -gst_fd_sink_query (GstPad * pad, GstQuery * query) +gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query) { + gboolean res = FALSE; GstFdSink *fdsink; - GstFormat format; - fdsink = GST_FD_SINK (GST_PAD_PARENT (pad)); + fdsink = GST_FD_SINK (bsink); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: + { + GstFormat format; + gst_query_parse_position (query, &format, NULL); + switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: gst_query_set_position (query, GST_FORMAT_BYTES, fdsink->current_pos); - return TRUE; + res = TRUE; + break; default: - return FALSE; + break; } - + break; + } case GST_QUERY_FORMATS: gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); - return TRUE; - + res = TRUE; + break; case GST_QUERY_URI: gst_query_set_uri (query, fdsink->uri); - return TRUE; + res = TRUE; + break; + case GST_QUERY_SEEKING:{ + GstFormat format; + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) { + gst_query_set_seeking (query, GST_FORMAT_BYTES, fdsink->seekable, 0, + -1); + } else { + gst_query_set_seeking (query, format, FALSE, 0, -1); + } + res = TRUE; + break; + } default: - return gst_pad_query_default (pad, query); + res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + } + return res; } static GstFlowReturn gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer) { GstFdSink *fdsink; - guint8 *data, *ptr; - gsize size, left; + GstMapInfo info; + guint8 *ptr; + gsize left; gint written; #ifndef HAVE_WIN32 @@ -227,16 +246,16 @@ gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer) g_return_val_if_fail (fdsink->fd >= 0, GST_FLOW_ERROR); - data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ); + gst_buffer_map (buffer, &info, GST_MAP_READ); - ptr = data; - left = size; + ptr = info.data; + left = info.size; again: #ifndef HAVE_WIN32 do { GST_DEBUG_OBJECT (fdsink, "going into select, have %" G_GSIZE_FORMAT - " bytes to write", size); + " bytes to write", info.size); retval = gst_poll_wait (fdsink->fdset, GST_CLOCK_TIME_NONE); } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); @@ -249,7 +268,7 @@ again: #endif GST_DEBUG_OBJECT (fdsink, "writing %" G_GSIZE_FORMAT " bytes to" - " file descriptor %d", size, fdsink->fd); + " file descriptor %d", info.size, fdsink->fd); written = write (fdsink->fd, ptr, left); @@ -276,7 +295,7 @@ again: if (G_UNLIKELY (left > 0)) goto again; - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &info); return GST_FLOW_OK; @@ -286,14 +305,14 @@ select_error: GST_ELEMENT_ERROR (fdsink, RESOURCE, READ, (NULL), ("select on file descriptor: %s.", g_strerror (errno))); GST_DEBUG_OBJECT (fdsink, "Error during select"); - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &info); return GST_FLOW_ERROR; } stopped: { GST_DEBUG_OBJECT (fdsink, "Select stopped"); - gst_buffer_unmap (buffer, data, size); - return GST_FLOW_WRONG_STATE; + gst_buffer_unmap (buffer, &info); + return GST_FLOW_FLUSHING; } #endif @@ -309,13 +328,13 @@ write_error: fdsink->fd, g_strerror (errno))); } } - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &info); return GST_FLOW_ERROR; } } static gboolean -gst_fd_sink_check_fd (GstFdSink * fdsink, int fd) +gst_fd_sink_check_fd (GstFdSink * fdsink, int fd, GError ** error) { struct stat stat_results; off_t result; @@ -347,6 +366,8 @@ invalid: { GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL), ("File descriptor %d is not valid: %s", fd, g_strerror (errno))); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE, + "File descriptor %d is not valid: %s", fd, g_strerror (errno)); return FALSE; } not_seekable: @@ -363,7 +384,7 @@ gst_fd_sink_start (GstBaseSink * basesink) GstPollFD fd = GST_POLL_FD_INIT; fdsink = GST_FD_SINK (basesink); - if (!gst_fd_sink_check_fd (fdsink, fdsink->fd)) + if (!gst_fd_sink_check_fd (fdsink, fdsink->fd, NULL)) return FALSE; if ((fdsink->fdset = gst_poll_new (TRUE)) == NULL) @@ -376,6 +397,9 @@ gst_fd_sink_start (GstBaseSink * basesink) fdsink->bytes_written = 0; fdsink->current_pos = 0; + fdsink->seekable = gst_fd_sink_do_seek (fdsink, 0); + GST_INFO_OBJECT (fdsink, "seeking supported: %d", fdsink->seekable); + return TRUE; /* ERRORS */ @@ -427,12 +451,15 @@ gst_fd_sink_unlock_stop (GstBaseSink * basesink) } static gboolean -gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd) +gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd, GError ** error) { - if (new_fd < 0) + if (new_fd < 0) { + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE, + "File descriptor %d is not valid", new_fd); return FALSE; + } - if (!gst_fd_sink_check_fd (fdsink, new_fd)) + if (!gst_fd_sink_check_fd (fdsink, new_fd, error)) goto invalid; /* assign the fd */ @@ -474,7 +501,7 @@ gst_fd_sink_set_property (GObject * object, guint prop_id, int fd; fd = g_value_get_int (value); - gst_fd_sink_update_fd (fdsink, fd); + gst_fd_sink_update_fd (fdsink, fd, NULL); break; } default: @@ -566,13 +593,14 @@ gst_fd_sink_event (GstBaseSink * sink, GstEvent * event) break; } - return TRUE; + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); seek_failed: { GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL), ("Error while seeking on file descriptor %d: %s", fdsink->fd, g_strerror (errno))); + gst_event_unref (event); return FALSE; } @@ -586,40 +614,37 @@ gst_fd_sink_uri_get_type (GType type) return GST_URI_SINK; } -static gchar ** +static const gchar *const * gst_fd_sink_uri_get_protocols (GType type) { - static gchar *protocols[] = { (char *) "fd", NULL }; + static const gchar *protocols[] = { "fd", NULL }; return protocols; } -static const gchar * +static gchar * gst_fd_sink_uri_get_uri (GstURIHandler * handler) { GstFdSink *sink = GST_FD_SINK (handler); - return sink->uri; + /* FIXME: make thread-safe */ + return g_strdup (sink->uri); } static gboolean -gst_fd_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +gst_fd_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) { - gchar *protocol; GstFdSink *sink = GST_FD_SINK (handler); gint fd; - protocol = gst_uri_get_protocol (uri); - if (strcmp (protocol, "fd") != 0) { - g_free (protocol); + if (sscanf (uri, "fd://%d", &fd) != 1) { + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File descriptor URI could not be parsed"); return FALSE; } - g_free (protocol); - - if (sscanf (uri, "fd://%d", &fd) != 1) - return FALSE; - return gst_fd_sink_update_fd (sink, fd); + return gst_fd_sink_update_fd (sink, fd, error); } static void diff --git a/plugins/elements/gstfdsink.h b/plugins/elements/gstfdsink.h index 90913b4..59393d0 100644 --- a/plugins/elements/gstfdsink.h +++ b/plugins/elements/gstfdsink.h @@ -59,6 +59,8 @@ struct _GstFdSink { int fd; guint64 bytes_written; guint64 current_pos; + + gboolean seekable; }; struct _GstFdSinkClass { diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c index 8e12d52..13c70bd 100644 --- a/plugins/elements/gstfdsrc.c +++ b/plugins/elements/gstfdsrc.c @@ -169,7 +169,7 @@ gst_fd_src_class_init (GstFdSrcClass * klass) G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Filedescriptor Source", "Source/File", "Read from a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>"); @@ -392,24 +392,23 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) GstBuffer *buf; gssize readbytes; guint blocksize; - GstClockTime timeout; - guint8 *data; - gsize maxsize; + GstMapInfo info; #ifndef HAVE_WIN32 + GstClockTime timeout; gboolean try_again; gint retval; #endif src = GST_FD_SRC (psrc); +#ifndef HAVE_WIN32 if (src->timeout > 0) { timeout = src->timeout * GST_USECOND; } else { timeout = GST_CLOCK_TIME_NONE; } -#ifndef HAVE_WIN32 do { try_again = FALSE; @@ -442,21 +441,22 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) blocksize = GST_BASE_SRC (src)->blocksize; /* create the buffer */ - buf = gst_buffer_new_allocate (NULL, blocksize, 0); + buf = gst_buffer_new_allocate (NULL, blocksize, NULL); if (G_UNLIKELY (buf == NULL)) goto alloc_failed; - data = gst_buffer_map (buf, NULL, &maxsize, GST_MAP_WRITE); + gst_buffer_map (buf, &info, GST_MAP_WRITE); do { - readbytes = read (src->fd, data, blocksize); + readbytes = read (src->fd, info.data, blocksize); GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes); } while (readbytes == -1 && errno == EINTR); /* retry if interrupted */ if (readbytes < 0) goto read_error; - gst_buffer_unmap (buf, data, readbytes); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, readbytes); if (readbytes == 0) goto eos; @@ -484,7 +484,7 @@ poll_error: stopped: { GST_DEBUG_OBJECT (psrc, "Poll stopped"); - return GST_FLOW_WRONG_STATE; + return GST_FLOW_FLUSHING; } #endif alloc_failed: @@ -496,14 +496,14 @@ eos: { GST_DEBUG_OBJECT (psrc, "Read 0 bytes. EOS."); gst_buffer_unref (buf); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } read_error: { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("read on file descriptor: %s.", g_strerror (errno))); GST_DEBUG_OBJECT (psrc, "Error reading from fd"); - gst_buffer_unmap (buf, data, 0); + gst_buffer_unmap (buf, &info); gst_buffer_unref (buf); return GST_FLOW_ERROR; } @@ -605,29 +605,31 @@ gst_fd_src_uri_get_type (GType type) return GST_URI_SRC; } -static gchar ** +static const gchar *const * gst_fd_src_uri_get_protocols (GType type) { - static gchar *protocols[] = { (char *) "fd", NULL }; + static const gchar *protocols[] = { "fd", NULL }; return protocols; } -static const gchar * +static gchar * gst_fd_src_uri_get_uri (GstURIHandler * handler) { GstFdSrc *src = GST_FD_SRC (handler); - return src->uri; + /* FIXME: make thread-safe */ + return g_strdup (src->uri); } static gboolean -gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** err) { gchar *protocol, *q; GstFdSrc *src = GST_FD_SRC (handler); gint fd; - guint64 size = -1; + guint64 size = (guint64) - 1; GST_INFO_OBJECT (src, "checking uri %s", uri); diff --git a/plugins/elements/gstfilesink.c b/plugins/elements/gstfilesink.c index 02fee92..7b5218b 100644 --- a/plugins/elements/gstfilesink.c +++ b/plugins/elements/gstfilesink.c @@ -220,7 +220,7 @@ gst_file_sink_class_init (GstFileSinkClass * klass) "Append to an already existing file", DEFAULT_APPEND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "File Sink", "Sink/File", "Write stream to a file", "Thomas Vander Stichele <thomas at apestaart dot org>"); @@ -269,7 +269,8 @@ gst_file_sink_dispose (GObject * object) } static gboolean -gst_file_sink_set_location (GstFileSink * sink, const gchar * location) +gst_file_sink_set_location (GstFileSink * sink, const gchar * location, + GError ** error) { if (sink->file) goto was_open; @@ -295,6 +296,9 @@ was_open: { g_warning ("Changing the `location' property on filesink when a file is " "open is not supported."); + g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE, + "Changing the 'location' property on filesink when a file is " + "open is not supported"); return FALSE; } } @@ -307,7 +311,7 @@ gst_file_sink_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: - gst_file_sink_set_location (sink, g_value_get_string (value)); + gst_file_sink_set_location (sink, g_value_get_string (value), NULL); break; case PROP_BUFFER_MODE: sink->buffer_mode = g_value_get_enum (value); @@ -478,6 +482,16 @@ gst_file_sink_query (GstBaseSink * bsink, GstQuery * query) res = TRUE; break; + case GST_QUERY_SEEKING: + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) { + gst_query_set_seeking (query, GST_FORMAT_BYTES, self->seekable, 0, -1); + } else { + gst_query_set_seeking (query, format, FALSE, 0, -1); + } + res = TRUE; + break; + default: res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); break; @@ -579,7 +593,7 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event) break; } - return TRUE; + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); /* ERRORS */ seek_failed: @@ -587,6 +601,7 @@ seek_failed: GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK, (_("Error while seeking in file \"%s\"."), filesink->filename), GST_ERROR_SYSTEM); + gst_event_unref (event); return FALSE; } flush_failed: @@ -594,6 +609,7 @@ flush_failed: GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE, (_("Error while writing to file \"%s\"."), filesink->filename), GST_ERROR_SYSTEM); + gst_event_unref (event); return FALSE; } } @@ -625,24 +641,23 @@ static GstFlowReturn gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer) { GstFileSink *filesink; - gsize size; - guint8 *data; + GstMapInfo info; filesink = GST_FILE_SINK (sink); - data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ); + gst_buffer_map (buffer, &info, GST_MAP_READ); GST_DEBUG_OBJECT (filesink, "writing %" G_GSIZE_FORMAT " bytes at %" G_GUINT64_FORMAT, - size, filesink->current_pos); + info.size, filesink->current_pos); - if (size > 0 && data != NULL) { - if (fwrite (data, size, 1, filesink->file) != 1) + if (info.size > 0 && info.data != NULL) { + if (fwrite (info.data, info.size, 1, filesink->file) != 1) goto handle_error; - filesink->current_pos += size; + filesink->current_pos += info.size; } - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &info); return GST_FLOW_OK; @@ -659,7 +674,7 @@ handle_error: ("%s", g_strerror (errno))); } } - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &info); return GST_FLOW_ERROR; } } @@ -685,36 +700,31 @@ gst_file_sink_uri_get_type (GType type) return GST_URI_SINK; } -static gchar ** +static const gchar *const * gst_file_sink_uri_get_protocols (GType type) { - static gchar *protocols[] = { (char *) "file", NULL }; + static const gchar *protocols[] = { "file", NULL }; return protocols; } -static const gchar * +static gchar * gst_file_sink_uri_get_uri (GstURIHandler * handler) { GstFileSink *sink = GST_FILE_SINK (handler); - return sink->uri; + /* FIXME: make thread-safe */ + return g_strdup (sink->uri); } static gboolean -gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** error) { - gchar *protocol, *location; + gchar *location; gboolean ret; GstFileSink *sink = GST_FILE_SINK (handler); - protocol = gst_uri_get_protocol (uri); - if (strcmp (protocol, "file") != 0) { - g_free (protocol); - return FALSE; - } - g_free (protocol); - /* allow file://localhost/foo/bar by stripping localhost but fail * for every other hostname */ if (g_str_has_prefix (uri, "file://localhost/")) { @@ -730,20 +740,26 @@ gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) /* Special case for "file://" as this is used by some applications * to test with gst_element_make_from_uri if there's an element * that supports the URI protocol. */ - gst_file_sink_set_location (sink, NULL); + gst_file_sink_set_location (sink, NULL, NULL); return TRUE; } else { location = gst_uri_get_location (uri); } - if (!location) + if (!location) { + g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI without location"); return FALSE; + } + if (!g_path_is_absolute (location)) { + g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI location must be an absolute path"); g_free (location); return FALSE; } - ret = gst_file_sink_set_location (sink, location); + ret = gst_file_sink_set_location (sink, location, error); g_free (location); return ret; diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index 803530f..8f55d1f 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -130,8 +130,7 @@ enum enum { PROP_0, - PROP_LOCATION, - PROP_FD + PROP_LOCATION }; static void gst_file_src_finalize (GObject * object); @@ -173,10 +172,6 @@ gst_file_src_class_init (GstFileSrcClass * klass) gobject_class->set_property = gst_file_src_set_property; gobject_class->get_property = gst_file_src_get_property; - g_object_class_install_property (gobject_class, PROP_FD, - g_param_spec_int ("fd", "File-descriptor", - "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_LOCATION, g_param_spec_string ("location", "File Location", "Location of the file to read", NULL, @@ -185,7 +180,7 @@ gst_file_src_class_init (GstFileSrcClass * klass) gobject_class->finalize = gst_file_src_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "File Source", "Source/File", "Read from arbitrary point in a file", @@ -214,6 +209,8 @@ gst_file_src_init (GstFileSrc * src) src->uri = NULL; src->is_regular = FALSE; + + gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE); } static void @@ -257,7 +254,7 @@ gst_file_src_set_location (GstFileSrc * src, const gchar * location) GST_INFO ("uri : %s", src->uri); } g_object_notify (G_OBJECT (src), "location"); - gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri); + /* FIXME 0.11: notify "uri" property once there is one */ return TRUE; @@ -305,9 +302,6 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_LOCATION: g_value_set_string (value, src->filename); break; - case PROP_FD: - g_value_set_int (value, src->fd); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -329,7 +323,9 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer * buf) { GstFileSrc *src; + guint to_read, bytes_read; int ret; + GstMapInfo info; guint8 *data; src = GST_FILE_SRC_CAST (basesrc); @@ -344,31 +340,42 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, src->read_position = offset; } - data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); - - GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", - length, offset); - - ret = read (src->fd, data, length); - if (G_UNLIKELY (ret < 0)) - goto could_not_read; + gst_buffer_map (buf, &info, GST_MAP_WRITE); + data = info.data; + + bytes_read = 0; + to_read = length; + while (to_read > 0) { + GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", + to_read, offset + bytes_read); + errno = 0; + ret = read (src->fd, data + bytes_read, to_read); + if (G_UNLIKELY (ret < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + goto could_not_read; + } - /* seekable regular files should have given us what we expected */ - if (G_UNLIKELY ((guint) ret < length && src->seekable)) - goto unexpected_eos; + /* files should eos if they read 0 and more was requested */ + if (G_UNLIKELY (ret == 0)) { + /* .. but first we should return any remaining data */ + if (bytes_read > 0) + break; + goto eos; + } - /* other files should eos if they read 0 and more was requested */ - if (G_UNLIKELY (ret == 0)) - goto eos; + to_read -= ret; + bytes_read += ret; - length = ret; + src->read_position += ret; + } - gst_buffer_unmap (buf, data, length); + gst_buffer_unmap (buf, &info); + if (bytes_read != length) + gst_buffer_resize (buf, 0, bytes_read); GST_BUFFER_OFFSET (buf) = offset; - GST_BUFFER_OFFSET_END (buf) = offset + length; - - src->read_position += length; + GST_BUFFER_OFFSET_END (buf) = offset + bytes_read; return GST_FLOW_OK; @@ -381,21 +388,16 @@ seek_failed: could_not_read: { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); - gst_buffer_unmap (buf, data, 0); - return GST_FLOW_ERROR; - } -unexpected_eos: - { - GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), - ("unexpected end of file.")); - gst_buffer_unmap (buf, data, 0); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, 0); return GST_FLOW_ERROR; } eos: { - GST_DEBUG ("non-regular file hits EOS"); - gst_buffer_unmap (buf, data, 0); - return GST_FLOW_UNEXPECTED; + GST_DEBUG ("EOS"); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, 0); + return GST_FLOW_EOS; } } @@ -518,7 +520,7 @@ no_filename: { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (_("No file name specified for reading.")), (NULL)); - return FALSE; + goto error_exit; } open_failed: { @@ -533,29 +535,30 @@ open_failed: GST_ERROR_SYSTEM); break; } - return FALSE; + goto error_exit; } no_stat: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("Could not get info on \"%s\"."), src->filename), (NULL)); - close (src->fd); - return FALSE; + goto error_close; } was_directory: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("\"%s\" is a directory."), src->filename), (NULL)); - close (src->fd); - return FALSE; + goto error_close; } was_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("File \"%s\" is a socket."), src->filename), (NULL)); - close (src->fd); - return FALSE; + goto error_close; } +error_close: + close (src->fd); +error_exit: + return FALSE; } /* unmap and close the file */ @@ -582,29 +585,30 @@ gst_file_src_uri_get_type (GType type) return GST_URI_SRC; } -static gchar ** +static const gchar *const * gst_file_src_uri_get_protocols (GType type) { - static gchar *protocols[] = { (char *) "file", NULL }; + static const gchar *protocols[] = { "file", NULL }; return protocols; } -static const gchar * +static gchar * gst_file_src_uri_get_uri (GstURIHandler * handler) { GstFileSrc *src = GST_FILE_SRC (handler); - return src->uri; + /* FIXME: make thread-safe */ + return g_strdup (src->uri); } static gboolean -gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, + GError ** err) { gchar *location, *hostname = NULL; gboolean ret = FALSE; GstFileSrc *src = GST_FILE_SRC (handler); - GError *error = NULL; if (strcmp (uri, "file://") == 0) { /* Special case for "file://" as this is used by some applications @@ -614,22 +618,19 @@ gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) return TRUE; } - location = g_filename_from_uri (uri, &hostname, &error); + location = g_filename_from_uri (uri, &hostname, err); - if (!location || error) { - if (error) { - GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri, - error->message); - g_error_free (error); - } else { - GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri); - } + if (!location || (err != NULL && *err != NULL)) { + GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri, + (err != NULL && *err != NULL) ? (*err)->message : "unknown error"); goto beach; } if ((hostname) && (strcmp (hostname, "localhost"))) { /* Only 'localhost' is permitted */ GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname); + g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, + "File URI with invalid hostname '%s'", hostname); goto beach; } #ifdef G_OS_WIN32 diff --git a/plugins/elements/gstfunnel.c b/plugins/elements/gstfunnel.c index 5b37e72..9a9f455 100644 --- a/plugins/elements/gstfunnel.c +++ b/plugins/elements/gstfunnel.c @@ -94,7 +94,7 @@ gst_funnel_pad_init (GstFunnelPad * pad) } static GstStaticPadTemplate funnel_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink%d", +GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); @@ -116,11 +116,15 @@ static GstPad *gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void gst_funnel_release_pad (GstElement * element, GstPad * pad); -static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer); -static gboolean gst_funnel_sink_event (GstPad * pad, GstEvent * event); -static GstCaps *gst_funnel_sink_getcaps (GstPad * pad, GstCaps * filter); +static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_funnel_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_funnel_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static gboolean gst_funnel_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_funnel_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); static void gst_funnel_dispose (GObject * object) @@ -148,7 +152,7 @@ gst_funnel_class_init (GstFunnelClass * klass) gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_funnel_dispose); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Funnel pipe fitting", "Generic", "N-to-1 pipe fitting", "Olivier Crete <olivier.crete@collabora.co.uk>"); @@ -189,8 +193,8 @@ gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_DEBUG_FUNCPTR (gst_funnel_sink_chain)); gst_pad_set_event_function (sinkpad, GST_DEBUG_FUNCPTR (gst_funnel_sink_event)); - gst_pad_set_getcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_funnel_sink_getcaps)); + gst_pad_set_query_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_funnel_sink_query)); gst_pad_set_active (sinkpad, TRUE); @@ -211,29 +215,11 @@ gst_funnel_release_pad (GstElement * element, GstPad * pad) gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad); } -static GstCaps * -gst_funnel_sink_getcaps (GstPad * pad, GstCaps * filter) -{ - GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad)); - GstCaps *caps; - - if (G_UNLIKELY (funnel == NULL)) - return gst_caps_new_any (); - - caps = gst_pad_peer_get_caps (funnel->srcpad, filter); - if (caps == NULL) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - gst_object_unref (funnel); - - return caps; -} - static GstFlowReturn -gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer) +gst_funnel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstFlowReturn res; - GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad)); + GstFunnel *funnel = GST_FUNNEL (parent); GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); GstEvent *event = NULL; GstClockTime newts; @@ -293,24 +279,18 @@ gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer) #if 0 out: #endif - gst_object_unref (funnel); return res; } static gboolean -gst_funnel_sink_event (GstPad * pad, GstEvent * event) +gst_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { - GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad)); + GstFunnel *funnel = GST_FUNNEL (parent); GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); gboolean forward = TRUE; gboolean res = TRUE; - if (G_UNLIKELY (funnel == NULL)) { - gst_event_unref (event); - return FALSE; - } - switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: { @@ -338,13 +318,24 @@ gst_funnel_sink_event (GstPad * pad, GstEvent * event) else gst_event_unref (event); - gst_object_unref (funnel); + return res; +} + +static gboolean +gst_funnel_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstFunnel *funnel = GST_FUNNEL (parent); + gboolean forward = TRUE; + gboolean res = TRUE; + + if (forward) + res = gst_pad_peer_query (funnel->srcpad, query); return res; } static gboolean -gst_funnel_src_event (GstPad * pad, GstEvent * event) +gst_funnel_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstElement *funnel; GstIterator *iter; @@ -353,11 +344,7 @@ gst_funnel_src_event (GstPad * pad, GstEvent * event) gboolean done = FALSE; GValue value = { 0, }; - funnel = gst_pad_get_parent_element (pad); - if (G_UNLIKELY (funnel == NULL)) { - gst_event_unref (event); - return FALSE; - } + funnel = GST_ELEMENT_CAST (parent); iter = gst_element_iterate_sink_pads (funnel); @@ -382,7 +369,6 @@ gst_funnel_src_event (GstPad * pad, GstEvent * event) } g_value_unset (&value); gst_iterator_free (iter); - gst_object_unref (funnel); gst_event_unref (event); return result; diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 460660f..50afaec 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -32,10 +32,10 @@ #endif #include <stdlib.h> +#include <string.h> #include "../../gst/gst-i18n-lib.h" #include "gstidentity.h" -#include <gst/gstmarshal.h> static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -63,7 +63,7 @@ enum #define DEFAULT_ERROR_AFTER -1 #define DEFAULT_DROP_PROBABILITY 0.0 #define DEFAULT_DATARATE 0 -#define DEFAULT_SILENT FALSE +#define DEFAULT_SILENT TRUE #define DEFAULT_SINGLE_SEGMENT FALSE #define DEFAULT_DUMP FALSE #define DEFAULT_SYNC FALSE @@ -107,10 +107,10 @@ static gboolean gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event); static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf); -static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform * - trans, GstBuffer * in_buf, GstBuffer ** out_buf); static gboolean gst_identity_start (GstBaseTransform * trans); static gboolean gst_identity_stop (GstBaseTransform * trans); +static GstStateChangeReturn gst_identity_change_state (GstElement * element, + GstStateChange transition); static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; @@ -125,41 +125,9 @@ gst_identity_finalize (GObject * object) g_free (identity->last_message); -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_free (&identity->notify_lock); -#endif - G_OBJECT_CLASS (parent_class)->finalize (object); } -/* fixme: do something about this */ -static void -marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value, - guint n_param_values, const GValue * param_values, gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1, - gpointer data2); - register marshalfunc_VOID__MINIOBJECT callback; - register GCClosure *cc = (GCClosure *) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA (closure)) { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } else { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = - (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : - cc->callback); - - callback (data1, g_value_get_boxed (param_values + 1), data2); -} - static void gst_identity_class_init (GstIdentityClass * klass) { @@ -254,11 +222,12 @@ gst_identity_class_init (GstIdentityClass * klass) gst_identity_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL, - marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_BUFFER); + g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); gobject_class->finalize = gst_identity_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Identity", "Generic", "Pass data without modification", "Erik Walthinsen <omega@cse.ogi.edu>"); @@ -267,11 +236,12 @@ gst_identity_class_init (GstIdentityClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate)); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_identity_change_state); + gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_identity_sink_event); gstbasetrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_identity_transform_ip); - gstbasetrans_class->prepare_output_buffer = - GST_DEBUG_FUNCPTR (gst_identity_prepare_output_buffer); gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start); gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop); } @@ -293,29 +263,13 @@ gst_identity_init (GstIdentity * identity) identity->last_message = NULL; identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_init (&identity->notify_lock); -#endif - gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE); } static void gst_identity_notify_last_message (GstIdentity * identity) { - /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent - * g_object_notify() on the same object might lead to crashes, see - * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups. - * So we really don't want to do a g_object_notify() here for out-of-band - * events with the streaming thread possibly also doing a g_object_notify() - * for an in-band buffer or event. This is fixed in GLib >= 2.26 */ -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_lock (&identity->notify_lock); - g_object_notify ((GObject *) identity, "last-message"); - g_static_rec_mutex_unlock (&identity->notify_lock); -#else g_object_notify_by_pspec ((GObject *) identity, pspec_last_message); -#endif } static gboolean @@ -328,20 +282,22 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) if (!identity->silent) { const GstStructure *s; + const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (identity); g_free (identity->last_message); + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); identity->last_message = - g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p", - GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), sstr, - event); + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (trans->sinkpad), tstr, GST_EVENT_TYPE (event), + sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (identity); @@ -361,7 +317,7 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) gst_segment_init (&segment, segment.format); news = gst_event_new_segment (&segment); - gst_pad_event_default (trans->sinkpad, news); + gst_pad_event_default (trans->sinkpad, GST_OBJECT_CAST (trans), news); } } @@ -372,39 +328,28 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE; } - - if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) { + if (identity->single_segment && GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { /* eat up segments */ gst_event_unref (event); ret = TRUE; } else { + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) { + GST_OBJECT_LOCK (identity); + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + gst_clock_id_unref (identity->clock_id); + identity->clock_id = NULL; + } + GST_OBJECT_UNLOCK (identity); + } + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); } return ret; } -static GstFlowReturn -gst_identity_prepare_output_buffer (GstBaseTransform * trans, - GstBuffer * in_buf, GstBuffer ** out_buf) -{ - GstIdentity *identity = GST_IDENTITY (trans); - - /* only bother if we may have to alter metadata */ - if (identity->datarate > 0 || identity->single_segment) { - if (gst_buffer_is_writable (in_buf)) - /* reuse */ - *out_buf = in_buf; - else { - /* copy */ - *out_buf = gst_buffer_copy (in_buf); - } - } else - *out_buf = in_buf; - - return GST_FLOW_OK; -} - static void gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf) { @@ -559,19 +504,41 @@ static void gst_identity_update_last_message_for_buffer (GstIdentity * identity, const gchar * action, GstBuffer * buf, gsize size) { - gchar ts_str[64], dur_str[64]; + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar flag_str[100]; GST_OBJECT_LOCK (identity); + { + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" + }; + int i; + char *end = flag_str; + end[0] = '\0'; + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { + if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { + strcpy (end, flag_list[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + } + g_free (identity->last_message); - identity->last_message = g_strdup_printf ("%s ******* (%s:%s)i " - "(%" G_GSIZE_FORMAT " bytes, timestamp: %s, duration: %s, offset: %" - G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - action, GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), - size, print_pretty_time (ts_str, sizeof (ts_str), - GST_BUFFER_TIMESTAMP (buf)), print_pretty_time (dur_str, - sizeof (dur_str), GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + identity->last_message = g_strdup_printf ("%s ******* (%s:%s) " + "(%" G_GSIZE_FORMAT " bytes, dts: %s, pts:%s, duration: %s, offset: %" + G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT + ", flags: %d %s) %p", action, + GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size, + print_pretty_time (dts_str, sizeof (dts_str), GST_BUFFER_DTS (buf)), + print_pretty_time (pts_str, sizeof (pts_str), GST_BUFFER_PTS (buf)), + print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_BUFFER_FLAGS (buf), flag_str, buf); GST_OBJECT_UNLOCK (identity); @@ -584,10 +551,9 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) GstFlowReturn ret = GST_FLOW_OK; GstIdentity *identity = GST_IDENTITY (trans); GstClockTime runtimestamp = G_GINT64_CONSTANT (0); - guint8 *data; gsize size; - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + size = gst_buffer_get_size (buf); if (identity->check_perfect) gst_identity_check_perfect (identity, buf); @@ -614,7 +580,11 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) } if (identity->dump) { - gst_util_dump_mem (data, size); + GstMapInfo info; + + gst_buffer_map (buf, &info, GST_MAP_READ); + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); } if (!identity->silent) { @@ -647,7 +617,6 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) timestamp = runtimestamp + GST_ELEMENT (identity)->base_time; /* save id if we need to unlock */ - /* FIXME: actually unlock this somewhere in the state changes */ identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp); GST_OBJECT_UNLOCK (identity); @@ -659,7 +628,7 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) identity->clock_id = NULL; } if (cret == GST_CLOCK_UNSCHEDULED) - ret = GST_FLOW_UNEXPECTED; + ret = GST_FLOW_EOS; } GST_OBJECT_UNLOCK (identity); } @@ -676,8 +645,6 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE; } - gst_buffer_unmap (buf, data, size); - return ret; /* ERRORS */ @@ -685,7 +652,6 @@ error_after: { GST_ELEMENT_ERROR (identity, CORE, FAILED, (_("Failed after iterations as requested.")), (NULL)); - gst_buffer_unmap (buf, data, size); return GST_FLOW_ERROR; } dropped: @@ -694,7 +660,6 @@ dropped: gst_identity_update_last_message_for_buffer (identity, "dropping", buf, size); } - gst_buffer_unmap (buf, data, size); /* return DROPPED to basetransform. */ return GST_BASE_TRANSFORM_FLOW_DROPPED; } @@ -749,6 +714,10 @@ gst_identity_set_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + if (identity->datarate > 0 || identity->single_segment) + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), FALSE); + else + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE); } static void @@ -837,3 +806,46 @@ gst_identity_stop (GstBaseTransform * trans) return TRUE; } + +static GstStateChangeReturn +gst_identity_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstIdentity *identity = GST_IDENTITY (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_OBJECT_LOCK (identity); + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + gst_clock_id_unref (identity->clock_id); + identity->clock_id = NULL; + } + GST_OBJECT_UNLOCK (identity); + break; + default: + break; + } + + 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: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} diff --git a/plugins/elements/gstidentity.h b/plugins/elements/gstidentity.h index a608d2b..fabc667 100644 --- a/plugins/elements/gstidentity.h +++ b/plugins/elements/gstidentity.h @@ -73,10 +73,6 @@ struct _GstIdentity { gchar *last_message; guint64 offset; gboolean signal_handoffs; - -#if !GLIB_CHECK_VERSION(2,26,0) - GStaticRecMutex notify_lock; -#endif }; struct _GstIdentityClass { diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c index 7235a47..564e721 100644 --- a/plugins/elements/gstinputselector.c +++ b/plugins/elements/gstinputselector.c @@ -59,28 +59,13 @@ #include "gstinputselector.h" +#include "gst/glib-compat-private.h" + GST_DEBUG_CATEGORY_STATIC (input_selector_debug); #define GST_CAT_DEFAULT input_selector_debug -#if GLIB_CHECK_VERSION(2, 26, 0) -#define NOTIFY_MUTEX_LOCK() -#define NOTIFY_MUTEX_UNLOCK() -#else -static GStaticRecMutex notify_mutex = G_STATIC_REC_MUTEX_INIT; -#define NOTIFY_MUTEX_LOCK() g_static_rec_mutex_lock (¬ify_mutex) -#define NOTIFY_MUTEX_UNLOCK() g_static_rec_mutex_unlock (¬ify_mutex) -#endif - -#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock) -#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond) -#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ - GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) - static GstStaticPadTemplate gst_input_selector_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink%d", +GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); @@ -99,7 +84,7 @@ enum PROP_SYNC_STREAMS }; -#define DEFAULT_SYNC_STREAMS FALSE +#define DEFAULT_SYNC_STREAMS TRUE #define DEFAULT_PAD_ALWAYS_OK TRUE @@ -178,11 +163,14 @@ static void gst_selector_pad_set_property (GObject * object, static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); static void gst_selector_pad_reset (GstSelectorPad * pad); -static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); -static GstCaps *gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter); -static gboolean gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps); -static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad); -static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_selector_pad_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_selector_pad_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad, + GstObject * parent); +static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstObject * parent, + GstBuffer * buf); G_DEFINE_TYPE (GstSelectorPad, gst_selector_pad, GST_TYPE_PAD); @@ -330,16 +318,14 @@ gst_selector_pad_reset (GstSelectorPad * pad) /* strictly get the linked pad from the sinkpad. If the pad is active we return * the srcpad else we return NULL */ static GstIterator * -gst_selector_pad_iterate_linked_pads (GstPad * pad) +gst_selector_pad_iterate_linked_pads (GstPad * pad, GstObject * parent) { GstInputSelector *sel; GstPad *otherpad; GstIterator *it = NULL; GValue val = { 0, }; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return NULL; + sel = GST_INPUT_SELECTOR (parent); otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE); if (otherpad) { @@ -349,13 +335,12 @@ gst_selector_pad_iterate_linked_pads (GstPad * pad) g_value_unset (&val); gst_object_unref (otherpad); } - gst_object_unref (sel); return it; } static gboolean -gst_selector_pad_event (GstPad * pad, GstEvent * event) +gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; gboolean forward; @@ -364,11 +349,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) GstPad *prev_active_sinkpad; GstPad *active_sinkpad; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) { - gst_event_unref (event); - return FALSE; - } + sel = GST_INPUT_SELECTOR (parent); selpad = GST_SELECTOR_PAD_CAST (pad); GST_INPUT_SELECTOR_LOCK (sel); @@ -380,9 +361,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) GST_INPUT_SELECTOR_UNLOCK (sel); if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) { - NOTIFY_MUTEX_LOCK (); g_object_notify (G_OBJECT (sel), "active-pad"); - NOTIFY_MUTEX_UNLOCK (); } switch (GST_EVENT_TYPE (event)) { @@ -486,44 +465,19 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) } else gst_event_unref (event); - gst_object_unref (sel); - return res; } -static GstCaps * -gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter) -{ - GstInputSelector *sel; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer"); - caps = gst_pad_peer_get_caps (sel->srcpad, filter); - if (caps == NULL) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - gst_object_unref (sel); - - return caps; -} - static gboolean -gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps) +gst_selector_pad_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstInputSelector *sel; - gboolean res; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return FALSE; + gboolean res = FALSE; - GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer"); - res = gst_pad_peer_accept_caps (sel->srcpad, caps); - gst_object_unref (sel); + switch (GST_QUERY_TYPE (query)) { + default: + res = gst_pad_query_default (pad, parent, query); + break; + } return res; } @@ -550,7 +504,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, GstPad *active_sinkpad; GstSelectorPad *active_selpad; GstSegment *seg, *active_seg; - GstClockTime running_time, active_running_time = -1; + GstClockTime running_time, active_running_time = GST_CLOCK_TIME_NONE; seg = &pad->segment; @@ -595,9 +549,10 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, * d) the active pad has no running time or the active * pad's running time is before this running time * e) the active pad has a non-time segment + * f) the active pad changed and has not pushed anything */ - while (pad != active_selpad && !sel->flushing && !pad->flushing && - (sel->blocked || active_running_time == -1 + while (pad != active_selpad && !sel->flushing && !pad->flushing + && active_selpad->pushed && (sel->blocked || active_running_time == -1 || running_time >= active_running_time)) { if (!sel->blocked) GST_DEBUG_OBJECT (pad, @@ -641,7 +596,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, static GstFlowReturn -gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) +gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstInputSelector *sel; GstFlowReturn res; @@ -652,7 +607,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) GstSegment *seg; GstEvent *start_event = NULL; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + sel = GST_INPUT_SELECTOR (parent); selpad = GST_SELECTOR_PAD_CAST (pad); seg = &selpad->segment; @@ -701,23 +656,24 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) /* if we have a pending segment, push it out now */ if (G_UNLIKELY (prev_active_sinkpad != active_sinkpad || selpad->segment_pending)) { - GST_DEBUG_OBJECT (pad, - "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, - seg->start, seg->stop, seg->time); - - start_event = gst_event_new_segment (seg); - gst_event_set_seqnum (start_event, selpad->segment_seqnum); - - selpad->segment_pending = FALSE; + if (G_UNLIKELY (seg->format == GST_FORMAT_UNDEFINED)) { + GST_ERROR_OBJECT (pad, "Buffers arrived before NEWSEGMENT event"); + } else { + GST_DEBUG_OBJECT (pad, + "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, + seg->start, seg->stop, seg->time); + + start_event = gst_event_new_segment (seg); + gst_event_set_seqnum (start_event, selpad->segment_seqnum); + selpad->segment_pending = FALSE; + } } GST_INPUT_SELECTOR_UNLOCK (sel); if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) { - NOTIFY_MUTEX_LOCK (); g_object_notify (G_OBJECT (sel), "active-pad"); - NOTIFY_MUTEX_UNLOCK (); } if (start_event) @@ -738,7 +694,6 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) selpad->pushed = TRUE; done: - gst_object_unref (sel); return res; /* dropped buffers */ @@ -767,12 +722,13 @@ flushing: GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf); GST_INPUT_SELECTOR_UNLOCK (sel); gst_buffer_unref (buf); - res = GST_FLOW_WRONG_STATE; + res = GST_FLOW_FLUSHING; goto done; } } static void gst_input_selector_dispose (GObject * object); +static void gst_input_selector_finalize (GObject * object); static void gst_input_selector_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -786,9 +742,10 @@ static void gst_input_selector_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn gst_input_selector_change_state (GstElement * element, GstStateChange transition); -static GstCaps *gst_input_selector_getcaps (GstPad * pad, GstCaps * filter); -static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event); -static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query); +static gboolean gst_input_selector_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_input_selector_query (GstPad * pad, GstObject * parent, + GstQuery * query); static gint64 gst_input_selector_block (GstInputSelector * self); /* FIXME: create these marshallers using glib-genmarshal */ @@ -837,6 +794,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); gobject_class->dispose = gst_input_selector_dispose; + gobject_class->finalize = gst_input_selector_finalize; gobject_class->set_property = gst_input_selector_set_property; gobject_class->get_property = gst_input_selector_get_property; @@ -859,7 +817,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) * buffers are dropped by input-selector that might be needed * when switching the active pad. * - * Since: 0.10.35 + * Since: 0.10.36 */ g_object_class_install_property (gobject_class, PROP_SYNC_STREAMS, g_param_spec_boolean ("sync-streams", "Sync Streams", @@ -880,7 +838,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL, gst_input_selector_marshal_INT64__VOID, G_TYPE_INT64, 0); - gst_element_class_set_details_simple (gstelement_class, "Input selector", + gst_element_class_set_static_metadata (gstelement_class, "Input selector", "Generic", "N-to-1 input stream selector", "Julien Moutte <julien@moutte.net>, " "Jan Schmidt <thaytan@mad.scientist.com>, " @@ -903,20 +861,19 @@ gst_input_selector_init (GstInputSelector * sel) sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); gst_pad_set_iterate_internal_links_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); - gst_pad_set_getcaps_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_input_selector_getcaps)); gst_pad_set_query_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_input_selector_query)); gst_pad_set_event_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_input_selector_event)); + GST_OBJECT_FLAG_SET (sel->srcpad, GST_PAD_FLAG_PROXY_CAPS); gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); /* sinkpad management */ sel->active_sinkpad = NULL; sel->padcount = 0; sel->sync_streams = DEFAULT_SYNC_STREAMS; - sel->lock = g_mutex_new (); - sel->cond = g_cond_new (); + g_mutex_init (&sel->lock); + g_cond_init (&sel->cond); sel->blocked = FALSE; } @@ -929,18 +886,20 @@ gst_input_selector_dispose (GObject * object) gst_object_unref (sel->active_sinkpad); sel->active_sinkpad = NULL; } - if (sel->lock) { - g_mutex_free (sel->lock); - sel->lock = NULL; - } - if (sel->cond) { - g_cond_free (sel->cond); - sel->cond = NULL; - } - G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_input_selector_finalize (GObject * object) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + g_mutex_clear (&sel->lock); + g_cond_clear (&sel->cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + /* this function must be called with the SELECTOR_LOCK. It returns TRUE when the * active pad changed. */ static gboolean @@ -1059,7 +1018,7 @@ gst_input_selector_get_linked_pad (GstInputSelector * sel, GstPad * pad, } static gboolean -gst_input_selector_event (GstPad * pad, GstEvent * event) +gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstInputSelector *sel; gboolean result = FALSE; @@ -1069,12 +1028,7 @@ gst_input_selector_event (GstPad * pad, GstEvent * event) GstPad *eventpad; GList *pushed_pads = NULL; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) { - gst_event_unref (event); - return FALSE; - } - + sel = GST_INPUT_SELECTOR (parent); /* Send upstream events to all sinkpads */ iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel)); @@ -1124,17 +1078,12 @@ gst_input_selector_event (GstPad * pad, GstEvent * event) /* query on the srcpad. We override this function because by default it will * only forward the query to one random sinkpad */ static gboolean -gst_input_selector_query (GstPad * pad, GstQuery * query) +gst_input_selector_query (GstPad * pad, GstObject * parent, GstQuery * query) { - gboolean res = TRUE; + gboolean res = FALSE; GstInputSelector *sel; - GstPad *otherpad; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return FALSE; - otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE); + sel = GST_INPUT_SELECTOR (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: @@ -1147,9 +1096,6 @@ gst_input_selector_query (GstPad * pad, GstQuery * query) resmax = -1; reslive = FALSE; - /* assume FALSE, we become TRUE if one query succeeds */ - res = FALSE; - /* perform the query on all sinkpads and combine the results. We take the * max of min and the min of max for the result latency. */ GST_INPUT_SELECTOR_LOCK (sel); @@ -1195,47 +1141,13 @@ gst_input_selector_query (GstPad * pad, GstQuery * query) break; } default: - if (otherpad) - res = gst_pad_peer_query (otherpad, query); + res = gst_pad_query_default (pad, parent, query); break; } - if (otherpad) - gst_object_unref (otherpad); - gst_object_unref (sel); return res; } -static GstCaps * -gst_input_selector_getcaps (GstPad * pad, GstCaps * filter) -{ - GstPad *otherpad; - GstInputSelector *sel; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - otherpad = gst_input_selector_get_linked_pad (sel, pad, FALSE); - - if (!otherpad) { - GST_DEBUG_OBJECT (pad, "Pad not linked, returning ANY"); - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - } else { - GST_DEBUG_OBJECT (pad, "Pad is linked (to %s:%s), returning peer caps", - GST_DEBUG_PAD_NAME (otherpad)); - /* if the peer has caps, use those. If the pad is not linked, this function - * returns NULL and we return ANY */ - if (!(caps = gst_pad_peer_get_caps (otherpad, filter))) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - gst_object_unref (otherpad); - } - - gst_object_unref (sel); - return caps; -} - /* check if the pad is the active sinkpad */ static inline gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) @@ -1286,7 +1198,7 @@ gst_input_selector_request_new_pad (GstElement * element, GST_INPUT_SELECTOR_LOCK (sel); GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount); - name = g_strdup_printf ("sink%d", sel->padcount++); + name = g_strdup_printf ("sink_%u", sel->padcount++); sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, "name", name, "direction", templ->direction, "template", templ, NULL); g_free (name); @@ -1295,15 +1207,15 @@ gst_input_selector_request_new_pad (GstElement * element, gst_pad_set_event_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_event)); - gst_pad_set_getcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps)); - gst_pad_set_acceptcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_acceptcaps)); + gst_pad_set_query_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_query)); gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_chain)); gst_pad_set_iterate_internal_links_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); gst_pad_set_active (sinkpad, TRUE); gst_element_add_pad (GST_ELEMENT (sel), sinkpad); GST_INPUT_SELECTOR_UNLOCK (sel); diff --git a/plugins/elements/gstinputselector.h b/plugins/elements/gstinputselector.h index 116c31c..8a5248a 100644 --- a/plugins/elements/gstinputselector.h +++ b/plugins/elements/gstinputselector.h @@ -40,8 +40,8 @@ G_BEGIN_DECLS typedef struct _GstInputSelector GstInputSelector; typedef struct _GstInputSelectorClass GstInputSelectorClass; -#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock) -#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond) +#define GST_INPUT_SELECTOR_GET_LOCK(sel) (&((GstInputSelector*)(sel))->lock) +#define GST_INPUT_SELECTOR_GET_COND(sel) (&((GstInputSelector*)(sel))->cond) #define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) #define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) #define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ @@ -58,8 +58,8 @@ struct _GstInputSelector { guint padcount; gboolean sync_streams; - GMutex *lock; - GCond *cond; + GMutex lock; + GCond cond; gboolean blocked; gboolean flushing; }; diff --git a/plugins/elements/gstmultiqueue.c b/plugins/elements/gstmultiqueue.c index 85083eb..09db153 100644 --- a/plugins/elements/gstmultiqueue.c +++ b/plugins/elements/gstmultiqueue.c @@ -136,6 +136,12 @@ struct _GstSingleQueue /* flowreturn of previous srcpad push */ GstFlowReturn srcresult; + /* If something was actually pushed on + * this pad after flushing/pad activation + * and the srcresult corresponds to something + * real + */ + gboolean pushed; /* segments */ GstSegment sink_segment; @@ -159,7 +165,11 @@ struct _GstSingleQueue guint32 last_oldid; /* Previously observed old_id, reset to MAXUINT32 on flush */ GstClockTime next_time; /* End running time of next buffer to be pushed */ GstClockTime last_time; /* Start running time of last pushed buffer */ - GCond *turn; /* SingleQueue turn waiting conditional */ + GCond turn; /* SingleQueue turn waiting conditional */ + + /* for serialized queries */ + GCond query_handled; + gboolean last_query; }; @@ -177,7 +187,7 @@ struct _GstMultiQueueItem guint32 posid; }; -static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, gint id); +static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, guint id); static void gst_single_queue_free (GstSingleQueue * squeue); static void wake_up_next_non_linked (GstMultiQueue * mq); @@ -186,12 +196,12 @@ static void compute_high_time (GstMultiQueue * mq); static void single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq); static void single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq); -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink%d", +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d", +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); @@ -247,11 +257,11 @@ enum }; #define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ - g_mutex_lock (q->qlock); \ + g_mutex_lock (&q->qlock); \ } G_STMT_END #define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ - g_mutex_unlock (q->qlock); \ + g_mutex_unlock (&q->qlock); \ } G_STMT_END static void gst_multi_queue_finalize (GObject * object); @@ -397,7 +407,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass) * streams by keeping the order in which buffers and events arrived compared * to active and linked streams. * - * Since: 0.10.35 + * Since: 0.10.36 */ g_object_class_install_property (gobject_class, PROP_SYNC_BY_RUNNING_TIME, g_param_spec_boolean ("sync-by-running-time", "Sync By Running Time", @@ -407,7 +417,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass) gobject_class->finalize = gst_multi_queue_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "MultiQueue", "Generic", "Multiple data queue", "Edward Hervey <edward@fluendo.com>"); gst_element_class_add_pad_template (gstelement_class, @@ -447,7 +457,7 @@ gst_multi_queue_init (GstMultiQueue * mqueue) mqueue->highid = -1; mqueue->high_time = GST_CLOCK_TIME_NONE; - mqueue->qlock = g_mutex_new (); + g_mutex_init (&mqueue->qlock); } static void @@ -461,7 +471,7 @@ gst_multi_queue_finalize (GObject * object) mqueue->queues_cookie++; /* free/unref instance data */ - g_mutex_free (mqueue->qlock); + g_mutex_clear (&mqueue->qlock); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -575,12 +585,12 @@ gst_multi_queue_get_property (GObject * object, guint prop_id, } static GstIterator * -gst_multi_queue_iterate_internal_links (GstPad * pad) +gst_multi_queue_iterate_internal_links (GstPad * pad, GstObject * parent) { GstIterator *it = NULL; GstPad *opad; GstSingleQueue *squeue; - GstMultiQueue *mq = GST_MULTI_QUEUE (gst_pad_get_parent (pad)); + GstMultiQueue *mq = GST_MULTI_QUEUE (parent); GValue val = { 0, }; GST_MULTI_QUEUE_MUTEX_LOCK (mq); @@ -604,7 +614,6 @@ gst_multi_queue_iterate_internal_links (GstPad * pad) out: GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); - gst_object_unref (mq); return it; } @@ -620,10 +629,10 @@ gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp, { GstMultiQueue *mqueue = GST_MULTI_QUEUE (element); GstSingleQueue *squeue; - gint temp_id = -1; + guint temp_id = -1; if (name) { - sscanf (name + 4, "%d", &temp_id); + sscanf (name + 4, "_%u", &temp_id); GST_LOG_OBJECT (element, "name : %s (id %d)", GST_STR_NULL (name), temp_id); } @@ -710,7 +719,7 @@ gst_multi_queue_change_state (GstElement * element, GstStateChange transition) for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) { sq = (GstSingleQueue *) tmp->data; sq->flushing = TRUE; - g_cond_signal (sq->turn); + g_cond_signal (&sq->turn); } GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue); break; @@ -741,27 +750,32 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush) sq->id); if (flush) { - sq->srcresult = GST_FLOW_WRONG_STATE; + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->srcresult = GST_FLOW_FLUSHING; gst_data_queue_set_flushing (sq->queue, TRUE); sq->flushing = TRUE; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); /* wake up non-linked task */ GST_LOG_OBJECT (mq, "SingleQueue %d : waking up eventually waiting task", sq->id); - GST_MULTI_QUEUE_MUTEX_LOCK (mq); - g_cond_signal (sq->turn); + g_cond_signal (&sq->turn); + sq->last_query = FALSE; + g_cond_signal (&sq->query_handled); GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); GST_LOG_OBJECT (mq, "SingleQueue %d : pausing task", sq->id); result = gst_pad_pause_task (sq->srcpad); sq->sink_tainted = sq->src_tainted = TRUE; } else { + GST_MULTI_QUEUE_MUTEX_LOCK (mq); gst_data_queue_flush (sq->queue); gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME); gst_segment_init (&sq->src_segment, GST_FORMAT_TIME); /* All pads start off not-linked for a smooth kick-off */ sq->srcresult = GST_FLOW_OK; + sq->pushed = FALSE; sq->cur_time = 0; sq->max_size.visible = mq->max_size.visible; sq->is_eos = FALSE; @@ -773,11 +787,10 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush) gst_data_queue_set_flushing (sq->queue, FALSE); /* Reset high time to be recomputed next */ - GST_MULTI_QUEUE_MUTEX_LOCK (mq); mq->high_time = GST_CLOCK_TIME_NONE; - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); sq->flushing = FALSE; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id); result = @@ -991,7 +1004,7 @@ get_running_time (GstSegment * segment, GstMiniObject * object, gboolean end) gint i, n; GstBuffer *buf; - n = gst_buffer_list_len (list); + n = gst_buffer_list_length (list); for (i = 0; i < n; i++) { buf = gst_buffer_list_get (list, i); if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { @@ -1036,16 +1049,10 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq, if (GST_IS_BUFFER (object)) { GstBuffer *buffer; GstClockTime timestamp, duration; -#if 0 - GstCaps *caps; -#endif buffer = GST_BUFFER_CAST (object); timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); -#if 0 - caps = GST_BUFFER_CAPS (buffer); -#endif apply_buffer (mq, sq, timestamp, duration, &sq->src_segment); @@ -1056,14 +1063,6 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq, "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT, sq->id, buffer, GST_TIME_ARGS (timestamp)); -#if 0 - /* Set caps on pad before pushing, this avoids core calling the acceptcaps - * function on the srcpad, which will call acceptcaps upstream, which might - * not accept these caps (anymore). */ - if (caps && caps != GST_PAD_CAPS (sq->srcpad)) - gst_pad_set_caps (sq->srcpad, caps); -#endif - result = gst_pad_push (sq->srcpad, buffer); } else if (GST_IS_EVENT (object)) { GstEvent *event; @@ -1072,7 +1071,7 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq, switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: - result = GST_FLOW_UNEXPECTED; + result = GST_FLOW_EOS; break; case GST_EVENT_SEGMENT: apply_segment (mq, sq, event, &sq->src_segment); @@ -1088,6 +1087,18 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq, sq->id, event, GST_EVENT_TYPE_NAME (event)); gst_pad_push_event (sq->srcpad, event); + } else if (GST_IS_QUERY (object)) { + GstQuery *query; + gboolean res; + + query = GST_QUERY_CAST (object); + + res = gst_pad_peer_query (sq->srcpad, query); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + sq->last_query = res; + g_cond_signal (&sq->query_handled); + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); } else { g_warning ("Unexpected object in singlequeue %d (refcounting problem?)", sq->id); @@ -1136,7 +1147,7 @@ gst_multi_queue_buffer_item_new (GstMiniObject * object, guint32 curid) } static GstMultiQueueItem * -gst_multi_queue_event_item_new (GstMiniObject * object, guint32 curid) +gst_multi_queue_mo_item_new (GstMiniObject * object, guint32 curid) { GstMultiQueueItem *item; @@ -1166,6 +1177,7 @@ gst_multi_queue_loop (GstPad * pad) guint32 newid; GstFlowReturn result; GstClockTime next_time; + gboolean is_buffer; sq = (GstSingleQueue *) gst_pad_get_element_private (pad); mq = sq->mqueue; @@ -1187,6 +1199,8 @@ gst_multi_queue_loop (GstPad * pad) object = gst_multi_queue_item_steal_object (item); gst_multi_queue_item_destroy (item); + is_buffer = GST_IS_BUFFER (object); + /* Get running time of the item. Events will have GST_CLOCK_TIME_NONE */ next_time = get_running_time (&sq->src_segment, object, TRUE); @@ -1198,14 +1212,13 @@ gst_multi_queue_loop (GstPad * pad) * or it's the first loop, or we just passed the previous highid, * we might need to wake some sleeping pad up, so there's extra work * there too */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); if (sq->srcresult == GST_FLOW_NOT_LINKED || (sq->last_oldid == G_MAXUINT32) || (newid != (sq->last_oldid + 1)) || sq->last_oldid > mq->highid) { GST_LOG_OBJECT (mq, "CHECKING sq->srcresult: %s", gst_flow_get_name (sq->srcresult)); - GST_MULTI_QUEUE_MUTEX_LOCK (mq); - /* Check again if we're flushing after the lock is taken, * the flush flag might have been changed in the meantime */ if (sq->flushing) { @@ -1245,7 +1258,7 @@ gst_multi_queue_loop (GstPad * pad) wake_up_next_non_linked (mq); mq->numwaiting++; - g_cond_wait (sq->turn, mq->qlock); + g_cond_wait (&sq->turn, &mq->qlock); mq->numwaiting--; if (sq->flushing) { @@ -1272,9 +1285,8 @@ gst_multi_queue_loop (GstPad * pad) /* We're done waiting, we can clear the nextid and nexttime */ sq->nextid = 0; sq->next_time = GST_CLOCK_TIME_NONE; - - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); if (sq->flushing) goto out_flushing; @@ -1283,6 +1295,7 @@ gst_multi_queue_loop (GstPad * pad) gst_flow_get_name (sq->srcresult)); /* Update time stats */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); next_time = get_running_time (&sq->src_segment, object, FALSE); if (next_time != GST_CLOCK_TIME_NONE) { if (sq->last_time == GST_CLOCK_TIME_NONE || sq->last_time < next_time) @@ -1293,21 +1306,59 @@ gst_multi_queue_loop (GstPad * pad) wake_up_next_non_linked (mq); } } + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); /* Try to push out the new object */ result = gst_single_queue_push_one (mq, sq, object); - sq->srcresult = result; object = NULL; + /* Check if we pushed something already and if this is + * now a switch from an active to a non-active stream. + * + * If it is, we reset all the waiting streams, let them + * push another buffer to see if they're now active again. + * This allows faster switching between streams and prevents + * deadlocks if downstream does any waiting too. + */ + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + if (sq->pushed && sq->srcresult == GST_FLOW_OK + && result == GST_FLOW_NOT_LINKED) { + GList *tmp; + + GST_LOG_OBJECT (mq, "SingleQueue %d : Changed from active to non-active", + sq->id); + + compute_high_id (mq); + + /* maybe no-one is waiting */ + if (mq->numwaiting > 0) { + /* Else figure out which singlequeue(s) need waking up */ + for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) { + GstSingleQueue *sq2 = (GstSingleQueue *) tmp->data; + + if (sq2->srcresult == GST_FLOW_NOT_LINKED) { + GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq2->id); + sq2->pushed = FALSE; + sq2->srcresult = GST_FLOW_OK; + g_cond_signal (&sq2->turn); + } + } + } + } + + if (is_buffer) + sq->pushed = TRUE; + sq->srcresult = result; + sq->last_oldid = newid; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + if (result != GST_FLOW_OK && result != GST_FLOW_NOT_LINKED - && result != GST_FLOW_UNEXPECTED) + && result != GST_FLOW_EOS) goto out_flushing; GST_LOG_OBJECT (mq, "AFTER PUSHING sq->srcresult: %s", gst_flow_get_name (sq->srcresult)); - sq->last_oldid = newid; - return; out_flushing: @@ -1317,6 +1368,7 @@ out_flushing: /* Need to make sure wake up any sleeping pads when we exit */ GST_MULTI_QUEUE_MUTEX_LOCK (mq); + compute_high_time (mq); compute_high_id (mq); wake_up_next_non_linked (mq); GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); @@ -1325,7 +1377,7 @@ out_flushing: * but might be stuck in one of our other full queues; * so empty this one and trigger dynamic queue growth. At * this point the srcresult is not OK, NOT_LINKED - * or UNEXPECTED, i.e. a real failure */ + * or EOS, i.e. a real failure */ gst_data_queue_flush (sq->queue); single_queue_underrun_cb (sq->queue, sq); gst_data_queue_set_flushing (sq->queue, TRUE); @@ -1345,7 +1397,7 @@ out_flushing: * _ we push with a unique id (curid) */ static GstFlowReturn -gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer) +gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstSingleQueue *sq; GstMultiQueue *mq; @@ -1361,7 +1413,7 @@ gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer) goto was_eos; /* Get a unique incrementing id */ - curid = G_ATOMIC_INT_ADD ((gint *) & mq->counter, 1); + curid = g_atomic_int_add ((gint *) & mq->counter, 1); GST_LOG_OBJECT (mq, "SingleQueue %d : about to enqueue buffer %p with id %d", sq->id, buffer, curid); @@ -1391,31 +1443,55 @@ flushing: } was_eos: { - GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return UNEXPECTED"); + GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return EOS"); gst_buffer_unref (buffer); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } } static gboolean -gst_multi_queue_sink_activate_push (GstPad * pad, gboolean active) +gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { + gboolean res; GstSingleQueue *sq; + GstMultiQueue *mq; sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = (GstMultiQueue *) gst_pad_get_parent (pad); - if (active) { - /* All pads start off linked until they push one buffer */ - sq->srcresult = GST_FLOW_OK; - } else { - sq->srcresult = GST_FLOW_WRONG_STATE; - gst_data_queue_flush (sq->queue); + /* mq is NULL if the pad is activated/deactivated before being + * added to the multiqueue */ + if (mq) + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + /* All pads start off linked until they push one buffer */ + sq->srcresult = GST_FLOW_OK; + sq->pushed = FALSE; + } else { + sq->srcresult = GST_FLOW_FLUSHING; + gst_data_queue_flush (sq->queue); + } + res = TRUE; + break; + default: + res = FALSE; + break; + } + + if (mq) { + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + gst_object_unref (mq); } - return TRUE; + + return res; } static gboolean -gst_multi_queue_sink_event (GstPad * pad, GstEvent * event) +gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstSingleQueue *sq; GstMultiQueue *mq; @@ -1426,7 +1502,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event) GstEvent *sref = NULL; sq = (GstSingleQueue *) gst_pad_get_element_private (pad); - mq = (GstMultiQueue *) gst_pad_get_parent (pad); + mq = (GstMultiQueue *) parent; type = GST_EVENT_TYPE (event); @@ -1467,9 +1543,9 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event) goto was_eos; /* Get an unique incrementing id. */ - curid = G_ATOMIC_INT_ADD ((gint *) & mq->counter, 1); + curid = g_atomic_int_add ((gint *) & mq->counter, 1); - item = gst_multi_queue_event_item_new ((GstMiniObject *) event, curid); + item = gst_multi_queue_mo_item_new ((GstMiniObject *) event, curid); GST_DEBUG_OBJECT (mq, "SingleQueue %d : Enqueuing event %p of type %s with id %d", @@ -1497,7 +1573,6 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event) break; } done: - gst_object_unref (mq); return res; flushing: @@ -1518,64 +1593,77 @@ was_eos: } } -static GstCaps * -gst_multi_queue_getcaps (GstPad * pad, GstCaps * filter) -{ - GstSingleQueue *sq = gst_pad_get_element_private (pad); - GstPad *otherpad; - GstCaps *result; - - otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad; - - GST_LOG_OBJECT (otherpad, "Getting caps from the peer of this pad"); - - result = gst_pad_peer_get_caps (otherpad, filter); - if (result == NULL) - result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - return result; -} - static gboolean -gst_multi_queue_acceptcaps (GstPad * pad, GstCaps * caps) +gst_multi_queue_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstSingleQueue *sq = gst_pad_get_element_private (pad); - GstPad *otherpad; - gboolean result; + gboolean res; + GstSingleQueue *sq; + GstMultiQueue *mq; - otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad; + sq = (GstSingleQueue *) gst_pad_get_element_private (pad); + mq = (GstMultiQueue *) parent; - GST_LOG_OBJECT (otherpad, "Accept caps from the peer of this pad"); + switch (GST_QUERY_TYPE (query)) { + default: + if (GST_QUERY_IS_SERIALIZED (query)) { + guint32 curid; + GstMultiQueueItem *item; - result = gst_pad_peer_accept_caps (otherpad, caps); + /* Get an unique incrementing id. */ + curid = g_atomic_int_add ((gint *) & mq->counter, 1); - return result; + item = gst_multi_queue_mo_item_new ((GstMiniObject *) query, curid); + + GST_DEBUG_OBJECT (mq, + "SingleQueue %d : Enqueuing query %p of type %s with id %d", + sq->id, query, GST_QUERY_TYPE_NAME (query), curid); + + GST_MULTI_QUEUE_MUTEX_LOCK (mq); + res = gst_data_queue_push (sq->queue, (GstDataQueueItem *) item); + g_cond_wait (&sq->query_handled, &mq->qlock); + res = sq->last_query; + GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); + } else { + /* default handling */ + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; } static gboolean -gst_multi_queue_src_activate_push (GstPad * pad, gboolean active) +gst_multi_queue_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { GstMultiQueue *mq; GstSingleQueue *sq; - gboolean result = FALSE; + gboolean result; sq = (GstSingleQueue *) gst_pad_get_element_private (pad); mq = sq->mqueue; GST_DEBUG_OBJECT (mq, "SingleQueue %d", sq->id); - if (active) { - result = gst_single_queue_flush (mq, sq, FALSE); - } else { - result = gst_single_queue_flush (mq, sq, TRUE); - /* make sure streaming finishes */ - result |= gst_pad_stop_task (pad); + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + result = gst_single_queue_flush (mq, sq, FALSE); + } else { + result = gst_single_queue_flush (mq, sq, TRUE); + /* make sure streaming finishes */ + result |= gst_pad_stop_task (pad); + } + break; + default: + result = FALSE; + break; } return result; } static gboolean -gst_multi_queue_src_event (GstPad * pad, GstEvent * event) +gst_multi_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstSingleQueue *sq = gst_pad_get_element_private (pad); @@ -1583,30 +1671,18 @@ gst_multi_queue_src_event (GstPad * pad, GstEvent * event) } static gboolean -gst_multi_queue_src_query (GstPad * pad, GstQuery * query) +gst_multi_queue_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstSingleQueue *sq = gst_pad_get_element_private (pad); - GstPad *peerpad; gboolean res; /* FIXME, Handle position offset depending on queue size */ - - /* default handling */ - if (!(peerpad = gst_pad_get_peer (sq->sinkpad))) - goto no_peer; - - res = gst_pad_query (peerpad, query); - - gst_object_unref (peerpad); - - return res; - - /* ERRORS */ -no_peer: - { - GST_LOG_OBJECT (sq->sinkpad, "Couldn't send query because we have no peer"); - return FALSE; + switch (GST_QUERY_TYPE (query)) { + default: + /* default handling */ + res = gst_pad_query_default (pad, parent, query); + break; } + return res; } /* @@ -1633,7 +1709,7 @@ wake_up_next_non_linked (GstMultiQueue * mq) && sq->next_time >= mq->high_time) || (sq->nextid != 0 && sq->nextid <= mq->highid)) { GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id); - g_cond_signal (sq->turn); + g_cond_signal (&sq->turn); } } } @@ -1664,10 +1740,10 @@ compute_high_id (GstMultiQueue * mq) if (sq->nextid < lowest) lowest = sq->nextid; - } else if (sq->srcresult != GST_FLOW_UNEXPECTED) { + } else if (sq->srcresult != GST_FLOW_EOS) { /* If we don't have a global highid, or the global highid is lower than * this single queue's last outputted id, store the queue's one, - * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */ + * unless the singlequeue is at EOS (srcresult = EOS) */ if ((highid == G_MAXUINT32) || (sq->oldid > highid)) highid = sq->oldid; } @@ -1709,10 +1785,10 @@ compute_high_time (GstMultiQueue * mq) if (lowest == GST_CLOCK_TIME_NONE || sq->next_time < lowest) lowest = sq->next_time; - } else if (sq->srcresult != GST_FLOW_UNEXPECTED) { + } else if (sq->srcresult != GST_FLOW_EOS) { /* If we don't have a global highid, or the global highid is lower than * this single queue's last outputted id, store the queue's one, - * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */ + * unless the singlequeue is at EOS (srcresult = EOS) */ if (highest == GST_CLOCK_TIME_NONE || sq->last_time > highest) highest = sq->last_time; } @@ -1758,8 +1834,6 @@ single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq) "Another queue is empty, bumping single queue %d max visible to %d", sq->id, sq->max_size.visible); } - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq); - goto beach; } /* check if we reached the hard time/bytes limits */ gst_data_queue_get_level (oq->queue, &ssize); @@ -1793,7 +1867,6 @@ single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq) g_signal_emit (mq, gst_multi_queue_signals[SIGNAL_OVERRUN], 0); } -beach: return; } @@ -1866,17 +1939,18 @@ gst_single_queue_free (GstSingleQueue * sq) /* DRAIN QUEUE */ gst_data_queue_flush (sq->queue); g_object_unref (sq->queue); - g_cond_free (sq->turn); + g_cond_clear (&sq->turn); + g_cond_clear (&sq->query_handled); g_free (sq); } static GstSingleQueue * -gst_single_queue_new (GstMultiQueue * mqueue, gint id) +gst_single_queue_new (GstMultiQueue * mqueue, guint id) { GstSingleQueue *sq; gchar *name; GList *tmp; - gint temp_id = (id == -1) ? 0 : id; + guint temp_id = (id == -1) ? 0 : id; GST_MULTI_QUEUE_MUTEX_LOCK (mqueue); @@ -1916,7 +1990,8 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id) GST_DEBUG_OBJECT (mqueue, "Creating GstSingleQueue id:%d", sq->id); sq->mqueue = mqueue; - sq->srcresult = GST_FLOW_WRONG_STATE; + sq->srcresult = GST_FLOW_FLUSHING; + sq->pushed = FALSE; sq->queue = gst_data_queue_new_full ((GstDataQueueCheckFullFunction) single_queue_check_full, (GstDataQueueFullCallback) single_queue_overrun_cb, @@ -1930,46 +2005,43 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id) sq->oldid = 0; sq->next_time = GST_CLOCK_TIME_NONE; sq->last_time = GST_CLOCK_TIME_NONE; - sq->turn = g_cond_new (); + g_cond_init (&sq->turn); + g_cond_init (&sq->query_handled); sq->sinktime = GST_CLOCK_TIME_NONE; sq->srctime = GST_CLOCK_TIME_NONE; sq->sink_tainted = TRUE; sq->src_tainted = TRUE; - name = g_strdup_printf ("sink%d", sq->id); + name = g_strdup_printf ("sink_%u", sq->id); sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, name); g_free (name); gst_pad_set_chain_function (sq->sinkpad, GST_DEBUG_FUNCPTR (gst_multi_queue_chain)); - gst_pad_set_activatepush_function (sq->sinkpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_push)); + gst_pad_set_activatemode_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode)); gst_pad_set_event_function (sq->sinkpad, GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event)); - gst_pad_set_getcaps_function (sq->sinkpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps)); - gst_pad_set_acceptcaps_function (sq->sinkpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps)); + gst_pad_set_query_function (sq->sinkpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query)); gst_pad_set_iterate_internal_links_function (sq->sinkpad, GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); + GST_OBJECT_FLAG_SET (sq->sinkpad, GST_PAD_FLAG_PROXY_CAPS); - name = g_strdup_printf ("src%d", sq->id); + name = g_strdup_printf ("src_%u", sq->id); sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name); g_free (name); - gst_pad_set_activatepush_function (sq->srcpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push)); - gst_pad_set_getcaps_function (sq->srcpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps)); - gst_pad_set_acceptcaps_function (sq->srcpad, - GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps)); + gst_pad_set_activatemode_function (sq->srcpad, + GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_mode)); gst_pad_set_event_function (sq->srcpad, GST_DEBUG_FUNCPTR (gst_multi_queue_src_event)); gst_pad_set_query_function (sq->srcpad, GST_DEBUG_FUNCPTR (gst_multi_queue_src_query)); gst_pad_set_iterate_internal_links_function (sq->srcpad, GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); + GST_OBJECT_FLAG_SET (sq->srcpad, GST_PAD_FLAG_PROXY_CAPS); gst_pad_set_element_private (sq->sinkpad, (gpointer) sq); gst_pad_set_element_private (sq->srcpad, (gpointer) sq); @@ -1979,14 +2051,14 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id) /* only activate the pads when we are not in the NULL state * and add the pad under the state_lock to prevend state changes * between activating and adding */ - g_static_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue)); + g_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue)); if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) { gst_pad_set_active (sq->srcpad, TRUE); gst_pad_set_active (sq->sinkpad, TRUE); } gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad); gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad); - g_static_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue)); + g_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue)); GST_DEBUG_OBJECT (mqueue, "GstSingleQueue [%d] created and pads added", sq->id); diff --git a/plugins/elements/gstmultiqueue.h b/plugins/elements/gstmultiqueue.h index bb3d840..04c7501 100644 --- a/plugins/elements/gstmultiqueue.h +++ b/plugins/elements/gstmultiqueue.h @@ -24,7 +24,7 @@ #define __GST_MULTI_QUEUE_H__ #include <gst/gst.h> -#include <gst/base/gstdataqueue.h> +#include "gstdataqueue.h" G_BEGIN_DECLS @@ -65,11 +65,11 @@ struct _GstMultiQueue { gboolean buffering; gint percent; - guint32 counter; /* incoming object counter, use atomic accesses */ + guint counter; /* incoming object counter, use atomic accesses */ guint32 highid; /* contains highest id of last outputted object */ GstClockTime high_time; /* highest start running time */ - GMutex * qlock; /* Global queue lock (vs object lock or individual */ + GMutex qlock; /* Global queue lock (vs object lock or individual */ /* queues lock). Protects nbqueues, queues, global */ /* GstMultiQueueSize, counter and highid */ diff --git a/plugins/elements/gstoutputselector.c b/plugins/elements/gstoutputselector.c index 2db7660..04422ad 100644 --- a/plugins/elements/gstoutputselector.c +++ b/plugins/elements/gstoutputselector.c @@ -44,7 +44,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_CAPS_ANY); static GstStaticPadTemplate gst_output_selector_src_factory = -GST_STATIC_PAD_TEMPLATE ("src%d", +GST_STATIC_PAD_TEMPLATE ("src_%u", GST_PAD_SRC, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); @@ -102,11 +102,14 @@ static GstPad *gst_output_selector_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * unused, const GstCaps * caps); static void gst_output_selector_release_pad (GstElement * element, GstPad * pad); -static GstFlowReturn gst_output_selector_chain (GstPad * pad, GstBuffer * buf); +static GstFlowReturn gst_output_selector_chain (GstPad * pad, + GstObject * parent, GstBuffer * buf); static GstStateChangeReturn gst_output_selector_change_state (GstElement * element, GstStateChange transition); -static gboolean gst_output_selector_handle_sink_event (GstPad * pad, +static gboolean gst_output_selector_event (GstPad * pad, GstObject * parent, GstEvent * event); +static gboolean gst_output_selector_query (GstPad * pad, GstObject * parent, + GstQuery * query); static void gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * sel, gint mode); @@ -136,7 +139,7 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass) DEFAULT_PAD_NEGOTIATION_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gst_element_class_set_details_simple (gstelement_class, "Output selector", + gst_element_class_set_static_metadata (gstelement_class, "Output selector", "Generic", "1-to-N output stream selector", "Stefan Kost <stefan.kost@nokia.com>"); gst_element_class_add_pad_template (gstelement_class, @@ -161,14 +164,16 @@ gst_output_selector_init (GstOutputSelector * sel) gst_pad_set_chain_function (sel->sinkpad, GST_DEBUG_FUNCPTR (gst_output_selector_chain)); gst_pad_set_event_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_output_selector_handle_sink_event)); + GST_DEBUG_FUNCPTR (gst_output_selector_event)); + gst_pad_set_query_function (sel->sinkpad, + GST_DEBUG_FUNCPTR (gst_output_selector_query)); gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad); /* srcpad management */ sel->active_srcpad = NULL; sel->nb_srcpads = 0; - gst_segment_init (&sel->segment, GST_FORMAT_TIME); + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); sel->pending_srcpad = NULL; sel->resend_latest = FALSE; @@ -280,15 +285,10 @@ gst_output_selector_get_property (GObject * object, guint prop_id, } } -static GstCaps * -gst_output_selector_sink_getcaps (GstPad * pad, GstCaps * filter) +static GstPad * +gst_output_selector_get_active (GstOutputSelector * sel) { - GstOutputSelector *sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad)); GstPad *active = NULL; - GstCaps *caps = NULL; - - if (G_UNLIKELY (sel == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); GST_OBJECT_LOCK (sel); if (sel->pending_srcpad) @@ -297,16 +297,7 @@ gst_output_selector_sink_getcaps (GstPad * pad, GstCaps * filter) active = gst_object_ref (sel->active_srcpad); GST_OBJECT_UNLOCK (sel); - if (active) { - caps = gst_pad_peer_get_caps (active, filter); - gst_object_unref (active); - } - if (caps == NULL) { - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - } - - gst_object_unref (sel); - return caps; + return active; } static void @@ -314,24 +305,16 @@ gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * sel, gint mode) { sel->pad_negotiation_mode = mode; - if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL) { - gst_pad_set_getcaps_function (sel->sinkpad, gst_pad_proxy_getcaps); - } else if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE) { - gst_pad_set_getcaps_function (sel->sinkpad, NULL); - } else { /* active */ - gst_pad_set_getcaps_function (sel->sinkpad, - gst_output_selector_sink_getcaps); - } } -static GstFlowReturn -forward_sticky_events (GstPad * pad, GstEvent * event, gpointer user_data) +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) { GstPad *srcpad = GST_PAD_CAST (user_data); - gst_pad_push_event (srcpad, gst_event_ref (event)); + gst_pad_push_event (srcpad, gst_event_ref (*event)); - return GST_FLOW_OK; + return TRUE; } static GstPad * @@ -347,7 +330,7 @@ gst_output_selector_request_new_pad (GstElement * element, GST_DEBUG_OBJECT (osel, "requesting pad"); GST_OBJECT_LOCK (osel); - padname = g_strdup_printf ("src%d", osel->nb_srcpads++); + padname = g_strdup_printf ("src_%u", osel->nb_srcpads++); srcpad = gst_pad_new_from_template (templ, padname); GST_OBJECT_UNLOCK (osel); @@ -391,7 +374,8 @@ gst_output_selector_switch (GstOutputSelector * osel) /* Switch */ GST_OBJECT_LOCK (GST_OBJECT (osel)); - GST_INFO ("switching to pad %" GST_PTR_FORMAT, osel->pending_srcpad); + GST_INFO_OBJECT (osel, "switching to pad %" GST_PTR_FORMAT, + osel->pending_srcpad); if (gst_pad_is_linked (osel->pending_srcpad)) { osel->active_srcpad = osel->pending_srcpad; res = TRUE; @@ -400,26 +384,29 @@ gst_output_selector_switch (GstOutputSelector * osel) osel->pending_srcpad = NULL; GST_OBJECT_UNLOCK (GST_OBJECT (osel)); - /* Send SEGMENT event and latest buffer if switching succeeded */ + /* Send SEGMENT event and latest buffer if switching succeeded + * and we already have a valid segment configured */ if (res) { - /* Send SEGMENT to the pad we are going to switch to */ - seg = &osel->segment; - /* If resending then mark segment start and position accordingly */ - if (osel->resend_latest && osel->latest_buffer && - GST_BUFFER_TIMESTAMP_IS_VALID (osel->latest_buffer)) { - start = position = GST_BUFFER_TIMESTAMP (osel->latest_buffer); - } else { - start = position = seg->position; - } + if (osel->segment.format != GST_FORMAT_UNDEFINED) { + /* Send SEGMENT to the pad we are going to switch to */ + seg = &osel->segment; + /* If resending then mark segment start and position accordingly */ + if (osel->resend_latest && osel->latest_buffer && + GST_BUFFER_TIMESTAMP_IS_VALID (osel->latest_buffer)) { + start = position = GST_BUFFER_TIMESTAMP (osel->latest_buffer); + } else { + start = position = seg->position; + } - seg->start = start; - seg->position = position; - ev = gst_event_new_segment (seg); + seg->start = start; + seg->position = position; + ev = gst_event_new_segment (seg); - if (!gst_pad_push_event (osel->active_srcpad, ev)) { - GST_WARNING_OBJECT (osel, - "newsegment handling failed in %" GST_PTR_FORMAT, - osel->active_srcpad); + if (!gst_pad_push_event (osel->active_srcpad, ev)) { + GST_WARNING_OBJECT (osel, + "newsegment handling failed in %" GST_PTR_FORMAT, + osel->active_srcpad); + } } /* Resend latest buffer to newly switched pad */ @@ -435,13 +422,13 @@ gst_output_selector_switch (GstOutputSelector * osel) } static GstFlowReturn -gst_output_selector_chain (GstPad * pad, GstBuffer * buf) +gst_output_selector_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstFlowReturn res; GstOutputSelector *osel; GstClockTime position, duration; - osel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad)); + osel = GST_OUTPUT_SELECTOR (parent); /* * The _switch function might push a buffer if 'resend-latest' is true. @@ -485,7 +472,6 @@ gst_output_selector_chain (GstPad * pad, GstBuffer * buf) GST_LOG_OBJECT (osel, "pushing buffer to %" GST_PTR_FORMAT, osel->active_srcpad); res = gst_pad_push (osel->active_srcpad, buf); - gst_object_unref (osel); return res; } @@ -520,17 +506,13 @@ gst_output_selector_change_state (GstElement * element, } static gboolean -gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) +gst_output_selector_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; GstOutputSelector *sel; GstPad *active = NULL; - sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) { - gst_event_unref (event); - return FALSE; - } + sel = GST_OUTPUT_SELECTOR (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: @@ -538,19 +520,13 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) switch (sel->pad_negotiation_mode) { case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL: /* Send caps to all src pads */ - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE: gst_event_unref (event); break; default: - GST_OBJECT_LOCK (sel); - if (sel->pending_srcpad) - active = gst_object_ref (sel->pending_srcpad); - else if (sel->active_srcpad) - active = gst_object_ref (sel->active_srcpad); - GST_OBJECT_UNLOCK (sel); - + active = gst_output_selector_get_active (sel); if (active) { res = gst_pad_push_event (active, event); gst_object_unref (active); @@ -569,23 +545,17 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) &sel->segment); /* Send newsegment to all src pads */ - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; } case GST_EVENT_EOS: /* Send eos to all src pads */ - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; default: { - GST_OBJECT_LOCK (sel); - if (sel->pending_srcpad) - active = gst_object_ref (sel->pending_srcpad); - else if (sel->active_srcpad) - active = gst_object_ref (sel->active_srcpad); - GST_OBJECT_UNLOCK (sel); - /* Send other events to pending or active src pad */ + active = gst_output_selector_get_active (sel); if (active) { res = gst_pad_push_event (active, event); gst_object_unref (active); @@ -596,7 +566,44 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) } } - gst_object_unref (sel); + return res; +} +static gboolean +gst_output_selector_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean res = TRUE; + GstOutputSelector *sel; + GstPad *active = NULL; + + sel = GST_OUTPUT_SELECTOR (parent); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + switch (sel->pad_negotiation_mode) { + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL: + /* Send caps to all src pads */ + res = gst_pad_proxy_query_caps (pad, query); + break; + case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE: + res = FALSE; + break; + default: + active = gst_output_selector_get_active (sel); + if (active) { + res = gst_pad_peer_query (active, query); + gst_object_unref (active); + } else { + res = FALSE; + } + break; + } + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } return res; } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 19ccf8f..aa494be 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -61,6 +61,7 @@ #include "gstqueue.h" #include "../../gst/gst-i18n-lib.h" +#include "../../gst/glib-compat-private.h" static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -91,7 +92,7 @@ GST_DEBUG_CATEGORY_STATIC (queue_dataflow); queue->cur_level.time, \ queue->min_threshold.time, \ queue->max_size.time, \ - queue->queue->length) + queue->queue.length) /* Queue signals and args */ enum @@ -127,7 +128,7 @@ enum #define DEFAULT_MAX_SIZE_TIME GST_SECOND /* 1 second */ #define GST_QUEUE_MUTEX_LOCK(q) G_STMT_START { \ - g_mutex_lock (q->qlock); \ + g_mutex_lock (&q->qlock); \ } G_STMT_END #define GST_QUEUE_MUTEX_LOCK_CHECK(q,label) G_STMT_START { \ @@ -137,13 +138,13 @@ enum } G_STMT_END #define GST_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \ - g_mutex_unlock (q->qlock); \ + g_mutex_unlock (&q->qlock); \ } G_STMT_END #define GST_QUEUE_WAIT_DEL_CHECK(q, label) G_STMT_START { \ STATUS (q, q->sinkpad, "wait for DEL"); \ q->waiting_del = TRUE; \ - g_cond_wait (q->item_del, q->qlock); \ + g_cond_wait (&q->item_del, &q->qlock); \ q->waiting_del = FALSE; \ if (q->srcresult != GST_FLOW_OK) { \ STATUS (q, q->srcpad, "received DEL wakeup"); \ @@ -155,7 +156,7 @@ enum #define GST_QUEUE_WAIT_ADD_CHECK(q, label) G_STMT_START { \ STATUS (q, q->srcpad, "wait for ADD"); \ q->waiting_add = TRUE; \ - g_cond_wait (q->item_add, q->qlock); \ + g_cond_wait (&q->item_add, &q->qlock); \ q->waiting_add = FALSE; \ if (q->srcresult != GST_FLOW_OK) { \ STATUS (q, q->srcpad, "received ADD wakeup"); \ @@ -167,14 +168,14 @@ enum #define GST_QUEUE_SIGNAL_DEL(q) G_STMT_START { \ if (q->waiting_del) { \ STATUS (q, q->srcpad, "signal DEL"); \ - g_cond_signal (q->item_del); \ + g_cond_signal (&q->item_del); \ } \ } G_STMT_END #define GST_QUEUE_SIGNAL_ADD(q) G_STMT_START { \ if (q->waiting_add) { \ STATUS (q, q->sinkpad, "signal ADD"); \ - g_cond_signal (q->item_add); \ + g_cond_signal (&q->item_add); \ } \ } G_STMT_END @@ -192,23 +193,27 @@ static void gst_queue_set_property (GObject * object, static void gst_queue_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer); +static GstFlowReturn gst_queue_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); static GstFlowReturn gst_queue_push_one (GstQueue * queue); static void gst_queue_loop (GstPad * pad); -static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query); +static gboolean gst_queue_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static gboolean gst_queue_acceptcaps (GstPad * pad, GstCaps * caps); -static GstCaps *gst_queue_getcaps (GstPad * pad, GstCaps * filter); -static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer); -static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer); static void gst_queue_locked_flush (GstQueue * queue); -static gboolean gst_queue_src_activate_push (GstPad * pad, gboolean active); -static gboolean gst_queue_sink_activate_push (GstPad * pad, gboolean active); +static gboolean gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); static gboolean gst_queue_is_empty (GstQueue * queue); static gboolean gst_queue_is_filled (GstQueue * queue); @@ -358,7 +363,7 @@ gst_queue_class_init (GstQueueClass * klass) gobject_class->finalize = gst_queue_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Queue", "Generic", "Simple data queue", "Erik Walthinsen <omega@cse.ogi.edu>"); gst_element_class_add_pad_template (gstelement_class, @@ -367,16 +372,12 @@ gst_queue_class_init (GstQueueClass * klass) gst_static_pad_template_get (&sinktemplate)); /* Registering debug symbols for function pointers */ - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_sink_activate_push); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_mode); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_sink); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_getcaps); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_acceptcaps); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_push); - GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_src); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_query); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_event); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query); + GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain); } static void @@ -385,23 +386,20 @@ gst_queue_init (GstQueue * queue) queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); gst_pad_set_chain_function (queue->sinkpad, gst_queue_chain); - gst_pad_set_activatepush_function (queue->sinkpad, - gst_queue_sink_activate_push); + gst_pad_set_activatemode_function (queue->sinkpad, + gst_queue_sink_activate_mode); gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event); - gst_pad_set_link_function (queue->sinkpad, gst_queue_link_sink); - gst_pad_set_getcaps_function (queue->sinkpad, gst_queue_getcaps); - gst_pad_set_acceptcaps_function (queue->sinkpad, gst_queue_acceptcaps); + gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query); + GST_PAD_SET_PROXY_CAPS (queue->sinkpad); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - gst_pad_set_activatepush_function (queue->srcpad, - gst_queue_src_activate_push); - gst_pad_set_link_function (queue->srcpad, gst_queue_link_src); - gst_pad_set_acceptcaps_function (queue->srcpad, gst_queue_acceptcaps); - gst_pad_set_getcaps_function (queue->srcpad, gst_queue_getcaps); + gst_pad_set_activatemode_function (queue->srcpad, + gst_queue_src_activate_mode); gst_pad_set_event_function (queue->srcpad, gst_queue_handle_src_event); gst_pad_set_query_function (queue->srcpad, gst_queue_handle_src_query); + GST_PAD_SET_PROXY_CAPS (queue->srcpad); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); GST_QUEUE_CLEAR_LEVEL (queue->cur_level); @@ -415,12 +413,13 @@ gst_queue_init (GstQueue * queue) queue->head_needs_discont = queue->tail_needs_discont = FALSE; queue->leaky = GST_QUEUE_NO_LEAK; - queue->srcresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + + g_mutex_init (&queue->qlock); + g_cond_init (&queue->item_add); + g_cond_init (&queue->item_del); - queue->qlock = g_mutex_new (); - queue->item_add = g_cond_new (); - queue->item_del = g_cond_new (); - queue->queue = g_queue_new (); + g_queue_init (&queue->queue); queue->sinktime = GST_CLOCK_TIME_NONE; queue->srctime = GST_CLOCK_TIME_NONE; @@ -438,98 +437,22 @@ gst_queue_init (GstQueue * queue) static void gst_queue_finalize (GObject * object) { + GstMiniObject *data; GstQueue *queue = GST_QUEUE (object); GST_DEBUG_OBJECT (queue, "finalizing queue"); - while (!g_queue_is_empty (queue->queue)) { - GstMiniObject *data = g_queue_pop_head (queue->queue); - - gst_mini_object_unref (data); - } - g_queue_free (queue->queue); - g_mutex_free (queue->qlock); - g_cond_free (queue->item_add); - g_cond_free (queue->item_del); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static gboolean -gst_queue_acceptcaps (GstPad * pad, GstCaps * caps) -{ - gboolean result; - GstQueue *queue; - GstPad *otherpad; - - queue = GST_QUEUE (gst_pad_get_parent (pad)); - if (G_UNLIKELY (queue == NULL)) - return FALSE; - - otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad); - result = gst_pad_peer_accept_caps (otherpad, caps); - - gst_object_unref (queue); - - return result; -} - -static GstCaps * -gst_queue_getcaps (GstPad * pad, GstCaps * filter) -{ - GstQueue *queue; - GstPad *otherpad; - GstCaps *result; - - queue = GST_QUEUE (gst_pad_get_parent (pad)); - if (G_UNLIKELY (queue == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad); - result = gst_pad_peer_get_caps (otherpad, filter); - if (result == NULL) - result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - gst_object_unref (queue); - - return result; -} - -static GstPadLinkReturn -gst_queue_link_sink (GstPad * pad, GstPad * peer) -{ - return GST_PAD_LINK_OK; -} - -static GstPadLinkReturn -gst_queue_link_src (GstPad * pad, GstPad * peer) -{ - GstPadLinkReturn result = GST_PAD_LINK_OK; - GstQueue *queue; - - queue = GST_QUEUE (gst_pad_get_parent (pad)); - - GST_DEBUG_OBJECT (queue, "queue linking source pad"); - - if (GST_PAD_LINKFUNC (peer)) { - result = GST_PAD_LINKFUNC (peer) (peer, pad); + while ((data = g_queue_pop_head (&queue->queue))) { + if (!GST_IS_QUERY (data)) + gst_mini_object_unref (data); } - if (GST_PAD_LINK_SUCCESSFUL (result)) { - GST_QUEUE_MUTEX_LOCK (queue); - if (queue->srcresult == GST_FLOW_OK) { - queue->push_newsegment = TRUE; - gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad); - GST_DEBUG_OBJECT (queue, "starting task as pad is linked"); - } else { - GST_DEBUG_OBJECT (queue, "not starting task reason %s", - gst_flow_get_name (queue->srcresult)); - } - GST_QUEUE_MUTEX_UNLOCK (queue); - } - gst_object_unref (queue); + g_queue_clear (&queue->queue); + g_mutex_clear (&queue->qlock); + g_cond_clear (&queue->item_add); + g_cond_clear (&queue->item_del); - return result; + G_OBJECT_CLASS (parent_class)->finalize (object); } /* calculate the diff between running time on the sink and src of the queue. @@ -631,12 +554,13 @@ apply_buffer (GstQueue * queue, GstBuffer * buffer, GstSegment * segment, static void gst_queue_locked_flush (GstQueue * queue) { - while (!g_queue_is_empty (queue->queue)) { - GstMiniObject *data = g_queue_pop_head (queue->queue); + GstMiniObject *data; + while ((data = g_queue_pop_head (&queue->queue))) { /* Then lose another reference because we are supposed to destroy that data when flushing */ - gst_mini_object_unref (data); + if (!GST_IS_QUERY (data)) + gst_mini_object_unref (data); } GST_QUEUE_CLEAR_LEVEL (queue->cur_level); queue->min_threshold.buffers = queue->orig_min_threshold.buffers; @@ -664,7 +588,7 @@ gst_queue_locked_enqueue_buffer (GstQueue * queue, gpointer item) queue->cur_level.bytes += gst_buffer_get_size (buffer); apply_buffer (queue, buffer, &queue->sink_segment, TRUE, TRUE); - g_queue_push_tail (queue->queue, item); + g_queue_push_tail (&queue->queue, item); GST_QUEUE_SIGNAL_ADD (queue); } @@ -685,12 +609,12 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item) case GST_EVENT_SEGMENT: apply_segment (queue, event, &queue->sink_segment, TRUE); /* if the queue is empty, apply sink segment on the source */ - if (queue->queue->length == 0) { + if (queue->queue.length == 0) { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "Apply segment on srcpad"); apply_segment (queue, event, &queue->src_segment, FALSE); queue->newseg_applied_to_src = TRUE; } - /* a new segment allows us to accept more buffers if we got UNEXPECTED + /* a new segment allows us to accept more buffers if we got EOS * from downstream */ queue->unexpected = FALSE; break; @@ -698,17 +622,17 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item) break; } - g_queue_push_tail (queue->queue, item); + g_queue_push_tail (&queue->queue, item); GST_QUEUE_SIGNAL_ADD (queue); } /* dequeue an item from the queue and update level stats, with QUEUE_LOCK */ static GstMiniObject * -gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer) +gst_queue_locked_dequeue (GstQueue * queue) { GstMiniObject *item; - item = g_queue_pop_head (queue->queue); + item = g_queue_pop_head (&queue->queue); if (item == NULL) goto no_item; @@ -726,7 +650,6 @@ gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer) if (queue->cur_level.buffers == 0) queue->cur_level.time = 0; - *is_buffer = TRUE; } else if (GST_IS_EVENT (item)) { GstEvent *event = GST_EVENT_CAST (item); @@ -749,8 +672,11 @@ gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer) default: break; } + } else if (GST_IS_QUERY (item)) { + GstQuery *query = GST_QUERY_CAST (item); - *is_buffer = FALSE; + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved query %p from queue", query); } else { g_warning ("Unexpected item %p dequeued from queue %s (refcounting problem?)", @@ -770,15 +696,11 @@ no_item: } static gboolean -gst_queue_handle_sink_event (GstPad * pad, GstEvent * event) +gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstQueue *queue; - queue = GST_QUEUE (gst_pad_get_parent (pad)); - if (G_UNLIKELY (queue == NULL)) { - gst_event_unref (event); - return FALSE; - } + queue = GST_QUEUE (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: @@ -789,7 +711,7 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event) /* now unblock the chain function */ GST_QUEUE_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; /* unblock the loop and chain functions */ GST_QUEUE_SIGNAL_ADD (queue); GST_QUEUE_SIGNAL_DEL (queue); @@ -812,12 +734,8 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event) queue->srcresult = GST_FLOW_OK; queue->eos = FALSE; queue->unexpected = FALSE; - if (gst_pad_is_linked (queue->srcpad)) { - gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop, - queue->srcpad); - } else { - GST_INFO_OBJECT (queue, "not re-starting task as pad is not linked"); - } + gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue_loop, + queue->srcpad); GST_QUEUE_MUTEX_UNLOCK (queue); STATUS (queue, pad, "after flush"); @@ -839,7 +757,6 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event) break; } done: - gst_object_unref (queue); return TRUE; /* ERRORS */ @@ -848,7 +765,6 @@ out_flushing: GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are flushing"); GST_QUEUE_MUTEX_UNLOCK (queue); - gst_object_unref (queue); gst_event_unref (event); return FALSE; } @@ -856,16 +772,52 @@ out_eos: { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS"); GST_QUEUE_MUTEX_UNLOCK (queue); - gst_object_unref (queue); gst_event_unref (event); return FALSE; } } static gboolean +gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstQueue *queue = GST_QUEUE_CAST (parent); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + default: + if (G_UNLIKELY (GST_QUERY_IS_SERIALIZED (query))) { + GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + GST_LOG_OBJECT (queue, "queuing query %p (%s)", query, + GST_QUERY_TYPE_NAME (query)); + g_queue_push_tail (&queue->queue, query); + GST_QUEUE_SIGNAL_ADD (queue); + while (queue->queue.length != 0) { + /* for as long as the queue has items, we know the query is + * not handled yet */ + GST_QUEUE_WAIT_DEL_CHECK (queue, out_flushing); + } + res = queue->last_query; + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; + + /* ERRORS */ +out_flushing: + { + GST_DEBUG_OBJECT (queue, "we are flushing"); + GST_QUEUE_MUTEX_UNLOCK (queue); + return FALSE; + } +} + +static gboolean gst_queue_is_empty (GstQueue * queue) { - if (queue->queue->length == 0) + if (queue->queue.length == 0) return TRUE; /* It is possible that a max size is reached before all min thresholds are. @@ -896,16 +848,16 @@ gst_queue_leak_downstream (GstQueue * queue) /* for as long as the queue is filled, dequeue an item and discard it */ while (gst_queue_is_filled (queue)) { GstMiniObject *leak; - gboolean is_buffer; - leak = gst_queue_locked_dequeue (queue, &is_buffer); + leak = gst_queue_locked_dequeue (queue); /* there is nothing to dequeue and the queue is still filled.. This should * not happen */ g_assert (leak != NULL); GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "queue is full, leaking item %p on downstream end", leak); - gst_mini_object_unref (leak); + if (!GST_IS_QUERY (leak)) + gst_mini_object_unref (leak); /* last buffer needs to get a DISCONT flag */ queue->head_needs_discont = TRUE; @@ -913,12 +865,12 @@ gst_queue_leak_downstream (GstQueue * queue) } static GstFlowReturn -gst_queue_chain (GstPad * pad, GstBuffer * buffer) +gst_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstQueue *queue; GstClockTime duration, timestamp; - queue = (GstQueue *) GST_OBJECT_PARENT (pad); + queue = GST_QUEUE_CAST (parent); /* we have to lock the queue since we span threads */ GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); @@ -1033,30 +985,19 @@ out_eos: gst_buffer_unref (buffer); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } out_unexpected: { - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "exit because we received UNEXPECTED"); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); GST_QUEUE_MUTEX_UNLOCK (queue); gst_buffer_unref (buffer); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } } -static void -gst_queue_push_newsegment (GstQueue * queue) -{ - GstEvent *event; - - event = gst_event_new_segment (&queue->src_segment); - GST_CAT_LOG_OBJECT (queue_dataflow, queue, "pushing real newsegment event"); - gst_pad_push_event (queue->srcpad, event); -} - /* dequeue an item from the queue an push it downstream. This functions returns * the result of the push. */ static GstFlowReturn @@ -1064,18 +1005,14 @@ gst_queue_push_one (GstQueue * queue) { GstFlowReturn result = GST_FLOW_OK; GstMiniObject *data; - gboolean is_buffer; - data = gst_queue_locked_dequeue (queue, &is_buffer); + data = gst_queue_locked_dequeue (queue); if (data == NULL) goto no_item; next: - if (is_buffer) { + if (GST_IS_BUFFER (data)) { GstBuffer *buffer; -#if 0 - GstCaps *caps; -#endif buffer = GST_BUFFER_CAST (data); @@ -1090,55 +1027,44 @@ next: } queue->head_needs_discont = FALSE; } -#if 0 - caps = GST_BUFFER_CAPS (buffer); -#endif GST_QUEUE_MUTEX_UNLOCK (queue); -#if 0 - /* set the right caps on the pad now. We do this before pushing the buffer - * because the pad_push call will check (using acceptcaps) if the buffer can - * be set on the pad, which might fail because this will be propagated - * upstream. Also note that if the buffer has NULL caps, it means that the - * caps did not change, so we don't have to change caps on the pad. */ - if (caps && caps != GST_PAD_CAPS (queue->srcpad)) - gst_pad_set_caps (queue->srcpad, caps); -#endif - - if (queue->push_newsegment) { - gst_queue_push_newsegment (queue); - } result = gst_pad_push (queue->srcpad, buffer); /* need to check for srcresult here as well */ GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); - if (result == GST_FLOW_UNEXPECTED) { - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "got UNEXPECTED from downstream"); + if (result == GST_FLOW_EOS) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream"); /* stop pushing buffers, we dequeue all items until we see an item that we * can push again, which is EOS or SEGMENT. If there is nothing in the * queue we can push, we set a flag to make the sinkpad refuse more - * buffers with an UNEXPECTED return value. */ - while ((data = gst_queue_locked_dequeue (queue, &is_buffer))) { - if (is_buffer) { + * buffers with an EOS return value. */ + while ((data = gst_queue_locked_dequeue (queue))) { + if (GST_IS_BUFFER (data)) { GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "dropping UNEXPECTED buffer %p", data); + "dropping EOS buffer %p", data); gst_buffer_unref (GST_BUFFER_CAST (data)); - } else { + } else if (GST_IS_EVENT (data)) { GstEvent *event = GST_EVENT_CAST (data); GstEventType type = GST_EVENT_TYPE (event); if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT) { /* we found a pushable item in the queue, push it out */ GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "pushing pushable event %s after UNEXPECTED", + "pushing pushable event %s after EOS", GST_EVENT_TYPE_NAME (event)); goto next; } GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "dropping UNEXPECTED event %p", event); + "dropping EOS event %p", event); gst_event_unref (event); + } else if (GST_IS_QUERY (data)) { + GstQuery *query = GST_QUERY_CAST (data); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping query %p because of EOS", query); + queue->last_query = FALSE; } } /* no more items in the queue. Set the unexpected flag so that upstream @@ -1148,24 +1074,27 @@ next: queue->unexpected = TRUE; result = GST_FLOW_OK; } - } else { + } else if (GST_IS_EVENT (data)) { GstEvent *event = GST_EVENT_CAST (data); GstEventType type = GST_EVENT_TYPE (event); GST_QUEUE_MUTEX_UNLOCK (queue); - if (queue->push_newsegment && type != GST_EVENT_SEGMENT) { - gst_queue_push_newsegment (queue); - } gst_pad_push_event (queue->srcpad, event); GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); - /* if we're EOS, return UNEXPECTED so that the task pauses. */ + /* if we're EOS, return EOS so that the task pauses. */ if (type == GST_EVENT_EOS) { GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "pushed EOS event %p, return UNEXPECTED", event); - result = GST_FLOW_UNEXPECTED; + "pushed EOS event %p, return EOS", event); + result = GST_FLOW_EOS; } + } else if (GST_IS_QUERY (data)) { + GstQuery *query = GST_QUERY_CAST (data); + + queue->last_query = gst_pad_peer_query (queue->srcpad, query); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "did query %p, return %d", query, queue->last_query); } return result; @@ -1179,7 +1108,7 @@ no_item: out_flushing: { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we are flushing"); - return GST_FLOW_WRONG_STATE; + return GST_FLOW_FLUSHING; } } @@ -1217,7 +1146,6 @@ gst_queue_loop (GstPad * pad) } ret = gst_queue_push_one (queue); - queue->push_newsegment = FALSE; queue->srcresult = ret; if (ret != GST_FLOW_OK) goto out_flushing; @@ -1235,11 +1163,14 @@ out_flushing: gst_pad_pause_task (queue->srcpad); GST_CAT_LOG_OBJECT (queue_dataflow, queue, "pause task, reason: %s", gst_flow_get_name (ret)); - GST_QUEUE_SIGNAL_DEL (queue); + if (ret == GST_FLOW_FLUSHING) + gst_queue_locked_flush (queue); + else + GST_QUEUE_SIGNAL_DEL (queue); GST_QUEUE_MUTEX_UNLOCK (queue); /* let app know about us giving up if upstream is not expected to do so */ - /* UNEXPECTED is already taken care of elsewhere */ - if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED)) { + /* EOS is already taken care of elsewhere */ + if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { GST_ELEMENT_ERROR (queue, STREAM, FAILED, (_("Internal data flow error.")), ("streaming task paused, reason %s (%d)", @@ -1251,15 +1182,11 @@ out_flushing: } static gboolean -gst_queue_handle_src_event (GstPad * pad, GstEvent * event) +gst_queue_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; - GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad)); + GstQueue *queue = GST_QUEUE (parent); - if (G_UNLIKELY (queue == NULL)) { - gst_event_unref (event); - return FALSE; - } #ifndef GST_DISABLE_GST_DEBUG GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%d)", event, GST_EVENT_TYPE (event)); @@ -1267,31 +1194,18 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event) res = gst_pad_push_event (queue->sinkpad, event); - gst_object_unref (queue); return res; } static gboolean -gst_queue_handle_src_query (GstPad * pad, GstQuery * query) +gst_queue_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad)); - GstPad *peer; + GstQueue *queue = GST_QUEUE (parent); gboolean res; - if (G_UNLIKELY (queue == NULL)) - return FALSE; - - if (!(peer = gst_pad_get_peer (queue->sinkpad))) { - gst_object_unref (queue); + res = gst_pad_query_default (pad, parent, query); + if (!res) return FALSE; - } - - res = gst_pad_query (peer, query); - gst_object_unref (peer); - if (!res) { - gst_object_unref (queue); - return FALSE; - } switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: @@ -1347,72 +1261,77 @@ gst_queue_handle_src_query (GstPad * pad, GstQuery * query) break; } - gst_object_unref (queue); return TRUE; } static gboolean -gst_queue_sink_activate_push (GstPad * pad, gboolean active) +gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) { - gboolean result = TRUE; + gboolean result; GstQueue *queue; - queue = GST_QUEUE (gst_pad_get_parent (pad)); + queue = GST_QUEUE (parent); - if (active) { - GST_QUEUE_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_OK; - queue->eos = FALSE; - queue->unexpected = FALSE; - GST_QUEUE_MUTEX_UNLOCK (queue); - } else { - /* step 1, unblock chain function */ - GST_QUEUE_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_WRONG_STATE; - gst_queue_locked_flush (queue); - GST_QUEUE_MUTEX_UNLOCK (queue); + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + /* step 1, unblock chain function */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + gst_queue_locked_flush (queue); + GST_QUEUE_MUTEX_UNLOCK (queue); + } + result = TRUE; + break; + default: + result = FALSE; + break; } - - gst_object_unref (queue); - return result; } static gboolean -gst_queue_src_activate_push (GstPad * pad, gboolean active) +gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) { - gboolean result = FALSE; + gboolean result; GstQueue *queue; - queue = GST_QUEUE (gst_pad_get_parent (pad)); - - if (active) { - GST_QUEUE_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_OK; - queue->eos = FALSE; - queue->unexpected = FALSE; - /* we do not start the task yet if the pad is not connected */ - if (gst_pad_is_linked (pad)) - result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad); - else { - GST_INFO_OBJECT (queue, "not starting task as pad is not linked"); - result = TRUE; - } - GST_QUEUE_MUTEX_UNLOCK (queue); - } else { - /* step 1, unblock loop function */ - GST_QUEUE_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_WRONG_STATE; - /* the item add signal will unblock */ - g_cond_signal (queue->item_add); - GST_QUEUE_MUTEX_UNLOCK (queue); + queue = GST_QUEUE (parent); + + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_OK; + queue->eos = FALSE; + queue->unexpected = FALSE; + result = + gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad); + GST_QUEUE_MUTEX_UNLOCK (queue); + } else { + /* step 1, unblock loop function */ + GST_QUEUE_MUTEX_LOCK (queue); + queue->srcresult = GST_FLOW_FLUSHING; + /* the item add signal will unblock */ + g_cond_signal (&queue->item_add); + GST_QUEUE_MUTEX_UNLOCK (queue); - /* step 2, make sure streaming finishes */ - result = gst_pad_stop_task (pad); + /* step 2, make sure streaming finishes */ + result = gst_pad_stop_task (pad); + } + break; + default: + result = FALSE; + break; } - - gst_object_unref (queue); - return result; } diff --git a/plugins/elements/gstqueue.h b/plugins/elements/gstqueue.h index 6ab8617..57ccc2a 100644 --- a/plugins/elements/gstqueue.h +++ b/plugins/elements/gstqueue.h @@ -38,6 +38,8 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QUEUE)) #define GST_IS_QUEUE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE)) +#define GST_QUEUE_CAST(obj) \ + ((GstQueue *)(obj)) typedef struct _GstQueue GstQueue; typedef struct _GstQueueSize GstQueueSize; @@ -105,7 +107,7 @@ struct _GstQueue { gboolean eos; /* the queue of data we're keeping our grubby hands on */ - GQueue *queue; + GQueue queue; GstQueueSize cur_level, /* currently in the queue */ @@ -116,11 +118,11 @@ struct _GstQueue { /* whether we leak data, and at which end */ gint leaky; - GMutex *qlock; /* lock for queue (vs object lock) */ + GMutex qlock; /* lock for queue (vs object lock) */ gboolean waiting_add; - GCond *item_add; /* signals buffers now available for reading */ + GCond item_add; /* signals buffers now available for reading */ gboolean waiting_del; - GCond *item_del; /* signals space now available for writing */ + GCond item_del; /* signals space now available for writing */ gboolean head_needs_discont, tail_needs_discont; gboolean push_newsegment; @@ -129,6 +131,8 @@ struct _GstQueue { /* whether the first new segment has been applied to src */ gboolean newseg_applied_to_src; + + gboolean last_query; }; struct _GstQueueClass { diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c index c89c6cd..82e2e11 100644 --- a/plugins/elements/gstqueue2.c +++ b/plugins/elements/gstqueue2.c @@ -63,6 +63,7 @@ #include <glib/gstdio.h> #include "gst/gst-i18n-lib.h" +#include "gst/glib-compat-private.h" #include <string.h> @@ -155,10 +156,10 @@ enum queue->max_level.time, \ (guint64) (!QUEUE_IS_USING_QUEUE(queue) ? \ queue->current->writing_pos - queue->current->max_reading_pos : \ - queue->queue->length)) + queue->queue.length)) #define GST_QUEUE2_MUTEX_LOCK(q) G_STMT_START { \ - g_mutex_lock (q->qlock); \ + g_mutex_lock (&q->qlock); \ } G_STMT_END #define GST_QUEUE2_MUTEX_LOCK_CHECK(q,res,label) G_STMT_START { \ @@ -168,13 +169,13 @@ enum } G_STMT_END #define GST_QUEUE2_MUTEX_UNLOCK(q) G_STMT_START { \ - g_mutex_unlock (q->qlock); \ + g_mutex_unlock (&q->qlock); \ } G_STMT_END #define GST_QUEUE2_WAIT_DEL_CHECK(q, res, label) G_STMT_START { \ STATUS (queue, q->sinkpad, "wait for DEL"); \ q->waiting_del = TRUE; \ - g_cond_wait (q->item_del, queue->qlock); \ + g_cond_wait (&q->item_del, &queue->qlock); \ q->waiting_del = FALSE; \ if (res != GST_FLOW_OK) { \ STATUS (queue, q->srcpad, "received DEL wakeup"); \ @@ -186,7 +187,7 @@ enum #define GST_QUEUE2_WAIT_ADD_CHECK(q, res, label) G_STMT_START { \ STATUS (queue, q->srcpad, "wait for ADD"); \ q->waiting_add = TRUE; \ - g_cond_wait (q->item_add, q->qlock); \ + g_cond_wait (&q->item_add, &q->qlock); \ q->waiting_add = FALSE; \ if (res != GST_FLOW_OK) { \ STATUS (queue, q->srcpad, "received ADD wakeup"); \ @@ -198,14 +199,14 @@ enum #define GST_QUEUE2_SIGNAL_DEL(q) G_STMT_START { \ if (q->waiting_del) { \ STATUS (q, q->srcpad, "signal DEL"); \ - g_cond_signal (q->item_del); \ + g_cond_signal (&q->item_del); \ } \ } G_STMT_END #define GST_QUEUE2_SIGNAL_ADD(q) G_STMT_START { \ if (q->waiting_add) { \ STATUS (q, q->sinkpad, "signal ADD"); \ - g_cond_signal (q->item_add); \ + g_cond_signal (&q->item_add); \ } \ } G_STMT_END @@ -223,26 +224,32 @@ static void gst_queue2_set_property (GObject * object, static void gst_queue2_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstFlowReturn gst_queue2_chain (GstPad * pad, GstBuffer * buffer); +static GstFlowReturn gst_queue2_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_queue2_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list); static GstFlowReturn gst_queue2_push_one (GstQueue2 * queue); static void gst_queue2_loop (GstPad * pad); -static gboolean gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static gboolean gst_queue2_handle_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_queue2_handle_src_query (GstPad * pad, GstQuery * query); +static gboolean gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); static gboolean gst_queue2_handle_query (GstElement * element, GstQuery * query); -static GstCaps *gst_queue2_getcaps (GstPad * pad, GstCaps * filter); -static gboolean gst_queue2_acceptcaps (GstPad * pad, GstCaps * caps); - -static GstFlowReturn gst_queue2_get_range (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer); +static GstFlowReturn gst_queue2_get_range (GstPad * pad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buffer); -static gboolean gst_queue2_src_activate_pull (GstPad * pad, gboolean active); -static gboolean gst_queue2_src_activate_push (GstPad * pad, gboolean active); -static gboolean gst_queue2_sink_activate_push (GstPad * pad, gboolean active); +static gboolean gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); static GstStateChangeReturn gst_queue2_change_state (GstElement * element, GstStateChange transition); @@ -251,6 +258,14 @@ static gboolean gst_queue2_is_filled (GstQueue2 * queue); static void update_cur_level (GstQueue2 * queue, GstQueue2Range * range); +typedef enum +{ + GST_QUEUE2_ITEM_TYPE_UNKNOWN = 0, + GST_QUEUE2_ITEM_TYPE_BUFFER, + GST_QUEUE2_ITEM_TYPE_BUFFER_LIST, + GST_QUEUE2_ITEM_TYPE_EVENT +} GstQueue2ItemType; + /* static guint gst_queue2_signals[LAST_SIGNAL] = { 0 }; */ static void @@ -358,7 +373,7 @@ gst_queue2_class_init (GstQueue2Class * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate)); - gst_element_class_set_details_simple (gstelement_class, "Queue 2", + gst_element_class_set_static_metadata (gstelement_class, "Queue 2", "Generic", "Simple data queue", "Erik Walthinsen <omega@cse.ogi.edu>, " @@ -375,32 +390,28 @@ gst_queue2_init (GstQueue2 * queue) gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_chain)); - gst_pad_set_activatepush_function (queue->sinkpad, - GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_push)); + gst_pad_set_chain_list_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_chain_list)); + gst_pad_set_activatemode_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_mode)); gst_pad_set_event_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event)); - gst_pad_set_getcaps_function (queue->sinkpad, - GST_DEBUG_FUNCPTR (gst_queue2_getcaps)); - gst_pad_set_acceptcaps_function (queue->sinkpad, - GST_DEBUG_FUNCPTR (gst_queue2_acceptcaps)); + gst_pad_set_query_function (queue->sinkpad, + GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query)); + GST_PAD_SET_PROXY_CAPS (queue->sinkpad); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - gst_pad_set_activatepull_function (queue->srcpad, - GST_DEBUG_FUNCPTR (gst_queue2_src_activate_pull)); - gst_pad_set_activatepush_function (queue->srcpad, - GST_DEBUG_FUNCPTR (gst_queue2_src_activate_push)); + gst_pad_set_activatemode_function (queue->srcpad, + GST_DEBUG_FUNCPTR (gst_queue2_src_activate_mode)); gst_pad_set_getrange_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue2_get_range)); - gst_pad_set_getcaps_function (queue->srcpad, - GST_DEBUG_FUNCPTR (gst_queue2_getcaps)); - gst_pad_set_acceptcaps_function (queue->srcpad, - GST_DEBUG_FUNCPTR (gst_queue2_acceptcaps)); gst_pad_set_event_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue2_handle_src_event)); gst_pad_set_query_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue2_handle_src_query)); + GST_PAD_SET_PROXY_CAPS (queue->srcpad); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); /* levels */ @@ -422,18 +433,18 @@ gst_queue2_init (GstQueue2 * queue) queue->sink_tainted = TRUE; queue->src_tainted = TRUE; - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; queue->is_eos = FALSE; queue->in_timer = g_timer_new (); queue->out_timer = g_timer_new (); - queue->qlock = g_mutex_new (); + g_mutex_init (&queue->qlock); queue->waiting_add = FALSE; - queue->item_add = g_cond_new (); + g_cond_init (&queue->item_add); queue->waiting_del = FALSE; - queue->item_del = g_cond_new (); - queue->queue = g_queue_new (); + g_cond_init (&queue->item_del); + g_queue_init (&queue->queue); queue->buffering_percent = 100; @@ -458,16 +469,16 @@ gst_queue2_finalize (GObject * object) GST_DEBUG_OBJECT (queue, "finalizing queue"); - while (!g_queue_is_empty (queue->queue)) { - GstMiniObject *data = g_queue_pop_head (queue->queue); + while (!g_queue_is_empty (&queue->queue)) { + GstMiniObject *data = g_queue_pop_head (&queue->queue); gst_mini_object_unref (data); } - g_queue_free (queue->queue); - g_mutex_free (queue->qlock); - g_cond_free (queue->item_add); - g_cond_free (queue->item_del); + g_queue_clear (&queue->queue); + g_mutex_clear (&queue->qlock); + g_cond_clear (&queue->item_add); + g_cond_clear (&queue->item_del); g_timer_destroy (queue->in_timer); g_timer_destroy (queue->out_timer); @@ -611,42 +622,6 @@ init_ranges (GstQueue2 * queue) queue->current = add_range (queue, 0); } -static gboolean -gst_queue2_acceptcaps (GstPad * pad, GstCaps * caps) -{ - GstQueue2 *queue; - GstPad *otherpad; - gboolean result; - - queue = GST_QUEUE2 (GST_PAD_PARENT (pad)); - - otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad); - result = gst_pad_peer_accept_caps (otherpad, caps); - - return result; -} - -static GstCaps * -gst_queue2_getcaps (GstPad * pad, GstCaps * filter) -{ - GstQueue2 *queue; - GstPad *otherpad; - GstCaps *result; - - queue = GST_QUEUE2 (gst_pad_get_parent (pad)); - if (G_UNLIKELY (queue == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad); - result = gst_pad_peer_get_caps (otherpad, filter); - if (result == NULL) - result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - gst_object_unref (queue); - - return result; -} - /* calculate the diff between running time on the sink and src of the queue. * This is the total amount of time in the queue. */ static void @@ -686,11 +661,9 @@ apply_segment (GstQueue2 * queue, GstEvent * event, GstSegment * segment, gst_event_copy_segment (event, segment); if (segment->format == GST_FORMAT_BYTES) { - if (QUEUE_IS_USING_TEMP_FILE (queue)) { + if (!QUEUE_IS_USING_QUEUE (queue) && is_sink) { /* start is where we'll be getting from and as such writing next */ queue->current = add_range (queue, segment->start); - /* update the stats for this range */ - update_cur_level (queue, queue->current); } } @@ -749,6 +722,52 @@ apply_buffer (GstQueue2 * queue, GstBuffer * buffer, GstSegment * segment, update_time_level (queue); } +static gboolean +buffer_list_apply_time (GstBuffer ** buf, guint idx, gpointer data) +{ + GstClockTime *timestamp = data; + + GST_TRACE ("buffer %u has ts %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT, idx, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (*buf))); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (*buf)) + *timestamp = GST_BUFFER_TIMESTAMP (*buf); + + if (GST_BUFFER_DURATION_IS_VALID (*buf)) + *timestamp += GST_BUFFER_DURATION (*buf); + + GST_TRACE ("ts now %" GST_TIME_FORMAT, GST_TIME_ARGS (*timestamp)); + return TRUE; +} + +/* take a buffer list and update segment, updating the time level of the queue */ +static void +apply_buffer_list (GstQueue2 * queue, GstBufferList * buffer_list, + GstSegment * segment, gboolean is_sink) +{ + GstClockTime timestamp; + + /* if no timestamp is set, assume it's continuous with the previous time */ + timestamp = segment->position; + + gst_buffer_list_foreach (buffer_list, buffer_list_apply_time, ×tamp); + + GST_DEBUG_OBJECT (queue, "last_stop updated to %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); + + segment->position = timestamp; + + if (is_sink) + queue->sink_tainted = TRUE; + else + queue->src_tainted = TRUE; + + /* calc diff with other end */ + update_time_level (queue); +} + static void update_buffering (GstQueue2 * queue) { @@ -819,7 +838,7 @@ update_buffering (GstQueue2 * queue) mode = GST_BUFFERING_DOWNLOAD; if (queue->byte_in_rate > 0) { - if (gst_pad_query_peer_duration (queue->sinkpad, GST_FORMAT_BYTES, + if (gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES, &duration)) { buffering_left = (gdouble) ((duration - @@ -984,6 +1003,8 @@ perform_seek_to_offset (GstQueue2 * queue, guint64 offset) GstEvent *event; gboolean res; + /* until we receive the FLUSH_STOP from this seek, we skip data */ + queue->seeking = TRUE; GST_QUEUE2_MUTEX_UNLOCK (queue); GST_DEBUG_OBJECT (queue, "Seeking to %" G_GUINT64_FORMAT, offset); @@ -1036,20 +1057,27 @@ gst_queue2_have_data (GstQueue2 * queue, guint64 offset, guint length) (offset + length) - range->writing_pos); } else { - GST_INFO_OBJECT (queue, "not found in any range"); - /* we don't have the range, see how far away we are, FIXME, find a good - * threshold based on the incoming rate. */ + GST_INFO_OBJECT (queue, "not found in any range off %" G_GUINT64_FORMAT + " len %u", offset, length); + /* we don't have the range, see how far away we are */ if (!queue->is_eos && queue->current) { + /* FIXME, find a good threshold based on the incoming rate. */ + guint64 threshold = 1024 * 512; + if (QUEUE_IS_USING_RING_BUFFER (queue)) { - if (offset < queue->current->offset || offset > - queue->current->writing_pos + QUEUE_MAX_BYTES (queue) - - queue->cur_level.bytes) { - perform_seek_to_offset (queue, offset); - } else { + guint64 distance; + + distance = QUEUE_MAX_BYTES (queue) - queue->cur_level.bytes; + /* don't wait for the complete buffer to fill */ + distance = MIN (distance, threshold); + + if (offset >= queue->current->offset && offset <= + queue->current->writing_pos + distance) { GST_INFO_OBJECT (queue, "requested data is within range, wait for data"); + return FALSE; } - } else if (offset < queue->current->writing_pos + 200000) { + } else if (offset < queue->current->writing_pos + threshold) { update_cur_pos (queue, queue->current, offset + length); GST_INFO_OBJECT (queue, "wait for data"); return FALSE; @@ -1122,7 +1150,7 @@ could_not_read: eos: { GST_DEBUG ("non-regular file hits EOS"); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } } @@ -1131,22 +1159,30 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, GstBuffer ** buffer) { GstBuffer *buf; + GstMapInfo info; guint8 *data; guint64 file_offset; guint block_length, remaining, read_length; guint64 rb_size; + guint64 max_size; guint64 rpos; GstFlowReturn ret = GST_FLOW_OK; /* allocate the output buffer of the requested size */ - buf = gst_buffer_new_allocate (NULL, length, 0); - data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); + if (*buffer == NULL) + buf = gst_buffer_new_allocate (NULL, length, NULL); + else + buf = *buffer; + + gst_buffer_map (buf, &info, GST_MAP_WRITE); + data = info.data; GST_DEBUG_OBJECT (queue, "Reading %u bytes from %" G_GUINT64_FORMAT, length, offset); rpos = offset; rb_size = queue->ring_buffer_max_size; + max_size = QUEUE_MAX_BYTES (queue); remaining = length; while (remaining > 0) { @@ -1165,16 +1201,16 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, GST_DEBUG_OBJECT (queue, "reading %" G_GUINT64_FORMAT ", writing %" G_GUINT64_FORMAT - ", level %" G_GUINT64_FORMAT, - rpos, queue->current->writing_pos, level); + ", level %" G_GUINT64_FORMAT ", max %" G_GUINT64_FORMAT, + rpos, queue->current->writing_pos, level, max_size); - if (level >= rb_size) { + if (level >= max_size) { /* we don't have the data but if we have a ring buffer that is full, we * need to read */ GST_DEBUG_OBJECT (queue, - "ring buffer full, reading ring-buffer-max-size %" - G_GUINT64_FORMAT " bytes", rb_size); - read_length = rb_size; + "ring buffer full, reading QUEUE_MAX_BYTES %" + G_GUINT64_FORMAT " bytes", max_size); + read_length = max_size; } else if (queue->is_eos) { /* won't get any more data so read any data we have */ if (level) { @@ -1182,21 +1218,20 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, "EOS hit but read %" G_GUINT64_FORMAT " bytes that we have", level); read_length = level; + remaining = level; + length = level; } else goto hit_eos; } } if (read_length == 0) { - if (QUEUE_IS_USING_RING_BUFFER (queue) - && queue->current->max_reading_pos > rpos) { - /* protect cached data (data between offset and max_reading_pos) - * and update current level */ + if (QUEUE_IS_USING_RING_BUFFER (queue)) { GST_DEBUG_OBJECT (queue, - "protecting cached data [%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT - "]", rpos, queue->current->max_reading_pos); - queue->current->max_reading_pos = rpos; - update_cur_level (queue, queue->current); + "update current position [%" G_GUINT64_FORMAT "-%" + G_GUINT64_FORMAT "]", rpos, queue->current->max_reading_pos); + update_cur_pos (queue, queue->current, rpos); + GST_QUEUE2_SIGNAL_DEL (queue); } GST_DEBUG_OBJECT (queue, "waiting for add"); GST_QUEUE2_WAIT_ADD_CHECK (queue, queue->srcresult, out_flushing); @@ -1251,7 +1286,8 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, GST_DEBUG_OBJECT (queue, "%u bytes left to read", remaining); } - gst_buffer_unmap (buf, data, length); + gst_buffer_unmap (buf, &info); + gst_buffer_resize (buf, 0, length); GST_BUFFER_OFFSET (buf) = offset; GST_BUFFER_OFFSET_END (buf) = offset + length; @@ -1264,20 +1300,25 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length, hit_eos: { GST_DEBUG_OBJECT (queue, "EOS hit and we don't have any requested data"); - gst_buffer_unref (buf); - return GST_FLOW_UNEXPECTED; + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_EOS; } out_flushing: { GST_DEBUG_OBJECT (queue, "we are flushing"); - gst_buffer_unref (buf); - return GST_FLOW_WRONG_STATE; + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); + return GST_FLOW_FLUSHING; } read_error: { GST_DEBUG_OBJECT (queue, "we have a read error"); - gst_buffer_unmap (buf, data, 0); - gst_buffer_unref (buf); + gst_buffer_unmap (buf, &info); + if (*buffer == NULL) + gst_buffer_unref (buf); return ret; } } @@ -1288,12 +1329,15 @@ gst_queue2_read_item_from_file (GstQueue2 * queue) { GstMiniObject *item; - if (queue->starting_segment != NULL) { + if (queue->stream_start_event != NULL) { + item = GST_MINI_OBJECT_CAST (queue->stream_start_event); + queue->stream_start_event = NULL; + } else if (queue->starting_segment != NULL) { item = GST_MINI_OBJECT_CAST (queue->starting_segment); queue->starting_segment = NULL; } else { GstFlowReturn ret; - GstBuffer *buffer; + GstBuffer *buffer = NULL; guint64 reading_pos; reading_pos = queue->current->reading_pos; @@ -1306,7 +1350,7 @@ gst_queue2_read_item_from_file (GstQueue2 * queue) case GST_FLOW_OK: item = GST_MINI_OBJECT_CAST (buffer); break; - case GST_FLOW_UNEXPECTED: + case GST_FLOW_EOS: item = GST_MINI_OBJECT_CAST (gst_event_new_eos ()); break; default: @@ -1442,8 +1486,8 @@ gst_queue2_locked_flush (GstQueue2 * queue) gst_queue2_flush_temp_file (queue); init_ranges (queue); } else { - while (!g_queue_is_empty (queue->queue)) { - GstMiniObject *data = g_queue_pop_head (queue->queue); + while (!g_queue_is_empty (&queue->queue)) { + GstMiniObject *data = g_queue_pop_head (&queue->queue); /* Then lose another reference because we are supposed to destroy that data when flushing */ @@ -1459,6 +1503,7 @@ gst_queue2_locked_flush (GstQueue2 * queue) gst_event_unref (queue->starting_segment); queue->starting_segment = NULL; queue->segment_event_received = FALSE; + gst_event_replace (&queue->stream_start_event, NULL); /* we deleted a lot of something */ GST_QUEUE2_SIGNAL_DEL (queue); @@ -1502,9 +1547,9 @@ out_flushing: static gboolean gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) { - guint8 *odata, *data, *ring_buffer; + GstMapInfo info; + guint8 *data, *ring_buffer; guint size, rb_size; - gsize osize; guint64 writing_pos, new_writing_pos; GstQueue2Range *range, *prev, *next; @@ -1515,13 +1560,13 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) ring_buffer = queue->ring_buffer; rb_size = queue->ring_buffer_max_size; - odata = gst_buffer_map (buffer, &osize, NULL, GST_MAP_READ); + gst_buffer_map (buffer, &info, GST_MAP_READ); - size = osize; - data = odata; + size = info.size; + data = info.data; GST_DEBUG_OBJECT (queue, "Writing %u bytes to %" G_GUINT64_FORMAT, size, - GST_BUFFER_OFFSET (buffer)); + writing_pos); while (size > 0) { guint to_write; @@ -1742,7 +1787,7 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) GST_QUEUE2_SIGNAL_ADD (queue); } - gst_buffer_unmap (buffer, odata, osize); + gst_buffer_unmap (buffer, &info); return TRUE; @@ -1750,14 +1795,14 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) out_flushing: { GST_DEBUG_OBJECT (queue, "we are flushing"); - gst_buffer_unmap (buffer, odata, osize); - /* FIXME - GST_FLOW_UNEXPECTED ? */ + gst_buffer_unmap (buffer, &info); + /* FIXME - GST_FLOW_EOS ? */ return FALSE; } seek_failed: { GST_ELEMENT_ERROR (queue, RESOURCE, SEEK, (NULL), GST_ERROR_SYSTEM); - gst_buffer_unmap (buffer, odata, osize); + gst_buffer_unmap (buffer, &info); return FALSE; } handle_error: @@ -1773,16 +1818,45 @@ handle_error: ("%s", g_strerror (errno))); } } - gst_buffer_unmap (buffer, odata, osize); + gst_buffer_unmap (buffer, &info); return FALSE; } } +static gboolean +buffer_list_create_write (GstBuffer ** buf, guint idx, gpointer q) +{ + GstQueue2 *queue = q; + + GST_TRACE_OBJECT (queue, + "writing buffer %u of size %" G_GSIZE_FORMAT " bytes", idx, + gst_buffer_get_size (*buf)); + + if (!gst_queue2_create_write (queue, *buf)) { + GST_INFO_OBJECT (queue, "create_write() returned FALSE, bailing out"); + return FALSE; + } + return TRUE; +} + +static gboolean +buffer_list_calc_size (GstBuffer ** buf, guint idx, gpointer data) +{ + guint *p_size = data; + gsize buf_size; + + buf_size = gst_buffer_get_size (*buf); + GST_TRACE ("buffer %u in has size %" G_GSIZE_FORMAT, idx, buf_size); + *p_size += buf_size; + return TRUE; +} + /* enqueue an item an update the level stats */ static void -gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, gboolean isbuffer) +gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, + GstQueue2ItemType item_type) { - if (isbuffer) { + if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { GstBuffer *buffer; guint size; @@ -1805,7 +1879,32 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, gboolean isbuffer) /* FIXME - check return value? */ gst_queue2_create_write (queue, buffer); } - } else if (GST_IS_EVENT (item)) { + } else if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GstBufferList *buffer_list; + guint size = 0; + + buffer_list = GST_BUFFER_LIST_CAST (item); + + gst_buffer_list_foreach (buffer_list, buffer_list_calc_size, &size); + GST_LOG_OBJECT (queue, "total size of buffer list: %u bytes", size); + + /* add buffer to the statistics */ + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers++; + queue->cur_level.bytes += size; + } + queue->bytes_in += size; + + /* apply new buffer to segment stats */ + apply_buffer_list (queue, buffer_list, &queue->sink_segment, TRUE); + + /* update the byterate stats */ + update_in_rates (queue); + + if (!QUEUE_IS_USING_QUEUE (queue)) { + gst_buffer_list_foreach (buffer_list, buffer_list_create_write, queue); + } + } else if (item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { GstEvent *event; event = GST_EVENT_CAST (item); @@ -1831,10 +1930,17 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, gboolean isbuffer) queue->starting_segment = event; item = NULL; } - /* a new segment allows us to accept more buffers if we got UNEXPECTED + /* a new segment allows us to accept more buffers if we got EOS * from downstream */ queue->unexpected = FALSE; break; + case GST_EVENT_STREAM_START: + if (!QUEUE_IS_USING_QUEUE (queue)) { + gst_event_replace (&queue->stream_start_event, event); + gst_event_unref (event); + item = NULL; + } + break; default: if (!QUEUE_IS_USING_QUEUE (queue)) goto unexpected_event; @@ -1853,7 +1959,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, gboolean isbuffer) update_buffering (queue); if (QUEUE_IS_USING_QUEUE (queue)) { - g_queue_push_tail (queue->queue, item); + g_queue_push_tail (&queue->queue, item); } else { gst_mini_object_unref (GST_MINI_OBJECT_CAST (item)); } @@ -1877,14 +1983,14 @@ unexpected_event: /* dequeue an item from the queue and update level stats */ static GstMiniObject * -gst_queue2_locked_dequeue (GstQueue2 * queue, gboolean * is_buffer) +gst_queue2_locked_dequeue (GstQueue2 * queue, GstQueue2ItemType * item_type) { GstMiniObject *item; if (!QUEUE_IS_USING_QUEUE (queue)) item = gst_queue2_read_item_from_file (queue); else - item = g_queue_pop_head (queue->queue); + item = g_queue_pop_head (&queue->queue); if (item == NULL) goto no_item; @@ -1895,7 +2001,7 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, gboolean * is_buffer) buffer = GST_BUFFER_CAST (item); size = gst_buffer_get_size (buffer); - *is_buffer = TRUE; + *item_type = GST_QUEUE2_ITEM_TYPE_BUFFER; GST_CAT_LOG_OBJECT (queue_dataflow, queue, "retrieved buffer %p from queue", buffer); @@ -1916,7 +2022,7 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, gboolean * is_buffer) } else if (GST_IS_EVENT (item)) { GstEvent *event = GST_EVENT_CAST (item); - *is_buffer = FALSE; + *item_type = GST_QUEUE2_ITEM_TYPE_EVENT; GST_CAT_LOG_OBJECT (queue_dataflow, queue, "retrieved event %p from queue", event); @@ -1932,11 +2038,36 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, gboolean * is_buffer) default: break; } + } else if (GST_IS_BUFFER_LIST (item)) { + GstBufferList *buffer_list; + guint size = 0; + + buffer_list = GST_BUFFER_LIST_CAST (item); + gst_buffer_list_foreach (buffer_list, buffer_list_calc_size, &size); + *item_type = GST_QUEUE2_ITEM_TYPE_BUFFER_LIST; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "retrieved buffer list %p from queue", buffer_list); + + if (QUEUE_IS_USING_QUEUE (queue)) { + queue->cur_level.buffers--; + queue->cur_level.bytes -= size; + } + queue->bytes_out += size; + + apply_buffer_list (queue, buffer_list, &queue->src_segment, FALSE); + /* update the byterate stats */ + update_out_rates (queue); + /* update the buffering */ + if (queue->use_buffering) + update_buffering (queue); + } else { g_warning ("Unexpected item %p dequeued from queue %s (refcounting problem?)", item, GST_OBJECT_NAME (queue)); item = NULL; + *item_type = GST_QUEUE2_ITEM_TYPE_UNKNOWN; } GST_QUEUE2_SIGNAL_DEL (queue); @@ -1951,24 +2082,25 @@ no_item: } static gboolean -gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) +gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { GstQueue2 *queue; - queue = GST_QUEUE2 (GST_OBJECT_PARENT (pad)); + queue = GST_QUEUE2 (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received flush start event"); - if (QUEUE_IS_USING_QUEUE (queue)) { + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { /* forward event */ gst_pad_push_event (queue->srcpad, event); /* now unblock the chain function */ GST_QUEUE2_MUTEX_LOCK (queue); - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; /* unblock the loop and chain functions */ GST_QUEUE2_SIGNAL_ADD (queue); GST_QUEUE2_SIGNAL_DEL (queue); @@ -1981,7 +2113,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) } else { GST_QUEUE2_MUTEX_LOCK (queue); /* flush the sink pad */ - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->sinkresult = GST_FLOW_FLUSHING; GST_QUEUE2_SIGNAL_DEL (queue); GST_QUEUE2_MUTEX_UNLOCK (queue); @@ -1993,7 +2125,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received flush stop event"); - if (QUEUE_IS_USING_QUEUE (queue)) { + if (GST_PAD_MODE (queue->srcpad) == GST_PAD_MODE_PUSH) { /* forward event */ gst_pad_push_event (queue->srcpad, event); @@ -2003,6 +2135,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) queue->sinkresult = GST_FLOW_OK; queue->is_eos = FALSE; queue->unexpected = FALSE; + queue->seeking = FALSE; /* reset rate counters */ reset_rate_timer (queue); gst_pad_start_task (queue->srcpad, (GstTaskFunction) gst_queue2_loop, @@ -2014,6 +2147,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) queue->is_eos = FALSE; queue->unexpected = FALSE; queue->sinkresult = GST_FLOW_OK; + queue->seeking = FALSE; GST_QUEUE2_MUTEX_UNLOCK (queue); gst_event_unref (event); @@ -2027,7 +2161,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event) /* refuse more events on EOS */ if (queue->is_eos) goto out_eos; - gst_queue2_locked_enqueue (queue, event, FALSE); + gst_queue2_locked_enqueue (queue, event, GST_QUEUE2_ITEM_TYPE_EVENT); GST_QUEUE2_MUTEX_UNLOCK (queue); } else { /* non-serialized events are passed upstream. */ @@ -2056,6 +2190,25 @@ out_eos: } static gboolean +gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query) +{ + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + default: + if (GST_QUERY_IS_SERIALIZED (query)) { + GST_WARNING_OBJECT (pad, "unhandled serialized query"); + res = FALSE; + } else { + res = gst_pad_query_default (pad, parent, query); + } + break; + } + return res; +} + +static gboolean gst_queue2_is_empty (GstQueue2 * queue) { /* never empty on EOS */ @@ -2065,7 +2218,7 @@ gst_queue2_is_empty (GstQueue2 * queue) if (!QUEUE_IS_USING_QUEUE (queue) && queue->current) { return queue->current->writing_pos <= queue->current->max_reading_pos; } else { - if (queue->queue->length == 0) + if (queue->queue.length == 0) return TRUE; } @@ -2117,18 +2270,9 @@ gst_queue2_is_filled (GstQueue2 * queue) } static GstFlowReturn -gst_queue2_chain (GstPad * pad, GstBuffer * buffer) +gst_queue2_chain_buffer_or_buffer_list (GstQueue2 * queue, + GstMiniObject * item, GstQueue2ItemType item_type) { - GstQueue2 *queue; - - queue = GST_QUEUE2 (GST_OBJECT_PARENT (pad)); - - GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of size %" - G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %" - GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); - /* we have to lock the queue since we span threads */ GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing); /* when we received EOS, we refuse more data */ @@ -2138,11 +2282,15 @@ gst_queue2_chain (GstPad * pad, GstBuffer * buffer) if (queue->unexpected) goto out_unexpected; + /* while we didn't receive the newsegment, we're seeking and we skip data */ + if (queue->seeking) + goto out_seeking; + if (!gst_queue2_wait_free_space (queue)) goto out_flushing; /* put buffer in queue now */ - gst_queue2_locked_enqueue (queue, buffer, TRUE); + gst_queue2_locked_enqueue (queue, item, item_type); GST_QUEUE2_MUTEX_UNLOCK (queue); return GST_FLOW_OK; @@ -2155,7 +2303,7 @@ out_flushing: GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because task paused, reason: %s", gst_flow_get_name (ret)); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_buffer_unref (buffer); + gst_mini_object_unref (item); return ret; } @@ -2163,19 +2311,102 @@ out_eos: { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_buffer_unref (buffer); + gst_mini_object_unref (item); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; + } +out_seeking: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we are seeking"); + GST_QUEUE2_MUTEX_UNLOCK (queue); + gst_mini_object_unref (item); + + return GST_FLOW_OK; } out_unexpected: { - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "exit because we received UNEXPECTED"); + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS"); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_buffer_unref (buffer); + gst_mini_object_unref (item); + + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_queue2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstQueue2 *queue; + + queue = GST_QUEUE2 (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of " + "size %" G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + return gst_queue2_chain_buffer_or_buffer_list (queue, + GST_MINI_OBJECT_CAST (buffer), GST_QUEUE2_ITEM_TYPE_BUFFER); +} + +static GstFlowReturn +gst_queue2_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * buffer_list) +{ + GstQueue2 *queue; - return GST_FLOW_UNEXPECTED; + queue = GST_QUEUE2 (parent); + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "received buffer list %p", buffer_list); + + return gst_queue2_chain_buffer_or_buffer_list (queue, + GST_MINI_OBJECT_CAST (buffer_list), GST_QUEUE2_ITEM_TYPE_BUFFER_LIST); +} + +static GstMiniObject * +gst_queue2_dequeue_on_eos (GstQueue2 * queue, GstQueue2ItemType * item_type) +{ + GstMiniObject *data; + + GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream"); + + /* stop pushing buffers, we dequeue all items until we see an item that we + * can push again, which is EOS or SEGMENT. If there is nothing in the + * queue we can push, we set a flag to make the sinkpad refuse more + * buffers with an EOS return value until we receive something + * pushable again or we get flushed. */ + while ((data = gst_queue2_locked_dequeue (queue, item_type))) { + if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer %p", data); + gst_buffer_unref (GST_BUFFER_CAST (data)); + } else if (*item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); + + if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT) { + /* we found a pushable item in the queue, push it out */ + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "pushing pushable event %s after EOS", GST_EVENT_TYPE_NAME (event)); + return data; + } + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS event %p", event); + gst_event_unref (event); + } else if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "dropping EOS buffer list %p", data); + gst_buffer_list_unref (GST_BUFFER_LIST_CAST (data)); + } } + /* no more items in the queue. Set the unexpected flag so that upstream + * make us refuse any more buffers on the sinkpad. Since we will still + * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the + * task function does not shut down. */ + queue->unexpected = TRUE; + return NULL; } /* dequeue an item from the queue an push it downstream. This functions returns @@ -2185,16 +2416,16 @@ gst_queue2_push_one (GstQueue2 * queue) { GstFlowReturn result = GST_FLOW_OK; GstMiniObject *data; - gboolean is_buffer = FALSE; + GstQueue2ItemType item_type; - data = gst_queue2_locked_dequeue (queue, &is_buffer); + data = gst_queue2_locked_dequeue (queue, &item_type); if (data == NULL) goto no_item; next: GST_QUEUE2_MUTEX_UNLOCK (queue); - if (is_buffer) { + if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) { GstBuffer *buffer; #if 0 GstCaps *caps; @@ -2216,56 +2447,59 @@ next: /* need to check for srcresult here as well */ GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); - if (result == GST_FLOW_UNEXPECTED) { - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "got UNEXPECTED from downstream"); - /* stop pushing buffers, we dequeue all items until we see an item that we - * can push again, which is EOS or SEGMENT. If there is nothing in the - * queue we can push, we set a flag to make the sinkpad refuse more - * buffers with an UNEXPECTED return value until we receive something - * pushable again or we get flushed. */ - while ((data = gst_queue2_locked_dequeue (queue, &is_buffer))) { - if (is_buffer) { - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "dropping UNEXPECTED buffer %p", data); - gst_buffer_unref (GST_BUFFER_CAST (data)); - } else if (GST_IS_EVENT (data)) { - GstEvent *event = GST_EVENT_CAST (data); - GstEventType type = GST_EVENT_TYPE (event); - - if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT) { - /* we found a pushable item in the queue, push it out */ - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "pushing pushable event %s after UNEXPECTED", - GST_EVENT_TYPE_NAME (event)); - goto next; - } - GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "dropping UNEXPECTED event %p", event); - gst_event_unref (event); - } - } - /* no more items in the queue. Set the unexpected flag so that upstream - * make us refuse any more buffers on the sinkpad. Since we will still - * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the - * task function does not shut down. */ - queue->unexpected = TRUE; + if (result == GST_FLOW_EOS) { + data = gst_queue2_dequeue_on_eos (queue, &item_type); + if (data != NULL) + goto next; + /* Since we will still accept EOS and SEGMENT we return _FLOW_OK + * to the caller so that the task function does not shut down */ result = GST_FLOW_OK; } - } else if (GST_IS_EVENT (data)) { + } else if (item_type == GST_QUEUE2_ITEM_TYPE_EVENT) { GstEvent *event = GST_EVENT_CAST (data); GstEventType type = GST_EVENT_TYPE (event); gst_pad_push_event (queue->srcpad, event); - /* if we're EOS, return UNEXPECTED so that the task pauses. */ + /* if we're EOS, return EOS so that the task pauses. */ if (type == GST_EVENT_EOS) { GST_CAT_LOG_OBJECT (queue_dataflow, queue, - "pushed EOS event %p, return UNEXPECTED", event); - result = GST_FLOW_UNEXPECTED; + "pushed EOS event %p, return EOS", event); + result = GST_FLOW_EOS; } GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + } else if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) { + GstBufferList *buffer_list; +#if 0 + GstBuffer *first_buf; + GstCaps *caps; +#endif + + buffer_list = GST_BUFFER_LIST_CAST (data); + +#if 0 + first_buf = gst_buffer_list_get (buffer_list, 0); + caps = (first_buf != NULL) ? GST_BUFFER_CAPS (first_buf) : NULL; + + /* set caps before pushing the buffer so that core does not try to do + * something fancy to check if this is possible. */ + if (caps && caps != GST_PAD_CAPS (queue->srcpad)) + gst_pad_set_caps (queue->srcpad, caps); +#endif + + result = gst_pad_push_list (queue->srcpad, buffer_list); + + /* need to check for srcresult here as well */ + GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); + if (result == GST_FLOW_EOS) { + data = gst_queue2_dequeue_on_eos (queue, &item_type); + if (data != NULL) + goto next; + /* Since we will still accept EOS and SEGMENT we return _FLOW_OK + * to the caller so that the task function does not shut down */ + result = GST_FLOW_OK; + } } return result; @@ -2279,7 +2513,7 @@ no_item: out_flushing: { GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we are flushing"); - return GST_FLOW_WRONG_STATE; + return GST_FLOW_FLUSHING; } } @@ -2337,8 +2571,8 @@ out_flushing: GST_CAT_LOG_OBJECT (queue_dataflow, queue, "pause task, reason: %s", gst_flow_get_name (queue->srcresult)); /* let app know about us giving up if upstream is not expected to do so */ - /* UNEXPECTED is already taken care of elsewhere */ - if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED)) { + /* EOS is already taken care of elsewhere */ + if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { GST_ELEMENT_ERROR (queue, STREAM, FAILED, (_("Internal data flow error.")), ("streaming task paused, reason %s (%d)", @@ -2350,15 +2584,11 @@ out_flushing: } static gboolean -gst_queue2_handle_src_event (GstPad * pad, GstEvent * event) +gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; - GstQueue2 *queue = GST_QUEUE2 (gst_pad_get_parent (pad)); + GstQueue2 *queue = GST_QUEUE2 (parent); - if (G_UNLIKELY (queue == NULL)) { - gst_event_unref (event); - return FALSE; - } #ifndef GST_DISABLE_GST_DEBUG GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%s)", event, GST_EVENT_TYPE_NAME (event)); @@ -2373,7 +2603,7 @@ gst_queue2_handle_src_event (GstPad * pad, GstEvent * event) /* now unblock the getrange function */ GST_QUEUE2_MUTEX_LOCK (queue); GST_DEBUG_OBJECT (queue, "flushing"); - queue->srcresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; GST_QUEUE2_SIGNAL_ADD (queue); GST_QUEUE2_MUTEX_UNLOCK (queue); @@ -2390,12 +2620,6 @@ gst_queue2_handle_src_event (GstPad * pad, GstEvent * event) /* now unblock the getrange function */ GST_QUEUE2_MUTEX_LOCK (queue); queue->srcresult = GST_FLOW_OK; - if (queue->current) { - /* forget the highest read offset, we'll calculate a new one when we - * get the next getrange request. We need to do this in order to reset - * the buffering percentage */ - queue->current->max_reading_pos = 0; - } GST_QUEUE2_MUTEX_UNLOCK (queue); /* when using a temp file, we eat the event */ @@ -2408,31 +2632,15 @@ gst_queue2_handle_src_event (GstPad * pad, GstEvent * event) break; } - gst_object_unref (queue); return res; } static gboolean -gst_queue2_peer_query (GstQueue2 * queue, GstPad * pad, GstQuery * query) -{ - gboolean ret = FALSE; - GstPad *peer; - - if ((peer = gst_pad_get_peer (pad))) { - ret = gst_pad_query (peer, query); - gst_object_unref (peer); - } - return ret; -} - -static gboolean -gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) +gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstQueue2 *queue; - queue = GST_QUEUE2 (gst_pad_get_parent (pad)); - if (G_UNLIKELY (queue == NULL)) - return FALSE; + queue = GST_QUEUE2 (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: @@ -2440,7 +2648,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) gint64 peer_pos; GstFormat format; - if (!gst_queue2_peer_query (queue, queue->sinkpad, query)) + if (!gst_pad_peer_query (queue->sinkpad, query)) goto peer_failed; /* get peer position */ @@ -2467,7 +2675,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) { GST_DEBUG_OBJECT (queue, "doing peer query"); - if (!gst_queue2_peer_query (queue, queue->sinkpad, query)) + if (!gst_pad_peer_query (queue->sinkpad, query)) goto peer_failed; GST_DEBUG_OBJECT (queue, "peer query success"); @@ -2482,7 +2690,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) /* FIXME - is this condition correct? what should ring buffer do? */ if (QUEUE_IS_USING_QUEUE (queue)) { /* no temp file, just forward to the peer */ - if (!gst_queue2_peer_query (queue, queue->sinkpad, query)) + if (!gst_pad_peer_query (queue->sinkpad, query)) goto peer_failed; GST_DEBUG_OBJECT (queue, "buffering forwarded to peer"); } else { @@ -2512,7 +2720,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) duration = writing_pos; } else { /* get duration of upstream in bytes */ - peer_res = gst_pad_query_peer_duration (queue->sinkpad, + peer_res = gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES, &duration); } @@ -2597,28 +2805,32 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query) case GST_QUERY_SCHEDULING: { gboolean pull_mode; + GstSchedulingFlags flags = 0; /* we can operate in pull mode when we are using a tempfile */ pull_mode = !QUEUE_IS_USING_QUEUE (queue); - gst_query_set_scheduling (query, pull_mode, pull_mode, FALSE, 0, -1, 1); + if (pull_mode) + flags |= GST_SCHEDULING_FLAG_SEEKABLE; + gst_query_set_scheduling (query, flags, 0, -1, 0); + if (pull_mode) + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); break; } default: /* peer handled other queries */ - if (!gst_queue2_peer_query (queue, queue->sinkpad, query)) + if (!gst_pad_query_default (pad, parent, query)) goto peer_failed; break; } - gst_object_unref (queue); return TRUE; /* ERRORS */ peer_failed: { GST_DEBUG_OBJECT (queue, "failed peer query"); - gst_object_unref (queue); return FALSE; } } @@ -2626,8 +2838,11 @@ peer_failed: static gboolean gst_queue2_handle_query (GstElement * element, GstQuery * query) { + GstQueue2 *queue = GST_QUEUE2 (element); + /* simply forward to the srcpad query function */ - return gst_queue2_handle_src_query (GST_QUEUE2_CAST (element)->srcpad, query); + return gst_queue2_handle_src_query (queue->srcpad, GST_OBJECT_CAST (element), + query); } static void @@ -2635,7 +2850,7 @@ gst_queue2_update_upstream_size (GstQueue2 * queue) { gint64 upstream_size = -1; - if (gst_pad_query_peer_duration (queue->sinkpad, GST_FORMAT_BYTES, + if (gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES, &upstream_size)) { GST_INFO_OBJECT (queue, "upstream size: %" G_GINT64_FORMAT, upstream_size); queue->upstream_size = upstream_size; @@ -2643,13 +2858,13 @@ gst_queue2_update_upstream_size (GstQueue2 * queue) } static GstFlowReturn -gst_queue2_get_range (GstPad * pad, guint64 offset, guint length, - GstBuffer ** buffer) +gst_queue2_get_range (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buffer) { GstQueue2 *queue; GstFlowReturn ret; - queue = GST_QUEUE2_CAST (gst_pad_get_parent (pad)); + queue = GST_QUEUE2_CAST (parent); length = (length == -1) ? DEFAULT_BUFFER_SIZE : length; GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing); @@ -2681,8 +2896,6 @@ gst_queue2_get_range (GstPad * pad, guint64 offset, guint length, ret = gst_queue2_create_read (queue, offset, length, buffer); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_object_unref (queue); - return ret; /* ERRORS */ @@ -2692,60 +2905,64 @@ out_flushing: GST_DEBUG_OBJECT (queue, "we are flushing"); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_object_unref (queue); return ret; } out_unexpected: { GST_DEBUG_OBJECT (queue, "read beyond end of file"); GST_QUEUE2_MUTEX_UNLOCK (queue); - gst_object_unref (queue); - return GST_FLOW_UNEXPECTED; + return GST_FLOW_EOS; } } /* sink currently only operates in push mode */ static gboolean -gst_queue2_sink_activate_push (GstPad * pad, gboolean active) +gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { - gboolean result = TRUE; + gboolean result; GstQueue2 *queue; - queue = GST_QUEUE2 (gst_pad_get_parent (pad)); + queue = GST_QUEUE2 (parent); - if (active) { - GST_QUEUE2_MUTEX_LOCK (queue); - GST_DEBUG_OBJECT (queue, "activating push mode"); - queue->srcresult = GST_FLOW_OK; - queue->sinkresult = GST_FLOW_OK; - queue->is_eos = FALSE; - queue->unexpected = FALSE; - reset_rate_timer (queue); - GST_QUEUE2_MUTEX_UNLOCK (queue); - } else { - /* unblock chain function */ - GST_QUEUE2_MUTEX_LOCK (queue); - GST_DEBUG_OBJECT (queue, "deactivating push mode"); - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; - gst_queue2_locked_flush (queue); - GST_QUEUE2_MUTEX_UNLOCK (queue); + switch (mode) { + case GST_PAD_MODE_PUSH: + if (active) { + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "activating push mode"); + queue->srcresult = GST_FLOW_OK; + queue->sinkresult = GST_FLOW_OK; + queue->is_eos = FALSE; + queue->unexpected = FALSE; + reset_rate_timer (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } else { + /* unblock chain function */ + GST_QUEUE2_MUTEX_LOCK (queue); + GST_DEBUG_OBJECT (queue, "deactivating push mode"); + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; + gst_queue2_locked_flush (queue); + GST_QUEUE2_MUTEX_UNLOCK (queue); + } + result = TRUE; + break; + default: + result = FALSE; + break; } - - gst_object_unref (queue); - return result; } /* src operating in push mode, we start a task on the source pad that pushes out * buffers from the queue */ static gboolean -gst_queue2_src_activate_push (GstPad * pad, gboolean active) +gst_queue2_src_activate_push (GstPad * pad, GstObject * parent, gboolean active) { gboolean result = FALSE; GstQueue2 *queue; - queue = GST_QUEUE2 (gst_pad_get_parent (pad)); + queue = GST_QUEUE2 (parent); if (active) { GST_QUEUE2_MUTEX_LOCK (queue); @@ -2760,8 +2977,8 @@ gst_queue2_src_activate_push (GstPad * pad, gboolean active) /* unblock loop function */ GST_QUEUE2_MUTEX_LOCK (queue); GST_DEBUG_OBJECT (queue, "deactivating push mode"); - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; /* the item add signal will unblock */ GST_QUEUE2_SIGNAL_ADD (queue); GST_QUEUE2_MUTEX_UNLOCK (queue); @@ -2770,19 +2987,17 @@ gst_queue2_src_activate_push (GstPad * pad, gboolean active) result = gst_pad_stop_task (pad); } - gst_object_unref (queue); - return result; } /* pull mode, downstream will call our getrange function */ static gboolean -gst_queue2_src_activate_pull (GstPad * pad, gboolean active) +gst_queue2_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active) { gboolean result; GstQueue2 *queue; - queue = GST_QUEUE2 (gst_pad_get_parent (pad)); + queue = GST_QUEUE2 (parent); if (active) { GST_QUEUE2_MUTEX_LOCK (queue); @@ -2808,26 +3023,46 @@ gst_queue2_src_activate_pull (GstPad * pad, gboolean active) GST_DEBUG_OBJECT (queue, "no temp file, cannot activate pull mode"); /* this is not allowed, we cannot operate in pull mode without a temp * file. */ - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; result = FALSE; } GST_QUEUE2_MUTEX_UNLOCK (queue); } else { GST_QUEUE2_MUTEX_LOCK (queue); GST_DEBUG_OBJECT (queue, "deactivating pull mode"); - queue->srcresult = GST_FLOW_WRONG_STATE; - queue->sinkresult = GST_FLOW_WRONG_STATE; + queue->srcresult = GST_FLOW_FLUSHING; + queue->sinkresult = GST_FLOW_FLUSHING; /* this will unlock getrange */ GST_QUEUE2_SIGNAL_ADD (queue); result = TRUE; GST_QUEUE2_MUTEX_UNLOCK (queue); } - gst_object_unref (queue); return result; } +static gboolean +gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) +{ + gboolean res; + + switch (mode) { + case GST_PAD_MODE_PULL: + res = gst_queue2_src_activate_pull (pad, parent, active); + break; + case GST_PAD_MODE_PUSH: + res = gst_queue2_src_activate_push (pad, parent, active); + break; + default: + GST_LOG_OBJECT (pad, "unknown activation mode %d", mode); + res = FALSE; + break; + } + return res; +} + static GstStateChangeReturn gst_queue2_change_state (GstElement * element, GstStateChange transition) { @@ -2857,6 +3092,7 @@ gst_queue2_change_state (GstElement * element, GstStateChange transition) } queue->segment_event_received = FALSE; queue->starting_segment = NULL; + gst_event_replace (&queue->stream_start_event, NULL); GST_QUEUE2_MUTEX_UNLOCK (queue); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -2891,6 +3127,7 @@ gst_queue2_change_state (GstElement * element, GstStateChange transition) gst_event_unref (queue->starting_segment); queue->starting_segment = NULL; } + gst_event_replace (&queue->stream_start_event, NULL); GST_QUEUE2_MUTEX_UNLOCK (queue); break; case GST_STATE_CHANGE_READY_TO_NULL: diff --git a/plugins/elements/gstqueue2.h b/plugins/elements/gstqueue2.h index ccbead6..25beef4 100644 --- a/plugins/elements/gstqueue2.h +++ b/plugins/elements/gstqueue2.h @@ -95,7 +95,7 @@ struct _GstQueue2 gboolean unexpected; /* the queue of data we're keeping our hands on */ - GQueue *queue; + GQueue queue; GstQueue2Size cur_level; /* currently in the queue */ GstQueue2Size max_level; /* max. amount of data allowed in the queue */ @@ -124,11 +124,11 @@ struct _GstQueue2 guint64 bytes_out; gdouble byte_out_rate; - GMutex *qlock; /* lock for queue (vs object lock) */ + GMutex qlock; /* lock for queue (vs object lock) */ gboolean waiting_add; - GCond *item_add; /* signals buffers now available for reading */ + GCond item_add; /* signals buffers now available for reading */ gboolean waiting_del; - GCond *item_del; /* signals space now available for writing */ + GCond item_del; /* signals space now available for writing */ /* temp location stuff */ gchar *temp_template; @@ -143,6 +143,9 @@ struct _GstQueue2 * because we can't save it on the file */ gboolean segment_event_received; GstEvent *starting_segment; + gboolean seeking; + + GstEvent *stream_start_event; guint64 ring_buffer_max_size; guint8 * ring_buffer; diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c index 90678c6..3cae773 100644 --- a/plugins/elements/gsttee.c +++ b/plugins/elements/gsttee.c @@ -48,6 +48,7 @@ #endif #include "gsttee.h" +#include "gst/glib-compat-private.h" #include <string.h> @@ -78,8 +79,8 @@ gst_tee_pull_mode_get_type (void) } /* lock to protect request pads from being removed while downstream */ -#define GST_TEE_DYN_LOCK(tee) g_mutex_lock ((tee)->dyn_lock) -#define GST_TEE_DYN_UNLOCK(tee) g_mutex_unlock ((tee)->dyn_lock) +#define GST_TEE_DYN_LOCK(tee) g_mutex_lock (&(tee)->dyn_lock) +#define GST_TEE_DYN_UNLOCK(tee) g_mutex_unlock (&(tee)->dyn_lock) #define DEFAULT_PROP_NUM_SRC_PADS 0 #define DEFAULT_PROP_HAS_SINK_LOOP FALSE @@ -100,7 +101,8 @@ enum PROP_ALLOC_PAD, }; -static GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE ("src%d", +static GstStaticPadTemplate tee_src_template = +GST_STATIC_PAD_TEMPLATE ("src_%u", GST_PAD_SRC, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); @@ -135,15 +137,22 @@ static void gst_tee_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_tee_dispose (GObject * object); -static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer); -static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list); -static gboolean gst_tee_sink_event (GstPad * pad, GstEvent * event); -static gboolean gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active); -static gboolean gst_tee_src_query (GstPad * pad, GstQuery * query); -static gboolean gst_tee_src_activate_pull (GstPad * pad, gboolean active); -static GstFlowReturn gst_tee_src_get_range (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buf); +static GstFlowReturn gst_tee_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstObject * parent, + GstBufferList * list); +static gboolean gst_tee_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_tee_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static gboolean gst_tee_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active); +static GstFlowReturn gst_tee_src_get_range (GstPad * pad, GstObject * parent, + guint64 offset, guint length, GstBuffer ** buf); static void gst_tee_dispose (GObject * object) @@ -171,7 +180,7 @@ gst_tee_finalize (GObject * object) g_free (tee->last_message); - g_mutex_free (tee->dyn_lock); + g_mutex_clear (&tee->dyn_lock); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -223,7 +232,7 @@ gst_tee_class_init (GstTeeClass * klass) g_object_class_install_property (gobject_class, PROP_ALLOC_PAD, pspec_alloc_pad); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Tee pipe fitting", "Generic", "1-to-N pipe fitting", @@ -241,22 +250,21 @@ gst_tee_class_init (GstTeeClass * klass) static void gst_tee_init (GstTee * tee) { - tee->dyn_lock = g_mutex_new (); + g_mutex_init (&tee->dyn_lock); tee->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); - tee->sink_mode = GST_ACTIVATE_NONE; + tee->sink_mode = GST_PAD_MODE_NONE; gst_pad_set_event_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sink_event)); - gst_pad_set_getcaps_function (tee->sinkpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - gst_pad_set_acceptcaps_function (tee->sinkpad, - GST_DEBUG_FUNCPTR (gst_tee_sink_acceptcaps)); - gst_pad_set_activatepush_function (tee->sinkpad, - GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push)); + gst_pad_set_query_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_sink_query)); + gst_pad_set_activatemode_function (tee->sinkpad, + GST_DEBUG_FUNCPTR (gst_tee_sink_activate_mode)); gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain)); gst_pad_set_chain_list_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain_list)); + GST_OBJECT_FLAG_SET (tee->sinkpad, GST_PAD_FLAG_PROXY_CAPS); gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); tee->last_message = NULL; @@ -265,21 +273,17 @@ gst_tee_init (GstTee * tee) static void gst_tee_notify_alloc_pad (GstTee * tee) { -#if !GLIB_CHECK_VERSION(2,26,0) - g_object_notify ((GObject *) tee, "alloc-pad"); -#else g_object_notify_by_pspec ((GObject *) tee, pspec_alloc_pad); -#endif } -static GstFlowReturn -forward_sticky_events (GstPad * pad, GstEvent * event, gpointer user_data) +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) { GstPad *srcpad = GST_PAD_CAST (user_data); - gst_pad_push_event (srcpad, gst_event_ref (event)); + gst_pad_push_event (srcpad, gst_event_ref (*event)); - return GST_FLOW_OK; + return TRUE; } static GstPad * @@ -289,7 +293,7 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, gchar *name; GstPad *srcpad; GstTee *tee; - GstActivateMode mode; + GstPadMode mode; gboolean res; PushData *data; @@ -298,7 +302,7 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_DEBUG_OBJECT (tee, "requesting pad"); GST_OBJECT_LOCK (tee); - name = g_strdup_printf ("src%d", tee->pad_counter++); + name = g_strdup_printf ("src_%u", tee->pad_counter++); srcpad = gst_pad_new_from_template (templ, name); g_free (name); @@ -316,11 +320,11 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_OBJECT_UNLOCK (tee); switch (mode) { - case GST_ACTIVATE_PULL: + case GST_PAD_MODE_PULL: /* we already have a src pad in pull mode, and our pull mode can only be SINGLE, so fall through to activate this new pad in push mode */ - case GST_ACTIVATE_PUSH: - res = gst_pad_activate_push (srcpad, TRUE); + case GST_PAD_MODE_PUSH: + res = gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); break; default: res = TRUE; @@ -330,15 +334,14 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, if (!res) goto activate_failed; - gst_pad_set_getcaps_function (srcpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - gst_pad_set_activatepull_function (srcpad, - GST_DEBUG_FUNCPTR (gst_tee_src_activate_pull)); + gst_pad_set_activatemode_function (srcpad, + GST_DEBUG_FUNCPTR (gst_tee_src_activate_mode)); gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query)); gst_pad_set_getrange_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_get_range)); /* Forward sticky events to the new srcpad */ gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad); + GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS); gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad); return srcpad; @@ -479,56 +482,29 @@ gst_tee_get_property (GObject * object, guint prop_id, GValue * value, } static gboolean -gst_tee_sink_event (GstPad * pad, GstEvent * event) +gst_tee_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; switch (GST_EVENT_TYPE (event)) { default: - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; } return res; } -/* on the sink we accept caps that are acceptable to all srcpads */ static gboolean -gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps) +gst_tee_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstTee *tee; - gboolean res, done; - GstIterator *it; - GValue item = { 0, }; - - tee = GST_TEE_CAST (GST_PAD_PARENT (pad)); - - it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (tee)); - - res = TRUE; - done = FALSE; - while (!done && res) { - switch (gst_iterator_next (it, &item)) { - case GST_ITERATOR_OK: - res &= gst_pad_peer_accept_caps (g_value_get_object (&item), caps); - g_value_reset (&item); - break; - case GST_ITERATOR_RESYNC: - res = TRUE; - gst_iterator_resync (it); - break; - case GST_ITERATOR_ERROR: - res = FALSE; - done = TRUE; - break; - case GST_ITERATOR_DONE: - done = TRUE; - break; - } - } - g_value_unset (&item); - gst_iterator_free (it); + gboolean res; + switch (GST_QUERY_TYPE (query)) { + default: + res = gst_pad_query_default (pad, parent, query); + break; + } return res; } @@ -549,11 +525,7 @@ gst_tee_do_message (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list) } GST_OBJECT_UNLOCK (tee); -#if !GLIB_CHECK_VERSION(2,26,0) - g_object_notify ((GObject *) tee, "last-message"); -#else g_object_notify_by_pspec ((GObject *) tee, pspec_last_message); -#endif } static GstFlowReturn @@ -714,12 +686,12 @@ error: } static GstFlowReturn -gst_tee_chain (GstPad * pad, GstBuffer * buffer) +gst_tee_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstFlowReturn res; GstTee *tee; - tee = GST_TEE_CAST (GST_OBJECT_PARENT (pad)); + tee = GST_TEE_CAST (parent); GST_DEBUG_OBJECT (tee, "received buffer %p", buffer); @@ -731,12 +703,12 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer) } static GstFlowReturn -gst_tee_chain_list (GstPad * pad, GstBufferList * list) +gst_tee_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list) { GstFlowReturn res; GstTee *tee; - tee = GST_TEE_CAST (gst_pad_get_parent (pad)); + tee = GST_TEE_CAST (parent); GST_DEBUG_OBJECT (tee, "received list %p", list); @@ -744,26 +716,35 @@ gst_tee_chain_list (GstPad * pad, GstBufferList * list) GST_DEBUG_OBJECT (tee, "handled list %s", gst_flow_get_name (res)); - gst_object_unref (tee); - return res; } static gboolean -gst_tee_sink_activate_push (GstPad * pad, gboolean active) +gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) { + gboolean res; GstTee *tee; - tee = GST_TEE (GST_OBJECT_PARENT (pad)); - - GST_OBJECT_LOCK (tee); - tee->sink_mode = active && GST_ACTIVATE_PUSH; + tee = GST_TEE (parent); - if (active && !tee->has_chain) - goto no_chain; - GST_OBJECT_UNLOCK (tee); + switch (mode) { + case GST_PAD_MODE_PUSH: + { + GST_OBJECT_LOCK (tee); + tee->sink_mode = active ? mode : GST_PAD_MODE_NONE; - return TRUE; + if (active && !tee->has_chain) + goto no_chain; + GST_OBJECT_UNLOCK (tee); + res = TRUE; + break; + } + default: + res = FALSE; + break; + } + return res; /* ERRORS */ no_chain: @@ -776,45 +757,54 @@ no_chain: } static gboolean -gst_tee_src_activate_pull (GstPad * pad, gboolean active) +gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, + gboolean active) { GstTee *tee; gboolean res; GstPad *sinkpad; - tee = GST_TEE (gst_pad_get_parent (pad)); + tee = GST_TEE (parent); - GST_OBJECT_LOCK (tee); + switch (mode) { + case GST_PAD_MODE_PULL: + { + GST_OBJECT_LOCK (tee); - if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) - goto cannot_pull; + if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) + goto cannot_pull; - if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad) - goto cannot_pull_multiple_srcs; + if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad) + goto cannot_pull_multiple_srcs; - sinkpad = gst_object_ref (tee->sinkpad); + sinkpad = gst_object_ref (tee->sinkpad); - GST_OBJECT_UNLOCK (tee); + GST_OBJECT_UNLOCK (tee); - res = gst_pad_activate_pull (sinkpad, active); - gst_object_unref (sinkpad); + res = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, active); + gst_object_unref (sinkpad); - if (!res) - goto sink_activate_failed; + if (!res) + goto sink_activate_failed; - GST_OBJECT_LOCK (tee); - if (active) { - if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE) - tee->pull_pad = pad; - } else { - if (pad == tee->pull_pad) - tee->pull_pad = NULL; + GST_OBJECT_LOCK (tee); + if (active) { + if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE) + tee->pull_pad = pad; + } else { + if (pad == tee->pull_pad) + tee->pull_pad = NULL; + } + tee->sink_mode = (active ? GST_PAD_MODE_PULL : GST_PAD_MODE_NONE); + GST_OBJECT_UNLOCK (tee); + break; + } + default: + res = TRUE; + break; } - tee->sink_mode = active & GST_ACTIVATE_PULL; GST_OBJECT_UNLOCK (tee); - gst_object_unref (tee); - return res; /* ERRORS */ @@ -823,7 +813,6 @@ cannot_pull: GST_OBJECT_UNLOCK (tee); GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode " "set to NEVER"); - gst_object_unref (tee); return FALSE; } cannot_pull_multiple_srcs: @@ -831,26 +820,24 @@ cannot_pull_multiple_srcs: GST_OBJECT_UNLOCK (tee); GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, " "pull-mode set to SINGLE"); - gst_object_unref (tee); return FALSE; } sink_activate_failed: { GST_INFO_OBJECT (tee, "Failed to %sactivate sink pad in pull mode", active ? "" : "de"); - gst_object_unref (tee); return FALSE; } } static gboolean -gst_tee_src_query (GstPad * pad, GstQuery * query) +gst_tee_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstTee *tee; gboolean res; GstPad *sinkpad; - tee = GST_TEE (gst_pad_get_parent (pad)); + tee = GST_TEE (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_SCHEDULING: @@ -882,12 +869,10 @@ gst_tee_src_query (GstPad * pad, GstQuery * query) break; } default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, parent, query); break; } - gst_object_unref (tee); - return res; } @@ -912,22 +897,20 @@ gst_tee_pull_eos (GstTee * tee) } static GstFlowReturn -gst_tee_src_get_range (GstPad * pad, guint64 offset, guint length, - GstBuffer ** buf) +gst_tee_src_get_range (GstPad * pad, GstObject * parent, guint64 offset, + guint length, GstBuffer ** buf) { GstTee *tee; GstFlowReturn ret; - tee = GST_TEE (gst_pad_get_parent (pad)); + tee = GST_TEE (parent); ret = gst_pad_pull_range (tee->sinkpad, offset, length, buf); if (ret == GST_FLOW_OK) ret = gst_tee_handle_data (tee, gst_buffer_ref (*buf), FALSE); - else if (ret == GST_FLOW_UNEXPECTED) + else if (ret == GST_FLOW_EOS) gst_tee_pull_eos (tee); - gst_object_unref (tee); - return ret; } diff --git a/plugins/elements/gsttee.h b/plugins/elements/gsttee.h index 626d750..5d6cc51 100644 --- a/plugins/elements/gsttee.h +++ b/plugins/elements/gsttee.h @@ -67,18 +67,18 @@ struct _GstTee { /*< private >*/ /* lock protecting dynamic pads */ - GMutex *dyn_lock; + GMutex dyn_lock; GstPad *sinkpad; GstPad *allocpad; - gint pad_counter; + guint pad_counter; gboolean has_chain; gboolean has_sink_loop; gboolean silent; gchar *last_message; - GstActivateMode sink_mode; + GstPadMode sink_mode; GstTeePullMode pull_mode; GstPad *pull_pad; }; @@ -87,7 +87,7 @@ struct _GstTeeClass { GstElementClass parent_class; }; -GType gst_tee_get_type (void); +GType gst_tee_get_type (void); G_END_DECLS diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index 9ed0bdf..436a4e9 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -141,38 +141,42 @@ static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad); #endif static gboolean gst_type_find_element_src_event (GstPad * pad, - GstEvent * event); -static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query); + GstObject * parent, GstEvent * event); +static gboolean gst_type_find_handle_src_query (GstPad * pad, + GstObject * parent, GstQuery * query); static gboolean gst_type_find_element_sink_event (GstPad * pad, - GstEvent * event); + GstObject * parent, GstEvent * event); static gboolean gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps); static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad, - GstBuffer * buffer); + GstObject * parent, GstBuffer * buffer); static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad, - guint64 offset, guint length, GstBuffer ** buffer); + GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer); static GstStateChangeReturn gst_type_find_element_change_state (GstElement * element, GstStateChange transition); -static gboolean gst_type_find_element_activate (GstPad * pad); -static gboolean -gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active); +static gboolean gst_type_find_element_activate_sink (GstPad * pad, + GstObject * parent); +static gboolean gst_type_find_element_activate_sink_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_type_find_element_activate_src_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); static GstFlowReturn gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, gboolean check_avail); static void gst_type_find_element_send_cached_events (GstTypeFindElement * typefind); +static void gst_type_find_element_loop (GstPad * pad); + static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 }; static void gst_type_find_element_have_type (GstTypeFindElement * typefind, - guint probability, const GstCaps * caps) + guint probability, GstCaps * caps) { - GstCaps *copy; - g_assert (caps != NULL); GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u", @@ -181,12 +185,10 @@ gst_type_find_element_have_type (GstTypeFindElement * typefind, GST_OBJECT_LOCK (typefind); if (typefind->caps) gst_caps_unref (typefind->caps); - typefind->caps = gst_caps_copy (caps); - copy = gst_caps_ref (typefind->caps); + typefind->caps = gst_caps_ref (caps); GST_OBJECT_UNLOCK (typefind); - gst_pad_push_event (typefind->src, gst_event_new_caps (copy)); - gst_caps_unref (copy); + gst_pad_push_event (typefind->src, gst_event_new_caps (caps)); } static void @@ -229,13 +231,13 @@ gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class) gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type", G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL, - gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE); typefind_class->have_type = GST_DEBUG_FUNCPTR (gst_type_find_element_have_type); - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "TypeFind", "Generic", "Finds the media type of a stream", @@ -258,19 +260,22 @@ gst_type_find_element_init (GstTypeFindElement * typefind) "sink"); gst_pad_set_activate_function (typefind->sink, - GST_DEBUG_FUNCPTR (gst_type_find_element_activate)); + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink)); + gst_pad_set_activatemode_function (typefind->sink, + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_sink_mode)); gst_pad_set_chain_function (typefind->sink, GST_DEBUG_FUNCPTR (gst_type_find_element_chain)); gst_pad_set_event_function (typefind->sink, GST_DEBUG_FUNCPTR (gst_type_find_element_sink_event)); + GST_PAD_SET_PROXY_ALLOCATION (typefind->sink); gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink); /* srcpad */ typefind->src = gst_pad_new_from_static_template (&type_find_element_src_template, "src"); - gst_pad_set_activatepull_function (typefind->src, - GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_pull)); + gst_pad_set_activatemode_function (typefind->src, + GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_mode)); gst_pad_set_getrange_function (typefind->src, GST_DEBUG_FUNCPTR (gst_type_find_element_getrange)); gst_pad_set_event_function (typefind->src, @@ -366,28 +371,43 @@ gst_type_find_element_get_property (GObject * object, guint prop_id, } static gboolean -gst_type_find_handle_src_query (GstPad * pad, GstQuery * query) +gst_type_find_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query) { GstTypeFindElement *typefind; gboolean res = FALSE; - GstPad *peer; - - typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); - peer = gst_pad_get_peer (typefind->sink); - if (peer == NULL) - return FALSE; - - res = gst_pad_query (peer, query); - if (!res) - goto out; + typefind = GST_TYPE_FIND_ELEMENT (parent); + GST_DEBUG_OBJECT (typefind, "Handling src query %s", + GST_QUERY_TYPE_NAME (query)); switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + /* FIXME, filter out the scheduling modes that we understand */ + res = gst_pad_peer_query (typefind->sink, query); + break; + case GST_QUERY_CAPS: + { + GST_DEBUG_OBJECT (typefind, + "Got caps query, our caps are %" GST_PTR_FORMAT, typefind->caps); + + /* We can hijack caps query if we typefind already */ + if (typefind->caps) { + gst_query_set_caps_result (query, typefind->caps); + res = TRUE; + } else { + res = gst_pad_peer_query (typefind->sink, query); + } + break; + } case GST_QUERY_POSITION: { gint64 peer_pos; GstFormat format; + if (!(res = gst_pad_peer_query (typefind->sink, query))) + goto out; + gst_query_parse_position (query, &format, &peer_pos); GST_OBJECT_LOCK (typefind); @@ -405,41 +425,112 @@ gst_type_find_handle_src_query (GstPad * pad, GstQuery * query) break; } default: + res = gst_pad_query_default (pad, parent, query); break; } - out: - gst_object_unref (peer); return res; } -#if 0 -static const GstEventMask * -gst_type_find_element_src_event_mask (GstPad * pad) +static gboolean +gst_type_find_element_seek (GstTypeFindElement * typefind, GstEvent * event) { - static const GstEventMask mask[] = { - {GST_EVENT_SEEK, - GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END | - GST_SEEK_FLAG_FLUSH}, - /* add more if you want, event masks suck and need to die anyway */ - {0,} - }; - - return mask; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + GstFormat format; + gboolean flush; + gdouble rate; + gint64 cur, stop; + GstSegment seeksegment = { 0, }; + + gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, + &stop_type, &stop); + + /* we can only seek on bytes */ + if (format != GST_FORMAT_BYTES) { + GST_DEBUG_OBJECT (typefind, "Can only seek on BYTES"); + return FALSE; + } + + /* copy segment, we need this because we still need the old + * segment when we close the current segment. */ + memcpy (&seeksegment, &typefind->segment, sizeof (GstSegment)); + + GST_DEBUG_OBJECT (typefind, "configuring seek"); + gst_segment_do_seek (&seeksegment, rate, format, flags, + cur_type, cur, stop_type, stop, NULL); + + flush = ! !(flags & GST_SEEK_FLAG_FLUSH); + + GST_DEBUG_OBJECT (typefind, "New segment %" GST_SEGMENT_FORMAT, &seeksegment); + + if (flush) { + GST_DEBUG_OBJECT (typefind, "Starting flush"); + gst_pad_push_event (typefind->sink, gst_event_new_flush_start ()); + gst_pad_push_event (typefind->src, gst_event_new_flush_start ()); + } else { + GST_DEBUG_OBJECT (typefind, "Non-flushing seek, pausing task"); + gst_pad_pause_task (typefind->sink); + } + + /* now grab the stream lock so that streaming cannot continue, for + * non flushing seeks when the element is in PAUSED this could block + * forever. */ + GST_DEBUG_OBJECT (typefind, "Waiting for streaming to stop"); + GST_PAD_STREAM_LOCK (typefind->sink); + + if (flush) { + GST_DEBUG_OBJECT (typefind, "Stopping flush"); + gst_pad_push_event (typefind->sink, gst_event_new_flush_stop (TRUE)); + gst_pad_push_event (typefind->src, gst_event_new_flush_stop (TRUE)); + } + + /* now update the real segment info */ + GST_DEBUG_OBJECT (typefind, "Committing new seek segment"); + memcpy (&typefind->segment, &seeksegment, sizeof (GstSegment)); + typefind->offset = typefind->segment.start; + + /* notify start of new segment */ + if (typefind->segment.flags & GST_SEEK_FLAG_SEGMENT) { + GstMessage *msg; + + msg = gst_message_new_segment_start (GST_OBJECT (typefind), + GST_FORMAT_BYTES, typefind->segment.start); + gst_element_post_message (GST_ELEMENT (typefind), msg); + } + + typefind->need_segment = TRUE; + + /* restart our task since it might have been stopped when we did the + * flush. */ + gst_pad_start_task (typefind->sink, + (GstTaskFunction) gst_type_find_element_loop, typefind->sink); + + /* streaming can continue now */ + GST_PAD_STREAM_UNLOCK (typefind->sink); + + return TRUE; } -#endif static gboolean -gst_type_find_element_src_event (GstPad * pad, GstEvent * event) +gst_type_find_element_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) { - GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent); if (typefind->mode != MODE_NORMAL) { /* need to do more? */ gst_mini_object_unref (GST_MINI_OBJECT_CAST (event)); return FALSE; } - return gst_pad_push_event (typefind->sink, event); + + /* Only handle seeks here if driving the pipeline */ + if (typefind->segment.format != GST_FORMAT_UNDEFINED && + GST_EVENT_TYPE (event) == GST_EVENT_SEEK) { + return gst_type_find_element_seek (typefind, event); + } else { + return gst_pad_push_event (typefind->sink, event); + } } static void @@ -518,10 +609,11 @@ no_data: } static gboolean -gst_type_find_element_sink_event (GstPad * pad, GstEvent * event) +gst_type_find_element_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { gboolean res = FALSE; - GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent); GST_DEBUG_OBJECT (typefind, "got %s event in mode %d", GST_EVENT_TYPE_NAME (event), typefind->mode); @@ -730,12 +822,13 @@ gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad, } static GstFlowReturn -gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer) +gst_type_find_element_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer) { GstTypeFindElement *typefind; GstFlowReturn res = GST_FLOW_OK; - typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + typefind = GST_TYPE_FIND_ELEMENT (parent); GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode); @@ -795,7 +888,7 @@ gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, data = gst_adapter_map (typefind->adapter, avail); caps = gst_type_find_helper_for_data (GST_OBJECT (typefind), data, avail, &probability); - gst_adapter_unmap (typefind->adapter, 0); + gst_adapter_unmap (typefind->adapter); if (caps == NULL && have_max) goto no_type_found; @@ -858,13 +951,13 @@ low_probability: } static GstFlowReturn -gst_type_find_element_getrange (GstPad * srcpad, +gst_type_find_element_getrange (GstPad * srcpad, GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer) { GstTypeFindElement *typefind; GstFlowReturn ret; - typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad)); + typefind = GST_TYPE_FIND_ELEMENT (parent); ret = gst_pad_pull_range (typefind->sink, offset, length, buffer); @@ -872,70 +965,50 @@ gst_type_find_element_getrange (GstPad * srcpad, } static gboolean -gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active) +gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { + gboolean res; GstTypeFindElement *typefind; - typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad)); - - return gst_pad_activate_pull (typefind->sink, active); + typefind = GST_TYPE_FIND_ELEMENT (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + /* make sure our task stops pushing, we can't call _stop here because this + * activation might happen from the streaming thread. */ + gst_pad_pause_task (typefind->sink); + res = gst_pad_activate_mode (typefind->sink, mode, active); + if (typefind->caps) { + GstCaps *caps; + GST_OBJECT_LOCK (typefind); + caps = gst_caps_ref (typefind->caps); + GST_OBJECT_UNLOCK (typefind); + gst_pad_push_event (typefind->src, gst_event_new_caps (caps)); + gst_caps_unref (caps); + } + break; + default: + res = TRUE; + break; + } + return res; } -static gboolean -gst_type_find_element_activate (GstPad * pad) +static void +gst_type_find_element_loop (GstPad * pad) { - GstTypeFindProbability probability = GST_TYPE_FIND_NONE; - GstCaps *found_caps = NULL; GstTypeFindElement *typefind; - GstQuery *query; - gboolean pull_mode; - - typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad)); - - /* if we have force caps, use those */ - GST_OBJECT_LOCK (typefind); - if (typefind->force_caps) { - found_caps = gst_caps_ref (typefind->force_caps); - probability = GST_TYPE_FIND_MAXIMUM; - GST_OBJECT_UNLOCK (typefind); - goto done; - } - GST_OBJECT_UNLOCK (typefind); - - /* 1. try to activate in pull mode. if not, switch to push and succeed. - 2. try to pull type find. - 3. deactivate pull mode. - 4. src pad might have been activated push by the state change. deactivate. - 5. if we didn't find any caps, try getting the uri extension by doing an uri - query. - 6. if we didn't find any caps, fail. - 7. emit have-type; maybe the app connected the source pad to something. - 8. if the sink pad is activated, we are in pull mode. succeed. - otherwise activate both pads in push mode and succeed. - */ - - /* 1 */ - query = gst_query_new_scheduling (); - - if (!gst_pad_peer_query (pad, query)) { - gst_query_unref (query); - goto typefind_push; - } - - gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL); - gst_query_unref (query); + GstFlowReturn ret = GST_FLOW_OK; - if (!pull_mode) - goto typefind_push; - - if (!gst_pad_activate_pull (pad, TRUE)) - goto typefind_push; - - /* 2 */ - GST_DEBUG_OBJECT (typefind, "find type in pull mode"); + typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); - { + if (typefind->mode == MODE_TYPEFIND) { GstPad *peer; + GstCaps *found_caps = NULL; + GstTypeFindProbability probability = GST_TYPE_FIND_NONE; + + GST_DEBUG_OBJECT (typefind, "find type in pull mode"); peer = gst_pad_get_peer (pad); if (peer) { @@ -945,8 +1018,9 @@ gst_type_find_element_activate (GstPad * pad) if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) { GST_WARNING_OBJECT (typefind, "Could not query upstream length!"); gst_object_unref (peer); - gst_pad_activate_pull (pad, FALSE); - return FALSE; + + ret = GST_FLOW_ERROR; + goto pause; } /* the size if 0, we cannot continue */ @@ -955,73 +1029,194 @@ gst_type_find_element_activate (GstPad * pad) GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (_("Stream contains no data.")), ("Can't typefind empty stream")); gst_object_unref (peer); - gst_pad_activate_pull (pad, FALSE); - return FALSE; + ret = GST_FLOW_ERROR; + goto pause; } ext = gst_type_find_get_extension (typefind, pad); - found_caps = gst_type_find_helper_get_range_ext (GST_OBJECT_CAST (peer), + found_caps = + gst_type_find_helper_get_range (GST_OBJECT_CAST (peer), + GST_OBJECT_PARENT (peer), (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)), (guint64) size, ext, &probability); g_free (ext); + GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps); + gst_object_unref (peer); } - } - /* the type find helpers might have triggered setcaps here (due to upstream) - * setting caps on buffers, which emits typefound signal and an element - * could have been linked and have its pads activated - * - * If we deactivate the pads in the following steps we might mess up - * downstream element. We should prevent that. - */ - if (typefind->mode == MODE_NORMAL) { - /* this means we already emitted typefound */ - GST_DEBUG ("Already managed to typefind !"); - goto really_done; + if (!found_caps || probability < typefind->min_probability) { + GST_DEBUG ("Trying to guess using extension"); + gst_caps_replace (&found_caps, NULL); + found_caps = + gst_type_find_guess_by_extension (typefind, pad, &probability); + } + + if (!found_caps || probability < typefind->min_probability) { + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); + gst_caps_replace (&found_caps, NULL); + ret = GST_FLOW_ERROR; + goto pause; + } + + GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); + g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], + 0, probability, found_caps); + typefind->mode = MODE_NORMAL; + gst_caps_unref (found_caps); + } else if (typefind->mode == MODE_NORMAL) { + GstBuffer *outbuf = NULL; + + if (typefind->need_segment) { + typefind->need_segment = FALSE; + gst_pad_push_event (typefind->src, + gst_event_new_segment (&typefind->segment)); + } + + /* Pull 4k blocks and send downstream */ + ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf); + if (ret != GST_FLOW_OK) + goto pause; + + typefind->offset += 4096; + + ret = gst_pad_push (typefind->src, outbuf); + if (ret != GST_FLOW_OK) + goto pause; + } else { + /* Error out */ + ret = GST_FLOW_ERROR; + goto pause; } - /* 3 */ - gst_pad_activate_pull (pad, FALSE); + return; + +pause: + { + const gchar *reason = gst_flow_get_name (ret); + gboolean push_eos = FALSE; + + GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason); + gst_pad_pause_task (typefind->sink); + + if (ret == GST_FLOW_EOS) { + /* perform EOS logic */ - /* 4 */ - gst_pad_activate_push (typefind->src, FALSE); + if (typefind->segment.flags & GST_SEEK_FLAG_SEGMENT) { + gint64 stop; - /* 5 */ - if (!found_caps || probability < typefind->min_probability) { - found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability); + /* for segment playback we need to post when (in stream time) + * we stopped, this is either stop (when set) or the duration. */ + if ((stop = typefind->segment.stop) == -1) + stop = typefind->offset; + + GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment"); + gst_element_post_message (GST_ELEMENT (typefind), + gst_message_new_segment_done (GST_OBJECT (typefind), + GST_FORMAT_BYTES, stop)); + } else { + push_eos = TRUE; + } + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { + /* for fatal errors we post an error message */ + GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL), + ("stream stopped, reason %s", reason)); + push_eos = TRUE; + } + if (push_eos) { + /* send EOS, and prevent hanging if no streams yet */ + GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream"); + gst_pad_push_event (typefind->src, gst_event_new_eos ()); + } + return; } +} - /* 6 */ - if (!found_caps || probability < typefind->min_probability) { - GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); - gst_caps_replace (&found_caps, NULL); - return FALSE; +static gboolean +gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) +{ + gboolean res; + GstTypeFindElement *typefind; + + typefind = GST_TYPE_FIND_ELEMENT (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + if (active) { + gst_segment_init (&typefind->segment, GST_FORMAT_BYTES); + typefind->need_segment = TRUE; + typefind->offset = 0; + res = TRUE; + } else { + res = gst_pad_stop_task (pad); + } + break; + case GST_PAD_MODE_PUSH: + if (active) + start_typefinding (typefind); + else + stop_typefinding (typefind); + + res = TRUE; + break; + default: + res = FALSE; + break; } + return res; +} + +static gboolean +gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) +{ + GstTypeFindElement *typefind; + GstQuery *query; + gboolean pull_mode; + GstCaps *found_caps = NULL; + GstTypeFindProbability probability = GST_TYPE_FIND_NONE; -done: - /* 7 */ - g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], - 0, probability, found_caps); - typefind->mode = MODE_NORMAL; -really_done: - gst_caps_unref (found_caps); + typefind = GST_TYPE_FIND_ELEMENT (parent); - /* 8 */ - if (gst_pad_is_active (pad)) - return TRUE; - else { - gboolean ret; + /* if we have force caps, use those */ + GST_OBJECT_LOCK (typefind); + if (typefind->force_caps) { + found_caps = gst_caps_ref (typefind->force_caps); + probability = GST_TYPE_FIND_MAXIMUM; + GST_OBJECT_UNLOCK (typefind); - ret = gst_pad_activate_push (typefind->src, TRUE); - ret &= gst_pad_activate_push (pad, TRUE); - return ret; + GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); + g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], + 0, probability, found_caps); + typefind->mode = MODE_NORMAL; + goto typefind_push; + } + GST_OBJECT_UNLOCK (typefind); + + query = gst_query_new_scheduling (); + + if (!gst_pad_peer_query (pad, query)) { + gst_query_unref (query); + goto typefind_push; } + + pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_unref (query); + + if (!pull_mode) + goto typefind_push; + + if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) + goto typefind_push; + + /* only start our task if we ourselves decide to start in pull mode */ + return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop, + pad); + typefind_push: { - start_typefinding (typefind); - return gst_pad_activate_push (pad, TRUE); + return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); } } diff --git a/plugins/elements/gsttypefindelement.h b/plugins/elements/gsttypefindelement.h index 5c34758..0242ec2 100644 --- a/plugins/elements/gsttypefindelement.h +++ b/plugins/elements/gsttypefindelement.h @@ -59,6 +59,11 @@ struct _GstTypeFindElement { GList * cached_events; GstCaps * force_caps; + + /* Only used when driving the pipeline */ + gboolean need_segment; + GstSegment segment; + guint64 offset; }; struct _GstTypeFindElementClass { @@ -66,8 +71,8 @@ struct _GstTypeFindElementClass { /* signals */ void (*have_type) (GstTypeFindElement *element, - guint probability, - const GstCaps * caps); + guint probability, + GstCaps *caps); }; GType gst_type_find_element_get_type (void); diff --git a/plugins/elements/gstvalve.c b/plugins/elements/gstvalve.c index 877d51e..a69b785 100644 --- a/plugins/elements/gstvalve.c +++ b/plugins/elements/gstvalve.c @@ -72,9 +72,12 @@ static void gst_valve_set_property (GObject * object, static void gst_valve_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean gst_valve_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer); -static GstCaps *gst_valve_getcaps (GstPad * pad, GstCaps * filter); +static GstFlowReturn gst_valve_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_valve_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_valve_query (GstPad * pad, GstObject * parent, + GstQuery * query); #define _do_init \ GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve"); @@ -103,7 +106,7 @@ gst_valve_class_init (GstValveClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate)); - gst_element_class_set_details_simple (gstelement_class, "Valve element", + gst_element_class_set_static_metadata (gstelement_class, "Valve element", "Filter", "Drops buffers and events or lets them through", "Olivier Crete <olivier.crete@collabora.co.uk>"); } @@ -115,8 +118,10 @@ gst_valve_init (GstValve * valve) valve->discont = FALSE; valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - gst_pad_set_getcaps_function (valve->srcpad, - GST_DEBUG_FUNCPTR (gst_valve_getcaps)); + gst_pad_set_event_function (valve->srcpad, + GST_DEBUG_FUNCPTR (gst_valve_event)); + gst_pad_set_query_function (valve->srcpad, + GST_DEBUG_FUNCPTR (gst_valve_query)); gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad); valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); @@ -124,8 +129,9 @@ gst_valve_init (GstValve * valve) GST_DEBUG_FUNCPTR (gst_valve_chain)); gst_pad_set_event_function (valve->sinkpad, GST_DEBUG_FUNCPTR (gst_valve_event)); - gst_pad_set_getcaps_function (valve->sinkpad, - GST_DEBUG_FUNCPTR (gst_valve_getcaps)); + gst_pad_set_query_function (valve->sinkpad, + GST_DEBUG_FUNCPTR (gst_valve_query)); + GST_PAD_SET_PROXY_CAPS (valve->sinkpad); gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad); } @@ -139,6 +145,7 @@ gst_valve_set_property (GObject * object, switch (prop_id) { case PROP_DROP: g_atomic_int_set (&valve->drop, g_value_get_boolean (value)); + gst_pad_push_event (valve->sinkpad, gst_event_new_reconfigure ()); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -162,10 +169,29 @@ gst_valve_get_property (GObject * object, } } + +static gboolean +forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstValve *valve = user_data; + + if (!gst_pad_push_event (valve->srcpad, gst_event_ref (*event))) + valve->need_repush_sticky = TRUE; + + return TRUE; +} + +static void +gst_valve_repush_sticky (GstValve * valve) +{ + valve->need_repush_sticky = FALSE; + gst_pad_sticky_events_foreach (valve->sinkpad, forward_sticky_events, valve); +} + static GstFlowReturn -gst_valve_chain (GstPad * pad, GstBuffer * buffer) +gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { - GstValve *valve = GST_VALVE (GST_OBJECT_PARENT (pad)); + GstValve *valve = GST_VALVE (parent); GstFlowReturn ret = GST_FLOW_OK; if (g_atomic_int_get (&valve->drop)) { @@ -178,6 +204,9 @@ gst_valve_chain (GstPad * pad, GstBuffer * buffer) valve->discont = FALSE; } + if (valve->need_repush_sticky) + gst_valve_repush_sticky (valve); + ret = gst_pad_push (valve->srcpad, buffer); } @@ -193,41 +222,42 @@ gst_valve_chain (GstPad * pad, GstBuffer * buffer) static gboolean -gst_valve_event (GstPad * pad, GstEvent * event) +gst_valve_event (GstPad * pad, GstObject * parent, GstEvent * event) { - GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad)); + GstValve *valve; gboolean ret = TRUE; - if (g_atomic_int_get (&valve->drop)) + valve = GST_VALVE (parent); + + if (g_atomic_int_get (&valve->drop)) { + valve->need_repush_sticky |= GST_EVENT_IS_STICKY (event); gst_event_unref (event); - else - ret = gst_pad_push_event (valve->srcpad, event); + } else { + if (valve->need_repush_sticky) + gst_valve_repush_sticky (valve); + ret = gst_pad_event_default (pad, parent, event); + } /* Ignore errors if "drop" was changed while the thread was blocked * downwards. */ - if (g_atomic_int_get (&valve->drop)) + if (g_atomic_int_get (&valve->drop)) { + valve->need_repush_sticky |= GST_EVENT_IS_STICKY (event); ret = TRUE; + } - gst_object_unref (valve); return ret; } -static GstCaps * -gst_valve_getcaps (GstPad * pad, GstCaps * filter) -{ - GstValve *valve = GST_VALVE (gst_pad_get_parent (pad)); - GstCaps *caps; - if (pad == valve->sinkpad) - caps = gst_pad_peer_get_caps (valve->srcpad, filter); - else - caps = gst_pad_peer_get_caps (valve->sinkpad, filter); - if (caps == NULL) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); +static gboolean +gst_valve_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstValve *valve = GST_VALVE (parent); - gst_object_unref (valve); + if (g_atomic_int_get (&valve->drop)) + return FALSE; - return caps; + return gst_pad_query_default (pad, parent, query); } diff --git a/plugins/elements/gstvalve.h b/plugins/elements/gstvalve.h index 0e6757c..7318af7 100644 --- a/plugins/elements/gstvalve.h +++ b/plugins/elements/gstvalve.h @@ -61,6 +61,7 @@ struct _GstValve /* Protected by the stream lock */ gboolean discont; + gboolean need_repush_sticky; GstPad *srcpad; GstPad *sinkpad; diff --git a/plugins/indexers/Makefile.am b/plugins/indexers/Makefile.am deleted file mode 100644 index a6615dd..0000000 --- a/plugins/indexers/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -plugin_LTLIBRARIES = libgstcoreindexers.la - -# FIXME 0.11: gstfileindex.c used libxml and mmap, rewrite using something else or remove - -noinst_HEADERS = \ - gstindexers.h - -libgstcoreindexers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la -libgstcoreindexers_la_SOURCES = gstindexers.c gstmemindex.c -libgstcoreindexers_la_CFLAGS = $(GST_OBJ_CFLAGS) -libgstcoreindexers_la_LIBADD = $(GST_OBJ_LIBS) $(GST_FILEINDEX_LIBS) -libgstcoreindexers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstcoreindexers_la_LIBTOOLFLAGS = --tag=disable-static - -%.c.gcov: .libs/libgstcoreindexers_la-%.gcda %.c - $(GCOV) -b -f -o $^ > $@.out - -gcov: $(libgstcoreindexers_la_SOURCES:=.gcov) - -Android.mk: Makefile.am - androgenizer -:PROJECT gstreamer -:SHARED libgstcoreindexers -:TAGS eng debug \ - -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ - -:SOURCES $(libgstcoreindexers_la_SOURCES) \ - -:CFLAGS $(DEFS) $(libgstcoreindexers_la_CFLAGS) \ - -:LDFLAGS $(libgstcoreindexers_la_LDFLAGS) \ - $(libgstcoreindexers_la_LIBADD) \ - -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_MAJORMINOR@ \ - > $@ - diff --git a/plugins/indexers/Makefile.in b/plugins/indexers/Makefile.in deleted file mode 100644 index 8a6b245..0000000 --- a/plugins/indexers/Makefile.in +++ /dev/null @@ -1,765 +0,0 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 = plugins/indexers -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-docbook.m4 \ - $(top_srcdir)/common/m4/as-libtool.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-doc.m4 \ - $(top_srcdir)/common/m4/gst-error.m4 \ - $(top_srcdir)/common/m4/gst-feature.m4 \ - $(top_srcdir)/common/m4/gst-function.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-parser.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.m4 \ - $(top_srcdir)/common/m4/gtk-doc.m4 \ - $(top_srcdir)/common/m4/introspection.m4 \ - $(top_srcdir)/common/m4/pkg.m4 \ - $(top_srcdir)/m4/check-checks.m4 $(top_srcdir)/m4/gettext.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__installdirs = "$(DESTDIR)$(plugindir)" -LTLIBRARIES = $(plugin_LTLIBRARIES) -am__DEPENDENCIES_1 = -am_libgstcoreindexers_la_OBJECTS = \ - libgstcoreindexers_la-gstindexers.lo \ - libgstcoreindexers_la-gstmemindex.lo -libgstcoreindexers_la_OBJECTS = $(am_libgstcoreindexers_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) -am__v_lt_0 = --silent -libgstcoreindexers_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(libgstcoreindexers_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(libgstcoreindexers_la_CFLAGS) $(CFLAGS) \ - $(libgstcoreindexers_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_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) -am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -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_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) -am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(libgstcoreindexers_la_SOURCES) -DIST_SOURCES = $(libgstcoreindexers_la_SOURCES) -HEADERS = $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AS = @AS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BISON_PATH = @BISON_PATH@ -CAT_ENTRY_END = @CAT_ENTRY_END@ -CAT_ENTRY_START = @CAT_ENTRY_START@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CHECK_MAJOR_VERSION = @CHECK_MAJOR_VERSION@ -CHECK_MICRO_VERSION = @CHECK_MICRO_VERSION@ -CHECK_MINOR_VERSION = @CHECK_MINOR_VERSION@ -CHECK_VERSION = @CHECK_VERSION@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIR = @DATADIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@ -DLLTOOL = @DLLTOOL@ -DOCBOOK_ROOT = @DOCBOOK_ROOT@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -ENABLE_SUBUNIT = @ENABLE_SUBUNIT@ -ERROR_CFLAGS = @ERROR_CFLAGS@ -EXEEXT = @EXEEXT@ -FFLAGS = @FFLAGS@ -FGREP = @FGREP@ -FLEX_PATH = @FLEX_PATH@ -GCOV = @GCOV@ -GCOV_CFLAGS = @GCOV_CFLAGS@ -GCOV_LIBS = @GCOV_LIBS@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GLIB_CFLAGS = @GLIB_CFLAGS@ -GLIB_LIBS = @GLIB_LIBS@ -GLIB_ONLY_CFLAGS = @GLIB_ONLY_CFLAGS@ -GLIB_ONLY_LIBS = @GLIB_ONLY_LIBS@ -GLIB_PREFIX = @GLIB_PREFIX@ -GLIB_REQ = @GLIB_REQ@ -GMP_LIBS = @GMP_LIBS@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -GSL_LIBS = @GSL_LIBS@ -GST_AGE = @GST_AGE@ -GST_ALL_CFLAGS = @GST_ALL_CFLAGS@ -GST_ALL_CXXFLAGS = @GST_ALL_CXXFLAGS@ -GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@ -GST_ALL_LIBS = @GST_ALL_LIBS@ -GST_CURRENT = @GST_CURRENT@ -GST_DISABLE_ALLOC_TRACE_DEFINE = @GST_DISABLE_ALLOC_TRACE_DEFINE@ -GST_DISABLE_GST_DEBUG_DEFINE = @GST_DISABLE_GST_DEBUG_DEFINE@ -GST_DISABLE_NET_DEFINE = @GST_DISABLE_NET_DEFINE@ -GST_DISABLE_OPTION_PARSING_DEFINE = @GST_DISABLE_OPTION_PARSING_DEFINE@ -GST_DISABLE_PARSE_DEFINE = @GST_DISABLE_PARSE_DEFINE@ -GST_DISABLE_PLUGIN_DEFINE = @GST_DISABLE_PLUGIN_DEFINE@ -GST_DISABLE_REGISTRY_DEFINE = @GST_DISABLE_REGISTRY_DEFINE@ -GST_DISABLE_TRACE_DEFINE = @GST_DISABLE_TRACE_DEFINE@ -GST_HAVE_MONOTONIC_CLOCK_DEFINE = @GST_HAVE_MONOTONIC_CLOCK_DEFINE@ -GST_HAVE_POSIX_TIMERS_DEFINE = @GST_HAVE_POSIX_TIMERS_DEFINE@ -GST_HAVE_UNALIGNED_ACCESS_DEFINE = @GST_HAVE_UNALIGNED_ACCESS_DEFINE@ -GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@ -GST_LIBVERSION = @GST_LIBVERSION@ -GST_LIB_LDFLAGS = @GST_LIB_LDFLAGS@ -GST_LICENSE = @GST_LICENSE@ -GST_LT_LDFLAGS = @GST_LT_LDFLAGS@ -GST_MAJORMINOR = @GST_MAJORMINOR@ -GST_OBJ_CFLAGS = @GST_OBJ_CFLAGS@ -GST_OBJ_CXXFLAGS = @GST_OBJ_CXXFLAGS@ -GST_OBJ_LIBS = @GST_OBJ_LIBS@ -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_PKG_CONFIG_PATH = @GST_PKG_CONFIG_PATH@ -GST_PKG_DEPS = @GST_PKG_DEPS@ -GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ -GST_PLUGIN_SCANNER_INSTALLED = @GST_PLUGIN_SCANNER_INSTALLED@ -GST_PRINTF_EXTENSION_POINTER_FORMAT_DEFINE = @GST_PRINTF_EXTENSION_POINTER_FORMAT_DEFINE@ -GST_PRINTF_EXTENSION_SEGMENT_FORMAT_DEFINE = @GST_PRINTF_EXTENSION_SEGMENT_FORMAT_DEFINE@ -GST_REGISTRY_DOC_TYPES = @GST_REGISTRY_DOC_TYPES@ -GST_REVISION = @GST_REVISION@ -GST_USING_PRINTF_EXTENSION_DEFINE = @GST_USING_PRINTF_EXTENSION_DEFINE@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -HAVE_DOCBOOK2HTML = @HAVE_DOCBOOK2HTML@ -HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ -HAVE_DVIPS = @HAVE_DVIPS@ -HAVE_EPSTOPDF = @HAVE_EPSTOPDF@ -HAVE_FIG2DEV = @HAVE_FIG2DEV@ -HAVE_GMP = @HAVE_GMP@ -HAVE_GSL = @HAVE_GSL@ -HAVE_JADETEX = @HAVE_JADETEX@ -HAVE_PNGTOPNM = @HAVE_PNGTOPNM@ -HAVE_PNMTOPS = @HAVE_PNMTOPS@ -HAVE_PS2PDF = @HAVE_PS2PDF@ -HAVE_XMLLINT = @HAVE_XMLLINT@ -HOST_CPU = @HOST_CPU@ -HTML_DIR = @HTML_DIR@ -INET_ATON_LIBS = @INET_ATON_LIBS@ -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@ -INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ -INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ -INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ -INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ -INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ -INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ -INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ -INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBDIR = @LIBDIR@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBM = @LIBM@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LOCALEDIR = @LOCALEDIR@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -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@ -PERL_PATH = @PERL_PATH@ -PKG_CONFIG = @PKG_CONFIG@ -PLUGINDIR = @PLUGINDIR@ -POSUB = @POSUB@ -PROFILE_CFLAGS = @PROFILE_CFLAGS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ -VALGRIND_LIBS = @VALGRIND_LIBS@ -VALGRIND_PATH = @VALGRIND_PATH@ -VERSION = @VERSION@ -WARNING_CFLAGS = @WARNING_CFLAGS@ -WIN32_LIBS = @WIN32_LIBS@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -XML_CATALOG = @XML_CATALOG@ -XSLTPROC = @XSLTPROC@ -XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -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@ -lt_ECHO = @lt_ECHO@ -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 = libgstcoreindexers.la - -# FIXME 0.11: gstfileindex.c used libxml and mmap, rewrite using something else or remove -noinst_HEADERS = \ - gstindexers.h - -libgstcoreindexers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la -libgstcoreindexers_la_SOURCES = gstindexers.c gstmemindex.c -libgstcoreindexers_la_CFLAGS = $(GST_OBJ_CFLAGS) -libgstcoreindexers_la_LIBADD = $(GST_OBJ_LIBS) $(GST_FILEINDEX_LIBS) -libgstcoreindexers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstcoreindexers_la_LIBTOOLFLAGS = --tag=disable-static -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 plugins/indexers/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu plugins/indexers/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 -libgstcoreindexers.la: $(libgstcoreindexers_la_OBJECTS) $(libgstcoreindexers_la_DEPENDENCIES) - $(AM_V_CCLD)$(libgstcoreindexers_la_LINK) -rpath $(plugindir) $(libgstcoreindexers_la_OBJECTS) $(libgstcoreindexers_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreindexers_la-gstindexers.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstcoreindexers_la-gstmemindex.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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(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 -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -libgstcoreindexers_la-gstindexers.lo: gstindexers.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreindexers_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreindexers_la_CFLAGS) $(CFLAGS) -MT libgstcoreindexers_la-gstindexers.lo -MD -MP -MF $(DEPDIR)/libgstcoreindexers_la-gstindexers.Tpo -c -o libgstcoreindexers_la-gstindexers.lo `test -f 'gstindexers.c' || echo '$(srcdir)/'`gstindexers.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreindexers_la-gstindexers.Tpo $(DEPDIR)/libgstcoreindexers_la-gstindexers.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstindexers.c' object='libgstcoreindexers_la-gstindexers.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreindexers_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreindexers_la_CFLAGS) $(CFLAGS) -c -o libgstcoreindexers_la-gstindexers.lo `test -f 'gstindexers.c' || echo '$(srcdir)/'`gstindexers.c - -libgstcoreindexers_la-gstmemindex.lo: gstmemindex.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreindexers_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreindexers_la_CFLAGS) $(CFLAGS) -MT libgstcoreindexers_la-gstmemindex.lo -MD -MP -MF $(DEPDIR)/libgstcoreindexers_la-gstmemindex.Tpo -c -o libgstcoreindexers_la-gstmemindex.lo `test -f 'gstmemindex.c' || echo '$(srcdir)/'`gstmemindex.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstcoreindexers_la-gstmemindex.Tpo $(DEPDIR)/libgstcoreindexers_la-gstmemindex.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstmemindex.c' object='libgstcoreindexers_la-gstmemindex.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstcoreindexers_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstcoreindexers_la_CFLAGS) $(CFLAGS) -c -o libgstcoreindexers_la-gstmemindex.lo `test -f 'gstmemindex.c' || echo '$(srcdir)/'`gstmemindex.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: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -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 - - -%.c.gcov: .libs/libgstcoreindexers_la-%.gcda %.c - $(GCOV) -b -f -o $^ > $@.out - -gcov: $(libgstcoreindexers_la_SOURCES:=.gcov) - -Android.mk: Makefile.am - androgenizer -:PROJECT gstreamer -:SHARED libgstcoreindexers -:TAGS eng debug \ - -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ - -:SOURCES $(libgstcoreindexers_la_SOURCES) \ - -:CFLAGS $(DEFS) $(libgstcoreindexers_la_CFLAGS) \ - -:LDFLAGS $(libgstcoreindexers_la_LDFLAGS) \ - $(libgstcoreindexers_la_LIBADD) \ - -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_MAJORMINOR@ \ - > $@ - -# 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/plugins/indexers/gstindexers.c b/plugins/indexers/gstindexers.c deleted file mode 100644 index f317c32..0000000 --- a/plugins/indexers/gstindexers.c +++ /dev/null @@ -1,43 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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. - */ - -#include <gst/gst_private.h> -#include <gst/gstversion.h> -#include <gst/gstplugin.h> - -#include "gstindexers.h" - -static gboolean -plugin_init (GstPlugin * plugin) -{ - gboolean res = TRUE; - - res &= gst_mem_index_plugin_init (plugin); - - /* FIXME 0.11: fix or remove GstFileIndex, which used mmap and libxml */ - /* res &= gst_file_index_plugin_init (plugin); */ - - return res; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "coreindexers", - "GStreamer core indexers", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/plugins/indexers/gstindexers.h b/plugins/indexers/gstindexers.h deleted file mode 100644 index 8180f8f..0000000 --- a/plugins/indexers/gstindexers.h +++ /dev/null @@ -1,33 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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_INDEXERS_H__ -#define __GST_INDEXERS_H__ - -G_BEGIN_DECLS - - -gboolean gst_mem_index_plugin_init (GstPlugin * plugin); - -/* gboolean gst_file_index_plugin_init (GstPlugin * plugin); */ - - -G_END_DECLS - -#endif /* __GST_INDEXERS_H__ */ diff --git a/plugins/indexers/gstmemindex.c b/plugins/indexers/gstmemindex.c deleted file mode 100644 index fd276fa..0000000 --- a/plugins/indexers/gstmemindex.c +++ /dev/null @@ -1,444 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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. - */ - -#include <gst/gst.h> - -#include "gstindexers.h" - -#define GST_TYPE_MEM_INDEX \ - (gst_index_get_type ()) -#define GST_MEM_INDEX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MEM_INDEX, GstMemIndex)) -#define GST_MEM_INDEX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MEM_INDEX, GstMemIndexClass)) -#define GST_IS_MEM_INDEX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MEM_INDEX)) -#define GST_IS_MEM_INDEX_CLASS(klass) \ - (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MEM_INDEX)) - -/* - * Object model: - * - * All entries are simply added to a GList first. Then we build - * an index to each entry for each id/format - * - * - * memindex - * -----------------------------... - * ! ! - * id1 id2 - * ------------ - * ! ! - * format1 format2 - * ! ! - * GTree GTree - * - * - * The memindex creates a MemIndexId object for each writer id, a - * Hashtable is kept to map the id to the MemIndexId - * - * The MemIndexId keeps a MemIndexFormatIndex for each format the - * specific writer wants indexed. - * - * The MemIndexFormatIndex keeps all the values of the particular - * format in a GTree, The values of the GTree point back to the entry. - * - * Finding a value for an id/format requires locating the correct GTree, - * then do a lookup in the Tree to get the required value. - */ - -typedef struct -{ - GstFormat format; - gint offset; - GTree *tree; -} -GstMemIndexFormatIndex; - -typedef struct -{ - gint id; - GHashTable *format_index; -} -GstMemIndexId; - -typedef struct _GstMemIndex GstMemIndex; -typedef struct _GstMemIndexClass GstMemIndexClass; - -struct _GstMemIndex -{ - GstIndex parent; - - GList *associations; - - GHashTable *id_index; -}; - -struct _GstMemIndexClass -{ - GstIndexClass parent_class; -}; - -/* Index signals and args */ -enum -{ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - /* FILL ME */ -}; - -static void gst_mem_index_finalize (GObject * object); - -static void gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry); -static GstIndexEntry *gst_mem_index_get_assoc_entry (GstIndex * index, gint id, - GstIndexLookupMethod method, GstAssocFlags flags, - GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data); - -#define CLASS(mem_index) GST_MEM_INDEX_CLASS (G_OBJECT_GET_CLASS (mem_index)) - -/*static guint gst_mem_index_signals[LAST_SIGNAL] = { 0 }; */ - -GType gst_mem_index_get_type (void); - -G_DEFINE_TYPE (GstMemIndex, gst_mem_index, GST_TYPE_INDEX); - -static void -gst_mem_index_class_init (GstMemIndexClass * klass) -{ - GObjectClass *gobject_class; - GstIndexClass *gstindex_class; - - gobject_class = (GObjectClass *) klass; - gstindex_class = (GstIndexClass *) klass; - - gobject_class->finalize = gst_mem_index_finalize; - - gstindex_class->add_entry = GST_DEBUG_FUNCPTR (gst_mem_index_add_entry); - gstindex_class->get_assoc_entry = - GST_DEBUG_FUNCPTR (gst_mem_index_get_assoc_entry); -} - -static void -gst_mem_index_init (GstMemIndex * index) -{ - GST_DEBUG ("created new mem index"); - - index->associations = NULL; - index->id_index = g_hash_table_new (g_int_hash, g_int_equal); -} - -static void -gst_mem_index_free_format (gpointer key, gpointer value, gpointer user_data) -{ - GstMemIndexFormatIndex *index = (GstMemIndexFormatIndex *) value; - - if (index->tree) { - g_tree_destroy (index->tree); - } - - g_slice_free (GstMemIndexFormatIndex, index); -} - -static void -gst_mem_index_free_id (gpointer key, gpointer value, gpointer user_data) -{ - GstMemIndexId *id_index = (GstMemIndexId *) value; - - if (id_index->format_index) { - g_hash_table_foreach (id_index->format_index, gst_mem_index_free_format, - NULL); - g_hash_table_destroy (id_index->format_index); - id_index->format_index = NULL; - } - - g_slice_free (GstMemIndexId, id_index); -} - -static void -gst_mem_index_finalize (GObject * object) -{ - GstMemIndex *memindex = GST_MEM_INDEX (object); - - /* Delete the trees referencing the associations first */ - if (memindex->id_index) { - g_hash_table_foreach (memindex->id_index, gst_mem_index_free_id, NULL); - g_hash_table_destroy (memindex->id_index); - memindex->id_index = NULL; - } - - /* Then delete the associations themselves */ - if (memindex->associations) { - g_list_foreach (memindex->associations, (GFunc) gst_index_entry_free, NULL); - g_list_free (memindex->associations); - memindex->associations = NULL; - } - - G_OBJECT_CLASS (gst_mem_index_parent_class)->finalize (object); -} - -static void -gst_mem_index_add_id (GstIndex * index, GstIndexEntry * entry) -{ - GstMemIndex *memindex = GST_MEM_INDEX (index); - GstMemIndexId *id_index; - - id_index = g_hash_table_lookup (memindex->id_index, &entry->id); - - if (!id_index) { - id_index = g_slice_new0 (GstMemIndexId); - - id_index->id = entry->id; - id_index->format_index = g_hash_table_new (g_int_hash, g_int_equal); - g_hash_table_insert (memindex->id_index, &id_index->id, id_index); - } -} - -static gint -mem_index_compare (gconstpointer a, gconstpointer b, gpointer user_data) -{ - GstMemIndexFormatIndex *index = user_data; - gint64 val1, val2; - gint64 diff; - - val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset); - val2 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) b), index->offset); - - diff = (val2 - val1); - - return (diff == 0 ? 0 : (diff > 0 ? 1 : -1)); -} - -static void -gst_mem_index_index_format (GstMemIndexId * id_index, GstIndexEntry * entry, - gint assoc) -{ - GstMemIndexFormatIndex *index; - GstFormat *format; - - format = &GST_INDEX_ASSOC_FORMAT (entry, assoc); - - index = g_hash_table_lookup (id_index->format_index, format); - - if (!index) { - index = g_slice_new0 (GstMemIndexFormatIndex); - - index->format = *format; - index->offset = assoc; - index->tree = g_tree_new_with_data (mem_index_compare, index); - - g_hash_table_insert (id_index->format_index, &index->format, index); - } - - g_tree_insert (index->tree, entry, entry); -} - -static void -gst_mem_index_add_association (GstIndex * index, GstIndexEntry * entry) -{ - GstMemIndex *memindex = GST_MEM_INDEX (index); - GstMemIndexId *id_index; - - memindex->associations = g_list_prepend (memindex->associations, entry); - - id_index = g_hash_table_lookup (memindex->id_index, &entry->id); - if (id_index) { - gint i; - - for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) { - gst_mem_index_index_format (id_index, entry, i); - } - } -} - -static void -gst_mem_index_add_object (GstIndex * index, GstIndexEntry * entry) -{ -} - -static void -gst_mem_index_add_format (GstIndex * index, GstIndexEntry * entry) -{ -} - -static void -gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry) -{ - GST_LOG_OBJECT (index, "added this entry"); - - switch (entry->type) { - case GST_INDEX_ENTRY_ID: - gst_mem_index_add_id (index, entry); - break; - case GST_INDEX_ENTRY_ASSOCIATION: - gst_mem_index_add_association (index, entry); - break; - case GST_INDEX_ENTRY_OBJECT: - gst_mem_index_add_object (index, entry); - break; - case GST_INDEX_ENTRY_FORMAT: - gst_mem_index_add_format (index, entry); - break; - default: - break; - } -} - -typedef struct -{ - gint64 value; - GstMemIndexFormatIndex *index; - gboolean exact; - GstIndexEntry *lower; - gint64 low_diff; - GstIndexEntry *higher; - gint64 high_diff; -} -GstMemIndexSearchData; - -static gint -mem_index_search (gconstpointer a, gconstpointer b) -{ - GstMemIndexSearchData *data = (GstMemIndexSearchData *) b; - GstMemIndexFormatIndex *index = data->index; - gint64 val1, val2; - gint64 diff; - - val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset); - val2 = data->value; - - diff = (val1 - val2); - if (diff == 0) - return 0; - - /* exact matching, don't update low/high */ - if (data->exact) - return (diff > 0 ? 1 : -1); - - if (diff < 0) { - if (diff > data->low_diff) { - data->low_diff = diff; - data->lower = (GstIndexEntry *) a; - } - diff = -1; - } else { - if (diff < data->high_diff) { - data->high_diff = diff; - data->higher = (GstIndexEntry *) a; - } - diff = 1; - } - - return diff; -} - -static GstIndexEntry * -gst_mem_index_get_assoc_entry (GstIndex * index, gint id, - GstIndexLookupMethod method, - GstAssocFlags flags, - GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data) -{ - GstMemIndex *memindex = GST_MEM_INDEX (index); - GstMemIndexId *id_index; - GstMemIndexFormatIndex *format_index; - GstIndexEntry *entry; - GstMemIndexSearchData data; - - id_index = g_hash_table_lookup (memindex->id_index, &id); - if (!id_index) - return NULL; - - format_index = g_hash_table_lookup (id_index->format_index, &format); - if (!format_index) - return NULL; - - data.value = value; - data.index = format_index; - data.exact = (method == GST_INDEX_LOOKUP_EXACT); - - /* setup data for low/high checks if we are not looking - * for an exact match */ - if (!data.exact) { - data.low_diff = G_MININT64; - data.lower = NULL; - data.high_diff = G_MAXINT64; - data.higher = NULL; - } - - entry = g_tree_search (format_index->tree, mem_index_search, &data); - - /* get the low/high values if we're not exact */ - if (entry == NULL && !data.exact) { - if (method == GST_INDEX_LOOKUP_BEFORE) - entry = data.lower; - else if (method == GST_INDEX_LOOKUP_AFTER) { - entry = data.higher; - } - } - - if (entry && ((GST_INDEX_ASSOC_FLAGS (entry) & flags) != flags)) { - if (method != GST_INDEX_LOOKUP_EXACT) { - GList *l_entry = g_list_find (memindex->associations, entry); - - entry = NULL; - - while (l_entry) { - entry = (GstIndexEntry *) l_entry->data; - - if (entry->id == id && (GST_INDEX_ASSOC_FLAGS (entry) & flags) == flags) - break; - - if (method == GST_INDEX_LOOKUP_BEFORE) - l_entry = g_list_next (l_entry); - else if (method == GST_INDEX_LOOKUP_AFTER) { - l_entry = g_list_previous (l_entry); - } - } - } else { - entry = NULL; - } - } - - return entry; -} - -gboolean -gst_mem_index_plugin_init (GstPlugin * plugin) -{ - GstIndexFactory *factory; - - factory = gst_index_factory_new ("memindex", - "A index that stores entries in memory", gst_mem_index_get_type ()); - - if (factory == NULL) { - g_warning ("failed to create memindex factory"); - return FALSE; - } - - GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name; - GST_PLUGIN_FEATURE (factory)->loaded = TRUE; - - gst_registry_add_feature (gst_registry_get_default (), - GST_PLUGIN_FEATURE (factory)); - - return TRUE; -} |