aboutsummaryrefslogtreecommitdiff
path: root/libs/gst/base
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@circular-chaos.org>2013-09-24 16:07:33 +0200
committerSebastian Dröge <slomo@circular-chaos.org>2013-09-24 16:08:31 +0200
commit4a6883f21d411dc411914054a69aa40d987bf66b (patch)
treeaede32630d47ab14da0fb9ca006a363ae3407dc3 /libs/gst/base
parent527b34cfbd859fccf6ee49024abdef526fd00674 (diff)
parent63f3a12981d4257915f0c1651ab409a08a1c66f8 (diff)
Merge branch 'upstream-experimental' into upstream
Diffstat (limited to 'libs/gst/base')
-rw-r--r--libs/gst/base/Makefile.am11
-rw-r--r--libs/gst/base/Makefile.in264
-rw-r--r--libs/gst/base/base.h39
-rw-r--r--libs/gst/base/gstadapter.c207
-rw-r--r--libs/gst/base/gstadapter.h11
-rw-r--r--libs/gst/base/gstbaseparse.c317
-rw-r--r--libs/gst/base/gstbaseparse.h25
-rw-r--r--libs/gst/base/gstbasesink.c205
-rw-r--r--libs/gst/base/gstbasesink.h8
-rw-r--r--libs/gst/base/gstbasesrc.c126
-rw-r--r--libs/gst/base/gstbasesrc.h4
-rw-r--r--libs/gst/base/gstbasetransform.c55
-rw-r--r--libs/gst/base/gstbasetransform.h4
-rw-r--r--libs/gst/base/gstbitreader-docs.h22
-rw-r--r--libs/gst/base/gstbitreader.c4
-rw-r--r--libs/gst/base/gstbitreader.h4
-rw-r--r--libs/gst/base/gstbytereader-docs.h4
-rw-r--r--libs/gst/base/gstbytereader.c33
-rw-r--r--libs/gst/base/gstbytereader.h4
-rw-r--r--libs/gst/base/gstbytewriter-docs.h4
-rw-r--r--libs/gst/base/gstbytewriter.c4
-rw-r--r--libs/gst/base/gstbytewriter.h4
-rw-r--r--libs/gst/base/gstcollectpads.c34
-rw-r--r--libs/gst/base/gstcollectpads.h4
-rw-r--r--libs/gst/base/gstdataqueue.c809
-rw-r--r--libs/gst/base/gstdataqueue.h163
-rw-r--r--libs/gst/base/gstindex.c4
-rw-r--r--libs/gst/base/gstindex.h4
-rw-r--r--libs/gst/base/gstmemindex.c4
-rw-r--r--libs/gst/base/gstpushsrc.c4
-rw-r--r--libs/gst/base/gstpushsrc.h4
-rw-r--r--libs/gst/base/gstqueuearray.c341
-rw-r--r--libs/gst/base/gstqueuearray.h50
-rw-r--r--libs/gst/base/gsttypefindhelper.c6
-rw-r--r--libs/gst/base/gsttypefindhelper.h4
35 files changed, 2495 insertions, 295 deletions
diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am
index ca7d4c8..076dc02 100644
--- a/libs/gst/base/Makefile.am
+++ b/libs/gst/base/Makefile.am
@@ -12,7 +12,9 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \
gstbytereader.c \
gstbytewriter.c \
gstcollectpads.c \
+ gstdataqueue.c \
gstpushsrc.c \
+ gstqueuearray.c \
gsttypefindhelper.c
libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS)
@@ -23,6 +25,7 @@ libgstbase_@GST_API_VERSION@includedir = \
$(includedir)/gstreamer-@GST_API_VERSION@/gst/base
libgstbase_@GST_API_VERSION@include_HEADERS = \
+ base.h \
gstadapter.h \
gstbaseparse.h \
gstbasesink.h \
@@ -32,7 +35,9 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \
gstbytereader.h \
gstbytewriter.h \
gstcollectpads.h \
+ gstdataqueue.h \
gstpushsrc.h \
+ gstqueuearray.h \
gsttypefindhelper.h
noinst_HEADERS = \
@@ -67,11 +72,10 @@ BUILT_GIRSOURCES = GstBase-@GST_API_VERSION@.gir
gir_headers=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@include_HEADERS))
gir_sources=$(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@_la_SOURCES))
-gir_cincludes=$(patsubst %,--c-include='gst/base/%',$(libgstbase_@GST_API_VERSION@include_HEADERS))
GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERSION@.la
$(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
- GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
+ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \
$(INTROSPECTION_SCANNER) -v --namespace GstBase \
--nsversion=@GST_API_VERSION@ \
--warn-all \
@@ -80,10 +84,9 @@ GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERS
-I$(top_srcdir)/libs \
-I$(top_builddir) \
-I$(top_builddir)/libs \
- $(gir_cincludes) \
+ --c-include "gst/base/base.h" \
--add-include-path=$(top_builddir)/gst \
--library-path=$(top_builddir)/gst \
- --library=$(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \
--library=libgstbase-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
--libtool="$(top_builddir)/libtool" \
diff --git a/libs/gst/base/Makefile.in b/libs/gst/base/Makefile.in
index f932360..9c97366 100644
--- a/libs/gst/base/Makefile.in
+++ b/libs/gst/base/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# Makefile.in generated by automake 1.14 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-# Foundation, Inc.
+# Copyright (C) 1994-2013 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.
@@ -18,23 +17,51 @@
VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
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;; \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
- test $$am__dry = yes; \
- }
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -56,15 +83,16 @@ host_triplet = @host@
target_triplet = @target@
@HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA)
subdir = libs/gst/base
-DIST_COMMON = README $(libgstbase_@GST_API_VERSION@include_HEADERS) \
- $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp \
+ $(libgstbase_@GST_API_VERSION@include_HEADERS) \
+ $(noinst_HEADERS) README
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 \
@@ -88,12 +116,14 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/pkg.m4 $(top_srcdir)/m4/ax_pthread.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/inttypes_h.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/longlong.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
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -142,17 +172,32 @@ am_libgstbase_@GST_API_VERSION@_la_OBJECTS = \
libgstbase_@GST_API_VERSION@_la-gstbytereader.lo \
libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo \
libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo \
+ libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo \
libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo \
+ libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo \
libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo
libgstbase_@GST_API_VERSION@_la_OBJECTS = \
$(am_libgstbase_@GST_API_VERSION@_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
+am__v_lt_1 =
libgstbase_@GST_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) \
$(libgstbase_@GST_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+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_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -165,20 +210,16 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
SOURCES = $(libgstbase_@GST_API_VERSION@_la_SOURCES)
DIST_SOURCES = $(libgstbase_@GST_API_VERSION@_la_SOURCES)
am__can_run_installinfo = \
@@ -189,6 +230,23 @@ am__can_run_installinfo = \
DATA = $(gir_DATA) $(typelibs_DATA)
HEADERS = $(libgstbase_@GST_API_VERSION@include_HEADERS) \
$(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -290,15 +348,11 @@ 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_LIBTOOLFLAGS = @GST_PLUGIN_LIBTOOLFLAGS@
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@
GST_VERSION_MAJOR = @GST_VERSION_MAJOR@
GST_VERSION_MICRO = @GST_VERSION_MICRO@
GST_VERSION_MINOR = @GST_VERSION_MINOR@
@@ -308,11 +362,9 @@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
GTKDOC_MKPDF = @GTKDOC_MKPDF@
GTKDOC_REBASE = @GTKDOC_REBASE@
-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@
@@ -320,6 +372,7 @@ HAVE_PNGTOPNM = @HAVE_PNGTOPNM@
HAVE_PNMTOPS = @HAVE_PNMTOPS@
HAVE_PS2PDF = @HAVE_PS2PDF@
HAVE_XMLLINT = @HAVE_XMLLINT@
+HAVE_XSLTPROC = @HAVE_XSLTPROC@
HOST_CPU = @HOST_CPU@
HTML_DIR = @HTML_DIR@
INSTALL = @INSTALL@
@@ -382,6 +435,7 @@ PERL_PATH = @PERL_PATH@
PKG_CONFIG = @PKG_CONFIG@
PLUGINDIR = @PLUGINDIR@
POSUB = @POSUB@
+PRINTF_CFLAGS = @PRINTF_CFLAGS@
PROFILE_CFLAGS = @PROFILE_CFLAGS@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
@@ -486,7 +540,9 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \
gstbytereader.c \
gstbytewriter.c \
gstcollectpads.c \
+ gstdataqueue.c \
gstpushsrc.c \
+ gstqueuearray.c \
gsttypefindhelper.c
libgstbase_@GST_API_VERSION@_la_CFLAGS = $(GST_OBJ_CFLAGS)
@@ -496,6 +552,7 @@ libgstbase_@GST_API_VERSION@includedir = \
$(includedir)/gstreamer-@GST_API_VERSION@/gst/base
libgstbase_@GST_API_VERSION@include_HEADERS = \
+ base.h \
gstadapter.h \
gstbaseparse.h \
gstbasesink.h \
@@ -505,7 +562,9 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \
gstbytereader.h \
gstbytewriter.h \
gstcollectpads.h \
+ gstdataqueue.h \
gstpushsrc.h \
+ gstqueuearray.h \
gsttypefindhelper.h
noinst_HEADERS = \
@@ -519,7 +578,6 @@ CLEANFILES = *.gcno *.gcda *.gcov $(am__append_1)
@HAVE_INTROSPECTION_TRUE@BUILT_GIRSOURCES = GstBase-@GST_API_VERSION@.gir
@HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@include_HEADERS))
@HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, $(libgstbase_@GST_API_VERSION@_la_SOURCES))
-@HAVE_INTROSPECTION_TRUE@gir_cincludes = $(patsubst %,--c-include='gst/base/%',$(libgstbase_@GST_API_VERSION@include_HEADERS))
# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to
# install anything - we need to install inside our prefix.
@@ -561,6 +619,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
@@ -587,12 +646,15 @@ uninstall-libLTLIBRARIES:
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
- @list='$(lib_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
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
libgstbase-@GST_API_VERSION@.la: $(libgstbase_@GST_API_VERSION@_la_OBJECTS) $(libgstbase_@GST_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgstbase_@GST_API_VERSION@_la_DEPENDENCIES)
$(AM_V_CCLD)$(libgstbase_@GST_API_VERSION@_la_LINK) -rpath $(libdir) $(libgstbase_@GST_API_VERSION@_la_OBJECTS) $(libgstbase_@GST_API_VERSION@_la_LIBADD) $(LIBS)
@@ -611,26 +673,31 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytereader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.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_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.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_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(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_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
@@ -698,6 +765,13 @@ libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo: gstcollectpads.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo `test -f 'gstcollectpads.c' || echo '$(srcdir)/'`gstcollectpads.c
+libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo: gstdataqueue.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdataqueue.c' object='libgstbase_@GST_API_VERSION@_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 $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c
+
libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo: gstpushsrc.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo `test -f 'gstpushsrc.c' || echo '$(srcdir)/'`gstpushsrc.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo
@@ -705,6 +779,13 @@ libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo: gstpushsrc.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo `test -f 'gstpushsrc.c' || echo '$(srcdir)/'`gstpushsrc.c
+libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo: gstqueuearray.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo `test -f 'gstqueuearray.c' || echo '$(srcdir)/'`gstqueuearray.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstqueuearray.c' object='libgstbase_@GST_API_VERSION@_la-gstqueuearray.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 $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo `test -f 'gstqueuearray.c' || echo '$(srcdir)/'`gstqueuearray.c
+
libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo: gsttypefindhelper.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo `test -f 'gsttypefindhelper.c' || echo '$(srcdir)/'`gsttypefindhelper.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Plo
@@ -781,26 +862,15 @@ uninstall-libgstbase_@GST_API_VERSION@includeHEADERS:
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(libgstbase_@GST_API_VERSION@includedir)'; $(am__uninstall_files_from_dir)
-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)
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
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; }; }'`; \
+ $(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -812,15 +882,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$$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; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -829,6 +895,21 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -978,21 +1059,21 @@ uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \
.MAKE: install-am install-strip
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libLTLIBRARIES clean-libtool 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-girDATA \
- install-html install-html-am install-info install-info-am \
- install-libLTLIBRARIES \
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am 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-girDATA install-html install-html-am \
+ install-info install-info-am install-libLTLIBRARIES \
install-libgstbase_@GST_API_VERSION@includeHEADERS install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip install-typelibsDATA 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-girDATA \
+ tags tags-am uninstall uninstall-am uninstall-girDATA \
uninstall-libLTLIBRARIES \
uninstall-libgstbase_@GST_API_VERSION@includeHEADERS \
uninstall-typelibsDATA
@@ -1017,7 +1098,7 @@ Android.mk: Makefile.am
@HAVE_INTROSPECTION_TRUE@GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERSION@.la
@HAVE_INTROSPECTION_TRUE@ $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
-@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
+@HAVE_INTROSPECTION_TRUE@ GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \
@HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_SCANNER) -v --namespace GstBase \
@HAVE_INTROSPECTION_TRUE@ --nsversion=@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --warn-all \
@@ -1026,10 +1107,9 @@ Android.mk: Makefile.am
@HAVE_INTROSPECTION_TRUE@ -I$(top_srcdir)/libs \
@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir) \
@HAVE_INTROSPECTION_TRUE@ -I$(top_builddir)/libs \
-@HAVE_INTROSPECTION_TRUE@ $(gir_cincludes) \
+@HAVE_INTROSPECTION_TRUE@ --c-include "gst/base/base.h" \
@HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/gst \
@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \
-@HAVE_INTROSPECTION_TRUE@ --library=$(top_builddir)/gst/libgstreamer-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --library=libgstbase-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \
diff --git a/libs/gst/base/base.h b/libs/gst/base/base.h
new file mode 100644
index 0000000..e741145
--- /dev/null
+++ b/libs/gst/base/base.h
@@ -0,0 +1,39 @@
+/* GStreamer
+ * Copyright (C) 2012 GStreamer developers
+ *
+ * base.h: single include header for gst-base library
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_BASE_H__
+#define __GST_BASE_H__
+
+#include <gst/base/gstadapter.h>
+#include <gst/base/gstbaseparse.h>
+#include <gst/base/gstbasesink.h>
+#include <gst/base/gstbasesrc.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/base/gstbitreader.h>
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbytewriter.h>
+#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstdataqueue.h>
+#include <gst/base/gstpushsrc.h>
+#include <gst/base/gstqueuearray.h>
+#include <gst/base/gsttypefindhelper.h>
+
+#endif /* __GST_BASE_H__ */
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index 5a15e68..4c3e730 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -83,12 +83,14 @@
*
* The adapter will keep track of the timestamps of the buffers
* that were pushed. The last seen timestamp before the current position
- * can be queried with gst_adapter_prev_timestamp(). This function can
- * optionally return the amount of bytes between the start of the buffer that
+ * can be queried with gst_adapter_prev_pts(). This function can
+ * optionally return the number of bytes between the start of the buffer that
* carried the timestamp and the current adapter position. The distance is
* useful when dealing with, for example, raw audio samples because it allows
* you to calculate the timestamp of the current adapter position by using the
- * last seen timestamp and the amount of bytes since.
+ * last seen timestamp and the amount of bytes since. Additionally, the
+ * gst_adapter_prev_pts_at_offset() can be used to determine the last
+ * seen timestamp at a particular offset in the adapter.
*
* A last thing to note is that while GstAdapter is pretty optimized,
* merging buffers still might be an operation that requires a malloc() and
@@ -707,15 +709,102 @@ gst_adapter_take (GstAdapter * adapter, gsize nbytes)
}
/**
+ * gst_adapter_take_buffer_fast:
+ * @adapter: a #GstAdapter
+ * @nbytes: the number of bytes to take
+ *
+ * Returns a #GstBuffer containing the first @nbytes of the @adapter.
+ * The returned bytes will be flushed from the adapter. This function
+ * is potentially more performant than gst_adapter_take_buffer() since
+ * it can reuse the memory in pushed buffers by subbuffering or
+ * merging. Unlike gst_adapter_take_buffer(), the returned buffer may
+ * be composed of multiple non-contiguous #GstMemory objects, no
+ * copies are made.
+ *
+ * Note that no assumptions should be made as to whether certain buffer
+ * flags such as the DISCONT flag are set on the returned buffer, or not.
+ * The caller needs to explicitly set or unset flags that should be set or
+ * unset.
+ *
+ * This function can return buffer up to the return value of
+ * gst_adapter_available() without making copies if possible.
+ *
+ * Caller owns a reference to the returned buffer. gst_buffer_unref() after
+ * usage.
+ *
+ * Free-function: gst_buffer_unref
+ *
+ * Returns: (transfer full): a #GstBuffer containing the first @nbytes of
+ * the adapter, or #NULL if @nbytes bytes are not available.
+ * gst_buffer_unref() when no longer needed.
+ *
+ * Since: 1.2
+ */
+
+GstBuffer *
+gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes)
+{
+ GstBuffer *buffer = NULL;
+ GstBuffer *cur;
+ GSList *item;
+ gsize skip;
+ gsize left = nbytes;
+
+ g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
+ g_return_val_if_fail (nbytes > 0, NULL);
+
+ GST_LOG_OBJECT (adapter, "taking buffer of %" G_GSIZE_FORMAT " bytes",
+ nbytes);
+
+ /* we don't have enough data, return NULL. This is unlikely
+ * as one usually does an _available() first instead of grabbing a
+ * random size. */
+ if (G_UNLIKELY (nbytes > adapter->size))
+ return NULL;
+
+ skip = adapter->skip;
+ cur = adapter->buflist->data;
+
+ if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
+ GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
+ " as head buffer", nbytes);
+ buffer = gst_buffer_ref (cur);
+ goto done;
+ }
+
+ for (item = adapter->buflist; item && left > 0; item = item->next) {
+ gsize size;
+
+ cur = item->data;
+ size = MIN (gst_buffer_get_size (cur) - skip, left);
+
+ GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes"
+ " via region copy", size);
+ if (buffer)
+ gst_buffer_copy_into (buffer, cur, GST_BUFFER_COPY_MEMORY, skip, size);
+ else
+ buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size);
+ skip = 0;
+ left -= size;
+ }
+
+done:
+ gst_adapter_flush_unchecked (adapter, nbytes);
+
+ return buffer;
+}
+
+/**
* gst_adapter_take_buffer:
* @adapter: a #GstAdapter
* @nbytes: the number of bytes to take
*
* Returns a #GstBuffer containing the first @nbytes bytes of the
* @adapter. The returned bytes will be flushed from the adapter.
- * This function is potentially more performant than gst_adapter_take()
- * since it can reuse the memory in pushed buffers by subbuffering
- * or merging.
+ * This function is potentially more performant than
+ * gst_adapter_take() since it can reuse the memory in pushed buffers
+ * by subbuffering or merging. This function will always return a
+ * buffer with a single memory region.
*
* Note that no assumptions should be made as to whether certain buffer
* flags such as the DISCONT flag are set on the returned buffer, or not.
@@ -949,6 +1038,104 @@ gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
}
/**
+ * gst_adapter_prev_pts_at_offset:
+ * @adapter: a #GstAdapter
+ * @offset: the offset in the adapter at which to get timestamp
+ * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ *
+ * Get the pts that was before the byte at offset @offset in the adapter. When
+ * @distance is given, the amount of bytes between the pts and the current
+ * position is returned.
+ *
+ * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
+ * the adapter is first created or when it is cleared. This also means that before
+ * the first byte with a pts is removed from the adapter, the pts
+ * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
+ *
+ * Since: 1.2
+ * Returns: The previously seen pts at given offset.
+ */
+GstClockTime
+gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
+ guint64 * distance)
+{
+ GstBuffer *cur;
+ GSList *g;
+ gsize read_offset = 0;
+ GstClockTime pts = adapter->pts;
+
+ g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+ g_return_val_if_fail (offset >= 0, GST_CLOCK_TIME_NONE);
+
+ g = adapter->buflist;
+
+ while (g && read_offset < offset + adapter->skip) {
+ cur = g->data;
+
+ read_offset += gst_buffer_get_size (cur);
+ if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (cur))) {
+ pts = GST_BUFFER_PTS (cur);
+ }
+
+ g = g_slist_next (g);
+ }
+
+ if (distance)
+ *distance = adapter->dts_distance + offset;
+
+ return pts;
+}
+
+/**
+ * gst_adapter_prev_dts_at_offset:
+ * @adapter: a #GstAdapter
+ * @offset: the offset in the adapter at which to get timestamp
+ * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ *
+ * Get the dts that was before the byte at offset @offset in the adapter. When
+ * @distance is given, the amount of bytes between the dts and the current
+ * position is returned.
+ *
+ * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
+ * the adapter is first created or when it is cleared. This also means that before
+ * the first byte with a dts is removed from the adapter, the dts
+ * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
+ *
+ * Since: 1.2
+ * Returns: The previously seen dts at given offset.
+ */
+GstClockTime
+gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset,
+ guint64 * distance)
+{
+ GstBuffer *cur;
+ GSList *g;
+ gsize read_offset = 0;
+ GstClockTime dts = adapter->dts;
+
+ g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+ g_return_val_if_fail (offset >= 0, GST_CLOCK_TIME_NONE);
+
+ g = adapter->buflist;
+
+ while (g && read_offset < offset + adapter->skip) {
+ cur = g->data;
+
+ read_offset += gst_buffer_get_size (cur);
+ if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cur))) {
+ dts = GST_BUFFER_DTS (cur);
+ }
+
+ g = g_slist_next (g);
+ }
+
+ if (distance)
+ *distance = adapter->dts_distance + offset;
+
+ return dts;
+}
+
+/**
* gst_adapter_masked_scan_uint32_peek:
* @adapter: a #GstAdapter
* @mask: mask to apply to data before matching against @pattern
@@ -971,7 +1158,7 @@ gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
*
* Returns: offset of the first match, or -1 if no match was found.
*/
-gsize
+gssize
gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
guint32 pattern, gsize offset, gsize size, guint32 * value)
{
@@ -1108,7 +1295,7 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
* // -> returns -1
* </programlisting>
*/
-gsize
+gssize
gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
guint32 pattern, gsize offset, gsize size)
{
diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h
index 5b89744..9683f3b 100644
--- a/libs/gst/base/gstadapter.h
+++ b/libs/gst/base/gstadapter.h
@@ -13,8 +13,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#include <gst/gst.h>
@@ -60,16 +60,19 @@ void gst_adapter_flush (GstAdapter *adapter, gs
gpointer gst_adapter_take (GstAdapter *adapter, gsize nbytes);
GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, gsize nbytes);
GList* gst_adapter_take_list (GstAdapter *adapter, gsize nbytes);
+GstBuffer * gst_adapter_take_buffer_fast (GstAdapter *adapter, gsize nbytes);
gsize gst_adapter_available (GstAdapter *adapter);
gsize gst_adapter_available_fast (GstAdapter *adapter);
GstClockTime gst_adapter_prev_pts (GstAdapter *adapter, guint64 *distance);
GstClockTime gst_adapter_prev_dts (GstAdapter *adapter, guint64 *distance);
+GstClockTime gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance);
+GstClockTime gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance);
-gsize gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
+gssize gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
guint32 pattern, gsize offset, gsize size);
-gsize gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
+gssize gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
guint32 pattern, gsize offset, gsize size, guint32 * value);
G_END_DECLS
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index 2f55c7c..0e0aaf4 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -246,8 +246,10 @@ struct _GstBaseParsePrivate
gint64 estimated_drift;
guint min_frame_size;
+ gboolean disable_passthrough;
gboolean passthrough;
gboolean pts_interpolate;
+ gboolean infer_ts;
gboolean syncable;
gboolean has_timing_info;
guint fps_num, fps_den;
@@ -357,6 +359,15 @@ typedef struct _GstBaseParseSeek
GstClockTime start_ts;
} GstBaseParseSeek;
+#define DEFAULT_DISABLE_PASSTHROUGH FALSE
+
+enum
+{
+ PROP_0,
+ PROP_DISABLE_PASSTHROUGH,
+ PROP_LAST
+};
+
#define GST_BASE_PARSE_INDEX_LOCK(parse) \
g_mutex_lock (&parse->priv->index_lock);
#define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
@@ -413,6 +424,11 @@ static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
GstEvent * event);
static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
+static void gst_base_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_base_parse_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent,
@@ -430,12 +446,17 @@ static void gst_base_parse_loop (GstPad * pad);
static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
-static gboolean gst_base_parse_sink_default (GstBaseParse * parse,
+static gboolean gst_base_parse_sink_event_default (GstBaseParse * parse,
GstEvent * event);
-static gboolean gst_base_parse_src_default (GstBaseParse * parse,
+static gboolean gst_base_parse_src_event_default (GstBaseParse * parse,
GstEvent * event);
+static gboolean gst_base_parse_sink_query_default (GstBaseParse * parse,
+ GstQuery * query);
+static gboolean gst_base_parse_src_query_default (GstBaseParse * parse,
+ GstQuery * query);
+
static void gst_base_parse_drain (GstBaseParse * parse);
static void gst_base_parse_post_bitrates (GstBaseParse * parse,
@@ -526,7 +547,26 @@ gst_base_parse_class_init (GstBaseParseClass * klass)
gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (GstBaseParsePrivate));
parent_class = g_type_class_peek_parent (klass);
+
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_parse_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_parse_get_property);
+
+ /**
+ * GstBaseParse:disable-passthrough:
+ *
+ * If set to #TRUE, baseparse will unconditionally force parsing of the
+ * incoming data. This can be required in the rare cases where the incoming
+ * side-data (caps, pts, dts, ...) is not trusted by the user and wants to
+ * force validation and parsing of the incoming data.
+ * If set to #FALSE, decision of whether to parse the data or not is up to
+ * the implementation (standard behaviour).
+ */
+ g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH,
+ g_param_spec_boolean ("disable-passthrough", "Disable passthrough",
+ "Force processing (disables passthrough)",
+ DEFAULT_DISABLE_PASSTHROUGH,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class = (GstElementClass *) klass;
gstelement_class->change_state =
@@ -538,8 +578,10 @@ gst_base_parse_class_init (GstBaseParseClass * klass)
#endif
/* Default handlers */
- klass->sink_event = gst_base_parse_sink_default;
- klass->src_event = gst_base_parse_src_default;
+ klass->sink_event = gst_base_parse_sink_event_default;
+ klass->src_event = gst_base_parse_src_event_default;
+ klass->sink_query = gst_base_parse_sink_query_default;
+ klass->src_query = gst_base_parse_src_query_default;
klass->convert = gst_base_parse_convert_default;
GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
@@ -601,6 +643,38 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
}
+static void
+gst_base_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstBaseParse *parse = GST_BASE_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_DISABLE_PASSTHROUGH:
+ parse->priv->disable_passthrough = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstBaseParse *parse = GST_BASE_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_DISABLE_PASSTHROUGH:
+ g_value_set_boolean (value, parse->priv->disable_passthrough);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static GstBaseParseFrame *
gst_base_parse_frame_copy (GstBaseParseFrame * frame)
{
@@ -724,11 +798,13 @@ gst_base_parse_reset (GstBaseParse * parse)
parse->priv->first_frame_offset = -1;
parse->priv->estimated_duration = -1;
parse->priv->estimated_drift = 0;
- parse->priv->next_pts = 0;
+ parse->priv->next_pts = GST_CLOCK_TIME_NONE;
parse->priv->next_dts = 0;
parse->priv->syncable = TRUE;
+ parse->priv->disable_passthrough = DEFAULT_DISABLE_PASSTHROUGH;
parse->priv->passthrough = FALSE;
parse->priv->pts_interpolate = TRUE;
+ parse->priv->infer_ts = TRUE;
parse->priv->has_timing_info = FALSE;
parse->priv->post_min_bitrate = TRUE;
parse->priv->post_avg_bitrate = TRUE;
@@ -881,7 +957,7 @@ gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
}
-/* gst_base_parse_sink_default:
+/* gst_base_parse_sink_event_default:
* @parse: #GstBaseParse.
* @event: #GstEvent to be handled.
*
@@ -893,7 +969,7 @@ gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
* Returns: %TRUE if the event was handled and not need forwarding.
*/
static gboolean
-gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
+gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
{
GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
gboolean ret = FALSE;
@@ -925,6 +1001,7 @@ gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
const GstSegment *in_segment;
GstSegment out_segment;
gint64 offset = 0, next_dts;
+ guint32 seqnum = gst_event_get_seqnum (event);
gst_event_parse_segment (event, &in_segment);
gst_segment_init (&out_segment, GST_FORMAT_TIME);
@@ -980,6 +1057,7 @@ gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
gst_event_unref (event);
event = gst_event_new_segment (&out_segment);
+ gst_event_set_seqnum (event, seqnum);
GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. %"
GST_SEGMENT_FORMAT, in_segment);
@@ -994,6 +1072,7 @@ gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
out_segment.time = 0;
event = gst_event_new_segment (&out_segment);
+ gst_event_set_seqnum (event, seqnum);
next_dts = 0;
} else {
@@ -1027,10 +1106,11 @@ gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
parse->priv->offset = offset;
parse->priv->sync_offset = offset;
parse->priv->next_dts = next_dts;
- if (parse->priv->pts_interpolate)
- parse->priv->next_pts = next_dts;
+ parse->priv->next_pts = GST_CLOCK_TIME_NONE;
parse->priv->last_pts = GST_CLOCK_TIME_NONE;
parse->priv->last_dts = GST_CLOCK_TIME_NONE;
+ parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
+ parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
parse->priv->discont = TRUE;
parse->priv->seen_keyframe = FALSE;
break;
@@ -1159,18 +1239,20 @@ gst_base_parse_sink_default (GstBaseParse * parse, GstEvent * event)
}
static gboolean
-gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+gst_base_parse_sink_query_default (GstBaseParse * parse, GstQuery * query)
{
- GstBaseParse *parse;
- GstBaseParseClass *bclass;
+ GstPad *pad;
gboolean res;
- parse = GST_BASE_PARSE (parent);
- bclass = GST_BASE_PARSE_GET_CLASS (parse);
+ pad = GST_BASE_PARSE_SINK_PAD (parse);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
+ GstBaseParseClass *bclass;
+
+ bclass = GST_BASE_PARSE_GET_CLASS (parse);
+
if (bclass->get_sink_caps) {
GstCaps *caps, *filter;
@@ -1204,7 +1286,7 @@ gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
}
default:
{
- res = gst_pad_query_default (pad, parent, query);
+ res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
break;
}
}
@@ -1212,6 +1294,52 @@ gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
return res;
}
+static gboolean
+gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ GstBaseParseClass *bclass;
+ GstBaseParse *parse;
+ gboolean ret;
+
+ parse = GST_BASE_PARSE (parent);
+ bclass = GST_BASE_PARSE_GET_CLASS (parse);
+
+ GST_DEBUG_OBJECT (parse, "%s query", GST_QUERY_TYPE_NAME (query));
+
+ if (bclass->sink_query)
+ ret = bclass->sink_query (parse, query);
+ else
+ ret = FALSE;
+
+ GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
+ GST_QUERY_TYPE_NAME (query), ret, query);
+
+ return ret;
+}
+
+static gboolean
+gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ GstBaseParseClass *bclass;
+ GstBaseParse *parse;
+ gboolean ret;
+
+ parse = GST_BASE_PARSE (parent);
+ bclass = GST_BASE_PARSE_GET_CLASS (parse);
+
+ GST_DEBUG_OBJECT (parse, "%s query: %" GST_PTR_FORMAT,
+ GST_QUERY_TYPE_NAME (query), query);
+
+ if (bclass->src_query)
+ ret = bclass->src_query (parse, query);
+ else
+ ret = FALSE;
+
+ GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
+ GST_QUERY_TYPE_NAME (query), ret, query);
+
+ return ret;
+}
/* gst_base_parse_src_event:
* @pad: #GstPad that received the event.
@@ -1250,7 +1378,7 @@ gst_base_parse_is_seekable (GstBaseParse * parse)
return parse->priv->syncable;
}
-/* gst_base_parse_src_default:
+/* gst_base_parse_src_event_default:
* @parse: #GstBaseParse.
* @event: #GstEvent that was received.
*
@@ -1259,7 +1387,7 @@ gst_base_parse_is_seekable (GstBaseParse * parse)
* Returns: TRUE if the event was handled and can be dropped.
*/
static gboolean
-gst_base_parse_src_default (GstBaseParse * parse, GstEvent * event)
+gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
{
gboolean res = FALSE;
@@ -1877,7 +2005,7 @@ gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
return ret;
}
-/* gst_base_parse_handle_and_push_buffer:
+/* gst_base_parse_handle_and_push_frame:
* @parse: #GstBaseParse.
* @klass: #GstBaseParseClass.
* @frame: (transfer full): a #GstBaseParseFrame
@@ -1929,6 +2057,12 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
}
}
+ /* interpolating and no valid pts yet,
+ * start with dts and carry on from there */
+ if (parse->priv->infer_ts && parse->priv->pts_interpolate
+ && !GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts))
+ parse->priv->next_pts = parse->priv->next_dts;
+
/* again use default handler to add missing metadata;
* we may have new information on frame properties */
gst_base_parse_parse_frame (parse, frame);
@@ -2157,7 +2291,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
size, gst_flow_get_name (ret));
gst_buffer_unref (buffer);
/* if we are not sufficiently in control, let upstream decide on EOS */
- if (ret == GST_FLOW_EOS &&
+ if (ret == GST_FLOW_EOS && !parse->priv->disable_passthrough &&
(parse->priv->passthrough ||
(parse->priv->pad_mode == GST_PAD_MODE_PUSH &&
!parse->priv->upstream_seekable)))
@@ -2615,7 +2749,8 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
- if (G_UNLIKELY (parse->priv->passthrough)) {
+ if (G_UNLIKELY (!parse->priv->disable_passthrough
+ && parse->priv->passthrough)) {
GstBaseParseFrame frame;
gst_base_parse_frame_init (&frame);
@@ -2664,10 +2799,21 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
* but interpolate in between */
pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
- if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts)) {
+ if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
parse->priv->prev_pts = parse->priv->next_pts = pts;
+
+ if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts))
parse->priv->prev_dts = parse->priv->next_dts = dts;
- }
+
+ /* we can mess with, erm interpolate, timestamps,
+ * and incoming stuff has PTS but no DTS seen so far,
+ * then pick up DTS from PTS and hope for the best ... */
+ if (parse->priv->infer_ts &&
+ parse->priv->pts_interpolate &&
+ !GST_CLOCK_TIME_IS_VALID (dts) &&
+ !GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts) &&
+ GST_CLOCK_TIME_IS_VALID (pts))
+ parse->priv->next_dts = pts;
/* always pass all available data */
data = gst_adapter_map (parse->priv->adapter, av);
@@ -2944,13 +3090,17 @@ gst_base_parse_loop (GstPad * pad)
if (G_UNLIKELY (parse->priv->push_stream_start)) {
gchar *stream_id;
+ GstEvent *event;
stream_id =
gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (parse),
NULL);
+ event = gst_event_new_stream_start (stream_id);
+ gst_event_set_group_id (event, gst_util_group_id_next ());
+
GST_DEBUG_OBJECT (parse, "Pushing STREAM_START");
- gst_pad_push_event (parse->srcpad, gst_event_new_stream_start (stream_id));
+ gst_pad_push_event (parse->srcpad, event);
parse->priv->push_stream_start = FALSE;
g_free (stream_id);
}
@@ -3390,6 +3540,23 @@ gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
}
/**
+ * gst_base_parse_set_infer_ts:
+ * @parse: a #GstBaseParse
+ * @infer_ts: %TRUE if parser should infer DTS/PTS from each other
+ *
+ * By default, the base class might try to infer PTS from DTS and vice
+ * versa. While this is generally correct for audio data, it may not
+ * be otherwise. Sub-classes implementing such formats should disable
+ * timestamp infering.
+ */
+void
+gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts)
+{
+ parse->priv->infer_ts = infer_ts;
+ GST_INFO_OBJECT (parse, "TS infering: %s", (infer_ts) ? "yes" : "no");
+}
+
+/**
* gst_base_parse_set_latency:
* @parse: a #GstBaseParse
* @min_latency: minimum parse latency
@@ -3443,14 +3610,12 @@ gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
}
static gboolean
-gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
+gst_base_parse_src_query_default (GstBaseParse * parse, GstQuery * query)
{
- GstBaseParse *parse;
gboolean res = FALSE;
+ GstPad *pad;
- parse = GST_BASE_PARSE (parent);
-
- GST_LOG_OBJECT (parse, "handling query: %" GST_PTR_FORMAT, query);
+ pad = GST_BASE_PARSE_SRC_PAD (parse);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
@@ -3462,7 +3627,7 @@ gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
gst_query_parse_position (query, &format, NULL);
/* try upstream first */
- res = gst_pad_query_default (pad, parent, query);
+ res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
if (!res) {
/* Fall back on interpreting segment */
GST_OBJECT_LOCK (parse);
@@ -3496,7 +3661,7 @@ gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
gst_query_parse_duration (query, &format, NULL);
/* consult upstream */
- res = gst_pad_query_default (pad, parent, query);
+ res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
/* otherwise best estimate from us */
if (!res) {
@@ -3516,7 +3681,7 @@ gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
/* consult upstream */
- res = gst_pad_query_default (pad, parent, query);
+ res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
/* we may be able to help if in TIME */
if (fmt == GST_FORMAT_TIME && gst_base_parse_is_seekable (parse)) {
@@ -3584,8 +3749,27 @@ gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
}
break;
}
+ case GST_QUERY_SEGMENT:
+ {
+ GstFormat format;
+ gint64 start, stop;
+
+ format = parse->segment.format;
+
+ start =
+ gst_segment_to_stream_time (&parse->segment, format,
+ parse->segment.start);
+ if ((stop = parse->segment.stop) == -1)
+ stop = parse->segment.duration;
+ else
+ stop = gst_segment_to_stream_time (&parse->segment, format, stop);
+
+ gst_query_set_segment (query, parse->segment.rate, format, start, stop);
+ res = TRUE;
+ break;
+ }
default:
- res = gst_pad_query_default (pad, parent, query);
+ res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
break;
}
return res;
@@ -3865,6 +4049,8 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
gint64 start, stop, seekpos, seekstop;
GstSegment seeksegment = { 0, };
GstClockTime start_ts;
+ guint32 seqnum;
+ GstEvent *segment_event;
/* try upstream first, unless we're driving the streaming thread ourselves */
if (parse->priv->pad_mode != GST_PAD_MODE_PULL) {
@@ -3875,6 +4061,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
gst_event_parse_seek (event, &rate, &format, &flags,
&start_type, &start, &stop_type, &stop);
+ seqnum = gst_event_get_seqnum (event);
GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, "
"start type %d at %" GST_TIME_FORMAT ", end type %d at %"
@@ -3965,10 +4152,14 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
if (flush) {
if (parse->srcpad) {
+ GstEvent *fevent = gst_event_new_flush_start ();
GST_DEBUG_OBJECT (parse, "sending flush start");
- gst_pad_push_event (parse->srcpad, gst_event_new_flush_start ());
+
+ gst_event_set_seqnum (fevent, seqnum);
+
+ gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
/* unlock upstream pull_range */
- gst_pad_push_event (parse->sinkpad, gst_event_new_flush_start ());
+ gst_pad_push_event (parse->sinkpad, fevent);
}
} else {
gst_pad_pause_task (parse->sinkpad);
@@ -3987,9 +4178,11 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
/* prepare for streaming again */
if (flush) {
+ GstEvent *fevent = gst_event_new_flush_stop (TRUE);
GST_DEBUG_OBJECT (parse, "sending flush stop");
- gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop (TRUE));
- gst_pad_push_event (parse->sinkpad, gst_event_new_flush_stop (TRUE));
+ gst_event_set_seqnum (fevent, seqnum);
+ gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
+ gst_pad_push_event (parse->sinkpad, fevent);
gst_base_parse_clear_queues (parse);
} else {
/* keep track of our position */
@@ -4002,9 +4195,10 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
/* store the newsegment event so it can be sent from the streaming thread. */
/* This will be sent later in _loop() */
parse->priv->pending_segment = TRUE;
+ segment_event = gst_event_new_segment (&parse->segment);
+ gst_event_set_seqnum (segment_event, seqnum);
parse->priv->pending_events =
- g_list_prepend (parse->priv->pending_events,
- gst_event_new_segment (&parse->segment));
+ g_list_prepend (parse->priv->pending_events, segment_event);
GST_DEBUG_OBJECT (parse, "Created newseg format %d, "
"start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
@@ -4040,8 +4234,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
parse->priv->seen_keyframe = FALSE;
parse->priv->discont = TRUE;
parse->priv->next_dts = start_ts;
- if (parse->priv->pts_interpolate)
- parse->priv->next_pts = start_ts;
+ parse->priv->next_pts = GST_CLOCK_TIME_NONE;
parse->priv->last_dts = GST_CLOCK_TIME_NONE;
parse->priv->last_pts = GST_CLOCK_TIME_NONE;
parse->priv->sync_offset = seekpos;
@@ -4069,6 +4262,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
seekstop = seekpos;
new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop);
+ gst_event_set_seqnum (new_event, seqnum);
/* store segment info so its precise details can be reconstructed when
* receiving newsegment;
@@ -4244,3 +4438,42 @@ gst_base_parse_change_state (GstElement * element, GstStateChange transition)
return result;
}
+
+/**
+ * gst_base_parse_set_ts_at_offset:
+ * @parse: a #GstBaseParse
+ * @offset: offset into current buffer
+ *
+ * This function should only be called from a @handle_frame implementation.
+ *
+ * GstBaseParse creates initial timestamps for frames by using the last
+ * timestamp seen in the stream before the frame starts. In certain
+ * cases, the correct timestamps will occur in the stream after the
+ * start of the frame, but before the start of the actual picture data.
+ * This function can be used to set the timestamps based on the offset
+ * into the frame data that the picture starts.
+ *
+ * Since: 1.2
+ */
+void
+gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset)
+{
+ GstClockTime pts, dts;
+
+ g_return_if_fail (GST_IS_BASE_PARSE (parse));
+ g_return_if_fail (offset >= 0);
+
+ pts = gst_adapter_prev_pts_at_offset (parse->priv->adapter, offset, NULL);
+ dts = gst_adapter_prev_dts_at_offset (parse->priv->adapter, offset, NULL);
+
+ if (!GST_CLOCK_TIME_IS_VALID (pts) || !GST_CLOCK_TIME_IS_VALID (dts)) {
+ GST_DEBUG_OBJECT (parse,
+ "offset adapter timestamps dts=%" GST_TIME_FORMAT " pts=%"
+ GST_TIME_FORMAT, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts));
+ }
+ if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
+ parse->priv->prev_pts = parse->priv->next_pts = pts;
+
+ if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts))
+ parse->priv->prev_dts = parse->priv->next_dts = dts;
+}
diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h
index d0a1be4..6c7dd71 100644
--- a/libs/gst/base/gstbaseparse.h
+++ b/libs/gst/base/gstbaseparse.h
@@ -15,8 +15,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BASE_PARSE_H__
@@ -213,6 +213,13 @@ struct _GstBaseParse {
* Called until it doesn't return GST_FLOW_OK anymore for
* the first buffers. Can be used by the subclass to detect
* the stream format.
+ * @sink_query: Optional.
+ * Query handler on the sink pad. This function should chain
+ * up to the parent implementation to let the default handler
+ * run (Since 1.2)
+ * @src_query: Optional.
+ * Query handler on the source pad. Should chain up to the
+ * parent to let the default handler run (Since 1.2)
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @check_valid_frame and @parse_frame needs to be
@@ -256,8 +263,14 @@ struct _GstBaseParseClass {
GstFlowReturn (*detect) (GstBaseParse * parse,
GstBuffer * buffer);
+ gboolean (*sink_query) (GstBaseParse * parse,
+ GstQuery * query);
+
+ gboolean (*src_query) (GstBaseParse * parse,
+ GstQuery * query);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ gpointer _gst_reserved[GST_PADDING_LARGE - 2];
};
GType gst_base_parse_get_type (void);
@@ -302,6 +315,9 @@ void gst_base_parse_set_passthrough (GstBaseParse * parse,
void gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
gboolean pts_interpolate);
+void gst_base_parse_set_infer_ts (GstBaseParse * parse,
+ gboolean infer_ts);
+
void gst_base_parse_set_frame_rate (GstBaseParse * parse,
guint fps_num,
guint fps_den,
@@ -324,6 +340,9 @@ gboolean gst_base_parse_add_index_entry (GstBaseParse * parse,
gboolean key,
gboolean force);
+void gst_base_parse_set_ts_at_offset (GstBaseParse *parse,
+ gsize offset);
+
G_END_DECLS
#endif /* __GST_BASE_PARSE_H__ */
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index bfb7696..9fcacd6 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -15,8 +15,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -265,6 +265,12 @@ struct _GstBaseSinkPrivate
/* for throttling and QoS */
GstClockTime earliest_in_time;
GstClockTime throttle_time;
+
+ /* for rate control */
+ guint64 max_bitrate;
+ GstClockTime rc_time;
+ GstClockTime rc_next;
+ gsize rc_accumulated;
};
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
@@ -292,6 +298,7 @@ struct _GstBaseSinkPrivate
#define DEFAULT_RENDER_DELAY 0
#define DEFAULT_ENABLE_LAST_SAMPLE TRUE
#define DEFAULT_THROTTLE_TIME 0
+#define DEFAULT_MAX_BITRATE 0
enum
{
@@ -306,6 +313,7 @@ enum
PROP_BLOCKSIZE,
PROP_RENDER_DELAY,
PROP_THROTTLE_TIME,
+ PROP_MAX_BITRATE,
PROP_LAST
};
@@ -397,7 +405,7 @@ static GstCaps *gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
/* check if an object was too late */
static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,
GstMiniObject * obj, GstClockTime rstart, GstClockTime rstop,
- GstClockReturn status, GstClockTimeDiff jitter);
+ GstClockReturn status, GstClockTimeDiff jitter, gboolean render);
static void
gst_base_sink_class_init (GstBaseSinkClass * klass)
@@ -511,8 +519,23 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
*/
g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME,
g_param_spec_uint64 ("throttle-time", "Throttle time",
- "The time to keep between rendered buffers", 0, G_MAXUINT64,
- DEFAULT_THROTTLE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ "The time to keep between rendered buffers (0 = disabled)", 0,
+ G_MAXUINT64, DEFAULT_THROTTLE_TIME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstBaseSink:max-bitrate:
+ *
+ * Control the maximum amount of bits that will be rendered per second.
+ * Setting this property to a value bigger than 0 will make the sink delay
+ * rendering of the buffers when it would exceed to max-bitrate.
+ *
+ * Since: 1.1.1
+ */
+ g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
+ g_param_spec_uint64 ("max-bitrate", "Max Bitrate",
+ "The maximum bits per second to render (0 = disabled)", 0,
+ G_MAXUINT64, DEFAULT_MAX_BITRATE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
@@ -643,6 +666,7 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
priv->cached_clock_id = NULL;
g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE);
priv->throttle_time = DEFAULT_THROTTLE_TIME;
+ priv->max_bitrate = DEFAULT_MAX_BITRATE;
GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_SINK);
}
@@ -1249,6 +1273,50 @@ gst_base_sink_get_throttle_time (GstBaseSink * sink)
return res;
}
+/**
+ * gst_base_sink_set_max_bitrate:
+ * @sink: a #GstBaseSink
+ * @max_bitrate: the max_bitrate in bits per second
+ *
+ * Set the maximum amount of bits per second that the sink will render.
+ *
+ * Since: 1.1.1
+ */
+void
+gst_base_sink_set_max_bitrate (GstBaseSink * sink, guint64 max_bitrate)
+{
+ g_return_if_fail (GST_IS_BASE_SINK (sink));
+
+ GST_OBJECT_LOCK (sink);
+ sink->priv->max_bitrate = max_bitrate;
+ GST_LOG_OBJECT (sink, "set max_bitrate to %" G_GUINT64_FORMAT, max_bitrate);
+ GST_OBJECT_UNLOCK (sink);
+}
+
+/**
+ * gst_base_sink_get_max_bitrate:
+ * @sink: a #GstBaseSink
+ *
+ * Get the maximum amount of bits per second that the sink will render.
+ *
+ * Returns: the maximum number of bits per second @sink will render.
+ *
+ * Since: 1.1.1
+ */
+guint64
+gst_base_sink_get_max_bitrate (GstBaseSink * sink)
+{
+ guint64 res;
+
+ g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
+
+ GST_OBJECT_LOCK (sink);
+ res = sink->priv->max_bitrate;
+ GST_OBJECT_UNLOCK (sink);
+
+ return res;
+}
+
static void
gst_base_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@@ -1283,6 +1351,9 @@ gst_base_sink_set_property (GObject * object, guint prop_id,
case PROP_THROTTLE_TIME:
gst_base_sink_set_throttle_time (sink, g_value_get_uint64 (value));
break;
+ case PROP_MAX_BITRATE:
+ gst_base_sink_set_max_bitrate (sink, g_value_get_uint64 (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1326,6 +1397,9 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_THROTTLE_TIME:
g_value_set_uint64 (value, gst_base_sink_get_throttle_time (sink));
break;
+ case PROP_MAX_BITRATE:
+ g_value_set_uint64 (value, gst_base_sink_get_max_bitrate (sink));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2002,8 +2076,8 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
/* FIXME: Casting to GstClockEntry only works because the types
* are the same */
if (G_LIKELY (sink->priv->cached_clock_id != NULL
- && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->
- priv->cached_clock_id) == clock)) {
+ && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->priv->
+ cached_clock_id) == clock)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) {
gst_clock_id_unref (sink->priv->cached_clock_id);
@@ -2392,6 +2466,18 @@ again:
/* adjust for latency */
stime = gst_base_sink_adjust_time (basesink, rstart);
+ /* adjust for rate control */
+ if (priv->rc_next == -1 || (stime != -1 && stime >= priv->rc_next)) {
+ GST_DEBUG_OBJECT (basesink, "reset rc_time to time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (stime));
+ priv->rc_time = stime;
+ priv->rc_accumulated = 0;
+ } else {
+ GST_DEBUG_OBJECT (basesink, "rate control next %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (priv->rc_next));
+ stime = priv->rc_next;
+ }
+
/* preroll done, we can sync since we are in PLAYING now. */
GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %"
GST_TIME_FORMAT ", adjusted %" GST_TIME_FORMAT,
@@ -2425,7 +2511,7 @@ again:
/* check if the object should be dropped */
*late = gst_base_sink_is_too_late (basesink, obj, rstart, rstop,
- status, jitter);
+ status, jitter, TRUE);
done:
return GST_FLOW_OK;
@@ -2651,7 +2737,7 @@ gst_base_sink_reset_qos (GstBaseSink * sink)
static gboolean
gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
GstClockTime rstart, GstClockTime rstop,
- GstClockReturn status, GstClockTimeDiff jitter)
+ GstClockReturn status, GstClockTimeDiff jitter, gboolean render)
{
gboolean late;
guint64 max_lateness;
@@ -2710,7 +2796,7 @@ gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
}
done:
- if (!late || !GST_CLOCK_TIME_IS_VALID (priv->last_render_time)) {
+ if (render && (!late || !GST_CLOCK_TIME_IS_VALID (priv->last_render_time))) {
priv->last_render_time = rstart;
/* the next allowed input timestamp */
if (priv->throttle_time > 0)
@@ -2834,7 +2920,7 @@ static GstFlowReturn
gst_base_sink_default_wait_event (GstBaseSink * basesink, GstEvent * event)
{
GstFlowReturn ret;
- gboolean late, step_end;
+ gboolean late, step_end = FALSE;
ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (event),
&late, &step_end);
@@ -2922,11 +3008,19 @@ gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
{
GstMessage *message;
guint32 seqnum;
+ guint group_id;
seqnum = gst_event_get_seqnum (event);
GST_DEBUG_OBJECT (basesink, "Now posting STREAM_START (seqnum:%d)",
seqnum);
message = gst_message_new_stream_start (GST_OBJECT_CAST (basesink));
+ if (gst_event_parse_group_id (event, &group_id)) {
+ gst_message_set_group_id (message, group_id);
+ } else {
+ GST_FIXME_OBJECT (basesink, "stream-start event without group-id. "
+ "Consider implementing group-id handling in the upstream "
+ "elements");
+ }
gst_message_set_seqnum (message, seqnum);
gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
break;
@@ -2957,7 +3051,7 @@ gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
/* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */
gst_event_copy_segment (event, &basesink->segment);
- GST_DEBUG_OBJECT (basesink, "configured SEGMENT %" GST_SEGMENT_FORMAT,
+ GST_DEBUG_OBJECT (basesink, "configured segment %" GST_SEGMENT_FORMAT,
&basesink->segment);
basesink->have_newsegment = TRUE;
GST_OBJECT_UNLOCK (basesink);
@@ -3116,6 +3210,13 @@ gst_base_sink_needs_preroll (GstBaseSink * basesink)
return res;
}
+static gboolean
+count_list_bytes (GstBuffer ** buffer, guint idx, GstBaseSinkPrivate * priv)
+{
+ priv->rc_accumulated += gst_buffer_get_size (*buffer);
+ return TRUE;
+}
+
/* with STREAM_LOCK, PREROLL_LOCK
*
* Takes a buffer and compare the timestamps with the last segment.
@@ -3130,7 +3231,7 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
{
GstBaseSinkClass *bclass;
GstBaseSinkPrivate *priv = basesink->priv;
- GstFlowReturn ret;
+ GstFlowReturn ret = GST_FLOW_OK;
GstClockTime start = GST_CLOCK_TIME_NONE, end = GST_CLOCK_TIME_NONE;
GstSegment *segment;
GstBuffer *sync_buf;
@@ -3196,17 +3297,38 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
goto out_of_segment;
}
- if (!is_list) {
- if (bclass->prepare) {
- ret = bclass->prepare (basesink, GST_BUFFER_CAST (obj));
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto prepare_failed;
- }
- } else {
- if (bclass->prepare_list) {
- ret = bclass->prepare_list (basesink, GST_BUFFER_LIST_CAST (obj));
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto prepare_failed;
+ if (bclass->prepare || bclass->prepare_list) {
+ gboolean do_sync = TRUE, stepped = FALSE, syncable = TRUE;
+ GstClockTime sstart, sstop, rstart, rstop, rnext;
+ GstStepInfo *current;
+
+ late = FALSE;
+ step_end = FALSE;
+
+ current = &priv->current_step;
+ syncable =
+ gst_base_sink_get_sync_times (basesink, obj, &sstart, &sstop, &rstart,
+ &rstop, &rnext, &do_sync, &stepped, current, &step_end);
+
+ if (!stepped && syncable && do_sync)
+ late =
+ gst_base_sink_is_too_late (basesink, obj, rstart, rstop,
+ GST_CLOCK_EARLY, 0, FALSE);
+ if (late)
+ goto dropped;
+
+ if (!is_list) {
+ if (bclass->prepare) {
+ ret = bclass->prepare (basesink, GST_BUFFER_CAST (obj));
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
+ goto prepare_failed;
+ }
+ } else {
+ if (bclass->prepare_list) {
+ ret = bclass->prepare_list (basesink, GST_BUFFER_LIST_CAST (obj));
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
+ goto prepare_failed;
+ }
}
}
@@ -3225,6 +3347,17 @@ again:
if (G_UNLIKELY (late))
goto dropped;
+ if (priv->max_bitrate) {
+ if (is_list) {
+ gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
+ (GstBufferListFunc) count_list_bytes, priv);
+ } else {
+ priv->rc_accumulated += gst_buffer_get_size (GST_BUFFER_CAST (obj));
+ }
+ priv->rc_next = priv->rc_time + gst_util_uint64_scale (priv->rc_accumulated,
+ 8 * GST_SECOND, priv->max_bitrate);
+ }
+
/* read once, to get same value before and after */
do_qos = g_atomic_int_get (&priv->qos_enabled);
@@ -3399,7 +3532,7 @@ gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
guint i, len;
GstBuffer *buffer;
- GST_INFO_OBJECT (pad, "chaining each buffer in list");
+ GST_LOG_OBJECT (pad, "chaining each buffer in list");
len = gst_buffer_list_length (list);
@@ -3573,7 +3706,6 @@ gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
res = gst_base_sink_default_do_seek (sink, &seeksegment);
}
-
if (flush) {
GST_DEBUG_OBJECT (sink, "stop flushing upstream");
gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
@@ -3593,6 +3725,9 @@ gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
res = FALSE;
}
+ GST_INFO_OBJECT (sink, "seeking done %d: %" GST_SEGMENT_FORMAT, res,
+ &seeksegment);
+
/* if successful seek, we update our real segment and push
* out the new segment. */
if (res) {
@@ -4579,8 +4714,21 @@ default_element_query (GstElement * element, GstQuery * query)
case GST_QUERY_SEGMENT:
{
if (basesink->pad_mode == GST_PAD_MODE_PULL) {
- gst_query_set_segment (query, basesink->segment.rate,
- GST_FORMAT_TIME, basesink->segment.start, basesink->segment.stop);
+ GstFormat format;
+ gint64 start, stop;
+
+ format = basesink->segment.format;
+
+ start =
+ gst_segment_to_stream_time (&basesink->segment, format,
+ basesink->segment.start);
+ if ((stop = basesink->segment.stop) == -1)
+ stop = basesink->segment.duration;
+ else
+ stop = gst_segment_to_stream_time (&basesink->segment, format, stop);
+
+ gst_query_set_segment (query, basesink->segment.rate, format, start,
+ stop);
res = TRUE;
} else {
res = gst_pad_peer_query (basesink->sinkpad, query);
@@ -4709,6 +4857,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
basesink->eos = FALSE;
priv->received_eos = FALSE;
gst_base_sink_reset_qos (basesink);
+ priv->rc_next = -1;
priv->commited = FALSE;
priv->call_preroll = TRUE;
priv->current_step.valid = FALSE;
diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h
index e4bb735..6f2ade7 100644
--- a/libs/gst/base/gstbasesink.h
+++ b/libs/gst/base/gstbasesink.h
@@ -16,8 +16,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BASE_SINK_H__
@@ -245,6 +245,10 @@ guint gst_base_sink_get_blocksize (GstBaseSink *sink);
void gst_base_sink_set_throttle_time (GstBaseSink *sink, guint64 throttle);
guint64 gst_base_sink_get_throttle_time (GstBaseSink *sink);
+/* max-bitrate */
+void gst_base_sink_set_max_bitrate (GstBaseSink *sink, guint64 max_bitrate);
+guint64 gst_base_sink_get_max_bitrate (GstBaseSink *sink);
+
GstClockReturn gst_base_sink_wait_clock (GstBaseSink *sink, GstClockTime time,
GstClockTimeDiff * jitter);
GstFlowReturn gst_base_sink_wait (GstBaseSink *sink, GstClockTime time,
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
index d04b513..e35824f 100644
--- a/libs/gst/base/gstbasesrc.c
+++ b/libs/gst/base/gstbasesrc.c
@@ -16,8 +16,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -224,8 +224,10 @@ struct _GstBaseSrcPrivate
/* if a stream-start event should be sent */
gboolean stream_start_pending;
- /* if segment should be sent */
+ /* if segment should be sent and a
+ * seqnum if it was originated by a seek */
gboolean segment_pending;
+ guint32 segment_seqnum;
/* if EOS is pending (atomic) */
gint pending_eos;
@@ -346,7 +348,7 @@ static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
static gboolean gst_base_src_seekable (GstBaseSrc * src);
static gboolean gst_base_src_negotiate (GstBaseSrc * basesrc);
static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset,
- guint * length);
+ guint * length, gboolean force);
static void
gst_base_src_class_init (GstBaseSrcClass * klass)
@@ -818,6 +820,7 @@ gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
/* Mark pending segment. Will be sent before next data */
src->priv->segment_pending = TRUE;
+ src->priv->segment_seqnum = gst_util_seqnum_next ();
GST_DEBUG_OBJECT (src,
"Starting new seamless segment. Start %" GST_TIME_FORMAT " stop %"
@@ -840,14 +843,16 @@ gst_base_src_send_stream_start (GstBaseSrc * src)
if (src->priv->stream_start_pending) {
gchar *stream_id;
+ GstEvent *event;
stream_id =
gst_pad_create_stream_id (src->srcpad, GST_ELEMENT_CAST (src), NULL);
GST_DEBUG_OBJECT (src, "Pushing STREAM_START");
- ret =
- gst_pad_push_event (src->srcpad,
- gst_event_new_stream_start (stream_id));
+ event = gst_event_new_stream_start (stream_id);
+ gst_event_set_group_id (event, gst_util_group_id_next ());
+
+ ret = gst_pad_push_event (src->srcpad, event);
src->priv->stream_start_pending = FALSE;
g_free (stream_id);
}
@@ -878,7 +883,7 @@ gst_base_src_set_caps (GstBaseSrc * src, GstCaps * caps)
res = bclass->set_caps (src, caps);
if (res)
- res = gst_pad_set_caps (src->srcpad, caps);
+ res = gst_pad_push_event (src->srcpad, gst_event_new_caps (caps));
return res;
}
@@ -1018,8 +1023,8 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
guint length = 0;
/* may have to refresh duration */
- if (g_atomic_int_get (&src->priv->dynamic_size))
- gst_base_src_update_length (src, 0, &length);
+ gst_base_src_update_length (src, 0, &length,
+ g_atomic_int_get (&src->priv->dynamic_size));
/* this is the duration as configured by the subclass. */
GST_OBJECT_LOCK (src);
@@ -1076,23 +1081,23 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
}
case GST_QUERY_SEGMENT:
{
+ GstFormat format;
gint64 start, stop;
GST_OBJECT_LOCK (src);
- /* no end segment configured, current duration then */
+
+ format = src->segment.format;
+
+ start =
+ gst_segment_to_stream_time (&src->segment, format,
+ src->segment.start);
if ((stop = src->segment.stop) == -1)
stop = src->segment.duration;
- start = src->segment.start;
+ else
+ stop = gst_segment_to_stream_time (&src->segment, format, stop);
- /* adjust to stream time */
- if (src->segment.time != -1) {
- start -= src->segment.time;
- if (stop != -1)
- stop -= src->segment.time;
- }
+ gst_query_set_segment (query, src->segment.rate, format, start, stop);
- gst_query_set_segment (query, src->segment.rate, src->segment.format,
- start, stop);
GST_OBJECT_UNLOCK (src);
res = TRUE;
break;
@@ -1288,6 +1293,8 @@ gst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment)
bclass = GST_BASE_SRC_GET_CLASS (src);
+ GST_INFO_OBJECT (src, "seeking: %" GST_SEGMENT_FORMAT, segment);
+
if (bclass->do_seek)
result = bclass->do_seek (src, segment);
@@ -1658,10 +1665,12 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
/* for deriving a stop position for the playback segment from the seek
* segment, we must take the duration when the stop is not set */
+ /* FIXME: This is never used below */
if ((stop = seeksegment.stop) == -1)
stop = seeksegment.duration;
src->priv->segment_pending = TRUE;
+ src->priv->segment_seqnum = seqnum;
}
src->priv->discont = TRUE;
@@ -1693,8 +1702,10 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
{
GstBaseSrc *src;
gboolean result = FALSE;
+ GstBaseSrcClass *bclass;
src = GST_BASE_SRC (element);
+ bclass = GST_BASE_SRC_GET_CLASS (src);
GST_DEBUG_OBJECT (src, "handling event %p %" GST_PTR_FORMAT, event, event);
@@ -1703,26 +1714,55 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
case GST_EVENT_FLUSH_START:
GST_DEBUG_OBJECT (src, "pushing flush-start event downstream");
result = gst_pad_push_event (src->srcpad, event);
+ /* also unblock the create function */
+ gst_base_src_activate_pool (src, FALSE);
+ /* unlock any subclasses, we need to do this before grabbing the
+ * LIVE_LOCK since we hold this lock before going into ::create. We pass an
+ * unlock to the params because of backwards compat (see seek handler)*/
+ if (bclass->unlock)
+ bclass->unlock (src);
+
+ /* the live lock is released when we are blocked, waiting for playing or
+ * when we sync to the clock. */
+ GST_LIVE_LOCK (src);
+ src->priv->flushing = TRUE;
+ /* clear pending EOS if any */
+ g_atomic_int_set (&src->priv->pending_eos, FALSE);
+ if (bclass->unlock_stop)
+ bclass->unlock_stop (src);
+ if (src->clock_id)
+ gst_clock_id_unschedule (src->clock_id);
+ GST_DEBUG_OBJECT (src, "signal");
+ GST_LIVE_SIGNAL (src);
+ GST_LIVE_UNLOCK (src);
event = NULL;
break;
case GST_EVENT_FLUSH_STOP:
+ {
+ gboolean start;
+
GST_LIVE_LOCK (src);
src->priv->segment_pending = TRUE;
- /* sending random flushes downstream can break stuff,
- * especially sync since all segment info will get flushed */
+ src->priv->flushing = FALSE;
GST_DEBUG_OBJECT (src, "pushing flush-stop event downstream");
result = gst_pad_push_event (src->srcpad, event);
+
+ gst_base_src_activate_pool (src, TRUE);
+
+ GST_OBJECT_LOCK (src->srcpad);
+ start = (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH);
+ GST_OBJECT_UNLOCK (src->srcpad);
+ if (start)
+ gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
+ src->srcpad, NULL);
GST_LIVE_UNLOCK (src);
event = NULL;
break;
+ }
/* downstream serialized events */
case GST_EVENT_EOS:
{
- GstBaseSrcClass *bclass;
-
- bclass = GST_BASE_SRC_GET_CLASS (src);
-
/* queue EOS and make sure the task or pull function performs the EOS
* actions.
*
@@ -2218,13 +2258,13 @@ no_sync:
/* Called with STREAM_LOCK and LIVE_LOCK */
static gboolean
-gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
+gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length,
+ gboolean force)
{
guint64 size, maxsize;
GstBaseSrcClass *bclass;
GstFormat format;
gint64 stop;
- gboolean dynamic;
bclass = GST_BASE_SRC_GET_CLASS (src);
@@ -2249,14 +2289,11 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
*length, size, stop, maxsize);
- dynamic = g_atomic_int_get (&src->priv->dynamic_size);
- GST_DEBUG_OBJECT (src, "dynamic size: %d", dynamic);
-
/* check size if we have one */
if (maxsize != -1) {
/* if we run past the end, check if the file became bigger and
* retry. */
- if (G_UNLIKELY (offset + *length >= maxsize || dynamic)) {
+ if (G_UNLIKELY (offset + *length >= maxsize || force)) {
/* see if length of the file changed */
if (bclass->get_size)
if (!bclass->get_size (src, &size))
@@ -2324,7 +2361,7 @@ again:
if (G_UNLIKELY (!bclass->create))
goto no_function;
- if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length)))
+ if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length, FALSE)))
goto unexpected_length;
/* track position */
@@ -2573,8 +2610,20 @@ gst_base_src_loop (GstPad * pad)
src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
+ /* Just leave immediately if we're flushing */
+ GST_LIVE_LOCK (src);
+ if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
+ goto flushing;
+ GST_LIVE_UNLOCK (src);
+
gst_base_src_send_stream_start (src);
+ /* The stream-start event could've caused something to flush us */
+ GST_LIVE_LOCK (src);
+ if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
+ goto flushing;
+ GST_LIVE_UNLOCK (src);
+
/* check if we need to renegotiate */
if (gst_pad_check_reconfigure (pad)) {
if (!gst_base_src_negotiate (src)) {
@@ -2588,7 +2637,7 @@ gst_base_src_loop (GstPad * pad)
GST_LIVE_LOCK (src);
- if (G_UNLIKELY (src->priv->flushing))
+ if (G_UNLIKELY (src->priv->flushing || GST_PAD_IS_FLUSHING (pad)))
goto flushing;
blocksize = src->blocksize;
@@ -2626,7 +2675,11 @@ gst_base_src_loop (GstPad * pad)
/* push events to close/start our segment before we push the buffer. */
if (G_UNLIKELY (src->priv->segment_pending)) {
- gst_pad_push_event (pad, gst_event_new_segment (&src->segment));
+ GstEvent *seg_event = gst_event_new_segment (&src->segment);
+
+ gst_event_set_seqnum (seg_event, src->priv->segment_seqnum);
+ src->priv->segment_seqnum = gst_util_seqnum_next ();
+ gst_pad_push_event (pad, seg_event);
src->priv->segment_pending = FALSE;
}
@@ -3137,6 +3190,7 @@ gst_base_src_start (GstBaseSrc * basesrc)
basesrc->num_buffers_left = basesrc->num_buffers;
basesrc->running = FALSE;
basesrc->priv->segment_pending = FALSE;
+ basesrc->priv->segment_seqnum = gst_util_seqnum_next ();
GST_LIVE_UNLOCK (basesrc);
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
@@ -3369,7 +3423,7 @@ gst_base_src_stop (GstBaseSrc * basesrc)
was_stopped:
{
- GST_DEBUG_OBJECT (basesrc, "was started");
+ GST_DEBUG_OBJECT (basesrc, "was stopped");
GST_OBJECT_UNLOCK (basesrc);
return TRUE;
}
diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h
index 466f0fc..9afd5e0 100644
--- a/libs/gst/base/gstbasesrc.h
+++ b/libs/gst/base/gstbasesrc.h
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BASE_SRC_H__
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
index fff751d..8e28154 100644
--- a/libs/gst/base/gstbasetransform.c
+++ b/libs/gst/base/gstbasetransform.c
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -149,9 +149,8 @@
* <itemizedlist><title>Special output buffer allocations</title>
* <listitem><para>
* Elements which need to do special allocation of their output buffers
- * other than what gst_buffer_pad_alloc allows should implement a
- * prepare_output_buffer method, which calls the parent implementation and
- * passes the newly allocated buffer.
+ * beyond allocating output buffers via the negotiated allocator or
+ * buffer pool should implement the prepare_output_buffer method.
* </para></listitem>
* </itemizedlist>
* <itemizedlist>
@@ -357,6 +356,9 @@ static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer ** outbuf);
static gboolean default_copy_metadata (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer * outbuf);
+static gboolean
+gst_base_transform_default_transform_meta (GstBaseTransform * trans,
+ GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf);
/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
@@ -408,6 +410,8 @@ gst_base_transform_class_init (GstBaseTransformClass * klass)
GST_DEBUG_FUNCPTR (gst_base_transform_default_propose_allocation);
klass->transform_size =
GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_size);
+ klass->transform_meta =
+ GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_meta);
klass->sink_event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);
@@ -546,6 +550,21 @@ gst_base_transform_transform_caps (GstBaseTransform * trans,
}
static gboolean
+gst_base_transform_default_transform_meta (GstBaseTransform * trans,
+ GstBuffer * inbuf, GstMeta * meta, GstBuffer * outbuf)
+{
+ const GstMetaInfo *info = meta->info;
+ const gchar *const *tags;
+
+ tags = gst_meta_api_type_get_tags (info->api);
+
+ if (!tags)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
gst_base_transform_default_transform_size (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, gsize size,
GstCaps * othercaps, gsize * othersize)
@@ -1237,9 +1256,9 @@ gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
/* get all the formats we can handle on this pad */
if (direction == GST_PAD_SRC)
- allowed = gst_pad_query_caps (trans->srcpad, NULL);
+ allowed = gst_pad_query_caps (trans->srcpad, caps);
else
- allowed = gst_pad_query_caps (trans->sinkpad, NULL);
+ allowed = gst_pad_query_caps (trans->sinkpad, caps);
if (!allowed) {
GST_DEBUG_OBJECT (trans, "gst_pad_query_caps() failed");
@@ -1299,7 +1318,7 @@ gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad,
GstCaps * incaps)
{
GstBaseTransformPrivate *priv = trans->priv;
- GstCaps *outcaps;
+ GstCaps *outcaps, *prevcaps;
gboolean ret = TRUE;
GST_DEBUG_OBJECT (pad, "have new caps %p %" GST_PTR_FORMAT, incaps, incaps);
@@ -1322,8 +1341,14 @@ gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad,
if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
goto failed_configure;
- /* let downstream know about our caps */
- ret = gst_pad_set_caps (trans->srcpad, outcaps);
+ prevcaps = gst_pad_get_current_caps (trans->srcpad);
+
+ if (!prevcaps || !gst_caps_is_equal (outcaps, prevcaps))
+ /* let downstream know about our caps */
+ ret = gst_pad_set_caps (trans->srcpad, outcaps);
+
+ if (prevcaps)
+ gst_caps_unref (prevcaps);
if (ret) {
/* try to get a pool when needed */
@@ -1592,6 +1617,10 @@ default_prepare_output_buffer (GstBaseTransform * trans,
GST_DEBUG_OBJECT (trans, "doing alloc of size %" G_GSIZE_FORMAT, outsize);
*outbuf = gst_buffer_new_allocate (priv->allocator, outsize, &priv->params);
+ if (!*outbuf) {
+ ret = GST_FLOW_ERROR;
+ goto alloc_failed;
+ }
copy_meta:
/* copy the metadata */
@@ -1644,7 +1673,7 @@ foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
GstBaseTransformClass *klass;
const GstMetaInfo *info = (*meta)->info;
GstBuffer *outbuf = data->outbuf;
- gboolean do_copy;
+ gboolean do_copy = FALSE;
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
@@ -1662,10 +1691,6 @@ foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
do_copy = klass->transform_meta (trans, outbuf, *meta, inbuf);
GST_DEBUG_OBJECT (trans, "transformed metadata %s: copy: %d",
g_type_name (info->api), do_copy);
- } else {
- do_copy = FALSE;
- GST_DEBUG_OBJECT (trans, "not copying metadata %s",
- g_type_name (info->api));
}
/* we only copy metadata when the subclass implemented a transform_meta
diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h
index 666fbb1..3330503 100644
--- a/libs/gst/base/gstbasetransform.h
+++ b/libs/gst/base/gstbasetransform.h
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BASE_TRANSFORM_H__
diff --git a/libs/gst/base/gstbitreader-docs.h b/libs/gst/base/gstbitreader-docs.h
index 80e8913..d2842d6 100644
--- a/libs/gst/base/gstbitreader-docs.h
+++ b/libs/gst/base/gstbitreader-docs.h
@@ -13,8 +13,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/* This header is not installed, it just contains stuff for gtk-doc to parse,
@@ -53,7 +53,7 @@ void gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader);
*
* Returns: unsigned 8 bit integer with the bits.
*/
-guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, guint nbits);
+guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_peek_bits_uint8_unchecked:
@@ -65,7 +65,7 @@ guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, gui
*
* Returns: unsigned 8 bit integer with the bits.
*/
-guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbits);
+guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_get_bits_uint16_unchecked:
@@ -77,7 +77,7 @@ guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbit
*
* Returns: unsigned 16 bit integer with the bits.
*/
-guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, guint nbits);
+guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_peek_bits_uint16_unchecked:
@@ -89,7 +89,7 @@ guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, g
*
* Returns: unsigned 16 bit integer with the bits.
*/
-guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nbits);
+guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_get_bits_uint32_unchecked:
@@ -101,7 +101,7 @@ guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nb
*
* Returns: unsigned 32 bit integer with the bits.
*/
-guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, guint nbits);
+guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_peek_bits_uint32_unchecked:
@@ -113,7 +113,7 @@ guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, g
*
* Returns: unsigned 32 bit integer with the bits.
*/
-guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nbits);
+guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, guint nbits);
/**
* gst_bit_reader_get_bits_uint64_unchecked:
@@ -125,10 +125,10 @@ guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nb
*
* Returns: unsigned 64 bit integer with the bits.
*/
-guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, guint nbits);
+guint64 gst_bit_reader_get_bits_uint64_unchecked (GstBitReader *reader, guint nbits);
/**
- * gst_bit_reader_peek_bits_uint16_unchecked:
+ * gst_bit_reader_peek_bits_uint64_unchecked:
* @reader: a #GstBitReader instance
* @nbits: number of bits to read
*
@@ -137,5 +137,5 @@ guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, g
*
* Returns: unsigned 64 bit integer with the bits.
*/
-guint64 gst_bit_reader_get_bits_uint64_unchecked (GstBitReader *reader, guint nbits);
+guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, guint nbits);
diff --git a/libs/gst/base/gstbitreader.c b/libs/gst/base/gstbitreader.c
index 0f8f587..2a325db 100644
--- a/libs/gst/base/gstbitreader.c
+++ b/libs/gst/base/gstbitreader.c
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
diff --git a/libs/gst/base/gstbitreader.h b/libs/gst/base/gstbitreader.h
index 4a2b4a0..240a7a3 100644
--- a/libs/gst/base/gstbitreader.h
+++ b/libs/gst/base/gstbitreader.h
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BIT_READER_H__
diff --git a/libs/gst/base/gstbytereader-docs.h b/libs/gst/base/gstbytereader-docs.h
index e6b08ac..866954f 100644
--- a/libs/gst/base/gstbytereader-docs.h
+++ b/libs/gst/base/gstbytereader-docs.h
@@ -13,8 +13,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/* This header is not installed, it just contains stuff for gtk-doc to parse,
diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c
index e1945d1..a5f9e40 100644
--- a/libs/gst/base/gstbytereader.c
+++ b/libs/gst/base/gstbytereader.c
@@ -15,8 +15,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -771,6 +771,31 @@ gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
return _gst_byte_reader_dup_data_inline (reader, size, val);
}
+/* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
+static inline gint
+_scan_for_start_code (const guint8 * data, guint offset, guint size)
+{
+ guint i = 0;
+
+ while (i <= (size - 4)) {
+ if (data[i + 2] > 1) {
+ i += 3;
+ } else if (data[i + 1]) {
+ i += 2;
+ } else if (data[i] || data[i + 2] != 1) {
+ i++;
+ } else {
+ break;
+ }
+ }
+
+ if (i <= (size - 4))
+ return i + offset;
+
+ /* nothing found */
+ return -1;
+}
+
/**
* gst_byte_reader_masked_scan_uint32:
* @reader: a #GstByteReader
@@ -831,6 +856,10 @@ gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
data = reader->data + reader->byte + offset;
+ /* Handle special case found in MPEG and H264 */
+ if ((pattern == 0x00000100) && (mask == 0xffffff00))
+ return _scan_for_start_code (data, offset, size);
+
/* set the state to something that does not match */
state = ~pattern;
diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h
index 15ac2ed..6ed0296 100644
--- a/libs/gst/base/gstbytereader.h
+++ b/libs/gst/base/gstbytereader.h
@@ -15,8 +15,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BYTE_READER_H__
diff --git a/libs/gst/base/gstbytewriter-docs.h b/libs/gst/base/gstbytewriter-docs.h
index c15b4c3..562eeae 100644
--- a/libs/gst/base/gstbytewriter-docs.h
+++ b/libs/gst/base/gstbytewriter-docs.h
@@ -13,8 +13,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/* This header is not installed, it just contains stuff for gtk-doc to parse,
diff --git a/libs/gst/base/gstbytewriter.c b/libs/gst/base/gstbytewriter.c
index 746a622..2d99480 100644
--- a/libs/gst/base/gstbytewriter.c
+++ b/libs/gst/base/gstbytewriter.c
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
diff --git a/libs/gst/base/gstbytewriter.h b/libs/gst/base/gstbytewriter.h
index 079e16f..f5c5502 100644
--- a/libs/gst/base/gstbytewriter.h
+++ b/libs/gst/base/gstbytewriter.h
@@ -14,8 +14,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_BYTE_WRITER_H__
diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c
index b6db9f4..d24e03b 100644
--- a/libs/gst/base/gstcollectpads.c
+++ b/libs/gst/base/gstcollectpads.c
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
* SECTION:gstcollectpads
@@ -55,7 +55,7 @@
* </para></listitem>
* <listitem><para>
* Data can also be dequeued in byte units using the gst_collect_pads_available(),
- * gst_collect_pads_read() and gst_collect_pads_flush() calls.
+ * gst_collect_pads_read_buffer() and gst_collect_pads_flush() calls.
* </para></listitem>
* <listitem><para>
* Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in
@@ -498,7 +498,7 @@ gst_collect_pads_clip_running_time (GstCollectPads * pads,
GstClockTime time;
*outbuf = buf;
- time = GST_BUFFER_TIMESTAMP (buf);
+ time = GST_BUFFER_PTS (buf);
/* invalid left alone and passed */
if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
@@ -510,9 +510,11 @@ gst_collect_pads_clip_running_time (GstCollectPads * pads,
} else {
GST_LOG_OBJECT (cdata->pad, "buffer ts %" GST_TIME_FORMAT " -> %"
GST_TIME_FORMAT " running time",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (time));
+ GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time));
*outbuf = gst_buffer_make_writable (buf);
- GST_BUFFER_TIMESTAMP (*outbuf) = time;
+ GST_BUFFER_PTS (*outbuf) = time;
+ GST_BUFFER_DTS (*outbuf) = gst_segment_to_running_time (&cdata->segment,
+ GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf));
}
}
@@ -1405,7 +1407,10 @@ gst_collect_pads_find_best_pad (GstCollectPads * pads,
buffer = gst_collect_pads_peek (pads, data);
/* if we have a buffer check if it is better then the current best one */
if (buffer != NULL) {
- timestamp = GST_BUFFER_TIMESTAMP (buffer);
+ timestamp = GST_BUFFER_DTS (buffer);
+ if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ timestamp = GST_BUFFER_PTS (buffer);
+ }
gst_buffer_unref (buffer);
if (best == NULL || pads->priv->compare_func (pads, data, timestamp,
best, best_time, pads->priv->compare_user_data) < 0) {
@@ -1569,10 +1574,11 @@ gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data,
if (pads->priv->clip_func) {
in = gst_buffer_new ();
- GST_BUFFER_TIMESTAMP (in) = time;
+ GST_BUFFER_PTS (in) = time;
+ GST_BUFFER_DTS (in) = time;
pads->priv->clip_func (pads, data, in, &out, pads->priv->clip_user_data);
if (out) {
- otime = GST_BUFFER_TIMESTAMP (out);
+ otime = GST_BUFFER_PTS (out);
gst_buffer_unref (out);
} else {
/* FIXME should distinguish between ahead or after segment,
@@ -1996,7 +2002,11 @@ gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
/* update segment last position if in TIME */
if (G_LIKELY (data->segment.format == GST_FORMAT_TIME)) {
- GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
+ GstClockTime timestamp;
+
+ timestamp = GST_BUFFER_DTS (buffer);
+ if (!GST_CLOCK_TIME_IS_VALID (timestamp))
+ timestamp = GST_BUFFER_PTS (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp))
data->segment.position = timestamp;
@@ -2058,7 +2068,9 @@ gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
unlock_done:
GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- unref_data (data);
+ /* data is definitely NULL if pad_removed goto was run. */
+ if (data)
+ unref_data (data);
if (buffer)
gst_buffer_unref (buffer);
return ret;
diff --git a/libs/gst/base/gstcollectpads.h b/libs/gst/base/gstcollectpads.h
index c33ca4f..4c99d58 100644
--- a/libs/gst/base/gstcollectpads.h
+++ b/libs/gst/base/gstcollectpads.h
@@ -16,8 +16,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_COLLECT_PADS_H__
diff --git a/libs/gst/base/gstdataqueue.c b/libs/gst/base/gstdataqueue.c
new file mode 100644
index 0000000..0c46f0c
--- /dev/null
+++ b/libs/gst/base/gstdataqueue.c
@@ -0,0 +1,809 @@
+/* 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, 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.
+ */
+
+#include <gst/gst.h>
+#include "string.h"
+#include "gstdataqueue.h"
+#include "gstqueuearray.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
+{
+ PROP_0,
+ PROP_CUR_LEVEL_VISIBLE,
+ PROP_CUR_LEVEL_BYTES,
+ PROP_CUR_LEVEL_TIME
+ /* FILL ME */
+};
+
+struct _GstDataQueuePrivate
+{
+ /* the array of data we're keeping our grubby hands on */
+ GstQueueArray *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;
+};
+
+#define GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \
+ GST_CAT_TRACE (data_queue_dataflow, \
+ "locking qlock from thread %p", \
+ g_thread_self ()); \
+ g_mutex_lock (&q->priv->qlock); \
+ GST_CAT_TRACE (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->priv->flushing) \
+ goto label; \
+ } G_STMT_END
+
+#define GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \
+ GST_CAT_TRACE (data_queue_dataflow, \
+ "unlocking qlock from thread %p", \
+ g_thread_self ()); \
+ g_mutex_unlock (&q->priv->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->priv->cur_level.visible, \
+ q->priv->cur_level.bytes, \
+ q->priv->cur_level.time, \
+ gst_queue_array_get_length (q->priv->queue))
+
+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 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"); \
+}
+
+#define parent_class gst_data_queue_parent_class
+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);
+
+ g_type_class_add_private (klass, sizeof (GstDataQueuePrivate));
+
+ 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, PROP_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, PROP_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, PROP_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->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (queue, GST_TYPE_DATA_QUEUE,
+ GstDataQueuePrivate);
+
+ queue->priv->cur_level.visible = 0; /* no content */
+ queue->priv->cur_level.bytes = 0; /* no content */
+ queue->priv->cur_level.time = 0; /* no content */
+
+ queue->priv->checkfull = NULL;
+
+ g_mutex_init (&queue->priv->qlock);
+ g_cond_init (&queue->priv->item_add);
+ g_cond_init (&queue->priv->item_del);
+ queue->priv->queue = gst_queue_array_new (50);
+
+ GST_DEBUG ("initialized queue's not_empty & not_full conditions");
+}
+
+/**
+ * gst_data_queue_new:
+ * @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: 1.2.0
+ */
+GstDataQueue *
+gst_data_queue_new (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->priv->checkfull = checkfull;
+ ret->priv->checkdata = checkdata;
+ ret->priv->fullcallback = fullcallback;
+ ret->priv->emptycallback = emptycallback;
+
+ return ret;
+}
+
+static void
+gst_data_queue_cleanup (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ while (!gst_queue_array_is_empty (priv->queue)) {
+ GstDataQueueItem *item = gst_queue_array_pop_head (priv->queue);
+
+ /* Just call the destroy notify on the item */
+ item->destroy (item);
+ }
+ priv->cur_level.visible = 0;
+ priv->cur_level.bytes = 0;
+ priv->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);
+ GstDataQueuePrivate *priv = queue->priv;
+
+ GST_DEBUG ("finalizing queue");
+
+ gst_data_queue_cleanup (queue);
+ gst_queue_array_free (priv->queue);
+
+ GST_DEBUG ("free mutex");
+ g_mutex_clear (&priv->qlock);
+ GST_DEBUG ("done free mutex");
+
+ g_cond_clear (&priv->item_add);
+ g_cond_clear (&priv->item_del);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static inline void
+gst_data_queue_locked_flush (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ STATUS (queue, "before flushing");
+ gst_data_queue_cleanup (queue);
+ STATUS (queue, "after flushing");
+ /* we deleted something... */
+ if (priv->waiting_del)
+ g_cond_signal (&priv->item_del);
+}
+
+static inline gboolean
+gst_data_queue_locked_is_empty (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ return (gst_queue_array_get_length (priv->queue) == 0);
+}
+
+static inline gboolean
+gst_data_queue_locked_is_full (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ return priv->checkfull (queue, priv->cur_level.visible,
+ priv->cur_level.bytes, priv->cur_level.time, priv->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: 1.2.0
+ */
+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: 1.2.0
+ */
+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: 1.2.0
+ */
+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: 1.2.0
+ */
+void
+gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ GST_DEBUG ("queue:%p , flushing:%d", queue, flushing);
+
+ GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ priv->flushing = flushing;
+ if (flushing) {
+ /* release push/pop functions */
+ if (priv->waiting_add)
+ g_cond_signal (&priv->item_add);
+ if (priv->waiting_del)
+ g_cond_signal (&priv->item_del);
+ }
+ GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+}
+
+static void
+gst_data_queue_push_force_unlocked (GstDataQueue * queue,
+ GstDataQueueItem * item)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ gst_queue_array_push_tail (priv->queue, item);
+
+ if (item->visible)
+ priv->cur_level.visible++;
+ priv->cur_level.bytes += item->size;
+ priv->cur_level.time += item->duration;
+}
+
+/**
+ * gst_data_queue_push_force:
+ * @queue: a #GstDataQueue.
+ * @item: a #GstDataQueueItem.
+ *
+ * Pushes a #GstDataQueueItem (or a structure that begins with the same fields)
+ * on the @queue. It ignores if the @queue is full or not and forces the @item
+ * to be pushed anyway.
+ * 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: 1.2.0
+ */
+gboolean
+gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ 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");
+ gst_data_queue_push_force_unlocked (queue, item);
+ STATUS (queue, "after pushing");
+ if (priv->waiting_add)
+ g_cond_signal (&priv->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_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: 1.2.0
+ */
+gboolean
+gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ 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 (priv->fullcallback))
+ priv->fullcallback (queue, priv->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)) {
+ priv->waiting_del = TRUE;
+ g_cond_wait (&priv->item_del, &priv->qlock);
+ priv->waiting_del = FALSE;
+ if (priv->flushing)
+ goto flushing;
+ }
+ }
+
+ gst_data_queue_push_force_unlocked (queue, item);
+
+ STATUS (queue, "after pushing");
+ if (priv->waiting_add)
+ g_cond_signal (&priv->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;
+ }
+}
+
+static gboolean
+_gst_data_queue_wait_non_empty (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ while (gst_data_queue_locked_is_empty (queue)) {
+ priv->waiting_add = TRUE;
+ g_cond_wait (&priv->item_add, &priv->qlock);
+ priv->waiting_add = FALSE;
+ if (priv->flushing)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * 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: 1.2.0
+ */
+gboolean
+gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ 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 (priv->emptycallback))
+ priv->emptycallback (queue, priv->checkdata);
+ else
+ g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0);
+ GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ if (!_gst_data_queue_wait_non_empty (queue))
+ goto flushing;
+ }
+
+ /* Get the item from the GQueue */
+ *item = gst_queue_array_pop_head (priv->queue);
+
+ /* update current level counter */
+ if ((*item)->visible)
+ priv->cur_level.visible--;
+ priv->cur_level.bytes -= (*item)->size;
+ priv->cur_level.time -= (*item)->duration;
+
+ STATUS (queue, "after popping");
+ if (priv->waiting_del)
+ g_cond_signal (&priv->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;
+ }
+}
+
+static gint
+is_of_type (gconstpointer a, gconstpointer b)
+{
+ return !G_TYPE_CHECK_INSTANCE_TYPE (a, GPOINTER_TO_SIZE (b));
+}
+
+/**
+ * gst_data_queue_peek:
+ * @queue: a #GstDataQueue.
+ * @item: pointer to store the returned #GstDataQueueItem.
+ *
+ * Retrieves the first @item available on the @queue without removing it.
+ * 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: 1.2.0
+ */
+gboolean
+gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ 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 peeking");
+
+ if (gst_data_queue_locked_is_empty (queue)) {
+ GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+ if (G_LIKELY (priv->emptycallback))
+ priv->emptycallback (queue, priv->checkdata);
+ else
+ g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0);
+ GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ if (!_gst_data_queue_wait_non_empty (queue))
+ goto flushing;
+ }
+
+ /* Get the item from the GQueue */
+ *item = gst_queue_array_peek_head (priv->queue);
+
+ STATUS (queue, "after peeking");
+ 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: 1.2.0
+ */
+gboolean
+gst_data_queue_drop_head (GstDataQueue * queue, GType type)
+{
+ gboolean res = FALSE;
+ GstDataQueueItem *leak = NULL;
+ guint idx;
+ GstDataQueuePrivate *priv = queue->priv;
+
+ g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
+
+ GST_DEBUG ("queue:%p", queue);
+
+ GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ idx = gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type));
+
+ if (idx == -1)
+ goto done;
+
+ leak = gst_queue_array_drop_element (priv->queue, idx);
+
+ if (leak->visible)
+ priv->cur_level.visible--;
+ priv->cur_level.bytes -= leak->size;
+ priv->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: 1.2.0
+ */
+void
+gst_data_queue_limits_changed (GstDataQueue * queue)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ g_return_if_fail (GST_IS_DATA_QUEUE (queue));
+
+ GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ if (priv->waiting_del) {
+ GST_DEBUG ("signal del");
+ g_cond_signal (&priv->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: 1.2.0
+ */
+void
+gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level)
+{
+ GstDataQueuePrivate *priv = queue->priv;
+
+ memcpy (level, (&priv->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);
+ GstDataQueuePrivate *priv = queue->priv;
+
+ GST_DATA_QUEUE_MUTEX_LOCK (queue);
+
+ switch (prop_id) {
+ case PROP_CUR_LEVEL_BYTES:
+ g_value_set_uint (value, priv->cur_level.bytes);
+ break;
+ case PROP_CUR_LEVEL_VISIBLE:
+ g_value_set_uint (value, priv->cur_level.visible);
+ break;
+ case PROP_CUR_LEVEL_TIME:
+ g_value_set_uint64 (value, priv->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/libs/gst/base/gstdataqueue.h b/libs/gst/base/gstdataqueue.h
new file mode 100644
index 0000000..c707c8b
--- /dev/null
+++ b/libs/gst/base/gstdataqueue.h
@@ -0,0 +1,163 @@
+/* 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, 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;
+typedef struct _GstDataQueuePrivate GstDataQueuePrivate;
+
+/**
+ * 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.
+ */
+
+struct _GstDataQueueItem
+{
+ GstMiniObject *object;
+ guint size;
+ guint64 duration;
+ gboolean visible;
+
+ /* user supplied destroy function */
+ GDestroyNotify destroy;
+
+ /* < private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstDataQueueSize:
+ * @visible: number of buffers
+ * @bytes: number of bytes
+ * @time: amount of time
+ *
+ * Structure describing the size of a queue.
+ */
+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.
+ */
+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.
+ */
+struct _GstDataQueue
+{
+ GObject object;
+
+ /*< private >*/
+ GstDataQueuePrivate *priv;
+ 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,
+ GstDataQueueFullCallback fullcallback,
+ GstDataQueueEmptyCallback emptycallback,
+ gpointer checkdata) G_GNUC_MALLOC;
+
+gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item);
+gboolean gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item);
+
+gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item);
+gboolean gst_data_queue_peek (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/libs/gst/base/gstindex.c b/libs/gst/base/gstindex.c
index a1b9d0e..3786e95 100644
--- a/libs/gst/base/gstindex.c
+++ b/libs/gst/base/gstindex.c
@@ -16,8 +16,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
diff --git a/libs/gst/base/gstindex.h b/libs/gst/base/gstindex.h
index 7e22efc..b943efb 100644
--- a/libs/gst/base/gstindex.h
+++ b/libs/gst/base/gstindex.h
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_INDEX_H__
diff --git a/libs/gst/base/gstmemindex.c b/libs/gst/base/gstmemindex.c
index aaeab12..b667447 100644
--- a/libs/gst/base/gstmemindex.c
+++ b/libs/gst/base/gstmemindex.c
@@ -13,8 +13,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#include <gst/gst.h>
diff --git a/libs/gst/base/gstpushsrc.c b/libs/gst/base/gstpushsrc.c
index a1bfa0a..f89fa0a 100644
--- a/libs/gst/base/gstpushsrc.c
+++ b/libs/gst/base/gstpushsrc.c
@@ -16,8 +16,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
diff --git a/libs/gst/base/gstpushsrc.h b/libs/gst/base/gstpushsrc.h
index b936d83..aabba00 100644
--- a/libs/gst/base/gstpushsrc.h
+++ b/libs/gst/base/gstpushsrc.h
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_PUSH_SRC_H__
diff --git a/libs/gst/base/gstqueuearray.c b/libs/gst/base/gstqueuearray.c
new file mode 100644
index 0000000..4b83959
--- /dev/null
+++ b/libs/gst/base/gstqueuearray.c
@@ -0,0 +1,341 @@
+/* GStreamer
+ * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
+ *
+ * gstqueuearray.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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstqueuearray
+ * @short_description: Array based queue object
+ *
+ * #GstQueueArray is an object that provides standard queue functionality
+ * based on an array instead of linked lists. This reduces the overhead
+ * caused by memory managment by a large factor.
+ */
+
+
+#include <string.h>
+#include <gst/gst.h>
+#include "gstqueuearray.h"
+
+struct _GstQueueArray
+{
+ /* < private > */
+ gpointer *array;
+ guint size;
+ guint head;
+ guint tail;
+ guint length;
+};
+
+/**
+ * gst_queue_array_new:
+ * @initial_size: Initial size of the new queue
+ *
+ * Allocates a new #GstQueueArray object with an initial
+ * queue size of @initial_size.
+ *
+ * Returns: a new #GstQueueArray object
+ *
+ * Since: 1.2.0
+ */
+GstQueueArray *
+gst_queue_array_new (guint initial_size)
+{
+ GstQueueArray *array;
+
+ array = g_slice_new (GstQueueArray);
+ array->size = initial_size;
+ array->array = g_new0 (gpointer, initial_size);
+ array->head = 0;
+ array->tail = 0;
+ array->length = 0;
+ return array;
+}
+
+
+/**
+ * gst_queue_array_free:
+ * @array: a #GstQueueArray object
+ *
+ * Frees queue @array and all memory associated to it.
+ *
+ * Since: 1.2.0
+ */
+void
+gst_queue_array_free (GstQueueArray * array)
+{
+ g_free (array->array);
+ g_slice_free (GstQueueArray, array);
+}
+
+/**
+ * gst_queue_array_pop_head:
+ * @array: a #GstQueueArray object
+ *
+ * Returns and head of the queue @array and removes
+ * it from the queue.
+ *
+ * Returns: The head of the queue
+ *
+ * Since: 1.2.0
+ */
+gpointer
+gst_queue_array_pop_head (GstQueueArray * array)
+{
+ gpointer ret;
+
+ /* empty array */
+ if (G_UNLIKELY (array->length == 0))
+ return NULL;
+ ret = array->array[array->head];
+ array->head++;
+ array->head %= array->size;
+ array->length--;
+ return ret;
+}
+
+/**
+ * gst_queue_array_pop_head:
+ * @array: a #GstQueueArray object
+ *
+ * Returns and head of the queue @array and does not
+ * remove it from the queue.
+ *
+ * Returns: The head of the queue
+ *
+ * Since: 1.2.0
+ */
+gpointer
+gst_queue_array_peek_head (GstQueueArray * array)
+{
+ /* empty array */
+ if (G_UNLIKELY (array->length == 0))
+ return NULL;
+ return array->array[array->head];
+}
+
+/**
+ * gst_queue_array_push_tail:
+ * @array: a #GstQueueArray object
+ * @data: object to push
+ *
+ * Pushes @data to the tail of the queue @array.
+ *
+ * Since: 1.2.0
+ */
+void
+gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
+{
+ /* Check if we need to make room */
+ if (G_UNLIKELY (array->length == array->size)) {
+ /* newsize is 50% bigger */
+ guint newsize = (3 * array->size) / 2;
+
+ /* copy over data */
+ if (array->tail != 0) {
+ gpointer *array2 = g_new0 (gpointer, newsize);
+ guint t1 = array->head;
+ guint t2 = array->size - array->head;
+
+ /* [0-----TAIL][HEAD------SIZE]
+ *
+ * We want to end up with
+ * [HEAD------------------TAIL][----FREEDATA------NEWSIZE]
+ *
+ * 1) move [HEAD-----SIZE] part to beginning of new array
+ * 2) move [0-------TAIL] part new array, after previous part
+ */
+
+ memcpy (array2, &array->array[array->head], t2 * sizeof (gpointer));
+ memcpy (&array2[t2], array->array, t1 * sizeof (gpointer));
+
+ g_free (array->array);
+ array->array = array2;
+ array->head = 0;
+ } else {
+ /* Fast path, we just need to grow the array */
+ array->array = g_renew (gpointer, array->array, newsize);
+ }
+ array->tail = array->size;
+ array->size = newsize;
+ }
+
+ array->array[array->tail] = data;
+ array->tail++;
+ array->tail %= array->size;
+ array->length++;
+}
+
+/**
+ * gst_queue_array_is_empty:
+ * @array: a #GstQueueArray object
+ *
+ * Checks if the queue @array is empty.
+ *
+ * Returns: %TRUE if the queue @array is empty
+ *
+ * Since: 1.2.0
+ */
+gboolean
+gst_queue_array_is_empty (GstQueueArray * array)
+{
+ return (array->length == 0);
+}
+
+/**
+ * gst_queue_array_drop_element:
+ * @array: a #GstQueueArray object
+ * @idx: index to drop
+ *
+ * Drops the queue element at position @idx from queue @array.
+ *
+ * Returns: the dropped element
+ *
+ * Since: 1.2.0
+ */
+gpointer
+gst_queue_array_drop_element (GstQueueArray * array, guint idx)
+{
+ int first_item_index, last_item_index;
+ gpointer element;
+
+ g_return_val_if_fail (array->length > 0, NULL);
+ g_return_val_if_fail (idx < array->size, NULL);
+
+ first_item_index = array->head;
+
+ /* tail points to the first free spot */
+ last_item_index = (array->tail - 1 + array->size) % array->size;
+
+ element = array->array[idx];
+
+ /* simple case idx == first item */
+ if (idx == first_item_index) {
+ /* move the head plus one */
+ array->head++;
+ array->head %= array->size;
+ array->length--;
+ return element;
+ }
+
+ /* simple case idx == last item */
+ if (idx == last_item_index) {
+ /* move tail minus one, potentially wrapping */
+ array->tail = (array->tail - 1 + array->size) % array->size;
+ array->length--;
+ return element;
+ }
+
+ /* non-wrapped case */
+ if (first_item_index < last_item_index) {
+ g_assert (first_item_index < idx && idx < last_item_index);
+ /* move everything beyond idx one step towards zero in array */
+ memmove (&array->array[idx],
+ &array->array[idx + 1], (last_item_index - idx) * sizeof (gpointer));
+ /* tail might wrap, ie if tail == 0 (and last_item_index == size) */
+ array->tail = (array->tail - 1 + array->size) % array->size;
+ array->length--;
+ return element;
+ }
+
+ /* only wrapped cases left */
+ g_assert (first_item_index > last_item_index);
+
+ if (idx < last_item_index) {
+ /* idx is before last_item_index, move data towards zero */
+ memmove (&array->array[idx],
+ &array->array[idx + 1], (last_item_index - idx) * sizeof (gpointer));
+ /* tail should not wrap in this case! */
+ g_assert (array->tail > 0);
+ array->tail--;
+ array->length--;
+ return element;
+ }
+
+ if (idx > first_item_index) {
+ element = array->array[idx];
+ /* idx is after first_item_index, move data to higher indices */
+ memmove (&array->array[first_item_index + 1],
+ &array->array[first_item_index],
+ (idx - first_item_index) * sizeof (gpointer));
+ array->head++;
+ /* head should not wrap in this case! */
+ g_assert (array->head < array->size);
+ array->length--;
+ return element;
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
+/**
+ * gst_queue_array_find:
+ * @array: a #GstQueueArray object
+ * @func: (allow-none): comparison function, or %NULL to find @data by value
+ * @data: data for comparison function
+ *
+ * Finds an element in the queue @array, either by comparing every element
+ * with @func or by looking up @data if no compare function @func is provided,
+ * and returning the index of the found element.
+ *
+ * Note that the index is not 0-based, but an internal index number with a
+ * random offset. The index can be used in connection with
+ * gst_queue_array_drop_element(). FIXME: return index 0-based and make
+ * _drop_element() take a 0-based index.
+ *
+ * Returns: Index of the found element or -1 if nothing was found.
+ *
+ * Since: 1.2.0
+ */
+guint
+gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
+{
+ guint i;
+
+ if (func != NULL) {
+ /* Scan from head to tail */
+ for (i = 0; i < array->length; i++) {
+ if (func (array->array[(i + array->head) % array->size], data) == 0)
+ return (i + array->head) % array->size;
+ }
+ } else {
+ for (i = 0; i < array->length; i++) {
+ if (array->array[(i + array->head) % array->size] == data)
+ return (i + array->head) % array->size;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * gst_queue_array_get_length:
+ * @array: a #GstQueueArray object
+ *
+ * Returns the length of the queue @array
+ *
+ * Returns: the length of the queue @array.
+ *
+ * Since: 1.2.0
+ */
+guint
+gst_queue_array_get_length (GstQueueArray * array)
+{
+ return array->length;
+}
diff --git a/libs/gst/base/gstqueuearray.h b/libs/gst/base/gstqueuearray.h
new file mode 100644
index 0000000..b640886
--- /dev/null
+++ b/libs/gst/base/gstqueuearray.h
@@ -0,0 +1,50 @@
+/* GStreamer
+ * Copyright (C) 2009-2010 Edward Hervey <bilboed@bilboed.com>
+ *
+ * gstqueuearray.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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+
+#ifndef __GST_QUEUE_ARRAY_H__
+#define __GST_QUEUE_ARRAY_H__
+
+typedef struct _GstQueueArray GstQueueArray;
+
+GstQueueArray * gst_queue_array_new (guint initial_size);
+
+void gst_queue_array_free (GstQueueArray * array);
+
+gpointer gst_queue_array_pop_head (GstQueueArray * array);
+gpointer gst_queue_array_peek_head (GstQueueArray * array);
+
+void gst_queue_array_push_tail (GstQueueArray * array,
+ gpointer data);
+
+gboolean gst_queue_array_is_empty (GstQueueArray * array);
+
+gpointer gst_queue_array_drop_element (GstQueueArray * array,
+ guint idx);
+
+guint gst_queue_array_find (GstQueueArray * array,
+ GCompareFunc func,
+ gpointer data);
+
+guint gst_queue_array_get_length (GstQueueArray * array);
+
+#endif
diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c
index 12ff79f..5f30c8c 100644
--- a/libs/gst/base/gsttypefindhelper.c
+++ b/libs/gst/base/gsttypefindhelper.c
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
@@ -116,7 +116,7 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
GstBuffer *buf = GST_BUFFER_CAST (bmp->buffer);
buf_offset = GST_BUFFER_OFFSET (buf);
- buf_size = gst_buffer_get_size (buf);
+ buf_size = bmp->map.size;
/* buffers are kept sorted by end offset (highest first) in the list, so
* at this point we save the current position and stop searching if
diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h
index 7919325..9447f9b 100644
--- a/libs/gst/base/gsttypefindhelper.h
+++ b/libs/gst/base/gsttypefindhelper.h
@@ -17,8 +17,8 @@
*
* 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __GST_TYPEFINDHELPER_H__