Merge branch 'master' into 0.11
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 25 Jan 2012 10:43:13 +0000 (11:43 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 25 Jan 2012 10:43:13 +0000 (11:43 +0100)
450 files changed:
.gitignore
Android.mk
ChangeLog
Makefile.am
NEWS
RELEASE
common
configure.ac
docs/design/Makefile.am
docs/design/draft-buffer2.txt [deleted file]
docs/design/draft-bufferpool.txt [deleted file]
docs/design/part-TODO.txt
docs/design/part-block.txt
docs/design/part-buffer.txt [new file with mode: 0644]
docs/design/part-bufferlist.txt [deleted file]
docs/design/part-bufferpool.txt [new file with mode: 0644]
docs/design/part-caps.txt
docs/design/part-controller.txt [new file with mode: 0644]
docs/design/part-element-transform.txt
docs/design/part-events.txt
docs/design/part-gstelement.txt
docs/design/part-gstobject.txt
docs/design/part-latency.txt
docs/design/part-memory.txt [new file with mode: 0644]
docs/design/part-messages.txt
docs/design/part-meta.txt [new file with mode: 0644]
docs/design/part-negotiation.txt
docs/design/part-overview.txt
docs/design/part-probes.txt [new file with mode: 0644]
docs/design/part-scheduling.txt
docs/design/part-seeking.txt
docs/design/part-segments.txt
docs/design/part-sparsestreams.txt
docs/design/part-streams.txt
docs/design/part-synchronisation.txt
docs/design/part-trickmodes.txt
docs/faq/using.xml
docs/gst/gstreamer-docs.sgml
docs/gst/gstreamer-sections.txt
docs/gst/gstreamer.types.in
docs/libs/Makefile.am
docs/libs/gstreamer-libs-docs.sgml
docs/libs/gstreamer-libs-sections.txt
docs/libs/gstreamer-libs.types
docs/manual/advanced-autoplugging.xml
docs/manual/advanced-dataaccess.xml
docs/manual/advanced-position.xml
docs/manual/highlevel-components.xml
docs/plugins/gstreamer-plugins.args
docs/plugins/gstreamer-plugins.hierarchy
docs/random/plan-0.11.txt [new file with mode: 0644]
docs/random/porting-to-0.11.txt [new file with mode: 0644]
docs/random/release
docs/random/status-0.11-14-jun-2011.txt [new file with mode: 0644]
docs/random/use-cases-0.11.txt [new file with mode: 0644]
docs/random/wtay/porting-list-0.11.txt [new file with mode: 0644]
gst/Makefile.am
gst/glib-compat-private.h
gst/gst.c
gst/gst.h
gst/gst_private.h
gst/gstatomicqueue.c
gst/gstbin.c
gst/gstbin.h
gst/gstbuffer.c
gst/gstbuffer.h
gst/gstbufferlist.c
gst/gstbufferlist.h
gst/gstbufferpool.c [new file with mode: 0644]
gst/gstbufferpool.h [new file with mode: 0644]
gst/gstbus.c
gst/gstbus.h
gst/gstcaps.c
gst/gstcaps.h
gst/gstchildproxy.h
gst/gstclock.c
gst/gstclock.h
gst/gstcompat.h
gst/gstconfig.h.in
gst/gstcontrolbinding.c [new file with mode: 0644]
gst/gstcontrolbinding.h [new file with mode: 0644]
gst/gstcontrolsource.c [moved from libs/gst/controller/gstcontrolsource.c with 65% similarity]
gst/gstcontrolsource.h [moved from libs/gst/controller/gstcontrolsource.h with 71% similarity]
gst/gstdatetime.c
gst/gstdatetime.h
gst/gstdebugutils.c
gst/gstdebugutils.h
gst/gstelement.c
gst/gstelement.h
gst/gstelementdetails.h [deleted file]
gst/gstelementfactory.c
gst/gstelementfactory.h
gst/gstelementmetadata.h [new file with mode: 0644]
gst/gsterror.c
gst/gsterror.h
gst/gstevent.c
gst/gstevent.h
gst/gstfilter.c [deleted file]
gst/gstfilter.h [deleted file]
gst/gstformat.c
gst/gstformat.h
gst/gstghostpad.c
gst/gstghostpad.h
gst/gstindexfactory.c [deleted file]
gst/gstindexfactory.h [deleted file]
gst/gstinfo.c
gst/gstinfo.h
gst/gstinterface.c [deleted file]
gst/gstinterface.h [deleted file]
gst/gstiterator.c
gst/gstiterator.h
gst/gstmarshal.list
gst/gstmemory.c [new file with mode: 0644]
gst/gstmemory.h [new file with mode: 0644]
gst/gstmessage.c
gst/gstmessage.h
gst/gstmeta.c [new file with mode: 0644]
gst/gstmeta.h [new file with mode: 0644]
gst/gstminiobject.c
gst/gstminiobject.h
gst/gstobject.c
gst/gstobject.h
gst/gstpad.c
gst/gstpad.h
gst/gstpadtemplate.c
gst/gstpadtemplate.h
gst/gstparamspecs.c
gst/gstparamspecs.h
gst/gstpipeline.c
gst/gstpipeline.h
gst/gstplugin.c
gst/gstplugin.h
gst/gstpluginfeature.c
gst/gstpluginfeature.h
gst/gstpluginloader.c
gst/gstpluginloader.h
gst/gstpoll.c
gst/gstpreset.c
gst/gstpreset.h
gst/gstquark.c
gst/gstquark.h
gst/gstquery.c
gst/gstquery.h
gst/gstregistry.c
gst/gstregistry.h
gst/gstregistrybinary.c
gst/gstregistrychunks.c
gst/gstsample.c [new file with mode: 0644]
gst/gstsample.h [new file with mode: 0644]
gst/gstsegment.c
gst/gstsegment.h
gst/gststructure.c
gst/gststructure.h
gst/gstsystemclock.c
gst/gstsystemclock.h
gst/gsttaglist.c
gst/gsttaglist.h
gst/gsttagsetter.c
gst/gsttagsetter.h
gst/gsttask.c
gst/gsttask.h
gst/gsttaskpool.h
gst/gsttrace.c
gst/gsttrace.h
gst/gsttypefind.c
gst/gsttypefind.h
gst/gsttypefindfactory.c
gst/gsttypefindfactory.h
gst/gsturi.c
gst/gsturi.h
gst/gstutils.c
gst/gstutils.h
gst/gstvalue.c
gst/gstvalue.h
gst/gstxml.c [deleted file]
gst/gstxml.h [deleted file]
gst/math-compat.h
gst/parse/Makefile.am
gstreamer.doap
gstreamer.spec.in
libs/gst/Makefile.am
libs/gst/base/Makefile.am
libs/gst/base/gstadapter.c
libs/gst/base/gstadapter.h
libs/gst/base/gstbaseparse.c
libs/gst/base/gstbaseparse.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasesrc.h
libs/gst/base/gstbasetransform.c
libs/gst/base/gstbasetransform.h
libs/gst/base/gstbitreader-docs.h
libs/gst/base/gstbitreader.c
libs/gst/base/gstbitreader.h
libs/gst/base/gstbytereader-docs.h
libs/gst/base/gstbytereader.c
libs/gst/base/gstbytereader.h
libs/gst/base/gstbytewriter.c
libs/gst/base/gstbytewriter.h
libs/gst/base/gstcollectpads.c
libs/gst/base/gstcollectpads.h
libs/gst/base/gstcollectpads2.c
libs/gst/base/gstcollectpads2.h
libs/gst/base/gstindex.c [moved from gst/gstindex.c with 96% similarity]
libs/gst/base/gstindex.h [moved from gst/gstindex.h with 92% similarity]
libs/gst/base/gstmemindex.c [moved from plugins/indexers/gstmemindex.c with 97% similarity]
libs/gst/base/gstpushsrc.c
libs/gst/base/gstpushsrc.h
libs/gst/base/gsttypefindhelper.c
libs/gst/base/gsttypefindhelper.h
libs/gst/check/Makefile.am
libs/gst/check/gstbufferstraw.c
libs/gst/check/gstbufferstraw.h
libs/gst/check/gstcheck.c
libs/gst/check/gstcheck.h
libs/gst/check/gstconsistencychecker.c
libs/gst/controller/Makefile.am
libs/gst/controller/gstcontrolbindingargb.c [new file with mode: 0644]
libs/gst/controller/gstcontrolbindingargb.h [new file with mode: 0644]
libs/gst/controller/gstcontrolbindingdirect.c [new file with mode: 0644]
libs/gst/controller/gstcontrolbindingdirect.h [new file with mode: 0644]
libs/gst/controller/gstcontroller.c [deleted file]
libs/gst/controller/gstcontroller.h [deleted file]
libs/gst/controller/gsthelper.c [deleted file]
libs/gst/controller/gstinterpolation.c [deleted file]
libs/gst/controller/gstinterpolationcontrolsource.c
libs/gst/controller/gstinterpolationcontrolsource.h
libs/gst/controller/gstinterpolationcontrolsourceprivate.h [deleted file]
libs/gst/controller/gstlfocontrolsource.c
libs/gst/controller/gstlfocontrolsource.h
libs/gst/controller/gstlfocontrolsourceprivate.h [deleted file]
libs/gst/controller/gsttimedvaluecontrolsource.c [new file with mode: 0644]
libs/gst/controller/gsttimedvaluecontrolsource.h [new file with mode: 0644]
libs/gst/controller/gsttriggercontrolsource.c [new file with mode: 0644]
libs/gst/controller/gsttriggercontrolsource.h [new file with mode: 0644]
libs/gst/controller/lib.c [deleted file]
libs/gst/dataprotocol/.gitignore [deleted file]
libs/gst/dataprotocol/Makefile.am [deleted file]
libs/gst/dataprotocol/dataprotocol.c [deleted file]
libs/gst/dataprotocol/dataprotocol.h [deleted file]
libs/gst/dataprotocol/dp-private.h [deleted file]
libs/gst/helpers/gst-plugin-scanner.c
libs/gst/net/Makefile.am
libs/gst/net/gstnetaddressmeta.c [new file with mode: 0644]
libs/gst/net/gstnetaddressmeta.h [moved from libs/gst/controller/gstcontrollerprivate.h with 50% similarity]
libs/gst/net/gstnetclientclock.c
libs/gst/net/gstnetclientclock.h
libs/gst/net/gstnettimepacket.c
libs/gst/net/gstnettimepacket.h
libs/gst/net/gstnettimeprovider.c
libs/gst/net/gstnettimeprovider.h
pkgconfig/Makefile.am
pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in [deleted file]
pkgconfig/gstreamer-dataprotocol.pc.in [deleted file]
pkgconfig/gstreamer-net-uninstalled.pc.in
pkgconfig/gstreamer-net.pc.in
pkgconfig/gstreamer-uninstalled.pc.in
pkgconfig/gstreamer.pc.in
plugins/Makefile.am
plugins/elements/Makefile.am
plugins/elements/gstcapsfilter.c
plugins/elements/gstdataqueue.c [moved from libs/gst/base/gstdataqueue.c with 94% similarity]
plugins/elements/gstdataqueue.h [moved from libs/gst/base/gstdataqueue.h with 93% similarity]
plugins/elements/gstfakesink.c
plugins/elements/gstfakesink.h
plugins/elements/gstfakesrc.c
plugins/elements/gstfdsink.c
plugins/elements/gstfdsrc.c
plugins/elements/gstfilesink.c
plugins/elements/gstfilesrc.c
plugins/elements/gstfilesrc.h
plugins/elements/gstfunnel.c
plugins/elements/gstidentity.c
plugins/elements/gstidentity.h
plugins/elements/gstinputselector.c
plugins/elements/gstinputselector.h
plugins/elements/gstmultiqueue.c
plugins/elements/gstmultiqueue.h
plugins/elements/gstoutputselector.c
plugins/elements/gstqueue.c
plugins/elements/gstqueue.h
plugins/elements/gstqueue2.c
plugins/elements/gstqueue2.h
plugins/elements/gsttee.c
plugins/elements/gsttee.h
plugins/elements/gsttypefindelement.c
plugins/elements/gsttypefindelement.h
plugins/elements/gstvalve.c
plugins/indexers/.gitignore [deleted file]
plugins/indexers/Makefile.am [deleted file]
plugins/indexers/gstfileindex.c [deleted file]
plugins/indexers/gstindexers.c [deleted file]
plugins/indexers/gstindexers.h [deleted file]
po/af.po
po/az.po
po/be.po
po/bg.po
po/ca.po
po/cs.po
po/da.po
po/de.po
po/el.po
po/en_GB.po
po/eo.po
po/es.po
po/eu.po
po/fi.po
po/fr.po
po/gl.po
po/hu.po
po/id.po
po/it.po
po/ja.po
po/lt.po
po/nb.po
po/nl.po
po/pl.po
po/pt_BR.po
po/ro.po
po/ru.po
po/rw.po
po/sk.po
po/sl.po
po/sq.po
po/sr.po
po/sv.po
po/tr.po
po/uk.po
po/vi.po
po/zh_CN.po
po/zh_TW.po
scripts/gst-uninstalled
tests/benchmarks/controller.c
tests/benchmarks/gstbufferstress.c
tests/benchmarks/gstclockstress.c
tests/benchmarks/gstpollstress.c
tests/check/Makefile.am
tests/check/elements/capsfilter.c
tests/check/elements/fakesink.c
tests/check/elements/fakesrc.c
tests/check/elements/fdsrc.c
tests/check/elements/filesink.c
tests/check/elements/filesrc.c
tests/check/elements/funnel.c
tests/check/elements/identity.c
tests/check/elements/multiqueue.c
tests/check/elements/queue.c
tests/check/elements/selector.c
tests/check/elements/tee.c
tests/check/elements/valve.c
tests/check/generic/sinks.c
tests/check/generic/states.c
tests/check/gst/.gitignore
tests/check/gst/capslist.h
tests/check/gst/gstbin.c
tests/check/gst/gstbuffer.c
tests/check/gst/gstbufferlist.c
tests/check/gst/gstcaps.c
tests/check/gst/gstcontroller.c [new file with mode: 0644]
tests/check/gst/gstelement.c
tests/check/gst/gstelementfactory.c
tests/check/gst/gstevent.c
tests/check/gst/gstghostpad.c
tests/check/gst/gstinfo.c
tests/check/gst/gstinterface.c [deleted file]
tests/check/gst/gstiterator.c
tests/check/gst/gstmemory.c [new file with mode: 0644]
tests/check/gst/gstmessage.c
tests/check/gst/gstmeta.c [new file with mode: 0644]
tests/check/gst/gstminiobject.c
tests/check/gst/gstobject.c
tests/check/gst/gstpad.c
tests/check/gst/gstparamspecs.c
tests/check/gst/gstpipeline.c
tests/check/gst/gstplugin.c
tests/check/gst/gstpreset.c
tests/check/gst/gstquery.c
tests/check/gst/gstregistry.c
tests/check/gst/gstsegment.c
tests/check/gst/gststructure.c
tests/check/gst/gsttag.c
tests/check/gst/gsttagsetter.c
tests/check/gst/gsttask.c
tests/check/gst/gstutils.c
tests/check/gst/gstvalue.c
tests/check/gst/gstxml.c [deleted file]
tests/check/gst/struct_arm.h
tests/check/gst/struct_hppa.h
tests/check/gst/struct_i386.h
tests/check/gst/struct_ppc32.h
tests/check/gst/struct_ppc64.h
tests/check/gst/struct_sparc.h
tests/check/gst/struct_x86_64.h
tests/check/libs/adapter.c
tests/check/libs/basesink.c
tests/check/libs/basesrc.c
tests/check/libs/bitreader.c
tests/check/libs/bytereader.c
tests/check/libs/collectpads.c
tests/check/libs/controller.c
tests/check/libs/gdp.c [deleted file]
tests/check/libs/gstlibscpp.cc
tests/check/libs/gstnettimeprovider.c
tests/check/libs/libsabi.c
tests/check/libs/test_transform.c
tests/check/libs/transform1.c
tests/check/libs/typefindhelper.c
tests/check/pipelines/parse-launch.c
tests/check/pipelines/queue-error.c
tests/check/pipelines/simple-launch-lines.c
tests/check/pipelines/stress.c
tests/examples/adapter/adapter_test.c
tests/examples/controller/.gitignore
tests/examples/controller/Makefile.am
tests/examples/controller/audio-example.c
tests/examples/controller/control-sources.c [new file with mode: 0644]
tests/examples/controller/text-color-example.c [new file with mode: 0644]
tests/examples/manual/Makefile.am
tests/examples/stepping/framestep1.c
tools/.gitignore
tools/BUGS [deleted file]
tools/Makefile.am
tools/README [deleted file]
tools/gst-feedback-m.m [deleted file]
tools/gst-feedback.1.in [deleted file]
tools/gst-inspect.c
tools/gst-launch.1.in
tools/gst-launch.c
tools/gst-run.c [deleted file]
tools/gst-typefind.c
tools/gst-xmlinspect.1.in [deleted file]
tools/gst-xmlinspect.c [deleted file]
tools/gst-xmllaunch.1.in [deleted file]
tools/gstreamer-completion
tools/xml2text.xsl [deleted file]
win32/MANIFEST
win32/common/config.h
win32/common/gstenumtypes.c
win32/common/gstenumtypes.h
win32/common/gstmarshal.c
win32/common/gstmarshal.h
win32/common/gstversion.h
win32/common/libgstbase.def
win32/common/libgstcontroller.def
win32/common/libgstdataprotocol.def
win32/common/libgstnet.def
win32/common/libgstreamer.def
win32/vs6/gstreamer.dsw
win32/vs6/libgstdataprotocol.dsp [deleted file]

index 297c199..da9b993 100644 (file)
@@ -44,3 +44,10 @@ gst-element-check.m4
 _stdint.h
 *.gir
 *.typelib
+Build
+*.user
+*.suo
+*.ipch
+*.sdf
+*.opensdf
+*.DS_Store
\ No newline at end of file
index 54788e1..a698256 100644 (file)
@@ -17,12 +17,10 @@ GST_BUILT_SOURCES :=                \
        pkgconfig/gstreamer-0.10.pc       \
        pkgconfig/gstreamer-base-0.10.pc      \
        pkgconfig/gstreamer-controller-0.10.pc    \
-       pkgconfig/gstreamer-dataprotocol-0.10.pc    \
        pkgconfig/gstreamer-net-0.10.pc \
        pkgconfig/gstreamer-0.10-uninstalled.pc       \
        pkgconfig/gstreamer-base-0.10-uninstalled.pc      \
        pkgconfig/gstreamer-controller-0.10-uninstalled.pc    \
-       pkgconfig/gstreamer-dataprotocol-0.10-uninstalled.pc    \
        pkgconfig/gstreamer-net-0.10-uninstalled.pc     \
        gst/Android.mk \
        gst/parse/Android.mk \
@@ -30,7 +28,6 @@ GST_BUILT_SOURCES :=          \
        libs/gst/Android.mk \
        libs/gst/base/Android.mk \
        libs/gst/controller/Android.mk \
-       libs/gst/dataprotocol/Android.mk \
        libs/gst/net/Android.mk \
        libs/gst/helpers/Android.mk \
        plugins/Android.mk \
@@ -54,7 +51,7 @@ gst-configure-real:
        PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \
        PKG_CONFIG_TOP_BUILD_DIR=/ \
        $(abspath $(gstreamer_TOP))/$(CONFIGURE) --host=arm-linux-androideabi \
-       --prefix=/system --disable-nls --disable-loadsave \
+       --prefix=/system --disable-nls \
        --disable-valgrind --disable-gtk-doc && \
        for file in $(GST_BUILT_SOURCES); do \
                rm -f $$file && \
index 91ee387..981d021 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-=== release 0.10.35 ===
+=== release 0.11.1 ===
 
-2011-06-15  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-29  Wim Taymans <wim.taymans@collabora.co.uk>
 
        * configure.ac:
-         releasing 0.10.35, "Nuclear Fission"
+         releasing 0.11.1, "Sweet New Blossom"
 
-2011-06-09 17:13:35 +0100  Javier Jardón <jjardon@gnome.org>
+2011-09-28 18:46:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstelement.h:
-       * gst/gstelementfactory.c:
-       * gst/gstelementfactory.h:
-       * gst/gstformat.h:
-       * gst/gstinfo.c:
-       * gst/gstinfo.h:
-       * gst/gstpad.c:
-       * gst/gstpad.h:
-       * gst/gstplugin.c:
-       * gst/gstplugin.h:
-       * gst/gstpluginfeature.c:
-       * gst/gstpluginfeature.h:
-       * gst/gstquery.h:
-       * gst/gststructure.h:
-       * gst/gsttaglist.c:
-       * gst/gsttaglist.h:
-       * gst/gsttagsetter.c:
-       * gst/gsttagsetter.h:
-       * gst/gsttrace.h:
-       * gst/gsturi.c:
-       * gst/gsturi.h:
-       * gst/gstutils.c:
-       * gst/gstutils.h:
-       * gst/gstvalue.h:
-         Use "const" instead G_CONST_RETURN
-         G_CONST_RETURN will be deprecated soon.
-         https://bugzilla.gnome.org/show_bug.cgi?id=652211
+       * gst/gstmemory.c:
+         memory: fix memory alignment
+         Fix compilation when POSIX_MEMALIGN is not set.
+         Debug the configured alignment.
+         Fixes https://bugzilla.gnome.org/show_bug.cgi?id=660300
 
-2011-06-04 00:30:15 -0700  David Schleef <ds@schleef.org>
+2011-09-28 18:44:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/glib-compat-private.h:
-       * gst/gstatomicqueue.c:
-       * gst/gstelementfactory.c:
-       * gst/gstpoll.c:
-       * gst/gstsystemclock.c:
-       * gst/gstutils.c:
-       * plugins/elements/gstmultiqueue.c:
-       * tests/benchmarks/gstclockstress.c:
-         Work around changes in g_atomic API
-         See #651514 for details.  It's apparently impossible to write code
-         that avoids both type punning warnings with old g_atomic headers and
-         assertions in the new.  Thus, macros and a version check.
+       * gst/gstpad.c:
+         pad: improve debug
 
-2011-05-25 13:40:30 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+2011-09-28 11:28:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstsystemclock.c:
-         systemclock: Placate gcc by defining EWOULDBLOCK to something
+       * libs/gst/base/gstbasetransform.c:
+         transform: fix after merge
 
-2011-05-25 12:47:51 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+2011-09-28 11:24:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstpoll.c:
-         poll: Fix WAKE_EVENT() to behave posixly on Windows
+         Merge branch 'master' into 0.11
 
-=== release 0.10.34 ===
+2011-09-28 11:16:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-2011-05-14 01:00:23 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.h:
+         docs: fix some more docs
 
-       * ChangeLog:
-       * NEWS:
-       * RELEASE:
-       * configure.ac:
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coreindexers.xml:
-       * gstreamer.doap:
-       * win32/common/config.h:
-       * win32/common/gstversion.h:
-         Release 0.10.34
+2011-09-26 19:52:13 +0100  Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
 
-2011-05-04 15:31:56 +0300  Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: send delayed events earlier
+         Some elements (such as videorate) might push buffers early,
+         for instance in in transform_ip. We want events (and in particular
+         any NEWSEGMENT event) to be pushed before that.
+         This fixes transmageddon wedging on converting a file starting
+         with a non zero offset to Ogg.
+         https://bugzilla.gnome.org/show_bug.cgi?id=660165
 
-       * libs/gst/base/gstbasesrc.c:
-         basesrc: do not set first buffer timestamp to 0 for live sources
-         Doing so avoids a large timestamp gap between first and second buffer
-         for live sources which take time to start up.
-         The first buffer now has a "live" timestamp based on the running time,
-         as other buffers do.
-         https://bugzilla.gnome.org/show_bug.cgi?id=649369
+2011-09-26 20:47:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-2011-05-10 11:11:15 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferpool.h:
+       * gst/gstcaps.h:
+       * gst/gstevent.h:
+       * gst/gstiterator.h:
+       * gst/gstmemory.c:
+       * gst/gstmessage.h:
+       * gst/gstmeta.h:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+       * gst/gstpad.h:
+       * gst/gstquery.c:
+         docs: fix docs
 
-       * plugins/elements/gstmultiqueue.c:
-         multiqueue: ensure thread safety when adding a pad
-         This seems to be a regression, and was causing crashes.
-         https://bugzilla.gnome.org/show_bug.cgi?id=649878
+2011-09-26 19:25:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-=== release 0.10.33 ===
+         Merge branch 'master' into 0.11
 
-2011-05-10 08:55:10 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-26 19:24:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * ChangeLog:
-       * NEWS:
-       * RELEASE:
-       * configure.ac:
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coreindexers.xml:
-       * gstreamer.doap:
-       * po/af.po:
-       * po/az.po:
-       * po/be.po:
-       * po/bg.po:
-       * po/ca.po:
-       * po/cs.po:
-       * po/da.po:
-       * po/de.po:
-       * po/el.po:
-       * po/en_GB.po:
-       * po/es.po:
-       * po/eu.po:
-       * po/fi.po:
-       * po/fr.po:
-       * po/gl.po:
-       * po/hu.po:
-       * po/id.po:
-       * po/it.po:
-       * po/ja.po:
-       * po/lt.po:
-       * po/nb.po:
-       * po/nl.po:
-       * po/pl.po:
-       * po/pt_BR.po:
-       * po/ro.po:
-       * po/ru.po:
-       * po/rw.po:
-       * po/sk.po:
-       * po/sl.po:
-       * po/sq.po:
-       * po/sr.po:
-       * po/sv.po:
-       * po/tr.po:
-       * po/uk.po:
-       * po/vi.po:
-       * po/zh_CN.po:
-       * po/zh_TW.po:
-       * win32/common/config.h:
-       * win32/common/gstversion.h:
-         Release 0.10.33
-         Highlights:
-         - new parser base class: GstBaseParse
-         - new core element: funnel
-         - OSX multi-arch fixes
-         - new QoS type for QoS events
-         - new progress message API to notify applications of asynchronous operations
-         - countless other fixes and improvements
+       * gst/gstsegment.h:
+         segment: improve API docs a little
 
-2011-05-06 23:40:58 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-26 00:30:47 +0300  Raimo Järvi <raimo.jarvi@gmail.com>
 
-       * libs/gst/base/gstbaseparse.c:
-         baseparse: don't post loads of empty taglists
-         Only post bitrate updates if there's something to post, don't
-         post empty taglists if nothing changed.
+       * gst/gstregistry.c:
+       * gst/gststructure.c:
+         gst: Fix compiler warnings on 64 bit mingw-w64
+         Fixes bug #660083.
 
-2011-05-06 11:35:36 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-25 16:10:53 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * gst/gstinfo.h:
-         info: avoid redefinition of symbols when debugging is off
-         The refactoring of gst_debug_add_log_function() now causes build failure when
-         debug-logging is turned off. Just move it to the conditional part of the header.
+       * tests/examples/helloworld/helloworld.c:
+         examples: fix bogus g_object_unref in helloworld example
+         GMainLoop is not a GObject.
+         https://bugzilla.gnome.org/show_bug.cgi?id=424143
 
-2011-05-04 15:29:42 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-23 13:09:25 +0200  Edward Hervey <bilboed@bilboed.com>
 
-       * tests/check/gst/gstminiobject.c:
-         tests: fix compiler warning in new miniobject test
-         gst/gstminiobject.c: In function ‘test_dup_null_mini_object’:
-         gst/gstminiobject.c:459:7: warning: assignment from incompatible pointer type
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstcaps.c
+         gst/gstpad.c
+         libs/gst/base/gstbasesink.c
+         libs/gst/base/gstbasesink.h
+         libs/gst/base/gstbasetransform.c
 
-2011-05-02 11:30:06 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+2011-09-21 13:43:48 +0200  Edward Hervey <bilboed@bilboed.com>
 
-       * gst/gstminiobject.c:
-       * tests/check/gst/gstminiobject.c:
-         miniobject: Fix dup_mini_object function to handle NULL gvalues
-         g_value_dup_object handles gvalues that contain NULL pointers,
-         gst_value_dup_mini_object should do the same.
-         https://bugzilla.gnome.org/show_bug.cgi?id=649195
+       * common:
+         Update common to 0.11 branch
 
-2011-05-03 13:55:43 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-20 13:04:06 +0100  Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
 
-       * libs/gst/base/gstbaseparse.c:
-         docs: it its %TRUE (constant)
-         As spotted by Tim.
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: delay serialized events when src caps are not set yet
+         https://bugzilla.gnome.org/show_bug.cgi?id=659571
 
-2011-05-02 16:22:56 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-13 17:04:31 +0400  Stas Sergeev <stsp@users.sourceforge.net>
 
-       * gst/gstelementfactory.c:
-         docs: fix copy'n'paste doc header mistake
+       * gst/gstpad.c:
+         pad: Set caps on pad before checking if the pad is linked
+         This allows the setcaps handler and notify::caps to link
+         the pad downstream and doesn't require hacks to always
+         provide a peer to the pad, like in decodebin2.
 
-2011-05-02 16:20:24 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-15 11:49:43 -0700  Fabrizio (Misto) Milo <mistobaan@gmail.com>
 
-       * gst/gstelement.h:
-       * gst/gstpluginfeature.h:
-         docs: add two trivial doc blobs
+       * gst/gstcaps.c:
+         caps: use g_value_take_string() and gst_value_get_caps() instead of accessing internal fields
 
-2011-05-02 16:03:29 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-16 13:38:41 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * libs/gst/base/gstbaseparse.c:
-         docs: add missing parameter docs
+       * gst/gstpad.c:
+         pad: add more debug logging for other chain function code path as well
 
-2011-05-02 16:00:52 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-16 13:13:30 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * libs/gst/dataprotocol/dataprotocol.h:
-         docs: add docs for GstDPPacketizer
+       * gst/gstpad.c:
+         pad: fix up printf format in debug message
+         Which I messed up.
 
-2011-05-02 15:52:58 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-15 13:20:15 +0100  Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
 
-       * gst/gstcaps.h:
-         docs: improve the syntax for the capsintersectmode docs
+       * gst/gstpad.c:
+         pad: make some debug traces more useful
+         https://bugzilla.gnome.org/show_bug.cgi?id=659139
 
-2011-05-02 15:48:01 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-14 22:54:18 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * gst/gstelement.c:
-         docs: fixup broken xref
+       * scripts/gstcvstest.sh:
+         scripts: remove gstcvstest.sh
 
-2011-05-02 15:46:59 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-13 23:04:09 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * docs/gst/gstreamer-sections.txt:
-       * docs/libs/gstreamer-libs-sections.txt:
-         docs: add new api to -section.txt
+       * libs/gst/controller/gstlfocontrolsource.c:
+         lfocontrolsource: fix clang compiler warning
+         Cast enum to int before checking for negative values, which are
+         impossible according to the enum list.
+         gstlfocontrolsource.c:652:45: error: comparison of unsigned enum expression < 0
+         is always false [-Werror,-Wtautological-compare]
+         if (waveform >= num_waveforms || waveform < 0) {
+         ~~~~~~~~ ^ ~
+         https://bugzilla.gnome.org/show_bug.cgi?id=653137
 
-2011-05-02 15:35:52 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-13 21:58:21 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * gst/gstatomicqueue.h:
-         docs: fix gtk-doc syntax
+       * tests/check/elements/filesrc.c:
+         tests: make sure filesrc returns escaped URIs even if the input was unescaped
+         https://bugzilla.gnome.org/show_bug.cgi?id=654673
 
-2011-05-02 15:30:13 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-10 18:15:49 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-         docs: don't duplicate info that we take from element-details
+       * gst/gstcaps.c:
+         caps: move log messages for caps creation/freeing into TRACE category
+         Reduce SPAM for GST_CAPS:5.
 
-2011-04-28 15:37:02 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-09 12:56:20 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
-       * docs/gst/gstreamer-sections.txt:
-         docs: remove non existing symbol
+       * gst/gstpad.c:
+         pad: Only do the subset check in gst_pad_accept_caps() if the pad claims to accept the caps
 
-2011-04-28 15:05:28 +0300  Stefan Kost <ensonic@users.sf.net>
+2011-09-07 17:21:55 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
 
-       * gst/gstbufferlist.c:
-       * gst/gstsystemclock.h:
-         docs: we don't need to document private members in opaque structs
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * plugins/elements/gstfilesink.c:
+         basesink: make it easy to override the pad query
+         Add a vmethod to handle the pad query.
+         Install a default handler for the pad query.
+         Use the new query function in filesink
 
-2011-04-30 16:55:36 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-08 14:39:30 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
-       * configure.ac:
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coreindexers.xml:
-       * docs/plugins/inspect/plugin-staticelements.xml:
-       * po/de.po:
-       * po/fr.po:
-       * win32/common/config.h:
-       * win32/common/gstversion.h:
-         0.10.32.4 pre-release
+       * libs/gst/base/gstbasetransform.c:
+         Revert "Revert "basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible""
+         This reverts commit 0bc6d49c950210bf422615fb8dc98c5adcd5e456.
+         Conflicts:
+         libs/gst/base/gstbasetransform.c
 
-2011-04-29 23:44:55 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-08 14:31:52 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
-       * gst/gstpluginfeature.h:
-         pluginfeature: include plugin.h in header where we use a GstPlugin pointer
-         Should fix issue with gstreamermm build where <gst/gstindex.h> is included
-         directly instead of gst/gst.h.
+       * gst/gstpad.c:
+         Revert "Revert "pad: Check for subsets, not non-empty intersections to check if caps are compatible""
+         This reverts commit 2bfada5581e35a2d37188f48a2c7442644f10bb3.
+         Conflicts:
+         gst/gstpad.c
+         For 0.11 we want to enforce that only subsets of the pad
+         caps are allowed. This breaks backward compatibility for
+         some elements, which is why we only print a warning in
+         0.10.
 
-2011-04-27 11:49:11 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-09-08 14:30:07 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
-       * configure.ac:
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-coreindexers.xml:
-       * po/bg.po:
-       * po/nl.po:
-       * po/pl.po:
-       * po/ru.po:
-       * win32/common/config.h:
-       * win32/common/gstversion.h:
-         0.10.32.3 pre-release
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstpad.c
+
+2011-09-08 14:29:00 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         Revert "pad: Use gst_pad_accept_caps() instead of manually checking when configuring a sinkpad"
+         This reverts commit d3cad28da936b037d877dc70c02286b81b680284.
+         It causes performance problems because acceptcaps() propagates downstream.
+
+2011-09-08 14:23:50 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         docs/design/draft-buffer2.txt
+         docs/design/part-TODO.txt
+         docs/design/part-block.txt
+         docs/design/part-bufferlist.txt
+         docs/design/part-caps.txt
+         docs/design/part-element-transform.txt
+         docs/design/part-events.txt
+         docs/design/part-negotiation.txt
+         gst/gstcaps.c
+         gst/gstevent.h
+         gst/gstghostpad.c
+         gst/gstinterface.c
+         gst/gstpad.c
+         gst/gstpad.h
+         gst/gstutils.c
+         libs/gst/base/gstbasesink.c
+         libs/gst/base/gstbasesrc.c
+         libs/gst/base/gstbasetransform.c
+         libs/gst/base/gsttypefindhelper.c
+         plugins/elements/gstcapsfilter.c
+         plugins/elements/gsttee.c
+         tests/check/generic/sinks.c
+         tools/gst-launch.1.in
+
+2011-09-08 13:41:19 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Use gst_pad_accept_caps() instead of manually checking when configuring a sinkpad
+
+2011-09-08 13:40:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Print a g_warning() if pad accept caps that are not a subset of its caps
+         In 0.11 only subsets are supported again as documented instead of also
+         allowing non-empty intersections.
+
+2011-09-08 13:26:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         Revert "basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible"
+         This reverts commit 5e5cc5e89e7e2858a6352fa4c81a374f6e5a6297.
+         See bug #658541.
+
+2011-09-08 13:26:01 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         Revert "pad: Check for subsets, not non-empty intersections to check if caps are compatible"
+         This reverts commit 0c5d50207326d74a4805bcd898bfac887540f12b.
+         See bug #658541.
+
+2011-09-07 13:14:38 +0200  Piotr Fusik <fox@scene.pl>
+
+       * README:
+       * docs/README:
+       * docs/design/draft-buffer2.txt:
+       * docs/design/draft-klass.txt:
+       * docs/design/part-MT-refcounting.txt:
+       * docs/design/part-TODO.txt:
+       * docs/design/part-activation.txt:
+       * docs/design/part-block.txt:
+       * docs/design/part-buffering.txt:
+       * docs/design/part-bufferlist.txt:
+       * docs/design/part-caps.txt:
+       * docs/design/part-clocks.txt:
+       * docs/design/part-element-sink.txt:
+       * docs/design/part-element-transform.txt:
+       * docs/design/part-events.txt:
+       * docs/design/part-framestep.txt:
+       * docs/design/part-gstelement.txt:
+       * docs/design/part-gstghostpad.txt:
+       * docs/design/part-latency.txt:
+       * docs/design/part-messages.txt:
+       * docs/design/part-missing-plugins.txt:
+       * docs/design/part-negotiation.txt:
+       * docs/design/part-qos.txt:
+       * docs/design/part-scheduling.txt:
+       * docs/design/part-seeking.txt:
+       * docs/design/part-states.txt:
+       * docs/design/part-stream-status.txt:
+       * docs/faq/Makefile.am:
+       * docs/faq/dependencies.xml:
+       * docs/faq/general.xml:
+       * docs/manual/Makefile.am:
+       * docs/manual/advanced-clocks.xml:
+       * docs/manual/advanced-dparams.xml:
+       * docs/manual/basics-elements.xml:
+       * docs/manual/basics-init.xml:
+       * docs/manual/basics-pads.xml:
+       * docs/manual/diagrams-general.svg:
+       * docs/manual/highlevel-components.xml:
+       * docs/manual/intro-gstreamer.xml:
+       * docs/pwg/Makefile.am:
+       * docs/pwg/advanced-tagging.xml:
+       * docs/pwg/intro-basics.xml:
+       * docs/pwg/intro-preface.xml:
+       * docs/pwg/other-base.xml:
+       * docs/pwg/other-source.xml:
+       * docs/random/autoplug2:
+       * docs/random/bbb/optional-properties:
+       * docs/random/bbb/streamselection:
+       * docs/random/caps:
+       * docs/random/company/gvadec.txt:
+       * docs/random/ensonic/draft-bufferpools.txt:
+       * docs/random/ensonic/embedded.txt:
+       * docs/random/ensonic/media-device-daemon.txt:
+       * docs/random/ensonic/plugindocs.txt:
+       * docs/random/ensonic/profiling.txt:
+       * docs/random/eos:
+       * docs/random/hierarchy:
+       * docs/random/i18n:
+       * docs/random/interfaces:
+       * docs/random/negotiation:
+       * docs/random/omega/sched/chains:
+       * docs/random/omega/testing/framework:
+       * docs/random/plugins:
+       * docs/random/rtp:
+       * docs/random/slomo/controller.txt:
+       * docs/random/sources:
+       * docs/random/streamheader:
+       * docs/random/testing/syntax:
+       * docs/random/types2:
+       * docs/random/uraeus/gstreamer_and_midi.txt:
+       * docs/random/vis-transform:
+       * docs/random/wtay/caps-negociation:
+       * docs/random/wtay/threading:
+       * docs/random/wtay/threads_hilevel:
+       * gst/gstbin.c:
+       * gst/gstcaps.c:
+       * gst/gstchildproxy.c:
+       * gst/gstelement.c:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstghostpad.c:
+       * gst/gstinterface.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstparamspecs.h:
+       * gst/gstparse.c:
+       * gst/gstpipeline.c:
+       * gst/gstplugin.c:
+       * gst/gstpluginfeature.c:
+       * gst/gstpluginfeature.h:
+       * gst/gstpoll.c:
+       * gst/gstregistry.c:
+       * gst/gststructure.c:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * gst/gstvalue.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gsttypefindhelper.c:
+       * libs/gst/controller/gstcontroller.c:
+       * libs/gst/controller/gsthelper.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttee.c:
+       * tests/benchmarks/capsnego.c:
+       * tests/check/elements/filesink.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstelementfactory.c:
+       * tests/check/gst/gstevent.c:
+       * tools/gst-launch.1.in:
+       * win32/README.txt:
+         docs, gst: typo fixes
+         https://bugzilla.gnome.org/show_bug.cgi?id=658449
+
+2011-09-07 15:07:20 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/gst/Makefile.am:
+       * docs/libs/Makefile.am:
+         docs: fix make distcheck
+         No point removin those empty override files from git, they'll
+         just be re-created later, so let's tell gtk-doc about them, so
+         it can clean them up properly.
+
+2011-09-07 16:02:31 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: If there's no peer we still have to transform ANY caps in getcaps()
+         Otherwise elements like capsfilter will return ANY caps if no
+         peer is present instead of the filter caps. The transform_caps()
+         vfunc could do transformations to the template caps that do not
+         result in the unmodified template caps.
+
+2011-09-07 14:05:03 +0200  Stefan Sauer <ensonic@users.sf.net>
+
+       * docs/gst/Makefile.am:
+       * docs/libs/Makefile.am:
+       * docs/plugins/Makefile.am:
+         docs: cleanup makefiles
+         Remove commented out parts that we don't need. Remove "the wingo addition" - no
+         so useful after all. Narrow down file-globs for plugin docs.
+
+2011-09-07 13:50:08 +0200  Stefan Sauer <ensonic@users.sf.net>
+
+       * gst/gstelement.c:
+         docs: escape % in docblob
+
+2011-09-02 19:46:06 +0400  Stas Sergeev <stas@stas.(none)>
+
+       * gst/gstghostpad.c:
+         ghostpad: Use gst_pad_set_caps() instead of manually changing caps
+         gst_pad_set_caps() does essentially the same but additionally calls
+         the pad's setcaps function.
+         Fixes bug #658076.
+
+2011-09-06 21:24:10 +0200  Stefan Sauer <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From a39eb83 to 11f0cd5
+
+2011-09-06 15:39:52 +0200  Stefan Sauer <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From 605cd9a to a39eb83
+
+2011-09-06 12:17:05 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Use check for subsets and not non-empty intersection to check if caps are compatible
+
+2011-09-06 12:19:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Check for subsets, not non-empty intersections to check if caps are compatible
+         Pads should only accept caps that are a subset of the pad caps, e.g.
+         they should accept only caps that have a non-empty intersection and
+         at least all fields of the pad caps.
+         Without this a pad that wants for example
+         "video/x-h264,stream-format=byte-stream"
+         will be happy to accept
+         "video/x-h264".
+
+2011-08-29 17:06:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbufferlist.c:
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+       * gst/gstminiobject.h:
+       * gst/gstquery.c:
+       * win32/common/libgstreamer.def:
+         miniobject: change to GST_DEFINE_MINI_OBJECT_TYPE
+         Append _TYPE to the macro for consistency with other similar macros.
+
+2011-08-29 15:34:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstmessage.c:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+       * gst/gstquery.c:
+       * win32/common/libgstreamer.def:
+         init: add _get_type() functions
+         Remove gst_mini_object_register() and add a GST_DEFINE_MINI_OBJECT macro to
+         define a _get_type() function for the boxed miniobject.
+         Remove a bunch of custom _get_type() functions and replace them with the
+         miniobject macro.
+         Rename some _init method to _priv_*_initialize() like the rest of them.
+         Inspired by patch from Johan Dahlin and see bug #657603
+
+2011-08-29 13:27:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstbuffer.c:
+       * gst/gstbufferlist.c:
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+       * gst/gstformat.c:
+       * gst/gstmessage.c:
+       * gst/gstplugin.c:
+       * gst/gstquery.c:
+       * gst/gstregistry.c:
+       * gst/gstregistrybinary.c:
+       * gst/gststructure.c:
+       * gst/gsttaglist.c:
+       * gst/gstvalue.c:
+       * win32/common/libgstreamer.def:
+         gst: add some _priv prefixes to private methods
+
+2011-08-29 12:38:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+         mini-object: use ref/unref directly in boxed copy/free
+         GLib will not call our copy/free with a NULL object
+
+2011-08-26 14:37:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstmessage.c
+         gst/gstquery.c
+         gst/gstregistrychunks.c
+         gst/gstsegment.c
+         libs/gst/base/gstbasetransform.c
+         libs/gst/base/gstbasetransform.h
+         libs/gst/base/gsttypefindhelper.c
+         plugins/elements/gsttypefindelement.c
+
+2011-08-26 14:18:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         base: rename allocation vmethods
+         Name the allocation vmethod on srcpad decide_allocation because source pads will
+         have to decide what allocation parameters will be used.
+         Name the allocation vmethod on sinkpads propose_allocation because they will
+         need to configure the allocation query with a proposed values for upstream.
+
+2011-08-26 14:17:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         buffer: improve flags
+         Rename DROP to DECODE_ONLY.
+         Add DROPPABLE flag to mark buffers that can be dropped to save bandwidth without
+         destroying the stream.
+
+2011-08-26 14:09:47 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gsttrace.h:
+       * gst/gsttypefind.h:
+         docs: add since 0.10.36 on the new _NONE enum values
+
+2011-08-26 00:13:16 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * tests/examples/stepping/framestep1.c:
+         stepping: use the proper argument order
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-26 00:06:12 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * plugins/indexers/gstfileindex.c:
+         fileindex: explicitly cast to the enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-26 00:00:25 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * plugins/elements/gsttypefindelement.c:
+         typefinder: use GST_TYPE_FIND_NONE instead of 0
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 23:53:58 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * libs/gst/controller/gstlfocontrolsource.c:
+         lfocontrolsource: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 23:49:38 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gsttypefind.h:
+       * libs/gst/base/gsttypefindhelper.c:
+         typefind: add GST_TYPE_FIND_NONE and use it
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 23:26:08 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: use the enum values for 0 and don't abuse on gboolean coincidence
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 23:06:56 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: put the arguments of g_return_val_if_fail in the proper order
+
+2011-08-25 22:48:54 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstparse.c:
+         parse: use GST_PARSE_FLAG_NONE instead of 0
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 22:42:08 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstvalue.c:
+         value: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 22:29:45 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstutils.c:
+         utils: minor changes related to enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 22:05:26 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gsttrace.c:
+       * gst/gsttrace.h:
+         trace: add GST_ALLOC_TRACE_NONE for consistency and use it
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:52:05 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gsttask.c:
+         task: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:49:29 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstsystemclock.c:
+       * gst/gsttagsetter.c:
+         tagsetter: use GST_TAG_MERGE_UNDEFINED instead of FALSE
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:30:57 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstsegment.c:
+         segment: use GST_SEEK_FLAG_NONE instead of 0
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:25:46 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstregistrychunks.c:
+         registrychunks: explicitly cast to the enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:18:15 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstquery.c:
+         query: minor changes related to enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-25 21:03:53 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstpadtemplate.c:
+         padtemplate: explicitly cast to the enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-16 23:00:47 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-16 22:51:29 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstmessage.c:
+         message: explicitly cast to the right enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-16 22:41:32 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstinfo.c:
+         info: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-16 22:37:08 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstindex.c:
+         index: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-16 22:29:59 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstformat.c:
+         format: use GST_FORMAT_UNDEFINED and few casts to GstFormat
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+
+2011-08-26 13:02:34 +0100  Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: Fix bodged previous commit
+
+2011-08-26 12:37:43 +0100  Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: Use GstPadDirection in the query vfunc
+         Wim suggested that using GstPadDirection instead of a GstPad in the
+         arguments to the new query vfunc would be more consistent with the other
+         functions.
+
+2011-08-26 13:40:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         buffer: rename _CLIP to _DROP flag
+         We can also use a flag to indicate that a frame should be decoded but not
+         displayed regardless of the the segment boundaries so we use the more generic
+         _DROP.
+
+2011-08-26 12:28:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: remove some unused variables
+
+2011-08-26 11:44:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: add vmethod to configure upstream bufferpool
+         Add a vmethod that can be implemented to influence the bufferpool that upstream
+         elements will use.
+
+2011-08-26 11:24:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: use pad direction like other vmethods
+
+2011-08-26 11:09:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         libs/gst/base/gstbasetransform.c
+         libs/gst/base/gstbasetransform.h
+
+2011-08-26 10:57:37 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gsturi.h:
+         uri: some doc fixes
+
+2011-08-25 11:02:16 +0100  Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         BaseTransform: Add a query vfunc
+
+2011-07-20 14:05:27 +0200  Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+
+       * plugins/elements/gstcapsfilter.c:
+         capsfilter: don't assume _get_caps still has to be
+         _set_caps only gets called when the buffer is actually pushed, so there
+         is a reasonably big window between when the initial caps are retrieved
+         and when the caps are set on our src pad. So we can't assume the not
+         having negotiated caps on our src pad means _get_caps still has to be
+         called.
+         Instead simply always suggest the new caps on buffer_alloc.
+
+2011-08-25 18:04:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         buffer: add clip flag
+
+2011-08-25 16:21:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         buffer: rework flags a little
+         Reorder buffer flags and add some new ones.
+         Remove the media specific flags, we can now easily do this with the FLAG_LAST
+         flag because we don't extend from GstBuffer anymore.
+
+2011-08-25 16:20:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * libs/gst/base/gstbasetransform.c:
+         buffer: always copy all buffer flags when asked
+         Don't try to be smart and copy only a subset of buffer flag
+
+2011-08-25 16:19:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         update defs
+
+2011-08-25 14:09:37 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gstbuffer.h:
+         buffer: pluralize the buffer flags
+
+2011-08-25 12:38:58 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * tests/check/generic/sinks.c:
+       * tests/check/pipelines/stress.c:
+         basesink: remove preroll-queue-len property
+         Remove the preroll-queue-len property and move its variables to a private
+         section so that we can remove them later.
+
+2011-08-24 10:43:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstobject.c
+
+2011-08-23 18:19:53 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: ensure start_time reset upon flush
+
+2011-08-23 11:55:17 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstobject.c:
+         gstobject: also remove the cast as this is causing the trouble
+
+2011-08-23 11:41:02 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstobject.c:
+         gstobject: use the atomic macros to deal with the glib change in the impl.
+
+2011-08-22 12:49:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstobject.c:
+       * gst/gstobject.h:
+         object: make _replace like the miniobject version
+
+2011-08-22 12:33:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstbuffer.h
+         gst/gstcaps.c
+         gst/gstcaps.h
+         gst/gstevent.c
+
+2011-08-22 12:19:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * gst/gstvalue.c:
+       * gst/gstvalue.h:
+       * tests/check/gst/capslist.h:
+       * tests/check/gst/gstcaps.c:
+       * tests/check/gst/gststructure.c:
+       * tests/check/gst/gstvalue.c:
+       * tests/check/pipelines/parse-launch.c:
+       * win32/common/libgstreamer.def:
+         value: remove our FOURCC GType
+         Remove our custom fourcc GValue.
+
+2011-08-21 14:07:08 -0700  David Schleef <ds@schleef.org>
+
+       * gst/gstobject.c:
+         object: make gst_object_replace() atomic
+
+2011-08-20 14:07:55 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelement.c:
+         docs: more clarification for element docs
+         Don't suggest deprecated method in the desction docs and try to be more helpful
+         in other places by suggesting related functions.
+
+2011-08-20 09:56:01 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelement.c:
+         docs: small clarification in the gst_element_get_request_pad docs
+         Make it more obvious that one should pass the template name.
+
+2011-08-18 20:46:01 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: don't use == in debug string
+         It messes up GST_DEBUG=*:5 make foo/bar.valgrind, because
+         our Makefile looks for '==' as marker of valgrind output.
+
+2011-08-18 20:44:01 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: fix crash on seek from streaming thread on newsegment event
+         Event if it's not allowed, we can easily prevent it, so let's do
+         that.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656771
+
+2011-08-17 17:56:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * win32/common/libgstreamer.def:
+         structure: add method to fixate one field
+
+2011-08-17 17:16:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: add default fixate function
+         Add a default fixate function which does gst_caps_fixate() because
+         gst_pad_fixate() does not do that anymore.
+
+2011-08-17 09:25:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * libs/gst/base/gstbasetransform.h:
+         docs: improve some docs
+
+2011-08-16 18:29:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: return processed number of bytes
+         Make _fill, _extract and _memset return the actual number of bytes that were
+         handled in case the buffer size is less than the specified size.
+
+2011-08-16 17:19:29 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstelementfactory.c:
+         docs: fix typo in element factory documentation
+
+2011-08-16 17:32:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/dataprotocol/dataprotocol.c:
+         buffer: rename PREROLL -> LIVE flag
+         Rename the GST_BUFFER_FLAG_PREROLL to GST_BUFFER_FLAG_LIVE and give the new flag
+         a meaning. The old PREROLL flag never had a clear meaning.
+
+2011-08-15 21:05:34 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         caps: fix compiler warning reported by ICC
+         The MAX macro expands to code that checks if an unsigned integer is < 0.
+         Fixes warning #186: pointless comparison of unsigned integer reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-10 11:39:23 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstbuffer.h:
+         buffer: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-10 11:07:49 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstelement.h:
+         gststate: explicitly cast to the enum type
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-09 23:42:26 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstevent.c:
+         event: explicitly cast to the right enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-09 23:33:43 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gsterror.c:
+         gsterror: explicitly cast to the right GstGError code enum types
+         Fixes warning #188: enumerated type mixed with another type reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-09 23:26:13 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstdebugutils.c:
+         debugutils: use GST_STATE_VOID_PENDING for GstState instead of 0
+         Fixes a warning reported by ICC.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-09 22:48:53 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+         caps: define GST_CAPS_FLAGS_NONE for consistency with other enumerations
+         Use them to fix warnings when building with ICC.
+         API: GST_CAPS_FLAGS_NONE
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-09 22:29:44 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gst.c:
+         gst: use GstDebugLevel enum type to fix a warning building with ICC
+         https://bugzilla.gnome.org/show_bug.cgi?id=656265
+
+2011-08-15 16:45:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: make fixate caps behave like other functions
+         Install a default fixate caps function on pads like all the other pad functions.
+
+2011-08-15 16:45:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: update for new symbols
+
+2011-08-15 14:43:14 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-08-15 14:40:38 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstpad.c:
+       * gst/gststructure.c:
+         caps: add fixate function
+         Add a fixate function and use it in gstpad.c
+
+2011-08-15 14:32:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+         structure: add function to fixate
+         Add a function to fixate a structure and use it for the default fixate function
+         in gstpad.c.
+
+2011-08-15 13:17:44 +0200  Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+       * scripts/gst-uninstalled:
+         gst-uninstalled: add Farsight and Nice support
+         https://bugzilla.gnome.org/show_bug.cgi?id=656557
+
+2011-08-15 14:17:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: fix default acceptcaps
+         Make the acceptcaps function behave like all the other functions with a default
+         implementation. Don't try to chain up to the default implementation when it was
+         set to NULL explicitly but return FALSE instead.
+         Fix some docs
+
+2011-08-15 13:24:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: fix some macros
+         Remove a rather usless macro to check if a pad mode is active and
+         add GST_PAD_IS_ACTIVE().
+
+2011-08-15 12:18:59 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting doc
+
+2011-08-15 12:16:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstdebugutils.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * win32/common/libgstreamer.def:
+         pad: remove gst_pad_get_negotiated_caps()
+         Remove gst_pad_get_negotiated_caps(), it does not realy do what it says,
+         gst_pad_get_current_caps() returns the currently negotiated caps on the pad
+         correctly.
+
+2011-08-12 19:27:21 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: fix deadlock in error path
+         Don't lock the same lock twice. Spotted by Josep Torre Valles.
+
+2011-08-12 12:45:01 +0300  Peteris Krisjanis <pecisk@gmail.com>
+
+       * gst/gstiterator.c:
+         iterator: Fix gst_iterator_next() element annotation
+
+2011-08-11 09:31:25 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/pwg/advanced-types.xml:
+         docs: fix typo in PWG
+         RBG -> RGB. Spotted by Will Thompson.
+         https://bugzilla.gnome.org/show_bug.cgi?id=656326
+
+2011-08-11 10:09:41 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstdebugutils.c:
+         debugutils: removed non-sense comment
+
+2011-08-10 17:07:54 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+         Merge remote-tracking branch 'origin/master' into 0.11
+         Conflicts:
+         gst/gstdebugutils.c
+         gst/gstelementdetails.h
+         gst/gstregistrychunks.c
+         tools/gst-run.c
+
+2011-08-08 19:36:04 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelementdetails.h:
+       * gst/gstregistrychunks.c:
+         registry: move utf-8 validation to registry saving time
+         Instead of checking for valid utf-8 element-details every time we create
+         elements (from plugin-init or registry), do it before we save the registry.
+         Fixes #656193.
+
+2011-08-10 11:01:58 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+       * gst/gstmeta.c:
+       * gst/gstpad.c:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/check/gstcheck.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+         Fix and clarify debug statements
+         Fixes build on MacOSX
+         Signed-off-by: Edward Hervey <edward.hervey@collabora.co.uk>
+
+2011-08-05 10:59:42 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         gstbuffer: Clarify doc
+
+2011-08-07 09:14:50 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/manual/basics-helloworld.xml:
+         docs: fix helloworld compile command line for newer gcc
+         https://bugzilla.gnome.org/show_bug.cgi?id=656092
+
+2011-08-06 18:20:51 +0200  Shaun Hoopes <hoopes01@student.uwa.edu.au>
+
+       * gst/gstdebugutils.c:
+         debugutils: improve dot file flow layout
+         Iterate source- and sink-pads separately to ensure that the graph reflects the
+         upstream/downstream order. Fixes #643269
+
+2011-08-06 14:17:50 +0200  Thomas Vander Stichele <thomas (at) apestaart (dot) org>
+
+       * gstreamer.spec.in:
+         gstreamer.spec: make buildable and parallel
+
+2011-08-05 12:12:33 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tools/gst-run.c:
+         tools: make unversioned wrapper look for -0.10 tools only
+         Don't want (incompatible) 0.11 tools to be picked up by accident.
+
+2011-08-04 18:00:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: add alloc vmethod
+         Make an alloc vmethod so that subclasses can override or call the default
+         implementation when they want.
+
+2011-08-04 17:26:34 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstbase.def:
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2011-08-04 17:12:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: cleanups and mark reconfigure
+         Don't abuse the result variable.
+         Mark the srcpad with a reconfigure so that negotiation happens.
+
+2011-08-04 17:12:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: add method to mark reconfigure
+
+2011-08-04 16:56:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: remove negotiation from the state change
+         Remove the negotiation from the state change function, it causes data transfer
+         and bufferpool negotiation, which is not supposed to be done. Since we have the
+         reconfigure state on the pad, the create function will do the negotiation as
+         soon as it gets in the streaming thread.
+
+2011-08-04 16:34:49 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: expose set_caps method
+         Expose a previously static method so that custom negotiate implementation can
+         call it and do the right thing.
+
+2011-08-04 13:48:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: PAUSED<->PLAY doesn't change pool state
+         Don't change the state of the bufferpool when going between PAUSED and PLAYING,
+         it will dealloc and realloc all buffers, which is clearly too invasive. We will
+         need to add some other way of unblocking the bufferpool.
+
+2011-08-04 11:00:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstmemory.c:
+         fix default alignment
+         A 0 alignment is the default.
+
+2011-08-04 10:54:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * win32/common/libgstreamer.def:
+         bufferpool: add gst_buffer_pool_is_active()
+
+2011-08-03 11:57:50 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * configure.ac:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         back to development
+
+=== release 0.11.0 ===
+
+2011-08-02 20:55:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * configure.ac:
+       * gstreamer.doap:
+       * po/af.po:
+       * po/az.po:
+       * po/be.po:
+       * po/bg.po:
+       * po/ca.po:
+       * po/cs.po:
+       * po/da.po:
+       * po/de.po:
+       * po/el.po:
+       * po/en_GB.po:
+       * po/es.po:
+       * po/eu.po:
+       * po/fi.po:
+       * po/fr.po:
+       * po/gl.po:
+       * po/hu.po:
+       * po/id.po:
+       * po/it.po:
+       * po/ja.po:
+       * po/lt.po:
+       * po/nb.po:
+       * po/nl.po:
+       * po/pl.po:
+       * po/pt_BR.po:
+       * po/ro.po:
+       * po/ru.po:
+       * po/rw.po:
+       * po/sk.po:
+       * po/sl.po:
+       * po/sq.po:
+       * po/sr.po:
+       * po/sv.po:
+       * po/tr.po:
+       * po/uk.po:
+       * po/vi.po:
+       * po/zh_CN.po:
+       * po/zh_TW.po:
+       * win32/common/config.h:
+       * win32/common/gstenumtypes.c:
+       * win32/common/gstenumtypes.h:
+       * win32/common/gstversion.h:
+         RELEASE 0.11
+
+2011-08-03 11:04:12 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting-to-0.11: Add section about GstIterator
+
+2011-08-01 18:12:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: don't add the same option twice
+         Make sure that we only add an option to the array once.
+
+2011-07-30 14:04:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * win32/common/libgstreamer.def:
+         bufferpool: add method to check for an option
+         Add a method to check if an option is supported on the bufferpool.
+
+2011-07-29 17:10:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * win32/common/libgstreamer.def:
+         bufferpool: add options API to bufferpool
+         Make it possible to query the supported options of a bufferpool and enable
+         options. This is a bit more generic than the API to enable metadata. The purpose
+         is to make it possible to add new custom config options to the configuration of
+         the bufferpool when supported.
+
+2011-07-28 12:11:36 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+         element: don't use G_CONST_RETURN
+         It's been deprecated in newer GLib versions
+
+2011-07-28 12:01:58 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/manual/advanced-position.xml:
+         manual: update for position/duration query API change
+
+2011-07-27 00:28:50 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tests/check/elements/fakesink.c:
+       * tests/check/elements/filesink.c:
+       * tests/check/generic/sinks.c:
+       * tests/examples/stepping/framestep1.c:
+         tests: update for query API changes
+
+2011-07-27 00:28:19 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+         plugins: update for query API changes
+
+2011-07-27 00:26:43 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+         base: update for query API changes
+
+2011-07-27 00:17:02 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstquery.c:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         gst: fix awkward dest_format inout parameter in query utility functions
+         The idea was originally that if one passed &dest_fmt with
+         dest_fmt=GST_FORMAT_DEFAULT, then the code answering the query
+         could change dest_fmt to the actual default format used. However,
+         in more than half a decade of GStreamer 0.10 no piece of code in
+         GStreamer has ever used that feature, nor are there that many
+         users of this API that actually check whether the format returned
+         is the original format passed before using the values returned.
+         Also, it's just annoying-to-use API in its own right.
+         For all these reasons, make it so that the destination format is
+         passed directly and can't be changed by the element queried.
+
+2011-07-27 12:50:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-07-27 12:49:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: add more comments
+
+2011-07-27 12:45:17 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetrans: also pass allocation query in in_place
+         When we are doing an in_place transform, don't do the allocation query but let
+         the upstream element decide.
+
+2011-07-26 22:41:59 -0700  Evan Nemerson <evan@coeus-group.com>
+
+       * libs/gst/base/gstbitreader.c:
+       * libs/gst/base/gstbytereader.c:
+         base: add missing (out) annotation for byte reader/writer functions
+         https://bugzilla.gnome.org/show_bug.cgi?id=655381
+
+2011-07-27 10:09:11 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstelementfactory.c:
+         elementfactory: fix g-i annotation for _create() and _make() to allow NULL object names
+
+2011-07-26 18:48:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: improve the getcaps function
+         Refactor calling the GETCAPS function and checks.
+         Move the filter code in one place.
+         When using fixed pad caps, get the currently configured caps and then fallback
+         to the GETCAPS function. We used to simply ignore the GETCAPS function, which
+         resulted in transform elements returning the template caps instead of doing the
+         caps transform.
+
+2011-07-26 15:43:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: only update caps when changed
+         Only call the event function with the caps event when the caps changed.
+
+2011-07-26 14:37:51 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: add some more debug info
+
+2011-07-26 12:21:38 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * plugins/elements/gstfilesink.c:
+         basesink: make it easy to override the pad query
+         Add a vmethod to handle the pad query.
+         Install a default handler for the pad query.
+         Add a vmethod to setup the allocation properties.
+         Use the new query function in filesink
+
+2011-07-26 12:20:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: improve docs
+
+2011-07-26 12:20:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: add allocation query just because
+
+2011-07-25 15:21:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpoll.c:
+         poll: improve debugging
+
+2011-07-25 12:53:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+         miniobject: avoid race in bufferpool release
+         Avoid playing with the refcount to decide when a buffer has been recycled by the
+         dispose function. The problem is that we then temporarily can have a buffer with
+         a refcount > 1 being acquired from the pool, which is not writable. Instead use
+         a simple boolean return value from the dispose function to inform the called
+         that the object was recycled or not.
+
+2011-07-25 12:49:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: use DEBUG instead of ERROR for logging
+         Don't use the ERROR log category because the allocation failure migh only be
+         bacause of a state change.
+
+2011-07-25 12:14:16 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: start with raised control socket
+         In the inactive state, the control socket should be in the raised state, we will
+         release it when we start.
+
+2011-07-24 11:24:44 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/pwg/advanced-clock.xml:
+       * docs/pwg/building-chainfn.xml:
+         pwd: discontinous event -> newsegment event
+         Fix a 0.8 leftover as mentioned on bug #621121.
+
+2011-07-24 09:05:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         talk about the basetransform sink_event vmethod
+
+2011-07-23 08:00:09 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/controller/gstcontrollerprivate.h:
+         controller: fix build failure due to compiler warning
+         Presumably with newer GLib version.
+         https://bugzilla.gnome.org/show_bug.cgi?id=655155
+
+2011-07-22 21:17:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+       * plugins/elements/gstidentity.c:
+         basetransform: fix sink event handling
+         Implement the sink event handling like the src event handler. Make the default
+         implementation parse and forward the event. This makes it possible to actually
+         return an error value from the event handler.
+
+2011-07-22 19:19:59 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: handle failures
+         Handle failure to activate the bufferpool.
+
+2011-07-22 19:11:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetrans: improve debugging.
+
+2011-07-21 18:50:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: add reset_buffer vmethod
+         Add a vmethod to reset a buffer to its original state. Add a default
+         implementation that resets the flags, timestamps and offsets.
+         Add some more docs.
+
+2011-07-21 17:42:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstidentity.c:
+         basetrans: Remove ref in passthrough
+         Remove the requirement to have to return a ref to the input buffer when in
+         passthrough mode. This saves a few ref/unref cycles and fixes another 0.11
+         FIXME.
+
+2011-07-21 17:29:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: make new  copy_metadata vmethod
+         Make a new copy_metadata vmethod and move the code to copy the timestamps, flags
+         and offsets into a default implementation. This will allow us to give the
+         subclasses a chance to override the copy method.
+
+2011-07-21 16:49:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         libs/gst/base/gstbaseparse.c
+         libs/gst/base/gstbasesink.c
+
+2011-07-21 16:39:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetrans: avoid intermediate method
+         Simply call the prepare_output_buffer method instead of calling an intermediate
+         function.
+
+2011-07-21 16:30:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: move the metadata copy code
+         Move the metadata copy code to the default prepare_output_buffer implementation.
+
+2011-07-21 15:49:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: move prepare_output_buffer code
+         Move the code for prepare_output_buffer to a default implementation. this allows
+         us to simplify some things and have subclasses call into the default
+         implementation when needed.
+
+2011-07-21 15:48:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: only get size for debug
+
+2011-07-21 14:18:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetrans: fix comment and warn
+         Emit a warning in the debug log when something seems weird.
+
+2011-07-21 14:14:58 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: only get caps for size transform
+         Delay getting the caps until we need to call the transform_size function.
+
+2011-07-21 13:56:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstidentity.c:
+         basetrans: remove useless variables from prepare_output_buffer
+         Remove the caps and size from the prepare_output_buffer function. with
+         bufferpools and capsnego done differently, we don't need this in most cases and
+         if we do, we can simply use the transform_size function and get the caps from
+         the srcpad.
+
+2011-07-18 17:22:41 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/manual/advanced-clocks.xml:
+         docs: clarify clocks docs in manual
+         After a question on the mailing list, mention that *flushing* seeks reset the
+         running time.
+
+2011-07-16 22:00:15 +0300  Raluca Elena Podiuc <ralucaelena1985@gmail.com>
+
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+         docs: removed double negation in event/message seq num description
+         https://bugzilla.gnome.org/show_bug.cgi?id=654751
+
+2011-07-16 12:21:12 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tests/check/elements/filesrc.c:
+         tests: make sure non-ASCII chars in filenames are escaped when creating URIs from them
+         https://bugzilla.gnome.org/show_bug.cgi?id=654673
+
+2011-07-15 16:04:11 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: don't accidentally disable the pool
+         When we set a pool and it is the same as the old pool, don't disable the pool.
+
+2011-07-15 13:27:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: call release_buffer after alloc
+         After we allocated a new buffer, call the release_buffer vmethod to put the new
+         buffer in the pool instead of assuming that the pool uses the default
+         release_method implementation.
+
+2011-07-15 11:52:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: add macro to check for flushing
+
+2011-07-15 11:51:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: improve debug message
+
+2011-07-14 12:45:33 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: fix printf format in debug message
+
+2011-07-13 11:39:15 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: unset PLAYING transition flag when transition completed
+
+2011-07-12 14:07:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: fix resize function some more
+         Don't remove memory blocks from the buffer when we clip and resize, instead set
+         the memory offset and size to 0. This allows us to make the buffer larger again
+         later.
+
+2011-07-12 13:40:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * tests/check/gst/gstbuffer.c:
+         buffer: improve size handling
+         Also handle the case where multiple empty memory blocks are in the buffer.
+         Add unit test for this.
+
+2011-07-12 12:00:58 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * tests/check/gst/gstbuffer.c:
+         buffer: fix _resize some more
+         Add more debug.
+         Alow resize to 0 bytes.
+         Do clipping correctly.
+         Add more unit tests. Also add a failing test: when we resize to 0 and then
+         try to resize back to the original size it fails because the memory was
+         removed.
+
+2011-07-11 18:00:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * tests/check/gst/gstbuffer.c:
+         buffer: fix negative offsets some more
+         Allow for negative offsets when doing memory copy and share.
+         Add fast path in the _get_sizes() function.
+         Fix resize for negative offset and expanding the buffer.
+         Add some unit tests.
+
+2011-07-11 16:43:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: add defs for new methods
+
+2011-07-11 16:42:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: fix _resize better
+
+2011-07-11 16:17:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * win32/common/libgstreamer.def:
+         buffer: add api to get the current memory offset
+         Also return the offset in a GstMemory block with the get_sizes() method. This
+         allows us to figure out how much prefix there is unused.
+         Change the resize function so that a negative offset can be given. This would
+         make it possible to resize the buffer so that the prefix becomes available.
+         Add gst_buffer_get_sizes() to return the offset and maxsize as well as the size.
+         Also change the buffer resize method so that we can specify a negative offset
+         to remove prefix bytes.
+
+2011-07-11 14:40:07 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: add some memory wrapped buffer allocation helpers
+
+2011-07-11 12:11:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.h:
+         miniobject: cleanup headers
+
+2011-07-11 11:40:08 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: eat incoming caps event
+         ... as it is typically up to baseclass to set proper src caps.
+
+2011-07-11 11:37:28 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: avoid inadvertently dropping an event
+         ... particularly a non-sticky serialized event that happens to pass
+         when an event update is pending.
+
+2011-07-04 12:58:54 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: try harder to arrange increasing position reporting
+         ... rather than having a momentary decreasing one while transitioning
+         to PLAYING.
+         Fixes #628021.
+
+2011-07-08 16:07:12 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: add new API to .def file
+
+2011-07-06 15:13:30 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: make idx argument to gst_buffer_take_memory() signed
+         Since -1 is acceptable, it should be signed.
+
+2011-07-07 14:57:18 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: fix invalid memory access in debug messages
+         Don't use buffers that we've given away or unrefed in debug messages.
+
+2011-07-07 11:14:34 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: fix after merge
+
+2011-07-07 11:13:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         libs/gst/base/gstbasesrc.c
+
+2011-07-06 16:08:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: add memset function
+
+2011-07-06 12:09:28 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: fix guards for gst_buffer_take_memory()
+         Since idx = -1 makes it default to idx=len, len is also
+         a valid input idx.
+
+2011-07-05 16:38:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: add class ref/unref
+
+2011-07-05 16:32:45 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/libs/transform1.c:
+         test: disable failing unit tests
+         Disable unit tests that are failing until someone ports this to 0.11
+
+2011-07-05 16:20:03 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstqueue.c:
+       * tests/check/elements/queue.c:
+         queue: fix unit test
+         Set the right position member in the segment event.
+         Add some debug to queue.
+
+2011-07-05 00:10:26 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * libs/gst/base/Makefile.am:
+       * libs/gst/check/Makefile.am:
+       * libs/gst/controller/Makefile.am:
+       * libs/gst/dataprotocol/Makefile.am:
+       * libs/gst/net/Makefile.am:
+         gst: make compiler warn about unstable API if GST_USE_UNSTABLE_API is not defined
+         And define it in our own build.
+
+2011-07-05 00:12:13 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: update .def files for latest API changes/additions
+
+2011-06-30 17:39:37 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: do not sneakily mess with current offset when updating length
+
+2011-06-28 22:18:46 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: unref allocation query when no longer needed
+
+2011-06-28 19:01:57 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: avoid iterating over a single NULL pad
+
+2011-06-20 23:28:07 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * docs/gst/gstreamer.types.in:
+       * docs/random/porting-to-0.11.txt:
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * gst/gstinterface.c:
+       * gst/gstinterface.h:
+       * tests/check/Makefile.am:
+       * tests/check/gst/.gitignore:
+       * tests/check/gst/gstinterface.c:
+       * tests/check/gst/struct_arm.h:
+       * tests/check/gst/struct_hppa.h:
+       * tests/check/gst/struct_i386.h:
+       * tests/check/gst/struct_ppc32.h:
+       * tests/check/gst/struct_ppc64.h:
+       * tests/check/gst/struct_sparc.h:
+       * tests/check/gst/struct_x86_64.h:
+         Remove GstImplementsInterface
+         It was a bit too clever, and didn't really work as an API,
+         confusing people to no end. Better implement specific methods
+         whether an interface is usable/available/ready on the interface
+         itself, or even add GError arguments, rather than try to have
+         per-instance interfaces.
+
+2011-06-25 13:51:52 -0700  Emmanuel Pacaud <emmanuel.pacaud@lapp.in2p3.fr>
+
+       * gst/gsttask.c:
+         task: Check for PR_SET_NAME before using
+         Fixes: #653172.
+         Signed-off-by: David Schleef <ds@schleef.org>
+
+2011-06-23 11:27:52 -0700  David Schleef <ds@schleef.org>
+
+       * common:
+         Automatic update of common submodule
+         From 69b981f to 605cd9a
+
+2011-06-23 18:03:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+         query: add method to check for metadata
+         Add a method to check if a certain metadata is supported in the ALLOCATION
+         query.
+
+2011-06-22 18:07:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-meta.txt:
+         docs: update design docs a little
+         Update the design doc with the current state of the videometadata.
+
+2011-06-22 17:12:34 +0200  Koop Mast <kwm at FreeBSD.org>
+
+       * plugins/elements/gsttee.c:
+         tee: use & instead of && for masking bits
+         See #653137
+
+2011-06-22 17:09:52 +0200  Koop Mast <kwm at FreeBSD.org>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: remove redundant ()
+         See #653137
+
+2011-06-22 17:05:27 +0200  Koop Mast <kwm at FreeBSD.org>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: fix seekstop
+         See #653137
+
+2011-06-22 16:58:53 +0200  Koop Mast <kwm at FreeBSD.org>
+
+       * gst/gstsegment.c:
+         segment: cast to right type
+         See #653137
+
+2011-06-22 16:38:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelementfactory.c:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+         uri: remove some _full variants
+
+2011-06-22 16:16:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbasesink.c:
+         tags: Remove crazy tag messages
+         Don't mix messages and pads and tags.
+         Make the sink post tag messages when a tag event is received.
+         Since tags are sticky on pads now, they can be retrieved from there
+         when needed.
+
+2011-06-22 12:28:14 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstelementfactory.c:
+         caps: Hide implementation details
+         Make the Array of structures private. This should allow us to implement
+         the array more efficiently or with some preallocated structures when
+         we want to later.
+         Add a new method to clean up a static structure so that we can remove some code
+         that pokes into the private bits of the caps.
+
+2011-06-22 12:26:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-negotiation.txt:
+         docs: update negotiation design doc
+
+2011-06-22 11:42:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferpool.c:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+         memory: rename GstMemoryAllocator -> GstAllocator
+         simplify the name of the allocator object.
+
+2011-06-21 17:54:38 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         configure.ac
+         win32/common/config.h
+         win32/common/gstversion.h
+
+2011-06-21 17:47:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-bufferpool.txt:
+         docs: update bufferpool design doc
+
+2011-06-21 17:47:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: improve debugging
+
+2011-06-21 15:15:44 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/manual/communication.png:
+         images: strip images of extra text tags
+
+2011-06-21 12:32:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: return empty metadata array
+         Return a string array with NULL instead of NULL from the default get_metas
+         function.
+
+2011-06-21 12:31:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: use event function directly
+         We will never go in this code path for CAPS events so directly call the event
+         function.
+
+2011-06-21 10:29:51 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: notify caps after we store the new caps
+         notify caps after we store the new caps so that the new caps are actually
+         visible for the app.
+
+2011-06-20 17:32:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: activate the bufferpool
+         always activate the bufferpool, even if we get it from the allocation
+         query.
+
+2011-06-20 17:32:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: always activate the pool we get
+         Activate the pool when we get it from the allocation query.
+
+2011-06-20 16:47:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         basetransform: inprove allocation handling
+         Add vmethod for subclasses to influence the pool and allocator.
+         Log when query fails.
+         Respect negotiated allocator and alignment.
+
+2011-06-20 16:46:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Improve logging
+         Log when things fail.
+         Fix a query leak.
+
+2011-06-20 16:44:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: improve debug
+         Log a debug line when there is no target pad and when this makes the default
+         implementation fail.
+         Take the internal pads directly when we can.
+
+2011-06-20 15:40:51 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * configure.ac:
+         configure.ac: bump required GLib to 2.26
+
+2011-06-20 13:26:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: add function to set metadata api
+         Add a function to retrieve an array of supported metadata apis from the the
+         bufferpool.
+         Add functions to configure and query the configured metadata apis in a
+         bufferpool configuration.
+
+2011-06-19 13:15:19 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         gstbuffer: Minor fix to docs
+         Adds missing parameter to docs of gst_buffer_copy_region
+
+2011-06-18 17:35:41 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * gst/gstpad.c:
+         gstpad: Remove unused variable do_event_actions
+         do_event_actions was always used as TRUE
+
+2011-06-18 14:38:53 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+         Bump gobject-introspection requirement to >= 0.6.8
+         For --add-init-section
+
+2011-06-16 17:27:21 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+         Bump git version after unplanned 0.10.35 release
+         Merge remote-tracking branch 'origin/0.10.35'
+
+2011-06-14 17:57:21 +0200  Philip Jägenstedt <philipj@opera.com>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Fix typo in documentation
+         Fixes #652577.
+
+2011-06-16 10:55:15 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstutils.h:
+         Revert "utils: remove some macros now in glib"
+         This reverts commit de29ae7b929cedbf6b9838ea53b05efabdce4ce7.
+         Re-adds GFLOAT_TO_LE, GFLOAT_TO_BE, GDOUBLE_TO_LE, and GDOUBLE_TO_BE.
+         Turns out these aren't in GLib yet afer all (since we didn't
+         actually open a bug to get them added..)
+
+=== release 0.10.35 ===
+
+2011-06-15 19:15:24 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * gstreamer.doap:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         Release 0.10.35
+         This is an ad-hoc release that is almost identical to 0.10.34:
+         * work around GLib atomic ops API change
+         * some minor win32/mingw fixes
+         * don't use G_CONST_RETURN in public headers
+
+2011-06-15 16:56:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: fix refcounting problem
+
+2011-06-09 17:13:35 +0100  Javier Jardón <jjardon@gnome.org>
+
+       * gst/gstelement.h:
+       * gst/gstelementfactory.c:
+       * gst/gstelementfactory.h:
+       * gst/gstformat.h:
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstplugin.c:
+       * gst/gstplugin.h:
+       * gst/gstpluginfeature.c:
+       * gst/gstpluginfeature.h:
+       * gst/gstquery.h:
+       * gst/gststructure.h:
+       * gst/gsttaglist.c:
+       * gst/gsttaglist.h:
+       * gst/gsttagsetter.c:
+       * gst/gsttagsetter.h:
+       * gst/gsttrace.h:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * gst/gstvalue.h:
+         Use "const" instead G_CONST_RETURN
+         G_CONST_RETURN will be deprecated soon.
+         https://bugzilla.gnome.org/show_bug.cgi?id=652211
+
+2011-06-04 00:30:15 -0700  David Schleef <ds@schleef.org>
+
+       * gst/glib-compat-private.h:
+       * gst/gstatomicqueue.c:
+       * gst/gstelementfactory.c:
+       * gst/gstpoll.c:
+       * gst/gstsystemclock.c:
+       * gst/gstutils.c:
+       * plugins/elements/gstmultiqueue.c:
+       * tests/benchmarks/gstclockstress.c:
+         Work around changes in g_atomic API
+         See #651514 for details.  It's apparently impossible to write code
+         that avoids both type punning warnings with old g_atomic headers and
+         assertions in the new.  Thus, macros and a version check.
+
+2011-05-25 13:40:30 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Placate gcc by defining EWOULDBLOCK to something
+
+2011-05-25 12:47:51 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+
+       * gst/gstpoll.c:
+         poll: Fix WAKE_EVENT() to behave posixly on Windows
+
+2011-06-14 15:18:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-TODO.txt:
+       * docs/random/status-0.11-14-jun-2011.txt:
+         docs: update docs
+
+2011-06-13 19:10:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-06-13 16:31:53 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferpool.c:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbytewriter.c:
+       * plugins/elements/gstfakesrc.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/libs/bitreader.c:
+       * tests/check/libs/bytereader.c:
+       * tests/check/libs/typefindhelper.c:
+         buffer: add index to _take_memory()
+         Add an index to gst_buffer_take_memory() so that we can also insert memory at a
+         certain offset. This is mostly interesting to prepend a header memory block to
+         the buffer.
+
+2011-06-13 16:30:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: don't forward scheduling query
+         The scheduling query should not be forwarded, because elements need to implement
+         special code to handle different scheduling methods.
+
+2011-06-13 12:07:03 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstpushsrc.c:
+       * libs/gst/base/gstpushsrc.h:
+         basesrc: Allocator buffers from negotiated allocator
+         Allocate buffers from the negotiated allocator or bufferpool.
+         Handle the state of the bufferpool when flushing.
+         Add fill method to pushsrc.
+
+2011-06-13 12:04:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: add more debug
+
+2011-06-13 11:51:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.h:
+         bufferpool: small indentation fix
+
+2011-06-13 11:50:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: pass the allocator as const
+
+2011-06-13 10:19:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: negotiate allocation
+         Add vmethod to configure allocation methods.
+         Remove some unused variables
+
+2011-06-11 20:45:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+         query: add some more checks
+         Make sure that the alignment is valid.
+         When we have a 0 size (variable buffer size), we can't have a bufferpool.
+
+2011-06-11 19:54:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+         query: set all default values
+         Fill all query values with good defaults.
+
+2011-06-11 18:52:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * libs/gst/base/gstbasetransform.c:
+         bufferpool: remove postfix parameter
+         Remove the postfix parameter, it's not used and can be done differently.
+
+2011-06-10 17:50:27 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: use same alignment values as GstMemory
+         Use the same alignment values for the bufferpool as we use for the GstMemory
+         API.
+
+2011-06-10 17:32:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: use new _check_reconfigure() method
+
+2011-06-10 17:32:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: add _check_reconfigure() method
+         Add a method to check and clear the RECONFIGURE flag on a pad.
+
+2011-06-10 16:47:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: add support for buffer in memory
+         Fix the code to support allocating the buffer and memory in one memory block.
+         Add an extra variable to store the memory of the buffer.
+         This code is disabled still because of complications.
+
+2011-06-10 16:46:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: expose default alignment
+         Export the gst_memory_alignment variable so that others can know the default
+         configured alignment of the system.
+
+2011-06-10 16:19:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+         memory: fix is_span
+         Subtract the offset of the parent from is_span.
+
+2011-06-10 13:59:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * configure.ac:
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+         memory: respect configured alignment
+         Move the alignment from GstBuffer to GstMemory.
+         make sure memory is at least aligned to the configured values.
+
+2011-06-10 13:40:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstcompat.h:
+       * gst/gstvalue.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/dataprotocol/dataprotocol.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstqueue2.c:
+         buffer: make new _buffer_allocate method
+         Make a new method to allocate a buffer + memory that takes the allocator and the
+         alignment as parameters. Provide a macro for the old method but prefer to use
+         the new method to encourage plugins to negotiate the allocator properly.
+
+2011-06-10 12:44:40 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/base/gstbasesrc.c:
+       * win32/common/libgstbase.def:
+         docs: update for gst_base_src_set_dynamic_size
+         Add to sections file and add Since: marker. Also update
+         win32 .def file.
+         API: gst_base_src_set_dynamic_size()
+
+2011-06-10 13:44:19 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * docs/design/Makefile.am:
+         design: part-bufferlist.txt was merged into another doc
+
+2011-06-10 13:34:59 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * docs/libs/gstreamer-libs-sections.txt:
+         docs: Update sections files for added/removed symbols
+
+2011-06-10 13:10:42 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * win32/common/libgstbase.def:
+       * win32/common/libgstreamer.def:
+         win32: Update for added/removed symbols
+
+2011-06-10 13:04:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * plugins/elements/gstfilesrc.c:
+         basesrc: add fill vmethod to basesrc
+         Add a new fill virtual method to basesrc. The purpose of this method is to fill
+         a provided buffer with data.
+         Add a default implementation of the create method that allocates a buffer and
+         calls the fill method on it. This would allow the base class to implement
+         bufferpool and allocator negotiation on behalf of the subclasses.
+         Fix the blocksize property.
+         Make filesrc use the new fill method.
+
+2011-06-10 12:09:49 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstelementfactory.c
+         gst/gstelementfactory.h
+         gst/gstpad.h
+         gst/gstpluginfeature.c
+         gst/gstpluginfeature.h
+
+2011-06-10 11:55:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * tests/check/elements/fakesink.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstpad.c:
+         event: add reset_time boolean to flush_stop event
+         Add a boolean to the flush_stop event to make it possible to implement flushes
+         that don't reset_time.
+         Make basesink post async_done with the reset_time property from the flush stop
+         event.
+         Fix some unit tests
+
+2011-06-09 17:13:35 +0100  Javier Jardón <jjardon@gnome.org>
+
+       * gst/gstelement.h:
+       * gst/gstelementfactory.c:
+       * gst/gstelementfactory.h:
+       * gst/gstformat.h:
+       * gst/gstinfo.c:
+       * gst/gstinfo.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstplugin.c:
+       * gst/gstplugin.h:
+       * gst/gstpluginfeature.c:
+       * gst/gstpluginfeature.h:
+       * gst/gstquery.h:
+       * gst/gststructure.h:
+       * gst/gsttaglist.c:
+       * gst/gsttaglist.h:
+       * gst/gsttagsetter.c:
+       * gst/gsttagsetter.h:
+       * gst/gsttrace.h:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * gst/gstvalue.h:
+         Use "const" instead G_CONST_RETURN
+         G_CONST_RETURN will be deprecated soon.
+         https://bugzilla.gnome.org/show_bug.cgi?id=652211
+
+2011-06-09 13:37:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: use new event methods to replace events
+         Using the new event methods, we can atomically transfer the event from the
+         pending list to the active list.
+
+2011-06-09 13:36:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.h:
+         event: make macros for new miniobject methods
+
+2011-06-09 13:35:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+         miniobject: add new methods to manage miniobject pointers
+         Add a new method to steal the miniobject stored at a location.
+         Add a new method to store a miniobject in a location and taking ownership
+         of the miniobject.
+
+2011-06-09 13:34:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.h:
+         pad: fix header
+
+2011-06-09 12:31:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.h:
+         pad: fix spurious include
+
+2011-06-09 12:01:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         libs/gst/base/gstbasesrc.c
+
+2011-06-09 11:39:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gsttee.c:
+         pad: forward events by default
+         Always forward all events in the default handler. Previously it used to not
+         forward caps events by default. It makes more sense to forward the caps events,
+         if the element is interested in the caps, it will implement an event handler to
+         retrieve the caps and then it can decide to forward or not. If the element has
+         no event handler, it probably just doesn't care about caps and it probably is
+         also not going to modify the data in a way that needs a caps change.
+
+2011-06-09 11:13:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: fix typo in docs
+
+2011-06-08 18:22:36 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesrc.c:
+         filesrc/fdsrc: indicate dynamic size handling to basesrc
+
+2011-06-08 18:22:03 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+         basesrc: add dynamic size handling
+         This allows subclass to indicate that size reported by src may not be static
+         and should as such be updated regularly, rather than only when really
+         needed.
+         Particular examples are filesrc or fdsrc reading from a file that is still
+         growing (e.g. being downloaded).
+         Fixes #652037.
+
+2011-06-08 20:14:16 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         Revert "basesrc: Send an update NEWSEGMENT event downstream if the duration changes"
+         This reverts commit 934faf163caf10ed3d54d81fd7b793069913dffd.
+         Original commit leads to possibly sending newsegment event downstream
+         in pull mode.  In push mode, quite some downstream elements
+         are likely to only expect newsegment event following a seek they performed
+         and as such may have their state messed up.
+
+2011-06-08 18:35:16 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+         basesink: inline the clip segment
+
+2011-06-08 17:25:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstpipeline.c:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         message: rename variable
+         Rename the new_base_time variable to reset_time, which looks better.
+
+2011-06-08 16:41:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstsegment.h:
+         segment: separate the seek and segment flags
+         Separate the seek flags and segment flags as separate enums because we might
+         want to have different flags for both.
+
+2011-06-08 13:40:32 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstpipeline.c:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * libs/gst/base/gstbasesink.c:
+         message: move the new_base_time flag to async_done
+         Move the flag to indicate that a new_base_time should be distributed to the
+         pipeline, from the async_start to the async_done message. This would allow us to
+         decide when to reset the pipeline time based on other reasons than the
+         FLUSH_START event.
+         The main goal eventually is to make the FLUSH events not reset time at all but
+         reset the time based on the first buffer or segment that prerolls the pipeline
+         again.
+
+2011-06-08 13:39:19 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+         docs: Update gstreamer-sections for new/removed API
+
+2011-06-08 13:30:49 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         gstbuffer: Remove deprecated GST_BUFFER_* macros
+         data, size, mallocdata and free_func no longer exist.
+
+2011-06-08 13:06:17 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Update for added/removed symbols
+
+2011-06-08 12:58:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: remove setcaps function
+         Remove the setcaps function, elements should use the caps event to be informed
+         of the format.
+
+2011-06-08 12:04:49 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-memory.txt:
+       * gst/gstmemory.c:
+       * tests/check/gst/gstmeta.c:
+         memory: Require implementation to implement _share
+         Require the memory implementations to implement a share operation. This allows
+         us to remove the fallback share implementation which uses a different allocator
+         implementation and complicates things too much.
+         Update design doc a bit.
+
+2011-06-08 11:03:50 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstquery.c:
+         memory: cleanups and improve docs
+         Make the fallback copy use the same memory allocator as the original object.
+         Improve some docs.
+         Require an alloc function when registering an allocator.
+         Remove gst_memory_allocator_get_default() and merge the feature in
+         gst_memory_allocator_find()
+         Fix locks on the hashtable.
+         Remove defined but not-implemented gst_memory_span() method.
+
+2011-06-07 18:18:27 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-memory.txt:
+         docs: add beginnings of memory design doc
+
+2011-06-07 17:54:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: pass user_data to the alloc function
+         Pass the user data that was passed to _register to the alloc function of an
+         allocator.
+
+2011-06-07 17:34:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.h:
+         memory: fix some typos
+
+2011-06-07 17:03:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstfilesrc.h:
+         filesrc: remove MMAP code
+         Remove the mmap code, it was disabled and probably needs a complete rewrite
+         anyway if this is to be ported to 0.11.
+
+2011-06-07 16:35:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+         query: add methods to query allocators
+         Add API to add and query allocator implementations to/from the ALLOCATION query.
+
+2011-06-07 16:14:50 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbufferpool.c:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: use allocators to allocate memory
+         Rename the GstMemoryImpl to GstMemoryAllocator because that's really what it is.
+         Add an alloc vmethod to the allocator members.
+         Improve registration of allocators.
+         Add methods to get and set the default allocator
+         Always use an allocator to allocate memory, use the default allocator when NULL
+         is passed.
+         Add user_data to the allocator Info so that we can pass extra info to the
+         allocator new method.
+
+2011-06-07 13:03:29 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/design/part-meta.txt:
+       * docs/design/part-negotiation.txt:
+         docs: minor fix and clarification
+
+2011-06-07 13:38:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.h:
+         event: move some more defines on top
+
+2011-06-07 13:25:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.h:
+       * gst/gstelementfactory.h:
+       * gst/gstevent.h:
+       * gst/gstmessage.h:
+       * gst/gstpad.h:
+       * gst/gstpadtemplate.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         fix some circular includes
+         typedef some structs before including other files to avoid circular dependencies
+         in the header files.
+
+2011-06-07 11:01:36 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Update for added/removed symbols
+
+2011-06-06 12:23:04 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * tests/check/elements/tee.c:
+         check/tee: Pads need to be activated before caps are set
+         Also add debugging to figure out what's going on
+
+2011-06-07 10:52:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         utils: remove proxy_setcaps
+         Remove proxy_setcaps, elements should use the caps event and forward caps
+         themselves.
+
+2011-06-07 10:51:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstoutputselector.c:
+         outputselector: fix refcounting of events
+         _pad_event_forward() takes ownership of the caps.
+
+2011-06-07 10:49:34 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Improve pad event forward code
+         Return TRUE when the pad has no parent or when there are no internally linked
+         pads.
+
+2011-06-07 10:04:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gsttee.c:
+         plugins: use the caps event
+         Use the caps event and avoid using the setcaps function. Use some of the new pad
+         forward functions to implement desired behaviour.
+
+2011-06-07 10:02:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Rename and rework the dispatcher function
+         Rename gst_pad_dispatcher() to gst_pad_forward() and make it more useful by
+         iterating the internal links of a pad and handling resync properly.
+         Add a method gst_pad_event_forward() that unconditionally forwards an event to
+         all internally linked pads.
+         Update some pad code to use the new forward function.
+
+2011-06-07 09:43:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstdebugutils.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/check/gstcheck.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tools/gst-inspect.c:
+         caps: use the caps event
+         Use the caps event instead of gst_pad_set_caps() and the setcaps function
+
+2011-06-06 16:11:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-TODO.txt:
+       * docs/design/part-block.txt:
+       * docs/design/part-buffer.txt:
+       * docs/design/part-bufferlist.txt:
+       * docs/design/part-caps.txt:
+       * docs/design/part-element-transform.txt:
+       * docs/design/part-events.txt:
+       * docs/design/part-gstelement.txt:
+       * docs/design/part-gstobject.txt:
+       * docs/design/part-latency.txt:
+       * docs/design/part-messages.txt:
+       * docs/design/part-meta.txt:
+       * docs/design/part-negotiation.txt:
+       * docs/design/part-overview.txt:
+       * docs/design/part-probes.txt:
+       * docs/design/part-seeking.txt:
+       * docs/design/part-segments.txt:
+       * docs/design/part-sparsestreams.txt:
+       * docs/design/part-streams.txt:
+       * docs/design/part-synchronisation.txt:
+       * docs/design/part-trickmodes.txt:
+         docs: go over design docs and fix things
+         Remove bufferlist part, it's merged with part-buffer.txt
+
+2011-06-06 11:21:23 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: Add enum/flags (de)registration in gst_(de)init
+
+2011-06-06 11:20:29 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Don't accept segments after EOS
+         And refactor the code slightly to avoid code duplication.
+         This solves a regression introduced by bdbc0693
+
+2011-06-06 10:27:57 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * tests/check/gst/gstghostpad.c:
+         check/ghostpad: Activate pads before checking for caps forwarding/setting
+         This is now done via in-band events, so the pads need to be active
+
+2011-06-05 18:11:22 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * docs/libs/gstreamer-libs-sections.txt:
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstbuffer.h:
+       * gst/gstbufferpool.h:
+       * gst/gstelement.h:
+       * gst/gstevent.h:
+       * gst/gstiterator.c:
+       * gst/gstmemory.h:
+       * gst/gstmessage.h:
+       * gst/gstminiobject.h:
+       * gst/gstobject.h:
+       * gst/gstpad.h:
+       * gst/gstquery.h:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstpushsrc.c:
+         docs: update for API changes
+         Also remove GST_PAD_CHECKGETRANGEFUNC macro
+
+2011-06-05 15:46:54 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-06-04 15:42:13 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/parse/Makefile.am:
+         parse: add prototypes for unused functions to avoid compiler warning
+         The warning is never fatal, because we don't use -Werror for the
+         parser helper library build, but the warnings are annoying anyway.
+
+2011-06-05 14:10:50 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tools/Makefile.am:
+       * tools/gst-run.c:
+         tools: remove unversioned gst-launch, gst-inspect and gst-typefind
+         The unversioned tool wrappers are confusing and annoying for packagers,
+         users and developers alike. A gst-launch pipeline that works in 0.10
+         will likely not work in 0.11 (e.g. because elements or properties get
+         renamed, or syntax changes). The unversioned tools also yield useless
+         results when used with gdb or valgrind. Packagers need to co-ordinate
+         the packaging of all major versions to make sure there are no conflicts
+         when both try to install the same files. When two major versions are
+         in use (e.g. 0.10 and 0.11/1.0), it may be unclear (when looking at
+         things on IRC/pastebin/mailing list etc.) which version is actually
+         being used when there are unversioned wrappers. For all these reasons,
+         it seems best to just remove them for now.
+
+2011-06-04 16:04:35 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * win32/common/config.h:
+       * win32/common/gstenumtypes.c:
+       * win32/common/gstenumtypes.h:
+       * win32/common/gstmarshal.c:
+       * win32/common/gstmarshal.h:
+       * win32/common/gstversion.h:
+       * win32/common/libgstreamer.def:
+         win32: update exports and other things
+
+2011-06-04 15:44:39 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * po/af.po:
+       * po/az.po:
+       * po/be.po:
+       * po/bg.po:
+       * po/ca.po:
+       * po/cs.po:
+       * po/da.po:
+       * po/de.po:
+       * po/el.po:
+       * po/en_GB.po:
+       * po/es.po:
+       * po/eu.po:
+       * po/fi.po:
+       * po/fr.po:
+       * po/gl.po:
+       * po/hu.po:
+       * po/id.po:
+       * po/it.po:
+       * po/ja.po:
+       * po/lt.po:
+       * po/nb.po:
+       * po/nl.po:
+       * po/pl.po:
+       * po/pt_BR.po:
+       * po/ro.po:
+       * po/ru.po:
+       * po/rw.po:
+       * po/sk.po:
+       * po/sl.po:
+       * po/sq.po:
+       * po/sr.po:
+       * po/sv.po:
+       * po/tr.po:
+       * po/uk.po:
+       * po/vi.po:
+       * po/zh_CN.po:
+       * po/zh_TW.po:
+         po: update for new translatable string and removed strings
+
+2011-06-04 15:23:56 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gst_private.h:
+       * gst/gstinfo.c:
+         info: remove GST_XML debug category as well
+
+2011-06-04 15:22:06 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * Android.mk:
+       * Makefile.am:
+       * configure.ac:
+       * docs/design/part-TODO.txt:
+       * docs/gst/gstreamer-sections.txt:
+       * gst/Makefile.am:
+       * gst/gstconfig.h.in:
+       * gst/parse/Makefile.am:
+       * gstreamer.spec.in:
+       * pkgconfig/gstreamer-uninstalled.pc.in:
+       * pkgconfig/gstreamer.pc.in:
+       * plugins/indexers/Makefile.am:
+       * plugins/indexers/gstindexers.c:
+       * plugins/indexers/gstindexers.h:
+       * tests/check/Makefile.am:
+       * tests/check/gst/.gitignore:
+       * tests/check/gst/gstxml.c:
+       * tests/check/gst/struct_arm.h:
+       * tests/check/gst/struct_hppa.h:
+       * tests/check/gst/struct_i386.h:
+       * tests/check/gst/struct_ppc32.h:
+       * tests/check/gst/struct_ppc64.h:
+       * tests/check/gst/struct_sparc.h:
+       * tests/check/gst/struct_x86_64.h:
+       * tests/examples/manual/Makefile.am:
+       * tools/.gitignore:
+       * tools/Makefile.am:
+       * tools/gst-launch.1.in:
+       * tools/gst-xmllaunch.1.in:
+         Remove everything libxml2- and loadsave-related
+
+2011-06-04 14:41:16 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tools/gst-launch.1.in:
+       * tools/gst-launch.c:
+         tools: remove SIGUSR* handling from gst-launch
+         Remove SIGUSR* handling from gst-launch, since it might interfere
+         with other things (e.g. libleaks), and should be done differently
+         anyway (either via support for simple timed-commands scripting or
+         remote control via DBus or so).
+
+2011-06-04 14:28:08 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gstreamer.spec.in:
+       * tools/.gitignore:
+       * tools/BUGS:
+       * tools/Makefile.am:
+       * tools/README:
+       * tools/gst-xmlinspect.1.in:
+       * tools/gst-xmlinspect.c:
+       * tools/xml2text.xsl:
+         tools: remove gst-xmlinspect
+         People should just query the registry themselves or write a small
+         python script if they need this functionality (which is likely
+         less work than parsing the XML that this script outputs, and I'm
+         not aware of anything using the xml2text xsl either).
+
+2011-06-04 14:22:05 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/faq/using.xml:
+       * gstreamer.spec.in:
+       * tools/.gitignore:
+       * tools/Makefile.am:
+       * tools/gst-feedback-m.m:
+       * tools/gst-feedback.1.in:
+         tools: remove gst-feedback
+         It's not really that useful, and no one's been using it for years.
+
+2011-06-04 14:13:07 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tests/check/gst/gstpad.c:
+       * tools/gst-inspect.c:
+       * tools/gst-xmlinspect.c:
+         tools, tests: fix some unused-but-set-variable compiler warnings
+
+2011-06-04 14:02:23 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * po/af.po:
+       * po/az.po:
+       * po/be.po:
+       * po/bg.po:
+       * po/ca.po:
+       * po/cs.po:
+       * po/da.po:
+       * po/de.po:
+       * po/el.po:
+       * po/en_GB.po:
+       * po/es.po:
+       * po/eu.po:
+       * po/fi.po:
+       * po/fr.po:
+       * po/gl.po:
+       * po/hu.po:
+       * po/id.po:
+       * po/it.po:
+       * po/ja.po:
+       * po/lt.po:
+       * po/nb.po:
+       * po/nl.po:
+       * po/pl.po:
+       * po/pt_BR.po:
+       * po/ro.po:
+       * po/ru.po:
+       * po/rw.po:
+       * po/sk.po:
+       * po/sl.po:
+       * po/sq.po:
+       * po/sr.po:
+       * po/sv.po:
+       * po/tr.po:
+       * po/uk.po:
+       * po/vi.po:
+       * po/zh_CN.po:
+       * po/zh_TW.po:
+         po: update for new translatable string
+
+2011-06-04 00:30:15 -0700  David Schleef <ds@schleef.org>
+
+       * gst/glib-compat-private.h:
+       * gst/gstatomicqueue.c:
+       * gst/gstelementfactory.c:
+       * gst/gstpoll.c:
+       * gst/gstsystemclock.c:
+       * gst/gstutils.c:
+       * plugins/elements/gstmultiqueue.c:
+       * tests/benchmarks/gstclockstress.c:
+         Work around changes in g_atomic API
+         See #651514 for details.  It's apparently impossible to write code
+         that avoids both type punning warnings with old g_atomic headers and
+         assertions in the new.  Thus, macros and a version check.
+
+2011-06-03 18:10:24 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/gstpad.h:
+         gstpad: Small doc fixup
+
+2011-06-03 15:53:21 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Update .def for latest APi changes
+
+2011-06-03 17:24:45 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.h:
+         pad: clean up probe flags
+
+2011-06-03 17:24:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-probes.txt:
+         docs: first version of probes document
+
+2011-06-03 16:46:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: check flushing in pullrange too
+
+2011-06-03 13:56:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: cleanups
+         Use defines instead of hardcoded values for masks.
+
+2011-06-03 13:25:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gststructure.c:
+       * tests/check/gst/gststructure.c:
+         structure: fix some more 0.11 fixmes
+         don't allow spaces in structure names and fix unit tests.
+
+2011-06-03 12:43:32 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-allocation.txt:
+       * docs/design/draft-bufferpool.txt:
+       * docs/design/part-bufferpool.txt:
+         docs: update bufferpool design doc
+         Move the bufferpool design doc from draft to part and merge it with
+         the allocation draft.
+
+2011-06-03 12:40:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: make the default behaviour to wait
+         The most common case is to not specify any flags when doing the allocation. Make
+         the allocation from a pool with a maximum amount of buffers block by default for
+         this reason.
+
+2011-06-03 11:15:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting doc
+
+2011-06-02 19:24:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: use caps event instead of setcaps
+
+2011-06-02 19:23:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+         ghostpad: remove setcaps functions
+         Remove the setcaps functions, it is now handled with the caps event.
+
+2011-06-02 18:28:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: pass the right alignment
+
+2011-06-02 18:28:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+         memmory: small cleanup
+
+2011-06-02 18:13:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+         memory: fix alignment calculations
+         Fix the alignment calculation.
+         Improve documentation.
+
+2011-06-02 18:13:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         pool: debug the config
+
+2011-06-02 15:38:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstutils.h:
+         utils: remove some macros now in glib
+         We depend on the right glib now
+
+2011-06-02 15:38:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gststructure.c:
+         structure: fix a FIXME
+
+2011-06-02 15:38:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstutils.c:
+         utils: use g_printerr() as stated in the FIXME
+
+2011-06-02 15:37:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: small cleanups
+
+2011-06-02 14:09:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+         element: inline the recursice state lock
+
+2011-06-02 13:46:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: inline the recursive stream lock
+
+2011-06-02 13:35:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: remove unused fields and methods and signals
+
+2011-06-02 13:23:53 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: use new gst_value_fixate instead
+         Use the new gst_value_fixate() function instead of our own version.
+
+2011-06-02 13:21:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstvalue.c:
+       * gst/gstvalue.h:
+         value: add function to fixate a value
+         Add a function to fixate a GValue. This is the same function as is in GstPad.
+
+2011-06-02 13:18:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+         caps: remove some custom refcounting methods
+         Remove some custom made refcounting methods and use the miniobject ones instead.
+
+2011-06-02 12:40:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: optimize linking
+         Optimize linking by only releasing the pad locks when there are link functions
+         installed on the pads.
+         Add some G_LIKELY here and there.
+         Move error paths out of the main code flow.
+
+2011-06-02 12:39:34 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: remove deprecated have-data signal
+
+2011-06-02 11:21:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: add idle probe for pull method too
+
+2011-06-02 11:01:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: more cleanups
+         Use miniobject unref when we can
+         Reuse existing data type identifier instead of an extra boolean.
+
+2011-06-01 19:47:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         plugins/elements/gstoutputselector.c
+
+2011-06-01 19:27:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * tests/check/elements/selector.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/gst/gstutils.c:
+       * tests/check/libs/basesrc.c:
+       * tests/check/pipelines/queue-error.c:
+         pad: further improve probes and pad blocking
+         Keep track of installed number of probes to shortcut emission.
+         Allow NULL callbacks, this is useful for blocking probes.
+         Improve probe selection based on the mask, an empty mask for the data or the
+         scheduling flags equals that all probes match.
+         Add some more debug info.
+         Don't check the flushing flag in the probe callback handler, this needs to be
+         done before calling the handler.
+         Fix blocking probes.
+         Fix unit tests
+
+2011-05-31 19:16:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * libs/gst/check/gstbufferstraw.c:
+       * libs/gst/check/gstconsistencychecker.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/gst/gstpipeline.c:
+         pad: implement pad block with probes
+
+2011-05-30 19:03:38 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * libs/gst/check/gstbufferstraw.c:
+       * libs/gst/check/gstconsistencychecker.c:
+       * tests/check/elements/selector.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/gst/gstpipeline.c:
+       * tests/check/gst/gstutils.c:
+       * tests/check/libs/basesrc.c:
+       * tests/check/pipelines/queue-error.c:
+         utils: remove _full variants of probes
+         Remove the _full variants and add the destroy notify to the regular methods.
+
+2011-06-01 15:29:20 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * tests/check/gst/struct_arm.h:
+         check/abi: Ignore GstXML* on arm when not present
+
+2011-05-31 18:31:53 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Use local priv variable instead of trans->priv
+
+2011-05-31 18:30:50 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * gst/gstsegment.c:
+         gstsegment: Remove dead assignment
+         base is unconditionally written a couple of lines below
+
+2011-05-31 18:30:30 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * gst/gstbin.c:
+       * gst/gstbufferpool.c:
+       * gst/gstelement.c:
+       * libs/gst/base/gstbasesink.c:
+         gst: Remove obvious dead assignments
+
+2011-05-31 13:43:47 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * plugins/elements/gstoutputselector.c:
+         outputselector: Remove dead assignment
+
+2011-05-30 18:29:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+         pad: Rework pad blocking, another attempt
+         Make the PadBlock callback take a GstBlockType parameter to handle the different
+         kind of stages in the pad block. This provides for more backwards compatibility
+         in the pad block API.
+         Separate blocking and unblocking into different methods, only blocking can do a
+         callback, unblock is always immediately. Also removed synchronous blocking, it
+         can always be implemented with a callback.
+
+2011-05-30 13:40:04 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * tests/check/elements/fakesink.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+         Revert "pad: rework pad blocking, first part"
+         This reverts commit 415da89f3c9fe46fc3361236df9a3b76e607e138.
+         Conflicts:
+         gst/gstpad.c
+
+2011-05-30 12:27:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: improve debugging
+
+2011-05-30 11:33:57 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gststructure.c:
+       * gst/gstvalue.c:
+         value: Consider "1" and "{1}" as equal in gst_value_compare()
+         Previously this was only done in the is_subset() check but
+         having it only there brings us into definition-hell where
+         "1" and "{1}" are subset of each other but not equal.
+
+2011-05-30 07:44:50 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tools/gst-launch.c:
+         gst-launch: Don't access the GstMessage structure directly
+
+2011-05-30 07:41:13 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-30 07:36:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gststructure.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Fix subset check for equivalent lists and scalar values
+         For example "{ 1 }" and "1" are not strictly equal but
+         both are a subset of each other. Also add a unit test
+         for this.
+
+2011-05-29 19:28:34 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/faq/general.xml:
+         docs: fix bugzilla URL
+         htpp -> http
+         https://bugzilla.gnome.org/show_bug.cgi?id=651362
+
+2011-05-28 10:24:37 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelement.h:
+         docs: xrefs more api around GstStateChange and GstStateChangeReturn.
+
+2011-05-28 09:51:45 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstmessage.h:
+         docs: xref the async messages to GstStateChange
+
+2011-05-27 17:20:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * tests/check/elements/fakesink.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+         pad: rework pad blocking, first part
+         Make pad block call the callback as soon as the pad is not in use. This makes it
+         possible to make sure that when the callback is called, no activity is happening
+         on the pad and that no activity will ever happen until the pad is unblocked
+         again. This makes pad blocking work when there is no dataflow or after EOS and
+         greatly helps dynamic pipelines.
+         Move the probe handling right where we wait on the pad block. The two are
+         related but not the same and the probe can eventually influence the pad
+         blocking as we'll se later.
+         Fix up some broken unit tests or tests that fail with the new behaviour.
+
+2011-05-27 17:18:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+       * tests/check/libs/basesrc.c:
+         basesrc: remove deprecated clean shutdown method
+
+2011-05-27 14:00:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gsttee.c:
+         tee: deactivate the pad after removing it
+         When releasing the request pad, first remove it from the element and then
+         deactivate it. If we do it the other way around, a gst_pad_push on the element
+         might return wrong-state before we had a chance to detect the removed pad in the
+         chain function.
+
+2011-05-27 15:14:32 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tools/gst-launch.c:
+         tools: catch and print missing-plugin messages in gst-launch
+         So that users get some feedback if they're using a pipeline
+         like  src ! decodebin2 ! sink  and are missing an element.
+
+2011-05-27 14:02:03 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Fix for SEGMENT event API changes
+
+2011-05-27 13:58:26 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-27 13:55:31 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * win32/common/libgstreamer.def:
+         caps: Add gst_caps_is_subset_structure()
+         API: gst_caps_is_subset_structure()
+         This allows to check if a structure is a subset of given
+         caps without allocating a new caps instance for it.
+
+2011-05-27 13:47:11 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * win32/common/libgstreamer.def:
+         structure: Add gst_structure_is_subset()
+         API: gst_structure_is_subset()
+
+2011-05-27 13:38:51 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Optimize gst_caps_is_subset()
+         ..and as a result gst_caps_is_equal() and others.
+         This now only checks if for every subset structure there is
+         a superset structure in the superset caps. Previously we were
+         subtracting one from another, creating completely new caps
+         and then even simplified them.
+         The new implemention now is about 1.27 times faster and doesn't
+         break the -base unit tests are anything anymore.
+
+2011-05-27 13:37:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Fix subset check in gst_caps_merge()
+         Caps A are a subset of caps B even if caps B doesn't
+         have all fields of caps A.
+         Also add a unit test for this.
+
+2011-05-27 12:56:03 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         Revert "caps: Optimize gst_caps_is_subset()"
+         This reverts commit 32248a9b852bcb568a5b642299ecc8e5bf48ea13.
+         This breaks some tests in -base and the failures should
+         be fixed first.
+
+2011-05-27 12:45:59 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         caps: Optimize gst_caps_is_subset()
+         ..and as a result gst_caps_is_equal() and others.
+         This now only checks if for every subset structure there is
+         a superset structure in the superset caps. Previously we were
+         subtracting one from another, creating completely new caps
+         and then even simplified them.
+         The new implemention now is about 1.27 times faster.
+
+2011-05-27 11:45:16 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Drop sticky events pushed on flushing srcpads instead of activating them immediately
+
+2011-05-26 14:56:12 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Pass the complete caps to transform_caps
+         Instead of passing it structure by structure. This allows
+         better optimized transform_caps functions and allows better
+         transformation decisions.
+         See bug #619844.
+
+2011-05-27 09:05:46 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Send an update NEWSEGMENT event downstream if the duration changes
+         This allows streaming the complete file for files that have grown since
+         streaming started.
+         Fixes bug #647940.
+
+2011-05-26 19:45:14 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: refactor _push_event
+         Rework _push_event() a little so that it drops events on blocking pads.
+         Make sure that events are forwarded when we unblock.
+         Add counter on the pad to keep track of busy pads.
+
+2011-05-26 18:21:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: refactor pre and post chain code
+
+2011-05-26 17:50:15 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: keep counter for active pads
+         Keep a counter to mark the amount of threads currently pushing data on the pad.
+
+2011-05-26 17:39:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: refactor pre push code
+         Refactor the code that is executed as the first step of a push operation where
+         we check the probes and blocking and resolve the peer.
+
+2011-05-26 17:08:03 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst_private.h:
+       * gst/gstpad.c:
+       * gst/gstutils.c:
+         pad: remove pad cache
+         Remove the pad cache as this is going to be reworked for new pad blocking and
+         probes.
+
+2011-05-26 16:48:14 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: simplify handling of buffer lists
+         Implement a default buffer-list function in case the element doesn't implement
+         one.
+         Also pass buffer-lists to the have-data signal, this allows us to remove some
+         backward compatibility code.
+
+2011-05-26 16:15:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+         pad: remove old gst_pad_set_blocked methods
+
+2011-05-26 14:14:13 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstpushsrc.c:
+         pushsrc: Fix infinite recursion in pushsrc query handler
+
+2011-05-26 13:36:48 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-25 16:02:10 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gstchildproxy.c:
+       * gst/gststructure.c:
+       * gst/gsttaglist.c:
+         gst: we can now use GLib 2.24 API unconditionally
+
+2011-05-25 15:54:01 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+         configure: bump GLib requirement to >= 2.24
+         http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement
+
+2011-05-25 15:38:30 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/random/release:
+         docs: update release instructions for gnome change
+
+2011-05-25 13:40:30 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+
+       * gst/gstsystemclock.c:
+         systemclock: Placate gcc by defining EWOULDBLOCK to something
+
+2011-05-25 12:47:51 +0400  Руслан Ижбулатов <lrn1986@gmail.com>
+
+       * gst/gstpoll.c:
+         poll: Fix WAKE_EVENT() to behave posixly on Windows
+
+2011-05-24 20:28:18 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstregistrybinary.h:
+         registrybinary: small cleanups
+         Remove unneeded braces from string define. Small doc improvement.
+
+2011-05-24 20:27:02 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstpreset.c:
+         preset: use guint for the version number parts
+         Use unsigned integers for extra safety (like we do in plugin version parsing).
+
+2011-05-24 18:39:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst_private.h:
+       * gst/gstelement.c:
+         remove some more deprecated methods
+
+2011-05-24 18:29:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpadtemplate.h:
+         padtemplate: remove unused flag
+
+2011-05-24 18:17:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelementfactory.c:
+       * gst/gstindexfactory.c:
+       * gst/gstpluginfeature.c:
+       * gst/gstpluginfeature.h:
+       * gst/gstregistry.c:
+       * gst/gstregistrychunks.c:
+       * libs/gst/base/gsttypefindhelper.c:
+       * tests/check/gst/gstplugin.c:
+       * tools/gst-inspect.c:
+       * tools/gst-xmlinspect.c:
+         feature: use object name
+         Remove the name property from the plugin feature and port code to use the object
+         name instead.
+
+2011-05-24 18:16:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * configure.ac:
+       * gst/gstconfig.h.in:
+         remove old glib check
+
+2011-05-24 17:43:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-24 17:36:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstquery.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstpushsrc.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttee.c:
+       * plugins/elements/gsttypefindelement.c:
+         scheduling: port to new scheduling query
+
+2011-05-24 12:52:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-scheduling.txt:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+         query: add SCHEDULING query
+         Add a new query to replace the checkgetrange function.
+
+2011-05-24 19:43:58 +0530  Debarshi Ray <rishi@gnu.org>
+
+       * libs/gst/check/gstcheck.h:
+         check: add fail_unless_equals_int64
+         https://bugzilla.gnome.org/show_bug.cgi?id=650973
+
+2011-05-24 16:14:57 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstoutputselector.c:
+         outputselector: Forward sticky events to newly created srcpads
+
+2011-05-24 16:13:22 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gsttee.c:
+         tee: Forward sticky events to newly created srcpads
+
+2011-05-24 16:08:41 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Add gst_pad_sticky_events_iterate() function
+
+2011-05-24 13:27:09 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstdebugutils.c:
+         debugutils: Fix for GstIterator API changes
+
+2011-05-24 13:28:00 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstdebugutils.c:
+         Revert "debugutils: Fix for GstIterator API changes"
+         This reverts commit e1cc3176d6fb8023bbe0c733615b2a8c420a2077.
+         This is not the 0.11 branch...
+
+2011-05-24 13:27:09 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstdebugutils.c:
+         debugutils: Fix for GstIterator API changes
+
+2011-05-24 09:48:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstpad.h
+
+2011-05-24 00:26:40 +0300  Kipp Cannon <kcannon@cita.utoronto.ca>
+
+       * gst/gstclock.h:
+         clock: improve the GST_TIME_FORMAT/ARGS docs
+
+2011-05-23 23:40:20 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstpad.h:
+         docs: hide this from the docs
+
+2011-05-23 18:30:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+         event: use GST_SEGMENT_FORMAT for segments
+
+2011-05-23 18:15:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         transform: fixes for bufferpool handling
+         Don't error out when the allocation query returns success.
+         Do bufferpool query after we pushed the caps event downstream so that we can get
+         a good bufferpool suggestion.
+         Also proxy the bufferpool query downstream when we operate in in_place mode.
+
+2011-05-23 18:14:27 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: improve debugging
+
+2011-05-23 16:53:01 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         transform: reset reconfigure state
+         When we negotiate new caps, reset the reconfigure state.
+
+2011-05-20 18:56:37 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: WIP handle bufferpool
+
+2011-05-21 19:06:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: avoid calling _set_caps() on the srcpad
+         Avoid installing a setcaps function on the srcpad and calling the setcaps
+         function, we can do more efficiently with sending the event ourself and calling
+         our vmethod.
+
+2011-05-20 16:03:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstpad.h
+         gst/gstplugin.h
+
+2011-05-20 15:58:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: remove some more code
+         Remove some more unused code from basetransform.
+         Prepare for implementing bufferpools.
+
+2011-05-20 15:50:05 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * win32/common/libgstbase.def:
+         win32: add new api
+
+2011-05-20 15:48:09 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstpad.h:
+       * gst/gstplugin.h:
+         deprecation-guards: fixup for commit 9ff4ec3104d2510b8f379ff38c671682ff795e33
+         Remove the deprecation guards for GST_PLUGIN_DEFINE_STATIC again (even though it
+         is deprecated) as we use it in the tests. Remove "_" for intlinkfunc.
+
+2011-05-20 13:06:57 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-20 13:03:51 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: Only reinit the cached GstClockID if it is for the same clock
+         The clock might have changed since the clock ID was created and in
+         that case we have to request a new one.
+
+2011-05-20 12:43:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+         element: add method to get metadata
+         Add a method to get the metadata from a klass.
+
+2011-05-20 12:43:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelementfactory.h:
+         factory: fix typo
+
+2011-05-20 12:18:48 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Always send a SEGMENT event when the active pad changes
+
+2011-05-20 12:16:59 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Fix copy&paste mistake in the srcpad event function
+
+2011-05-20 12:07:45 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         docs/plugins/gstreamer-plugins.hierarchy
+
+2011-05-20 12:00:11 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: Send upstream events to all sinkpads, not only the selected one
+         This makes sure that SEEK events are sent to all upstream elements, which is
+         required if different streams are completely distinct pipeline parts. Also this
+         allows QoS to be done on deselected streams, flushes to be handled correctly,
+         etc.
+
+2011-05-20 11:36:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * tests/check/gst/gstpad.c:
+         pad: add pending event for sticky events
+         Change the sticky event array so that it contains a pending and an active event.
+         Events on the sinkpad are copied to the pending array and after the eventfunc
+         returned TRUE, moved to the active event. This allows us to queue new events
+         like when we do per-pad offsets without removing the currently active event.
+         Remove the active argument from the gst_pad_get_sticky_event() method, the
+         pending events are not something we want to expose.
+
+2011-05-20 00:39:10 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstpreset.c:
+       * gst/gstpreset.h:
+         preset: include cleanup
+         Only have include in the installed header we need to use it. Move the includes
+         needed by the implementation to the c file.
+
+2011-05-19 23:19:30 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/plugins/gstreamer-plugins.args:
+       * docs/plugins/gstreamer-plugins.hierarchy:
+       * docs/plugins/gstreamer-plugins.interfaces:
+         docs: update plugin introspection data
+         Now more files are merged and produced in a canonical fashion, which hopefully
+         creates less or no delta in the future.
+
+2011-05-19 22:56:28 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From 9e5bbd5 to 69b981f
+
+2011-05-19 19:07:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstpad.c:
+         tests: caps are not stored on flushing pads
+         Caps are now also stored on flushing pads in the inactive state.
+
+2011-05-19 19:01:09 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: apply pad offset on sinkpad events too
+         Apply the pad offset in the send_event() function as well.
+
+2011-05-19 18:27:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: add per-pad offsets
+         When linking pads and when copying a segment event from the sourc pad to the
+         sinkpad, apply the src and sinkpad offsets to the segment base. Make sure that
+         we only modify the event stored on the sinkpad and never the one on the source
+         pad.
+         When changing the pad offset, perform the segment copy with the updated offsets.
+         When pushing a segment event, apply the srcpad offset before sending the event
+         to the peer pad.
+         This part is missing the adjustment of the segment event on the sinkpad, which
+         is for a later patch.
+
+2011-05-19 16:26:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: add methods to adjust the offset
+         Add methods to adjust the offset. This will be used to change the segment events
+         with an offset so that we can tweak the timing of the stream on a per-pad base.
+
+2011-05-19 12:11:43 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstinputselector.h:
+         inputselector: Port to the new segment API
+         The switch action signal with the stop and start running times
+         is not necessary anymore. Closing of segments is not necessary
+         and adjusting the start running time of a segment can later be
+         done with new GstPad API.
+
+2011-05-19 11:30:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstghostpad.h
+
+2011-05-18 19:43:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: store sticky events on flushing sinkpads too
+         First store the sticky event on the sinkpad in the inactive state, then check
+         for the flushing flag. We want to have the events on sinkpads at all times,
+         ready to be activated when the pad becomes active.
+
+2011-05-18 18:53:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: move caps check to central location
+         Make a function to call the eventfunc and perform a caps check when we are
+         dispatching a caps event.
+         This makes sure that all code paths correctly check that the caps are
+         acceptable before sending the caps to the eventfunction.
+
+2011-05-18 18:52:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: avoid calling setcaps too many times
+         Don't call setcaps, the caps event will take care of propagating the caps on all
+         pads.
+
+2011-05-18 18:48:03 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+         query: add allocation query name
+         Add ALLOCATION query name and guard some functions against invalid queries.
+
+2011-05-18 16:56:13 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstcollectpads.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/libs/basesrc.c:
+       * win32/common/libgstbase.def:
+       * win32/common/libgstreamer.def:
+         event: Make SEGMENT event parsing API more consistent with the others
+
+2011-05-18 16:47:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: relax caps check
+         Also run the caps transform function on ANY caps, like we used to do before.
+         This makes sure that capsfilter has a chance to filter ANY caps as well.
+
+2011-05-18 16:29:10 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Don't forget to take the object lock when getting a sticky event
+
+2011-05-18 16:26:31 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Add function to get sticky events from a pad
+         API: gst_pad_get_sticky_event()
+
+2011-05-18 15:43:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * tests/check/gst/gstevent.c:
+         event: fix event copy
+         Fix parent refcount on event copy.
+         Fix unit test.
+
+2011-05-18 15:29:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: notify caps property change in callsetcaps
+         Notify the caps property change in the backwards compatible function to call the
+         setcaps function.
+
+2011-05-18 16:09:19 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From fd35073 to 9e5bbd5
+
+2011-05-18 15:04:48 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/gst/gstreamer-sections.txt:
+         docs: remove GstProxyPad from private section
+
+2011-05-18 15:02:02 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstghostpad.h:
+       * gst/gstminiobject.c:
+         docs: use the same name for the argument in prototype and docs
+
+2011-05-18 14:59:45 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/examples/manual/Makefile.am:
+         manual: put generated sources to BUILT_SOURCES and clean them on make clean
+
+2011-05-18 13:19:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-18 13:14:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstminiobject.c
+         gst/gstpad.c
+         gst/gstpad.h
+         gst/gstplugin.h
+         libs/gst/base/gstbaseparse.c
+
+2011-05-18 14:10:12 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/examples/manual/Makefile.am:
+         manual: reinsert missing space to fix previous commit
+
+2011-05-18 13:54:42 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/examples/manual/Makefile.am:
+         manual: simplify the snipet extraction rules
+         Use $< instead of repeating the name of the dependency.
+
+2011-05-18 10:59:38 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/examples/manual/Makefile.am:
+         manual: don't extract the xml example anymore, its gone
+         As a followup for commit cda5a353d27326c0272a79c92c11c221a4092da4 don't try
+         extracting an example that has been removed.
+
+2011-05-18 12:23:39 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From 46dfcea to fd35073
+
+2011-05-18 11:21:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-events.txt:
+         docs: update docs some more
+
+2011-05-18 11:08:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-events.txt:
+       * gst/gstpad.c:
+       * tests/check/gst/gstpad.c:
+         pad: rework sticky events a little
+         Update the design docs with some clear rules for how sticky events are
+         handled.
+         Reimplement the sticky tags, use a small structure to hold the event and its
+         current state (active or inactive).
+         Events on sinkpads only become active when the event function returned success
+         for the event.
+         When linking, only update events that are different.
+         Avoid making a copy of the event array, use the object lock to protect the event
+         array and release it only to call the event function. This will need to check
+         if something changed, later.
+         Disable a test in the unit test, it can't work yet.
+
+2011-05-17 22:17:14 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: maintain frame state during frame parsing round
+         See #650093.
+
+2011-05-12 11:55:20 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbaseparse.h:
+         baseparse: provide latency query support
+
+2011-05-17 22:15:38 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: make minimum frame size handling more efficient and convenient
+         While some formats allow subclass to determine a specific subsequent
+         needed frame size, others may to need to scan for markers and can only
+         request 'additional data' by whatever reasonable available step.
+         In push mode, trying to minimize additional latency leads to step size
+         being the next input buffer.  In pull mode, any reasonable step size
+         (such as already used by buffer caching) can be applied.
+
+2011-05-17 22:38:14 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: set correct buffer size
+
+2011-05-06 10:54:08 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * tools/gst-inspect.c:
+         inspect: show flags the same way they need to be entered
+         The (de)serialisation uses "+" and not " | ".
+
+2011-04-28 11:34:39 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstpluginfeature.c:
+       * gst/gstpluginfeature.h:
+       * gst/gstregistry.c:
+       * gst/gstregistrychunks.c:
+         pluginfeature: avoid duplicating feature->name
+         The feature name is not supposed to change over time anyway. In order to enforce
+         this parentize features to the registry and make the feature->name pointing to
+         GstObject:name. In 0.11 we could consider of removing the feature->name variable
+         (FIXME comment added).
+         Fixes: #459466
+
+2011-05-02 15:36:14 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gst_private.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstplugin.h:
+         docs: add deprecation guards
+         Move GstPadIntLinkFunction to private header to avoid a dozen #ifdefs. Use a
+         gpointer in public header instead.
+
+2011-05-17 19:03:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: don't push sticky events on flush
+         Only allow serialized and non-flush events forward the sticky events.
+
+2011-05-17 18:23:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstghostpad.c:
+         test: reset pad caps properly
+
+2011-05-17 18:23:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: add more debug
+
+2011-05-17 18:21:38 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: remove unused code
+         The code to make sure that caps are properly set on both pads, it now happens
+         automatically with the caps event.
+
+2011-05-17 17:53:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstsegment.c:
+         tests: fix tests
+         Remove the tests that handle incompatible formats, we don't want that anymore.
+
+2011-05-17 17:51:58 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstsegment.c:
+         segment: handle wraparound better
+         Now that we use unsigned values for the segment, handle wraparound when seeking
+         better.
+
+2011-05-17 16:50:53 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstpad.c:
+         pad: remove unref, the object is NULL
+
+2011-05-17 14:01:05 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+         event: The RECONFIGURE element only exists in 0.11
+         Implementing it properly in 0.10 seems to be impossible.
+
+2011-05-17 13:13:11 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/elements/selector.c:
+       * tests/check/elements/valve.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstpad.c:
+         tests: Update for caps/pad template related API changes
+
+2011-05-17 12:25:22 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+         base: Update for caps/pad template related API changes
+
+2011-05-17 12:04:27 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstutils.c:
+         gst: Update for caps/pad template related API changes
+
+2011-05-17 12:12:23 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstelement.c:
+         element: Consider GstPadTemplate as immutable
+         Don't copy the templates when creating subclasses but only increase
+         their refcount.
+
+2011-05-17 12:10:27 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstelement.c:
+       * gst/gstpadtemplate.c:
+         padtemplate: Create pad templates with floating refs
+         And take ownership of the floating ref in gst_element_add_pad_template()
+
+2011-05-17 12:07:03 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstpadtemplate.c:
+         padtemplate: Improve reference handling of the template's caps
+         gst_pad_template_new() does not take ownership of the caps anymore.
+
+2011-05-16 13:39:25 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+         miniobject: delay private data initialisation until actually needed
+         We only use the private instance data for weak references for now,
+         so can delay initialisation until actually needed (microoptimisation)
+
+2011-05-17 11:59:00 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstpadtemplate.c:
+         pad: Let template related functions return new references
+         gst_pad_template_get_caps(), gst_pad_get_pad_template_caps()
+         and gst_pad_get_pad_template() return a new reference of the
+         caps or template now and the return value needs to be
+         unreffed after usage.
+
+2011-05-17 11:45:46 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * tests/check/gst/gstevent.c:
+         Revert "event: example of how to optimize events"
+         This reverts commit fa28e2c5e6e5e172be308c0c50f44ed6f39e1a71.
+         The optimization only has minimal impact on the performance and
+         makes everything more complex.
+
+2011-05-17 11:45:42 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstevent.c:
+         Revert "event: update the structure when needed"
+         This reverts commit 905100cdbe580d4d182bfd9d5ec9b368a110f464.
+
+2011-05-17 11:22:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gststructure.c:
+         structure: Fix compilation
+
+2011-05-17 11:20:05 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/elements/fdsrc.c:
+       * tests/check/elements/filesrc.c:
+       * tests/check/gst/gstquery.c:
+         Revert "query: allow _make_writable on query handlers"
+         This reverts commit cf4fbc005c5c530c2a509a943a05b91d6c9af3fb.
+         This change did not improve the situation for bindings because
+         queries are usually created, then directly passed to a function
+         and not stored elsewhere, and the writability problem with
+         miniobjects usually happens with buffers or caps instead.
+
+2011-05-17 11:19:16 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         Revert "bin: Dereference GstQuery** before passing it to GST_QUERY_TYPE_NAME"
+         This reverts commit 437c92b403e0c7da9b9d4509ef4ffbd05710df2b.
+
+2011-05-17 11:19:14 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+         Revert "ghostpad: fix g_return_* with new query"
+         This reverts commit 877c1c28ff957ca92911eadfc785f8661d9e0127.
+
+2011-05-17 09:40:38 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         win32/common/libgstreamer.def
+
+2011-05-17 09:35:54 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+         structure: Make both parameters to gst_structure_is_equal() const
+
+2011-05-17 09:33:47 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gststructure.c:
+         structure: Update Since markers to the correct version
+
+2011-05-17 09:33:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * win32/common/libgstreamer.def:
+         structure: Add gst_structure_intersect()
+         API: gst_structure_intersect()
+
+2010-09-10 18:33:34 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * win32/common/libgstreamer.def:
+         gststructure: Add gst_structure_can_intersect API
+         Allows checking if two structures can intersect without having to
+         go through GstCaps
+         API: gst_structure_can_intersect
+         https://bugzilla.gnome.org/show_bug.cgi?id=629300
+
+2010-09-10 18:14:05 +0200  Edward Hervey <bilboed@bilboed.com>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+       * win32/common/libgstreamer.def:
+         gstructure: New API: gst_structure_is_equal
+         Allows checking equality of GstStructure without having to create
+         intermediary GstCaps.
+         API: gst_structure_is_equal
+         https://bugzilla.gnome.org/show_bug.cgi?id=629300
+
+2011-05-16 19:09:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstutils.c:
+         tests: set elements in PAUSED
+         Set elements in PAUSED before trying to set caps on pads.
+
+2011-05-16 19:05:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstghostpad.c:
+         test: fix ghostpad test
+         We need to have activated pads before we can pass around caps.
+         Don't set NULL caps on pads.
+
+2011-05-16 19:04:35 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: avoid setting NULL caps on pads
+
+2011-05-16 18:48:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: fix buffer refcounting
+         When we fail to allocate an output buffer, set the buffer pointer to NULL or
+         else the calling function will try to unref it.
+         Remove some old comments
+
+2011-05-16 18:29:29 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstcapsfilter.c:
+         capsfilter: allow NULL filters and fix refcounting
+
+2011-05-16 18:12:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         caps: only add the structure when we could set the parent
+
+2011-05-16 17:53:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: fix g_return_* with new query
+
+2011-05-16 17:24:11 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Update list of exported symbols
+
+2011-05-16 16:59:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+         inputselector: handle more formats
+         Use the segment format instead of a hardcoded _TIME.
+
+2011-05-16 16:57:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: handle more formats
+         Don't hardcode GST_FORMAT_TIME in places, we can work with many formats.
+
+2011-05-16 16:54:02 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch '0.11' of ssh://git.freedesktop.org/git/gstreamer/gstreamer into 0.11
+
+2011-05-16 16:53:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         configure.ac
+         docs/gst/gstreamer-sections.txt
+         gst/gstbin.c
+         gst/gstelement.c
+         gst/gstelement.h
+         gst/gstghostpad.c
+         gst/gstminiobject.c
+         gst/gstminiobject.h
+         libs/gst/base/gstbasesrc.c
+         libs/gst/base/gstbasetransform.c
+         plugins/elements/gstinputselector.c
+         tests/check/gst/gstminiobject.c
+
+2011-05-16 16:10:49 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/manual/advanced-autoplugging.xml:
+       * docs/manual/highlevel-components.xml:
+         update manual code examples for new _get_caps()
+
+2011-05-13 08:34:33 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/elements/multiqueue.c:
+       * tests/check/elements/selector.c:
+       * tests/check/elements/valve.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/gst/gstutils.c:
+       * tests/check/libs/test_transform.c:
+       * tests/check/libs/transform1.c:
+         tests: Update for negotiation related API changes
+
+2011-05-11 15:38:09 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gstvalve.c:
+         elements: Update for negotiation related API changes
+         The filter caps are only forwarded and returned instead
+         of ANY caps in the core elements because they don't do
+         anything caps specific.
+
+2011-05-11 15:12:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+         base: Improve negotiation with new getcaps() filter
+
+2011-05-10 17:56:33 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         gst: Add a filter caps parameter to all get_caps() functions
+         This is used to pass the possible caps and preferences to
+         the pad and to allow better negotiation decisions.
+
+2011-04-19 20:05:07 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gstqueue2.h:
+         queue2: adjust input data rate estimation
+         ... being aware of possible initial higher burst rate.
+
+2011-05-13 18:07:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/plugins/gstreamer-plugins.args:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstinfo.c:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstsegment.c:
+       * gst/gstsegment.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+       * libs/gst/base/gstcollectpads.c:
+       * libs/gst/check/gstconsistencychecker.c:
+       * libs/gst/dataprotocol/dataprotocol.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * tests/check/elements/fakesink.c:
+       * tests/check/elements/filesink.c:
+       * tests/check/elements/multiqueue.c:
+       * tests/check/elements/queue.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstinfo.c:
+       * tests/check/gst/gstsegment.c:
+       * tests/check/libs/basesrc.c:
+         Rework GstSegment handling
+         Improve GstSegment, rename some fields. The idea is to have the GstSegment
+         structure represent the timing structure of the buffers as they are generated by
+         the source or demuxer element.
+         gst_segment_set_seek() -> gst_segment_do_seek()
+         Rename the NEWSEGMENT event to SEGMENT.
+         Make parsing of the SEGMENT event into a GstSegment structure.
+         Pass a GstSegment structure when making a new SEGMENT event. This allows us to
+         pass the timing info directly to the next element. No accumulation is needed in
+         the receiving element, all the info is inside the element.
+         Remove gst_segment_set_newsegment(): This function as used to accumulate
+         segments received from upstream, which is now not needed anymore because the
+         segment event contains the complete timing information.
+
+2011-05-16 10:25:10 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Re-implement notify::caps
+
+2011-05-14 14:02:06 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/plugins/gstreamer-plugins.args:
+       * gst/gstelement.h:
+       * gst/gstghostpad.c:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+         docs: fix up some Since markers and update for new multiqueue args
+
+2011-05-12 16:48:41 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: Don't interprete pipelines without sink elements as always being in EOS state
+         Some tests (e.g. elements/capsfilter) have pipelines with dangling
+         sinkpads and without a sink element. These pipelines can never post
+         an EOS message (because this is only valid by a sink) and as such
+         should never get an EOS message posted by the bin.
+
+2011-05-12 15:51:22 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstsystemclock.c:
+         systemclock: Only retry writing to the socket for EAGAIN, EWOULDBLOCK and EINTR
+         Fixes infinite loop in some cases, bug #650002.
+
+2011-05-12 09:59:20 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * win32/common/libgstreamer.def:
+         miniobject: Add new miniobject weak ref/unref functions to the docs
+
+2011-05-12 09:55:45 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+         miniobject: Minor cleanup of last commit
+
+2011-05-11 13:09:19 -0400  José Alburquerque <jaalburqu@svn.gnome.org>
+
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+       * tests/check/gst/gstminiobject.c:
+         miniobject: Add weak referencing functionality
+         API: gst_mini_object_weak_ref()
+         API: gst_mini_object_weak_unref()
+         Add weak referencing functionality to GstMiniObject, which
+         allows to get notifications when an mini object is destroyed
+         but doesn't increase the real refcount. This is mostly
+         useful for bindings.
+         Fixes bug #609473.
+
+2011-03-19 10:28:49 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstinputselector.h:
+         inputselector: Add sync mode that syncs inactive pads to the running time of the active pad
+         Fixes bug #645017.
+
+2011-03-22 13:19:47 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstmultiqueue.h:
+         multiqueue: Add mode to synchronize deactivated/not-linked streams by the running time
+         Fixes bug #645107, #600648.
+
+2011-04-18 14:26:33 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: Only post EOS messages after reaching the PLAYING state
+         Fixes bug #647756.
+
+2011-05-10 16:37:44 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gst_private.h:
+       * gst/gstbin.c:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+         element: Add GstElement::state_changed vfunc
+         API: GstElement::state_changed
+         This is always called when the state of an element has changed and
+         before the corresponding state-changed message is posted on the bus.
+
+2011-05-06 16:44:29 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+       * win32/common/libgstreamer.def:
+         ghostpad: Add docs for all the new, public functions
+
+2011-05-06 16:15:51 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: Add guards against invalid parameters to the new, public functions
+
+2011-05-06 16:00:22 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+       * win32/common/libgstreamer.def:
+         ghostpad: Rename ghostpad/proxypad default functions
+         API: gst_ghost_pad_activate_pull_default
+         API: gst_ghost_pad_activate_push_default
+         API: gst_ghost_pad_internal_activate_pull_default
+         API: gst_ghost_pad_internal_activate_push_default
+         API: gst_ghost_pad_link_default
+         API: gst_ghost_pad_setcaps_default
+         API: gst_ghost_pad_unlink_default
+         API: gst_proxy_pad_acceptcaps_default
+         API: gst_proxy_pad_bufferalloc_default
+         API: gst_proxy_pad_chain_default
+         API: gst_proxy_pad_chain_list_default
+         API: gst_proxy_pad_checkgetrange_default
+         API: gst_proxy_pad_event_default
+         API: gst_proxy_pad_fixatecaps_default
+         API: gst_proxy_pad_getcaps_default
+         API: gst_proxy_pad_getrange_default
+         API: gst_proxy_pad_iterate_internal_links_default
+         API: gst_proxy_pad_query_default
+         API: gst_proxy_pad_query_type_default
+         API: gst_proxy_pad_setcaps_default
+
+2011-05-06 15:50:20 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+         ghostpad: Make all the internal caps functions public
+         This is useful if ghostpad/proxypads should be used but
+         additional code should be executed, e.g. for tracking
+         segments in the event function.
+
+2011-05-06 15:25:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+         ghostpad: Only implement the iterate_internal_links function on proxypads
+         ghostpads inherit it from their parent class. Also make it threadsafe.
+
+2011-05-06 15:16:09 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstghostpad.c:
+       * gst/gstghostpad.h:
+       * tests/check/gst/gstghostpad.c:
+       * win32/common/libgstreamer.def:
+         ghostpad: API: Expose gst_proxy_pad_get_internal()
+         This allows to get the internal pad of ghostpads and
+         proxypads without using gst_pad_iterate_internal_links()
+         and is much more convenient.
+         The internal pad of a ghostpad is the pad of the opposite direction
+         that is used to link to the ghostpad target.
+
+2011-05-05 17:54:56 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: When trying to fixate the sink suggestion prefer its structure order
+
+2011-05-05 11:28:38 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Merge structures when intersecting instead of appending them
+         This prevents adding duplicates over and over again to the resulting
+         caps if they already describe the new intersection result.
+         While this changes intersection from O(n*m) to O(n^2*m), it results in
+         smaller caps, which in the end will decrease further processing times.
+         For example in an audioconvert ! audioconvert ! audioconvert pipeline,
+         when forwarding the downstream caps preference in basetransform
+         (see e26da72de25a91c3eaad9f7c8b2f53ba888a0394) this results in
+         16 instead of 191 caps structures.
+
+2011-05-04 11:29:15 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: In getcaps() prefer the caps order and caps of downstream if possible
+
+2011-05-03 17:26:53 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Prefer caps order given by the subclass of the template caps order
+
+2011-04-20 22:52:36 +0200  Miguel Angel Cabrera Moya <madmac2501@gmail.com>
+
+       * gst/parse/types.h:
+       * tests/check/pipelines/parse-launch.c:
+         parse: don't unescape inside quotes
+         Escaped characters inside quoted strings are supposed to be unescaped by
+         deserialization functions, not by parsing functions.
+         https://bugzilla.gnome.org/show_bug.cgi?id=648025
+
+2011-04-18 10:04:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Remove unnecessary FIXME
+         Resetting the result is not necessary when resyncing because
+         pads that previously got the event will be skipped and we
+         need to consider the results of the previous pushes.
+
+2011-04-18 09:53:55 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: If activating one pad failed error out early instead of trying to activate the next pads
+         If one pad fails to activate the complete activation process will fail
+         anyway and trying to activate the other pads only wastes time.
+
+2011-04-18 09:49:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: If activating one pad failed error out early instead of trying to activate the next pads
+         If one pad fails to activate the complete activation process will fail
+         anyway and trying to activate the other pads only wastes time.
+
+2011-05-14 09:31:33 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         Back to development
+
+=== release 0.10.34 ===
+
+2011-05-14 01:00:23 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * gstreamer.doap:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         Release 0.10.34
+
+2011-05-13 08:38:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/gst/gstmeta.c:
+         meta: Fix compilation of the unit test after removal of the serialize/deserialize functions
+
+2011-05-04 15:31:56 +0300  Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: do not set first buffer timestamp to 0 for live sources
+         Doing so avoids a large timestamp gap between first and second buffer
+         for live sources which take time to start up.
+         The first buffer now has a "live" timestamp based on the running time,
+         as other buffers do.
+         https://bugzilla.gnome.org/show_bug.cgi?id=649369
+
+2011-05-11 19:10:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+         meta: remove (de)serialize functions
+         Add a GType to the metadata to identify the GstMetaInfo.
+         We can remove the (de)serialize functions for the metadata because we can
+         register GTtype transform functions between various types to implement
+         serialization later.
+
+2011-05-11 18:17:45 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+       * gst/gststructure.c:
+       * gst/gststructure.h:
+         structure: more cleanups
+         gst_structure_get_type() -> _gst_structure_type to avoid method calls for
+         getting the GType that initialized at the start.
+         Hide some structure fields in private data so that we can change the
+         implementation.
+         Move structure equality check from caps.c to structure.c where it belongs.
+
+2011-05-11 18:07:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: remove obsolete code
+         Remove some obsolete code.
+         Don't try to reconfigure when we don't have sink caps.
+
+2011-05-11 16:46:49 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: Dereference GstQuery** before passing it to GST_QUERY_TYPE_NAME
+
+2011-05-11 16:03:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+         event: update the structure when needed
+         When we get the structure of an event, make sure it also contains the fields
+         that we keep in fast variables, this way we can easily serialize and debug
+         the events. We would probably later simply prefer to register a transform
+         function to G_TYPE_STRING and G_TYPE_BYTEARRAY etc..
+
+2011-05-11 16:01:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         caps: cleanups
+         We don't need to check if the type is 0, the init function is only called once
+         in the beginning.
+
+2011-05-11 12:04:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+         event: clean up some macros
+         Avoid executing a method for GST_TYPE_EVENT but instead use the type variable
+         directly. We can do this because we register it before anything else.
+
+2011-05-11 15:48:15 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbus.c:
+         bus: Fix GST_DEBUG parameters to be consistent with the format string
+
+2011-05-11 15:26:02 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Implement support for pad reconfiguration again
+
+2011-05-11 15:18:56 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstcapsfilter.c:
+         capsfilter: Fix deadlock, gst_pad_get_current_caps() already takes the pad's object lock
+
+2011-05-11 11:06:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * tests/check/gst/gstevent.c:
+         event: example of how to optimize events
+         Use a structure for the QoS event by 'extending' the GstEventImpl structure.
+         This should avoid allocation of GstStructures and its contents.
+
+2011-05-10 11:11:15 +0200  Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: ensure thread safety when adding a pad
+         This seems to be a regression, and was causing crashes.
+         https://bugzilla.gnome.org/show_bug.cgi?id=649878
+
+2011-05-10 18:36:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/elements/fdsrc.c:
+       * tests/check/elements/filesrc.c:
+       * tests/check/gst/gstquery.c:
+         query: allow _make_writable on query handlers
+         Pass a GstQuery ** to the query handlers so that they can make the query
+         writable before using a setter on it.
+         Port code to new API.
+
+2011-05-10 16:46:15 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting doc
+
+2011-05-10 16:41:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gsttee.c:
+         element: use request_new_pad_full as the default
+         Add GstCaps to request_new_pad so that request_new_pad_full can be removed.
+         Fix elements.
+
+2011-05-10 16:23:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting doc
+
+2011-05-10 15:41:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+         query: make sure query is writable
+         Make sure the Query is writable before executing the setters.
+
+2011-05-10 15:33:53 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstinfo.c:
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+       * tests/check/gst/gstquery.c:
+         query: Hide GstStructure in queries
+         Hide the GstStructure from the query API.
+         Rename some methods to match the more common names in GObject libraries.
+         Add some more useful query API.
+
+2011-05-10 13:34:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbus.c:
+       * gst/gstinfo.c:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * plugins/elements/gstfakesink.c:
+         message: hide the message structure field
+         Make a private structure to hold the GstStructure bits of the message.
+         Add some more useful macros like we have for events.
+
+=== release 0.10.33 ===
+
+2011-05-10 08:55:10 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * ChangeLog:
+       * NEWS:
+       * RELEASE:
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * gstreamer.doap:
+       * po/af.po:
+       * po/az.po:
+       * po/be.po:
+       * po/bg.po:
+       * po/ca.po:
+       * po/cs.po:
+       * po/da.po:
+       * po/de.po:
+       * po/el.po:
+       * po/en_GB.po:
+       * po/es.po:
+       * po/eu.po:
+       * po/fi.po:
+       * po/fr.po:
+       * po/gl.po:
+       * po/hu.po:
+       * po/id.po:
+       * po/it.po:
+       * po/ja.po:
+       * po/lt.po:
+       * po/nb.po:
+       * po/nl.po:
+       * po/pl.po:
+       * po/pt_BR.po:
+       * po/ro.po:
+       * po/ru.po:
+       * po/rw.po:
+       * po/sk.po:
+       * po/sl.po:
+       * po/sq.po:
+       * po/sr.po:
+       * po/sv.po:
+       * po/tr.po:
+       * po/uk.po:
+       * po/vi.po:
+       * po/zh_CN.po:
+       * po/zh_TW.po:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         Release 0.10.33
+         Highlights:
+         - new parser base class: GstBaseParse
+         - new core element: funnel
+         - OSX multi-arch fixes
+         - new QoS type for QoS events
+         - new progress message API to notify applications of asynchronous operations
+         - countless other fixes and improvements
+
+2011-05-10 12:29:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.h:
+         caps: fix the macros a little
+
+2011-05-10 11:50:16 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstinfo.c:
+       * libs/gst/check/gstconsistencychecker.c:
+       * libs/gst/dataprotocol/dataprotocol.c:
+         event: Hide the GstStructure
+         Hide the GstStructure of the event in the implementation specific part so that
+         we can change it.
+         Add methods to check and make the event writable.
+         Add a new method to get a writable GstStructure of the element.
+         Avoid directly accising the event structure.
+
+2011-05-09 18:48:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * tests/check/gst/gstevent.c:
+         event: _qos_full -> _qos
+
+2011-05-09 17:51:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstsegment.c:
+       * gst/gstsegment.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstcollectpads.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * tests/check/elements/fakesink.c:
+       * tests/check/elements/filesink.c:
+       * tests/check/elements/multiqueue.c:
+       * tests/check/elements/queue.c:
+       * tests/check/generic/sinks.c:
+       * tests/check/gst/gstevent.c:
+       * tests/check/gst/gstinfo.c:
+       * tests/check/gst/gstsegment.c:
+       * tests/check/libs/basesrc.c:
+         segment: remove _full version
+         Rename the _full versions of the functions to the normal function names.
+
+2011-05-09 16:39:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstsegment.c:
+       * gst/gstsegment.h:
+       * libs/gst/base/gstbasesink.c:
+       * plugins/elements/gstinputselector.c:
+         segment: remove abs_rate from segment structure
+         Remove the abs_rate field from the segment structure, we can trivially compute
+         it when needed.
+
+2011-05-09 16:21:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * tests/check/elements/selector.c:
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstcaps.c:
+       * tests/check/gst/gstghostpad.c:
+       * tests/check/libs/transform1.c:
+         caps: remove caps from buffers and pads
+         Remove the GstCaps from buffers and pads. We now use CAPS events to negotiate
+         formats between element.
+
+2011-05-09 15:06:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Use CAPs event
+         Use the caps event to configure basetransform.
+         Remove force_alloc hack, we don't need this in 0.11 with new upstream
+         negotiation.
+         Avoid getting some pad caps.
+
+2011-05-09 15:06:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: add some more debug
+
+2011-05-08 11:02:16 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Add new symbols
+
+2011-05-08 11:01:57 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         gstbuffer: Fix unitialized variables
+
+2011-05-09 10:54:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstutils.c:
+       * tools/gst-inspect.c:
+       * tools/gst-xmlinspect.c:
+         tools: avoid using pad caps
+         Avoid directly accessing the pad caps, use gst_pad_get_current_caps() instead.
+
+2011-05-08 13:14:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-05-08 13:07:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+         basesink: use CAPS event instead of setcaps function
+
+2011-05-08 12:46:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gsttypefindhelper.c:
+       * libs/gst/check/gstcheck.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstpad.c:
+       * tools/gst-launch.c:
+         base: avoid using buffer caps
+         Comment all code using buffer caps.
+         Rework capsfilter code a little.
+         Fix some unit tests
+
+2011-05-08 12:43:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: improve caps event handling
+         Fix replace of caps events when linking: we need to unref the old ones.
+         Make sure we pass error values around.
+         Move backward compat code into the default handler for now.
+
+2011-05-08 12:38:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+         event: don't ref the caps
+         Use a different way of getting the caps from the caps event so that no
+         refcounting happens.
+
+2011-05-08 12:37:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: avoid using buffer caps
+
+2011-05-06 23:40:58 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: don't post loads of empty taglists
+         Only post bitrate updates if there's something to post, don't
+         post empty taglists if nothing changed.
+
+2011-05-06 19:04:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+         pad: avoid using the old GST_PAD_CAPS
+         Don't use GST_PAD_CAPS but instead use the new gst_pad_get_current_caps()
+         method.
+         Avoid setting caps on buffers.
+
+2011-05-06 19:03:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: add 2 new caps methods
+         Add method to get the currently configured caps on the pad.
+         Add a method to check if caps are configured on a pad.
+
+2011-05-06 17:59:33 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+         pad: implement fixed caps with an object flag
+         Implement fixed caps with an object flag instead of a custom getcaps function.
+
+2011-05-06 17:30:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: don't use buffer caps for negotiation
+         Don't use the buffer caps for negotiation anymore but use the CAPS events.
+         Make the _set_caps method produce the CAPS event, add some backward
+         compatibility code to trigger the setcaps functions on src and sinkpads.
+         Remove all negotiation code from the chain functions.
+         Don't use the GST_PAD_CAPS variable anymore to store the caps but retrieve the
+         caps from the sticky event array.
+
+2011-05-06 16:14:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/elements/selector.c:
+         selector: don't unset caps
+
+2011-05-06 16:14:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gsttypefindelement.c:
+         typefind: don't unset caps
+
+2011-05-06 16:13:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/check/gstcheck.c:
+         check: let the normal code unset caps
+
+2011-05-06 16:11:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstoutputselector.c:
+         outputselector: handle NULL pads in some cases
+
+2011-05-06 16:11:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: let the pad clean up in activate
+
+2011-05-06 15:55:31 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: don't mess with pad caps in activate
+         When deactivating a pad, let the pad decide what fields to clear.
+
+2011-05-06 15:51:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+         event: only allow fixed caps in caps event
+
+2011-05-06 13:01:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstevent.c:
+         event: Improve documentation of gst_event_new_reconfigure()
+
+2011-05-06 12:23:01 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting doc
+
+2011-05-06 12:19:16 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * libs/gst/base/gstbasesink.c:
+       * win32/common/libgstreamer.def:
+         element: rename gst_element_lost_state_full()
+         Rename gst_element_lost_state_full() to gst_element_lost_state() and
+         remove the old method name.
+
+2011-05-06 12:09:00 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.h:
+         pad: clean up the .h file a bit
+
+2011-05-06 11:14:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/Makefile.am:
+       * gst/gst.c:
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * win32/common/libgstreamer.def:
+         pad: implement more sticky events
+         Remove the context again, adding an extra layer of refcounting and object
+         creation to manage an array is too complicated and inefficient. Use a simple
+         array again.
+         Also implement event updates when calling gst_pad_chain() and
+         gst_event_send_event() directly.
+
+2011-05-06 11:35:36 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstinfo.h:
+         info: avoid redefinition of symbols when debugging is off
+         The refactoring of gst_debug_add_log_function() now causes build failure when
+         debug-logging is turned off. Just move it to the conditional part of the header.
+
+2011-05-06 11:00:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.h:
+         event: reorder events
+         Reorder the sticky events so that they are in the order they should be pushed.
+
+2011-05-05 19:24:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: simplify some more
+         If we get a context in the chain functions we always need to do a full update of
+         the context on the peer pad.
+
+2011-05-05 18:56:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: improve context passing some more
+         Pass the context downstream when it got updated.
+         Have two ways of informing downstream of events, do a full context update when
+         the CONTEXT_PENDING flag is set and simply forward the event otherwise.
+         Set the CONTENT_PENDING flag when linking pads.
+         We don't need to old context anymore when updating the context of a pad.
+
+2011-05-05 18:21:21 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Don't get the parent twice in the setcaps function
+
+2011-05-05 16:59:36 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Fix refcount leak of the parent in the default event dispatch function
+
+2011-05-05 16:32:11 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: improve passing around the context
+         Improve passing around the context, only send the context to the peer element
+         when the CONTEXT_PENDING flag is set.
+
+2011-05-05 16:05:20 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         win32: Update exports
+
+2011-03-17 11:52:42 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstbin.c:
+       * tests/check/gst/gstiterator.c:
+         tests: Update for new GstIterator API
+
+2011-03-17 11:32:24 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * win32/common/libgstreamer.def:
+         docs/def: Add new symbols, remove old symbols
+
+2011-03-17 11:32:11 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gsttee.c:
+         elements: Update everything for the new GstIterator API
+
+2011-03-17 11:31:59 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstelement.c:
+       * gst/gstformat.c:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstquery.c:
+       * gst/gstutils.c:
+       * gst/gstvalue.c:
+         gst: Update everything for the new GstIterator API
+
+2011-03-16 10:50:39 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstiterator.c:
+       * gst/gstiterator.h:
+       * gst/gstplugin.c:
+         iterator: Refactor GstIterator to be more binding friendly and have saner refcounting
+         Fixes bug #638987.
+
+2011-01-08 12:27:55 -0200  Johan Dahlin <johan@gnome.org>
+
+       * gst/gstiterator.c:
+       * gst/gstiterator.h:
+         iterator: register as a boxed type
+         https://bugzilla.gnome.org/show_bug.cgi?id=638987
+
+2011-01-08 12:14:40 -0200  Johan Dahlin <johan@gnome.org>
+
+       * gst/gstiterator.c:
+         iterator: use GSlice
+         https://bugzilla.gnome.org/show_bug.cgi?id=638987
+
+2011-01-08 12:12:41 -0200  Johan Dahlin <johan@gnome.org>
+
+       * gst/gstbin.c:
+       * gst/gstiterator.c:
+         iterator: free struct in gst_iterator_free
+         https://bugzilla.gnome.org/show_bug.cgi?id=638987
+
+2011-01-08 12:07:55 -0200  Johan Dahlin <johan@gnome.org>
+
+       * gst/gstiterator.c:
+       * gst/gstiterator.h:
+         iterator: store size in the struct
+         https://bugzilla.gnome.org/show_bug.cgi?id=638987
+
+2011-05-05 11:28:38 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * tests/check/gst/gstcaps.c:
+         caps: Merge structures when intersecting instead of appending them
+         This prevents adding duplicates over and over again to the resulting
+         caps if they already describe the new intersection result.
+         While this changes intersection from O(n*m) to O(n^2*m), it results in
+         smaller caps, which in the end will decrease further processing times.
+         For example in an audioconvert ! audioconvert ! audioconvert pipeline,
+         when forwarding the downstream caps preference in basetransform
+         (see e26da72de25a91c3eaad9f7c8b2f53ba888a0394) this results in
+         16 instead of 191 caps structures.
+
+2011-05-04 11:29:15 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: In getcaps() prefer the caps order and caps of downstream if possible
+
+2011-05-03 17:26:53 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Prefer caps order given by the subclass of the template caps order
+
+2011-05-03 14:13:59 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Use the reconfigure flag on the pad instead of the event
+
+2011-05-03 14:11:34 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Use new reconfigure flag on the pads instead of the reconfigure event
+
+2011-05-03 13:42:44 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Keep track of reconfigure events and the pad-needs-reconfiguring status
+
+2011-05-03 13:05:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * win32/common/libgstreamer.def:
+         event: Rename renegotiate event to reconfigure
+         In 0.11 this event will also do reconfiguration of buffer pools
+         and similar things, not just renegotiation.
+
+2010-03-17 21:24:55 +0000  Olivier Crête <olivier.crete@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Send renegotiate event on link
+
+2010-03-17 21:17:10 +0000  Olivier Crête <olivier.crete@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Drop renegotiate event if there is no getcaps function on a sink pad
+         If there is no custom getcaps function on a sink pad, then changes in
+         downstream caps will never be propagated, so there is no point in trying to
+         renegotiate the capabilities.
+
+2011-04-26 16:39:56 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Only renegotiate once after receiving a renegotiate event
+         Also make this threadsafe.
+
+2011-01-17 14:13:46 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+
+       * libs/gst/base/gstbasesrc.c:
+         basesrc: Handle the new renegotiate event
+         Makes basesrc handle the new renegotiate event by using a
+         renegotiate flag.
+
+2011-04-26 16:48:05 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Also call gst_base_transform_reconfigure() on renegotiate events
+
+2011-01-17 14:13:46 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Handle the new renegotiate event
+         Let basetransform push a renegotiate event upstream
+         when it gets a new suggestion
+
+2011-01-17 11:51:49 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * win32/common/libgstreamer.def:
+         event: Adding new renegotiate event
+
+2011-05-05 13:10:42 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: pass the context around
+         Pass the context from srcpad to sinkpad before dataflow when something
+         changed.
+
+2011-05-05 11:17:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: update the context lazyly
+
+2011-05-05 11:16:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: init the GType early
+
+2011-05-05 11:16:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2011-05-05 10:40:14 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+         context: add foreach function
+         Add a function to iterate over all stored events.
+
+2011-05-05 10:37:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+       * gst/gstevent.h:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gsttypefindhelper.c:
+       * libs/gst/check/gstcheck.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/elements/selector.c:
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstcaps.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/libs/transform1.c:
+       * tools/gst-launch.c:
+         Revert "context: use context on buffers instead of caps"
+         This reverts commit 9ef1346b1fa0bd2bb42cd991a52ff308a728bdb6.
+         Way to much for one commit and I'm not sure we want to get rid of the pad caps
+         just like that. It's nice to have the buffer and its type in onw nice bundle
+         without having to drag the complete context with it.
+
+2011-04-20 22:52:36 +0200  Miguel Angel Cabrera Moya <madmac2501@gmail.com>
+
+       * gst/parse/types.h:
+       * tests/check/pipelines/parse-launch.c:
+         parse: don't unescape inside quotes
+         Escaped characters inside quoted strings are supposed to be unescaped by
+         deserialization functions, not by parsing functions.
+         https://bugzilla.gnome.org/show_bug.cgi?id=648025
+
+2011-04-18 14:26:33 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: Only post EOS messages after reaching the PLAYING state
+         Fixes bug #647756.
+
+2011-04-18 10:04:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Remove unnecessary FIXME
+         Resetting the result is not necessary when resyncing because
+         pads that previously got the event will be skipped and we
+         need to consider the results of the previous pushes.
+
+2011-04-18 09:53:55 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: If activating one pad failed error out early instead of trying to activate the next pads
+         If one pad fails to activate the complete activation process will fail
+         anyway and trying to activate the other pads only wastes time.
+
+2011-04-18 09:49:04 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+         bin: If activating one pad failed error out early instead of trying to activate the next pads
+         If one pad fails to activate the complete activation process will fail
+         anyway and trying to activate the other pads only wastes time.
+
+2011-05-05 12:28:02 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         basetransform: Remove nowadays unused and uninitialized setcaps variable
+
+2011-05-05 12:27:51 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         docs/gst/gstreamer-sections.txt
+         gst/gstelementfactory.c
+         gst/gstminiobject.c
+
+2011-05-04 18:59:47 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+       * gst/gstevent.h:
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * libs/gst/base/gstbaseparse.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gsttypefindhelper.c:
+       * libs/gst/check/gstcheck.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/elements/selector.c:
+       * tests/check/elements/tee.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstcaps.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/libs/transform1.c:
+       * tools/gst-launch.c:
+         context: use context on buffers instead of caps
+         Put the srcpad context on buffers instead of caps. This allows us to associate
+         all the relevant info contained in events with a buffer.
+
+2011-05-04 15:29:42 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * tests/check/gst/gstminiobject.c:
+         tests: fix compiler warning in new miniobject test
+         gst/gstminiobject.c: In function ‘test_dup_null_mini_object’:
+         gst/gstminiobject.c:459:7: warning: assignment from incompatible pointer type
+
+2011-05-04 15:53:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcontext.h:
+       * gst/gstevent.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: use the context to store sticky events
+         Store the sticky events in the context of a source pad.
+
+2011-05-04 15:20:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/Makefile.am:
+       * gst/gstcontext.c:
+       * gst/gstcontext.h:
+       * gst/gstevent.h:
+         context: add helper object to manage events
+         Add a helper object to manage the events that define the context of a buffer and
+         a stream.
+
+2011-05-04 11:07:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2011-05-04 11:03:05 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         event: add new CAPS event
+         Add a new CAPS event that will be used to negotiate downstream elements. It'll
+         also stick on pad so that we can remove the GstCaps field on pads and the
+         GstCaps field on buffers.
+
+2011-05-03 18:58:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: more sticky events work
+         Copy the sticky events from the srcpad to the sinkpad when linking pads. Set the
+         STICKY_PENDING flag to make sure that the sticky events are dispatched before
+         pushing the next buffer to the element.
+
+2011-05-03 16:11:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: improve porting doc
+
+2011-05-02 18:45:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting document
+
+2011-05-02 11:30:06 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+       * tests/check/gst/gstminiobject.c:
+         miniobject: Fix dup_mini_object function to handle NULL gvalues
+         g_value_dup_object handles gvalues that contain NULL pointers,
+         gst_value_dup_mini_object should do the same.
+         https://bugzilla.gnome.org/show_bug.cgi?id=649195
+
+2011-05-03 13:55:43 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * libs/gst/base/gstbaseparse.c:
+         docs: it its %TRUE (constant)
+         As spotted by Tim.
+
+2011-05-02 16:22:56 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelementfactory.c:
+         docs: fix copy'n'paste doc header mistake
+
+2011-05-02 16:20:24 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelement.h:
+       * gst/gstpluginfeature.h:
+         docs: add two trivial doc blobs
+
+2011-05-02 16:03:29 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * libs/gst/base/gstbaseparse.c:
+         docs: add missing parameter docs
+
+2011-05-02 16:00:52 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * libs/gst/dataprotocol/dataprotocol.h:
+         docs: add docs for GstDPPacketizer
+
+2011-05-02 15:52:58 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstcaps.h:
+         docs: improve the syntax for the capsintersectmode docs
+
+2011-05-02 15:48:01 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstelement.c:
+         docs: fixup broken xref
+
+2011-05-02 15:46:59 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/gst/gstreamer-sections.txt:
+       * docs/libs/gstreamer-libs-sections.txt:
+         docs: add new api to -section.txt
+
+2011-05-02 15:35:52 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstatomicqueue.h:
+         docs: fix gtk-doc syntax
+
+2011-05-02 15:30:13 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * plugins/elements/gstfunnel.c:
+         docs: don't duplicate info that we take from element-details
+
+2011-04-28 15:37:02 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/gst/gstreamer-sections.txt:
+         docs: remove non existing symbol
+
+2011-04-28 15:05:28 +0300  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstbufferlist.c:
+       * gst/gstsystemclock.h:
+         docs: we don't need to document private members in opaque structs
+
+2011-04-29 13:43:07 +0200  Philippe Normand <pnormand@igalia.com>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstpreset.c:
+       * gst/gstregistry.c:
+       * tests/check/gst/gstpreset.c:
+         core: store presets, registry and plugins in XDG directories.
+         Presets and plugins moved to $XDG_DATA_HOME/gstreamer-0.11/
+         root directory. Registry moved to $XDG_CACHE_HOME/gstreamer-0.11/.
+         Fixes bug #518597.
+
+2011-05-03 09:41:48 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         configure.ac
+         gst/gstbus.c
+
+2011-05-02 18:34:18 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstinfo.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         event: add sticky flags to events
+         Add the sticky flag to events and a sticky index.
+         Keep sticky events in an array on each pad.
+         Remove GST_EVENT_SRC(), it is causing refcycles with sticky events, was not used
+         and is not very interesting anyway.
+
+2011-05-02 11:09:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+         query: improve allocation parameters query
+         Use the same parameters as those used for the bufferpool. Make sure we can pass
+         a minimum and maximum amount of buffers needed.
+
+2011-04-30 16:55:36 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * docs/plugins/inspect/plugin-staticelements.xml:
+       * po/de.po:
+       * po/fr.po:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         0.10.32.4 pre-release
+
+2011-04-29 23:44:55 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstpluginfeature.h:
+         pluginfeature: include plugin.h in header where we use a GstPlugin pointer
+         Should fix issue with gstreamermm build where <gst/gstindex.h> is included
+         directly instead of gst/gst.h.
+
+2011-04-29 13:42:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbasetransform.c:
+         transform: do pad_alloc fallback correctly
+
+2011-04-29 13:26:19 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstghostpad.c:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasetransform.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttee.c:
+       * plugins/elements/gstvalve.c:
+       * tests/check/elements/funnel.c:
+       * tests/check/elements/tee.c:
+       * tests/check/elements/valve.c:
+       * tests/check/libs/test_transform.c:
+       * tests/check/libs/transform1.c:
+       * tools/gst-inspect.c:
+       * tools/gst-xmlinspect.c:
+       * win32/common/libgstreamer.def:
+         Remove pad_alloc, this can now be done better
+         Remove pad_alloc and all references. This can now be done more efficiently and
+         more flexible with the ALLOCATION query and the bufferpool objects. There is no
+         reverse negotiation yet but that will be done with an event later.
+
+2011-04-29 12:11:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+         query: init the ALLOCATION query correctly
+         Don't add the 'pool' property instead of adding it with a NULL array.
+
+2011-04-29 10:50:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+       * win32/common/libgstreamer.def:
+         query: fix parsing of the ALLOCATION query
+         Add methods for parsing the caps and the need_pool boolean.
+
+2011-04-28 16:20:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+       * win32/common/libgstreamer.def:
+         query: fix typo in method name and improve docs
+         Fixed typo in method name and add/improve the docs.
+
+2011-04-28 15:31:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-allocation.txt:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+       * gst/gstquery.c:
+       * gst/gstquery.h:
+       * win32/common/libgstreamer.def:
+         bufferpool: add query to request pool and configuration
+         Add a query to request allocation parameters and optionally a bufferpool as
+         well. This should allow elements to discover downstream capabilities and also
+         use the downstream allocators.
+
+2011-04-27 18:10:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbus.c:
+         bus: fix timeout handling
+
+2011-04-27 17:56:12 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-bufferpool.txt:
+       * gst/gstbufferpool.c:
+         bufferpool: fix some docs
+
+2011-04-27 17:55:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         event: improve argument names of segments
+
+2011-04-27 11:49:11 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-coreindexers.xml:
+       * po/bg.po:
+       * po/nl.po:
+       * po/pl.po:
+       * po/ru.po:
+       * win32/common/config.h:
+       * win32/common/gstversion.h:
+         0.10.32.3 pre-release
 
 2011-04-26 15:42:46 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
          This reverts commit 14d7db1b527b05f029819057aef5c123ac7e013d.
          https://bugzilla.gnome.org/show_bug.cgi?id=647493
 
+2011-04-25 11:10:47 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * gst/gstformat.c:
+       * gst/gstparse.c:
+       * gst/gstquery.c:
+       * gst/gsttagsetter.c:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbaseparse.c:
+         Small cosmetic cleanups
+         Make sure the return values from g_return_* are of the right type.
+
+2011-04-25 10:56:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstqueue2.c:
+         queue2: fix mixing of return values
+
+2011-04-25 10:30:41 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-04-15 22:00:11 -0700  David Schleef <ds@schleef.org>
 
        * gst/gstutils.c:
          parent which does not have a poll anymore these days.
          https://bugzilla.gnome.org/show_bug.cgi?id=648297
 
+2011-04-20 19:08:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2011-04-20 19:03:49 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: remove unused variable
+
+2011-04-20 19:00:07 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: don't touch base_time or clock in state change
+         Don't touch the base_time or the clock when setting an element to the READY or
+         NULL state. It is the parent that will manage this for us.
+
+2011-04-19 20:52:05 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbufferlist.c:
+         bufferlist: Implement gst_buffer_list_foreach()
+
+2011-04-19 19:30:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-04-19 18:57:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: add method to compare buffer data
+         Add method to compare the data in a buffer.
+
+2011-04-19 16:21:15 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         configure.ac
+
 2011-04-19 14:05:23 +0200  Havard Graff <havard.graff@tandberg.com>
 
        * gst/gstpad.c:
        * gst/gstquery.h:
          query: const-ify formats arguments to gst_query_set_formatsv()
 
+2011-04-18 18:19:51 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/elements/fakesink.c:
+       * tests/check/gst/gstparamspecs.c:
+       * tests/check/gst/gsttagsetter.c:
+       * tests/check/libs/test_transform.c:
+       * tests/check/pipelines/parse-launch.c:
+         tests: Use G_DEFINE_TYPE instead of GST_BOILERPLATE
+
+2011-04-18 18:19:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+         base{sink,src}: Don't try to fixate ANY caps
+
+2011-04-18 18:07:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstoutputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttee.c:
+       * plugins/elements/gsttypefindelement.c:
+       * plugins/elements/gstvalve.c:
+         elements: Use G_DEFINE_TYPE instead of GST_BOILERPLATE
+
+2011-04-18 17:33:34 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/net/gstnetclientclock.c:
+         net: Use G_DEFINE_TYPE instead of GST_BOILERPLATE
+
+2011-04-18 17:32:17 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstcollectpads.c:
+       * libs/gst/base/gstpushsrc.c:
+         base: Use G_DEFINE_TYPE instead of GST_BOILERPLATE
+
+2011-04-18 17:28:37 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstutils.h:
+         utils: Remove GST_BOILERPLATE and friends
+
+2011-04-18 10:47:26 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Make the size parameter of gst_pad_alloc_buffer() unsigned
+         Internally guints were used everywhere already.
+
+2011-04-18 10:41:18 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: Don't allow fixating ANY caps and remove FIXME
+
+2011-04-18 10:36:41 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstbin.c:
+         bin: Enable DURATION query caching
+         Elements must now post a DURATION message on the bus if they
+         change the duration in PAUSED or PLAYING.
+
 2011-04-16 15:20:08 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * libs/gst/base/gstbaseparse.c:
          docs: remove reference to baseparse API that didn't make it
 
+2011-04-16 16:06:02 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-04-16 15:28:53 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * tests/check/gst/gstelement.c:
+         element: Add test for inheriting metadata/pad templates
+
+2011-04-16 15:24:01 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+         base: Update docs to say class_init instead of base_init
+         And remove a useless base_init in basesrc
+
+2011-04-16 15:23:46 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * libs/gst/net/gstnettimeprovider.c:
+         net: Use G_DEFINE_TYPE
+
+2011-04-16 15:23:19 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstbin.c:
+       * gst/gstpipeline.c:
+         gst: Don't use base_init and use G_DEFINE_TYPE instead of GST_BOILERPLATE
+
+2011-04-16 15:03:33 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstelement.c:
+       * gst/gstpadtemplate.c:
+         element: Inherit element metadata and pad templates from parent classes
+         This allows to add pad templates and set metadata in class_init instead of
+         base_init. base_init is a concept that is not supported by almost all
+         languages and copying the templates/metadata for subclasses is the more
+         intuitive way of doing things.
+         Subclasses can override pad templates of parent classes by adding a new
+         template with the same now.
+         Also gst_element_class_add_pad_template() now takes ownership of the
+         pad template, which was assumed by all code before anyway.
+         Fixes bug #491501.
+
 2011-04-16 14:56:03 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * configure.ac:
        * win32/common/libgstbase.def:
          win32: add new baseparse API to libgstbase.def
 
+2011-04-16 09:33:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-04-16 09:32:17 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
        * win32/common/libgstreamer.def:
          win32: Add exports for the GstParseContext and GstBufferListIterator types
 
+2011-04-16 08:59:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-04-15 20:58:51 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * gst/gstpluginloader.c:
          buffers through pipelines. As such, adding output of the buffer pointers
          to these messages allows tracking of specific buffers, easing debugging.
 
+2011-04-11 10:53:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbaseparse.c:
+         baseparse: port to 0.11
+
+2011-04-11 10:26:54 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         android/base.mk
+         android/controller.mk
+         android/dataprotocol.mk
+         android/elements.mk
+         android/gst-inspect.mk
+         android/gst-launch.mk
+         android/gst-plugin-scanner.mk
+         android/gst.mk
+         android/indexers.mk
+         android/net.mk
+         win32/common/libgstbase.def
+
+2011-04-11 10:20:10 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: add FIXME
+
 2011-01-27 14:33:08 +0100  Alessandro Decina <alessandro.d@gmail.com>
 
        * .gitignore:
          element: unref event in default_send_event in case element has no pads
          Spotted by  Haakon Sporsheim.
 
+2011-04-09 04:07:04 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * tests/check/gst/.gitignore:
+         check: Ignore new gstmeta binary
+
+2011-04-09 04:05:48 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * docs/design/Makefile.am:
+         design: draft-buffer2.txt no longer exists
+
+2011-04-09 04:05:20 +0200  Edward Hervey <edward.hervey@collabora.co.uk>
+
+       * gst/Makefile.am:
+         gst: Don't forget to dist gstelementmetadata.h
+
 2011-04-08 19:07:02 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * libs/gst/base/gstbaseparse.c:
        * plugins/elements/gstfunnel.c:
          funnel: minor element description fix
 
+2011-04-07 16:13:56 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-04-07 16:02:43 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.h:
+         memory: add NO_SHARE flag to memory
+         Add a NO_SHARE flag to memory to indicate that it should not be shared
+         between buffers.
+
 2011-04-07 16:08:34 +0300  Stefan Kost <ensonic@users.sf.net>
 
        * docs/random/draft-missing-plugins.txt:
          before already.
          Fixes bug #635718.
 
+2011-04-06 19:19:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmemory.c:
+         memory: don't follow the parent in the fallback share
+
+2011-04-06 18:57:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstminiobject.c:
+         buffer: make memory writable in _peek
+         Make the memory writable when we are asked to _peek with MAP_WRITE.
+         Improve debugging of miniobject.
+
+2011-04-06 16:37:40 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+         miniobject: fix debug
+
+2011-04-06 14:20:59 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-04-06 14:06:49 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
        * gst/gst_private.h:
          Automatic update of common submodule
          From 1ccbe09 to c3cafe1
 
+2011-04-04 11:17:28 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-04-04 03:33:46 +0200  Andoni Morales Alastruey <ylatuya@gmail.com>
 
        * gst/gstpoll.c:
        * gst/gstelement.c:
          element: strto[u]l() returns a g[u]long
 
+2011-04-01 10:47:48 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2011-04-01 10:46:06 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting guide with bufferlist changes
+
 2011-03-31 19:25:30 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * docs/design/part-seeking.txt:
          design docs: document expected behaviour for ACCURATE and KEY_UNIT seek flags
 
+2011-03-31 18:39:57 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * libs/gst/base/gstbytewriter.c:
+         bytewriter: don't add NULL data
+
+2011-03-31 17:55:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         tests/check/gst/struct_x86_64.h
+
+2011-03-31 17:51:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gst.c:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+       * gst/gstpad.c:
+       * libs/gst/base/gstbasesink.c:
+       * tests/check/gst/gstbufferlist.c:
+       * tests/check/gst/gstpad.c:
+       * win32/common/libgstreamer.def:
+         bufferlist: simplify bufferlists
+         We now have multiple memory blocks as part of the buffers and we can therefore
+         reduce the bufferlist to a simple array of buffers.
+
 2011-03-31 10:53:03 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
        * tests/check/gst/struct_x86_64.h:
        * tests/check/libs/struct_x86_64.h:
          libsabi: Add lots of new structures for x86-64
 
-2011-03-30 10:48:47 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-31 10:31:22 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting doc
+
+2011-03-30 20:05:26 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: fix for API change
+
+2011-03-30 19:58:52 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11-fdo
+         Conflicts:
+         docs/plugins/gstreamer-plugins.hierarchy
+         gst/gstelement.c
+
+2011-03-30 19:01:13 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmeta.c:
+         docs: update docs
+
+2011-03-30 18:45:08 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * docs/plugins/gstreamer-plugins.hierarchy:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * win32/common/libgstreamer.def:
+         docs: update documentation
+
+2011-03-30 16:47:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstcompat.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstcollectpads.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesrc.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstmeta.c:
+       * tests/check/libs/adapter.c:
+       * win32/common/libgstreamer.def:
+         buffer: more API tweaks
+         _trim -> _resize
+         _create_sub -> copy_region
+
+2011-03-30 15:29:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-buffer.txt:
+       * docs/design/part-bufferlist.txt:
+         design: update design docs
+
+2011-03-30 13:04:34 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-meta.txt:
+       * gst/gstbuffer.c:
+         design: update docs
+
+2011-03-30 10:48:47 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstmultiqueue.c:
+       * tests/check/elements/multiqueue.c:
+         multiqueue: Make assignment of queue IDs and pad names threadsafe
+         Also add a test for naming pads by the caller and return NULL
+         when requesting an already existing pad.
+
+2011-03-29 23:58:43 +0200  Andreas Frisch <fraxinas@opendreambox.org>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Set the single queue ID to the ID of the requested pad if one was given by the caller
+
+2011-03-29 19:17:55 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * win32/common/libgstreamer.def:
+         memory: further memory tweaking
+         Allow for automatic merging of memory block in the _map function and automatic
+         freeing of the temporary memory.
+         Remove some unneeded functions.
+         Add possibility to force writable spanned memory.
+
+2011-03-29 17:17:46 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: implement COPY_MERGE
+
+2011-03-29 16:52:21 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * win32/common/libgstreamer.def:
+         buffer: clean up _span and add more g_return_if..
+
+2011-03-29 16:22:46 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: Fix sanity checks for request pad templates without %
+
+2011-03-29 13:51:25 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: optimize memory handling
+
+2011-03-29 11:57:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: Add some more sanity checks to the pad name checking of request pads in all cases
+         Especially check if a pad with that name already exists.
+
+2011-03-29 11:52:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstelement.c:
+         element: Check %u too when trying to find a pad template for a request pad
+
+2011-03-29 11:31:30 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: move implementation details in private struct
+
+2011-03-28 21:01:13 +0200  Fraxinas <andreas.frisch@multimedia-labs.de>
+
+       * plugins/elements/gstmultiqueue.c:
+         multiqueue: Fix arbitrary sink + source pad naming
+         Use the string provided by the caller for the sinkpad name
+         if possible. Note that all sanity checking for this name
+         is already done in GstElement.
+         Fixes Bug #645931
+
+2011-03-29 11:18:36 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: Add some more documentation about the behaviour of funnel
+
+2011-03-29 11:08:57 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: Send a newsegment event after flush-stop
+
+2011-03-29 11:07:48 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: Some random cleanup
+
+2011-03-29 10:56:00 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+         funnel: Use a GstPad subclass for the sinkpads instead of using the pad's element private data
+
+2011-03-29 10:42:31 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * docs/plugins/gstreamer-plugins-docs.sgml:
+       * docs/plugins/gstreamer-plugins-sections.txt:
+       * docs/plugins/gstreamer-plugins.hierarchy:
+       * docs/plugins/inspect/plugin-coreelements.xml:
+       * docs/plugins/inspect/plugin-staticelements.xml:
+       * plugins/elements/Makefile.am:
+       * plugins/elements/gstelements.c:
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstfunnel.h:
+       * tests/check/Makefile.am:
+       * tests/check/elements/funnel.c:
+         funnel: Integrate into the build system and rename the types
+
+2011-03-29 10:39:42 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * plugins/elements/gstfunnel.c:
+       * plugins/elements/gstfunnel.h:
+       * tests/check/elements/funnel.c:
+         funnel: Import funnel element from farsight2
+
+2011-03-29 11:07:36 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstpad.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesrc.c:
+       * tests/check/gst/gstbuffer.c:
+       * win32/common/libgstreamer.def:
+         buffer: more buffer updates
+
+2011-03-28 20:20:39 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: fix defs
+
+2011-03-28 20:11:20 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11-fdo
+         Conflicts:
+         gst/gst.c
+         libs/gst/base/gstcollectpads.c
+
+2011-03-28 19:19:44 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+       * libs/gst/base/gstbasetransform.c:
+         buffer: fix subbuffers
+
+2011-03-28 16:40:24 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: implemet trim and set_size
+
+2011-03-28 15:52:17 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * libs/gst/check/Makefile.am:
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/check/gstcheck.h:
+       * win32/common/libgstreamer.def:
+         buffer: more fixes
+
+2011-03-28 10:28:02 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.h:
+         buffer: add more methods
+
+2011-03-24 21:21:00 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: add class init
+
+2011-03-24 21:18:52 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * libs/gst/base/gstadapter.c:
+       * tests/check/elements/filesrc.c:
+       * tests/check/gst/gstmeta.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/libs/adapter.c:
+       * win32/common/libgstbase.def:
+       * win32/common/libgstreamer.def:
+         buffer: fix remaining unit tests
+
+2011-03-24 20:09:02 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * tests/check/gst/gstbuffer.c:
+         buffer: fix unit test
+
+2011-03-24 13:01:00 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * libs/gst/base/gstadapter.c:
+       * tests/check/gst/gstbufferlist.c:
+       * tests/check/gst/gstmeta.c:
+       * tests/check/gst/gstpad.c:
+         memory: remove memory metadata again
+
+2011-03-24 11:49:46 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmemory.c:
+       * tests/check/libs/adapter.c:
+         memory: more fixes
+         Automatically make the memory of a buffer writable when the buffer is writable
+         and the memory is asked to mapped WRITE.
+         Add docs
+
+2011-03-23 20:52:27 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstmultiqueue.c:
-       * tests/check/elements/multiqueue.c:
-         multiqueue: Make assignment of queue IDs and pad names threadsafe
-         Also add a test for naming pads by the caller and return NULL
-         when requesting an already existing pad.
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbytewriter.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstinputselector.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gsttypefindelement.c:
+       * plugins/elements/gstvalve.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstminiobject.c:
+       * tests/check/libs/bitreader.c:
+       * tests/check/libs/bytereader.c:
+       * tests/check/libs/typefindhelper.c:
+         memory: more work on implementing buffer memory
 
-2011-03-29 23:58:43 +0200  Andreas Frisch <fraxinas@opendreambox.org>
+2011-03-22 20:51:06 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstmultiqueue.c:
-         multiqueue: Set the single queue ID to the ID of the requested pad if one was given by the caller
+       * gst/gst.c:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/libs/adapter.c:
+       * tests/check/libs/bitreader.c:
+       * tests/check/libs/bytereader.c:
+       * tests/check/libs/test_transform.c:
+       * tests/check/libs/transform1.c:
+         memory: more work on porting the unit tests
 
-2011-03-29 16:22:46 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-21 19:15:27 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstelement.c:
-         element: Fix sanity checks for request pad templates without %
+       * tests/check/elements/fakesrc.c:
+       * tests/check/elements/filesink.c:
+       * tests/check/elements/filesrc.c:
+       * tests/check/elements/identity.c:
+       * tests/check/elements/multiqueue.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstbufferlist.c:
+       * tests/check/gst/gstelementfactory.c:
+       * tests/check/gst/gstmeta.c:
+       * tests/check/gst/gstminiobject.c:
+       * tests/check/gst/gstpad.c:
+       * tests/check/gst/gststructure.c:
+       * tests/check/gst/gsttag.c:
+       * tests/check/gst/gstvalue.c:
+       * tests/check/libs/typefindhelper.c:
+         tests: make some tests compile
 
-2011-03-29 11:57:58 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-21 18:13:55 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstelement.c:
-         element: Add some more sanity checks to the pad name checking of request pads in all cases
-         Especially check if a pad with that name already exists.
+       * docs/manual/advanced-dataaccess.xml:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gsttypefind.c:
+       * gst/gsttypefind.h:
+       * gst/gstutils.c:
+       * gst/gstvalue.c:
+       * libs/gst/base/gstadapter.c:
+       * libs/gst/base/gstadapter.h:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * libs/gst/base/gstbasetransform.h:
+       * libs/gst/base/gstbitreader.c:
+       * libs/gst/base/gstbitreader.h:
+       * libs/gst/base/gstbytereader.c:
+       * libs/gst/base/gstbytereader.h:
+       * libs/gst/base/gstbytewriter.c:
+       * libs/gst/base/gstbytewriter.h:
+       * libs/gst/base/gstcollectpads.c:
+       * libs/gst/base/gstcollectpads.h:
+       * libs/gst/base/gsttypefindhelper.c:
+       * libs/gst/base/gsttypefindhelper.h:
+       * libs/gst/check/gstcheck.c:
+       * libs/gst/dataprotocol/dataprotocol.c:
+       * plugins/elements/gstcapsfilter.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfdsink.c:
+       * plugins/elements/gstfdsrc.c:
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gstmultiqueue.c:
+       * plugins/elements/gstqueue.c:
+       * plugins/elements/gstqueue2.c:
+       * plugins/elements/gsttee.c:
+       * plugins/elements/gsttypefindelement.c:
+       * plugins/elements/gsttypefindelement.h:
+       * tests/examples/adapter/adapter_test.c:
+       * tools/gst-launch.c:
+         memory: port code to new buffer data API
 
-2011-03-29 11:52:06 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-21 13:07:42 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * gst/gstelement.c:
-         element: Check %u too when trying to find a pad template for a request pad
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferpool.c:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+       * gst/gstmeta.c:
+       * gst/gstpad.c:
+         memory: more fixes
+         Fix span and is_span
+         Implement buffer memory
 
-2011-03-28 21:01:13 +0200  Fraxinas <andreas.frisch@multimedia-labs.de>
+2011-03-21 09:51:53 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstmultiqueue.c:
-         multiqueue: Fix arbitrary sink + source pad naming
-         Use the string provided by the caller for the sinkpad name
-         if possible. Note that all sanity checking for this name
-         is already done in GstElement.
-         Fixes Bug #645931
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmemory.h:
+         WIP use memory in buffer
 
-2011-03-29 11:18:36 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-20 11:42:39 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-         funnel: Add some more documentation about the behaviour of funnel
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: more improvements
 
-2011-03-29 11:08:57 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-19 10:45:37 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-         funnel: Send a newsegment event after flush-stop
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: more memory improvements
 
-2011-03-29 11:07:48 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-18 21:45:39 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-         funnel: Some random cleanup
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: add more memory operations
 
-2011-03-29 10:56:00 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-18 19:28:17 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-         funnel: Use a GstPad subclass for the sinkpads instead of using the pad's element private data
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * gst/gstmemory.c:
+       * gst/gstmemory.h:
+         memory: add memory implementation
 
-2011-03-29 10:42:31 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-18 18:35:42 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * docs/plugins/gstreamer-plugins-docs.sgml:
-       * docs/plugins/gstreamer-plugins-sections.txt:
-       * docs/plugins/gstreamer-plugins.hierarchy:
-       * docs/plugins/inspect/plugin-coreelements.xml:
-       * docs/plugins/inspect/plugin-staticelements.xml:
-       * plugins/elements/Makefile.am:
-       * plugins/elements/gstelements.c:
-       * plugins/elements/gstfunnel.c:
-       * plugins/elements/gstfunnel.h:
-       * tests/check/Makefile.am:
-       * tests/check/elements/funnel.c:
-         funnel: Integrate into the build system and rename the types
+       * gst/gstmemory.h:
+         memory: add API for handling memory blocks
+         Adds some API to handle memory blocks.
 
-2011-03-29 10:39:42 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2011-03-08 18:18:24 +0000  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfunnel.c:
-       * plugins/elements/gstfunnel.h:
-       * tests/check/elements/funnel.c:
-         funnel: Import funnel element from farsight2
+       * gst/gstmeta.h:
+         meta: fix docs
 
 2011-03-28 21:21:00 +0530  Arun Raghavan <arun.raghavan@collabora.co.uk>
 
          file with playbin2 and switching between the streams for example.
          Fixes bug #644935.
 
+2011-03-17 10:53:49 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * win32/common/libgstreamer.def:
+         utils: Remove deprecated gst_element_factory_can_{sink,src}_caps()
+
+2011-03-17 10:50:43 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstbufferlist.c
+
 2011-03-16 12:01:21 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
        * gst/gstpad.c:
        * win32/common/libgstreamer.def:
          win32: Update .def file for API addition
 
+2011-03-10 10:25:07 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-03-09 16:15:33 +0200  Stefan Kost <ensonic@users.sf.net>
 
        * docs/pwg/advanced-types.xml:
          tests: add a unit test for gst_caps_new_simple
          Add a test for the crash in bug #642271.
 
+2011-03-08 18:05:42 +0000  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-buffer2.txt:
+       * docs/design/part-meta.txt:
+         docs: rename draft to official doc
+
+2011-03-08 16:58:49 +0000  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * tests/check/gst/gstmeta.c:
+         meta: implement transform function
+         Replace subbuffer and copy vmethods by a more generic transform function that
+         can then be parametrised by transform specific data. This should allow us to
+         implement make-writable and more future transform functions.
+
+2011-03-08 17:06:30 +0000  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
 2011-03-08 11:55:29 +0200  Stefan Kost <ensonic@users.sf.net>
 
        * tests/check/gst/gstelementfactory.c:
          No need to check for media_type!=NULL as the function we call that actual create
          the structure does a full check anyway.
 
-2011-03-08 10:06:23 +0200  Stefan Kost <ensonic@users.sf.net>
+2011-03-08 10:06:23 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstcaps.c:
+       * gst/gststructure.c:
+         caps,structure: trim trailing whitespace
+
+2011-03-04 08:28:25 +1000  Jonathan Matthew <jonathan@d14n.org>
+
+       * gst/gstcaps.c:
+         caps: don't create broken caps for invalid media types
+         Check if structure has been created before appending it to the caps. Free the
+         caps in the case of an error to not conceal it be returning empty caps.
+         Fixes #642271
+
+2011-03-07 16:21:47 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/examples/helloworld/helloworld.c:
+         examples: update hello world example
+         Our helloworld example thatw e reference from the manual has been a bit
+         complicated to serve a first contact with gstreamer. Since we have and
+         promote playbin2 as a playback api use it here.
+         Based on work from Mathias Hasselmann <mathias.hasselmann@gmx.de>
+         Fixes #424143
+
+2011-03-04 19:02:33 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-buffer2.txt:
+         docs: update metadata draft
+
+2011-03-04 18:11:19 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+         miniobject: remove FIXME
+         Now that we don't subclass buffers anymore, the FIXME about limited
+         functionality of the copy function is irrelevant.
+
+2011-03-04 17:43:24 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: add flag registration
+
+2011-03-04 17:25:02 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+         pad: more preroll lock to basesink
+         Move the preroll lock to basesink where it belongs.
+
+2011-03-04 16:05:44 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-bufferpool.txt:
+         docs: update bufferpool draft
+
+2011-03-04 12:06:11 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbufferpool.c:
+         bufferpool: add more debug info
+
+2011-03-03 18:38:32 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: add debug
+
+2011-03-03 18:21:31 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: add some more debug info
+
+2011-03-03 16:31:49 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         bufferpool: add caps to the config
+         Add the caps to the configuration parameters of the pool.
+         Initialize the private data
+
+2011-03-02 11:57:40 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2011-03-02 11:57:06 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+         buffer: release buffer to pool in dispose
+         Use the dispose method to release the buffer to the pool when it is configured.
+
+2011-02-22 12:35:45 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         buffer: add pool to buffer structure
+         Keep a pointer to the bufferpool. Release the buffer to the pool when
+         finalizing. Make sure the pool sets itself as the pool member of buffers that it
+         sends out.
+
+2011-02-22 12:35:06 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: add pool flags type
+
+2011-02-22 11:05:09 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * win32/common/libgstreamer.def:
+         docs: update bufferpool docs
+
+2011-02-21 18:43:19 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: Refactor stopping of the pool
+         Move some methods around.
+         Make sure we check for config parsing errors.
+         Increment the outstanding buffers before calling acquire so that we can be sure
+         that set_active() doesn't free the pool from under us.
+
+2011-02-21 17:33:38 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: Rework buffer management a little
+         Add start/stop methods to allow for bulk allocation of buffers.
+         Free buffers only when all outstanding buffers returned.
+         Make things more threadsafe wrt flushing and starting/stopping by
+         keeping track of start and stop method calls.
+
+2011-02-21 12:18:41 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: memory management cleanups
+         Use a lock to protect concurrect execution of set_config and set_active.
+         Start freeing the buffers when flushing and all buffers are returned to the
+         pool.
+         Make a copy of the config to avoid crashing with concurrent access.
+
+2011-02-18 16:35:46 +0100  Stefan Kost <ensonic@users.sf.net>
+
+       * gst/gstbufferpool.c:
+         bufferpool: also allow NULL params in _acquire
+
+2011-02-18 16:15:30 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: more updates
+         Keep track if the buffer is configured and block activation when not configured
+         yet.
+         Keep track of outstanding buffers and disallow configuration when not all
+         buffers are returned to the pool. We need to do this or else we might end up
+         with wrong buffers in the pool.
+         Add return value to set_active.
+         Small cleanups. Fix finalize.
+
+2011-02-18 12:50:21 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: rename 'flushing' to 'active'
+         Rename the flushing variable and methods to active to better match
+         the other gstreamer name conventions
+
+2011-02-17 18:37:19 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+         bufferpool: prealloc when unset flushing
+         According to the design doc we need to prealloc buffers when we unset the
+         flushing state, not in set_config.
+         Set the flushing state better.
+
+2011-02-17 17:29:27 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstquark.c:
+       * gst/gstquark.h:
+         bufferpool: use quarks for structure fields
+
+2011-02-17 16:46:51 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+       * win32/common/libgstreamer.def:
+         bufferpool: use GstStructure to configure the pool
+         Use a GstStructure to provide the pool with the right configuration. Also
+         provide some helper methods to configure such a structure.
+         don't pass the config in alloc_buffer, pool implementation will already have
+         parsed it during set_config.
+         Update defs
 
-       * gst/gstcaps.c:
-       * gst/gststructure.c:
-         caps,structure: trim trailing whitespace
+2011-02-17 12:55:37 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-2011-03-04 08:28:25 +1000  Jonathan Matthew <jonathan@d14n.org>
+       * win32/common/libgstreamer.def:
+         fix defs
 
-       * gst/gstcaps.c:
-         caps: don't create broken caps for invalid media types
-         Check if structure has been created before appending it to the caps. Free the
-         caps in the case of an error to not conceal it be returning empty caps.
-         Fixes #642271
+2010-11-02 18:56:29 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-2011-03-07 16:21:47 +0200  Stefan Kost <ensonic@users.sf.net>
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * gst/gstbufferpool.c:
+       * gst/gstbufferpool.h:
+         bufferpool: add simple bufferpool helper object
 
-       * tests/examples/helloworld/helloworld.c:
-         examples: update hello world example
-         Our helloworld example thatw e reference from the manual has been a bit
-         complicated to serve a first contact with gstreamer. Since we have and
-         promote playbin2 as a playback api use it here.
-         Based on work from Mathias Hasselmann <mathias.hasselmann@gmx.de>
-         Fixes #424143
+2011-03-02 11:08:34 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+         Conflicts:
+         gst/gstregistry.h
 
 2011-03-02 13:55:36 +0530  Arun Raghavan <arun.raghavan@collabora.co.uk>
 
          docs: small updates as suggested on a blog
          Link from convinience api to the underlying api.
 
+2011-02-28 10:05:47 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+         meta: add timing metadata
+
+2011-02-28 10:05:38 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.h:
+         miniobject: fix whitespace
+
+2011-02-28 09:39:44 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstmeta.c:
+         tests: add memory unit test
+
+2011-02-27 20:54:58 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+         meta: simplify a bit
+
+2011-02-27 20:42:15 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * win32/common/libgstreamer.def:
+         meta: add default memory metadata
+         Add a metadata implementation for normall malloced memory.
+
+2011-02-27 19:40:45 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstmeta.h:
+       * tests/check/gst/gstmeta.c:
+       * win32/common/libgstreamer.def:
+         meta: separate add and get methods
+         Make separate api for getting and adding metadata. This allows us to pass extra
+         parameters to the init functions when creating metadata, which is needed for
+         specific API implementations.
+         Add beginnings of memory metadata.
+
+2011-02-27 12:21:32 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-buffer2.txt:
+       * gst/gstminiobject.h:
+       * win32/common/libgstreamer.def:
+         docs: update docs and defs
+
+2011-02-26 18:14:36 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: remove useless method
+         Remove the method to retrieve metadata by api. One will always use the
+         GstMetaInfo to get metadata.
+
+2011-02-25 16:31:11 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+         buffer: remove owner_priv now that we have metadata
+         Now that we have metadata we can remove the owner_priv field.
+
+2011-02-25 13:23:19 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: fix defs
+
+2011-02-25 13:15:25 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * gst/Makefile.am:
+       * gst/gst.c:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbuffermeta.c:
+       * gst/gstbuffermeta.h:
+       * gst/gstmeta.c:
+       * gst/gstmeta.h:
+       * tests/check/Makefile.am:
+       * tests/check/gst/gstbuffermeta.c:
+       * tests/check/gst/gstmeta.c:
+         metadata: Rename to GstMeta
+         Rename to the shorter GstMeta
+         Add docs
+         Add api to get metadata by API
+
+2011-02-25 10:37:07 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: fix defs
+
+2010-11-15 11:49:24 +0100  Philippe Normand <phil at base-art.net>
+
+       * gst/gstbuffer.c:
+         buffer: fix memory corruption
+
+2010-04-07 11:34:23 +0200  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstbuffermeta.c:
+       * tests/check/gst/gstbuffermeta.c:
+         buffermeta: fix compilation
+
+2010-02-26 13:11:43 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-buffer2.txt:
+       * gst/gstbuffermeta.h:
+         updates
+
+2009-12-27 22:03:32 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstbuffermeta.c:
+         meta: improve test a little
+
+2009-12-17 12:34:42 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/Makefile.am:
+       * gst/gst.c:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbuffermeta.c:
+       * gst/gstbuffermeta.h:
+       * tests/check/Makefile.am:
+       * tests/check/gst/gstbuffermeta.c:
+       * win32/common/libgstreamer.def:
+         buffermeta: add beginnings of buffer metadata
+         Add first implementation of arbitrary buffer metadata. We use a simple linked
+         linked of slice allocated metadata chunks. Future implementations could use
+         something more performant.
+         Add get, remove, iterate methods to handle the metadata.
+
+2011-02-25 10:19:25 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/design/draft-buffer2.txt:
+         design: add api tag
+         We want to find metadata based on the API it implements and based on the
+         specific implementation.
+
 2011-02-24 17:11:49 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * gst/gsturi.c:
          gsturi.c:854:16: error: unused variable 'abs_clean'
          gsturi.c:788:1: error: 'gst_file_utils_canonicalise_path' defined but not used
 
-2011-02-24 15:32:00 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2011-02-24 15:32:00 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * plugins/elements/gstfilesink.c:
+       * plugins/elements/gstfilesrc.c:
+       * tests/check/elements/filesrc.c:
+         filesrc, filesink: fix URI creation regression for non-absolute locations
+         Passing e.g. location=foo would lead to warnings because g_filename_to_uri()
+         wants an absolute file path and returns NULL otherwise. Use brand-new
+         gst_filename_to_uri() instead, which will try harder to create a proper
+         URI for us.
+         Also add unit test.
+
+2011-02-24 15:18:43 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gsturi.c:
+       * gst/gsturi.h:
+       * win32/common/libgstreamer.def:
+         uri: add gst_filename_to_uri() that takes relative filenames
+         Add function that (unlike the GLib equivalent) also accepts paths that
+         aren't absolute and will clean up relative markers such as ./ and ../
+         before forming a URI.
+         Fixes warnings with e.g. filesrc location=foo ! typefind caused by the
+         recent switch to g_filename_to_uri(), but also actually creates valid
+         URIs for the first time.
+         Windows code paths could need some more work, e.g. we don't clean up
+         the relative markers there for now (because path could have \ and /
+         as separators).
+         API: gst_filename_to_uri()
+
+2011-02-24 16:20:01 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/check/gst/gstabi.c:
+       * tests/check/libs/libsabi.c:
+         tests: refix the tests (missing #endif)
+
+2011-02-24 16:11:17 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/check/Makefile.am:
+         Makefile.am: add new abi headers to nodist_HEADERS
+
+2011-02-21 11:24:45 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tools/gst-launch.1.in:
+       * tools/gst-launch.c:
+         gst-launch: add index support
+         When option "-i" is given, set an index object on the pipeline and compute
+         statistics for all index writers. Print a sumary when shutting down the
+         pipeline.
+
+2011-02-24 15:12:14 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/check/libs/libsabi.c:
+       * tests/check/libs/struct_arm.h:
+         tests: add abi check data for ARM (libs)
+
+2011-02-24 15:02:37 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * tests/check/gst/gstabi.c:
+       * tests/check/gst/struct_arm.h:
+         tests: add abi check data for ARM
+
+2011-02-24 13:55:35 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+         buffer: add owner private as intermediate solution
+         Add an owner private field where the owner of a buffer can store some extra
+         information. We can use this to implement most of the subclassing that happens
+         now. Later this will be removed and replaced by arbitrary buffer metadata.
+
+2011-02-24 10:28:20 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+         caps: remove poisoning
+
+2011-02-23 16:48:00 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbufferlist.c:
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+       * gst/gstminiobject.h:
+       * gst/gstquery.c:
+         miniobject: cleanups
+         Use the stored size in the miniobject to free the miniobject.
+         Refactor some init methods.
+
+2011-02-23 15:43:49 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting guide
+
+2011-02-23 12:54:21 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting guide
+
+2011-02-23 12:44:54 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.h:
+         caps: warn when make_writable result is ignored
+
+2011-02-23 12:08:03 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstreamer.def:
+         defs: fix defs
+
+2011-02-23 12:01:55 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+         gst: fix type registration
+         We need to have the types of the miniobjects before registering the
+         tranforms.
+
+2011-02-23 12:01:16 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstelementfactory.c:
+         elementfactory: improve caps string management
+
+2011-02-23 12:00:42 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstminiobject.c:
+         miniobject: clear flags in init
+
+2011-02-23 12:33:58 +0200  Stefan Kost <ensonic@users.sf.net>
+
+       * docs/gst/running.xml:
+         docs: tell that ORC_CODE can contain a list of flags
+
+2011-02-23 10:31:44 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+       * gst/gstminiobject.h:
+         miniobject: fix flags
+
+2011-02-22 19:30:59 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstevent.c:
+         fix compilation after rebase
+
+2010-11-02 13:31:25 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gst.c:
+       * gst/gst_private.h:
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * plugins/elements/gsttypefindelement.c:
+         improve type registration
+
+2010-11-02 12:58:14 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstbufferlist.c:
+       * gst/gstcaps.c:
+       * gst/gstelementfactory.c:
+       * gst/gstminiobject.c:
+       * gst/gstregistrychunks.c:
+         fix compilation
+
+2009-12-07 20:32:12 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.h:
+       * gst/gstbufferlist.h:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstevent.h:
+       * gst/gstmessage.h:
+       * gst/gstminiobject.h:
+       * gst/gstquery.h:
+         fix macros
+
+2009-12-05 15:18:09 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: set boxed type correctly
+
+2009-12-05 14:16:57 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+         miniobject: small fixes
+         Make dataflow happen.
+
+2009-12-04 23:52:32 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstbuffer.c:
+       * gst/gstcaps.c:
+       * gst/gstevent.c:
+       * gst/gstmessage.c:
+       * gst/gstminiobject.c:
+       * gst/gstpad.c:
+       * gst/gstquery.c:
+       * gst/gsttaglist.c:
+       * gst/gstvalue.c:
+       * libs/gst/base/gstbasesink.c:
+       * plugins/elements/gstfakesink.c:
+       * plugins/elements/gstfakesrc.c:
+       * plugins/elements/gstfilesrc.c:
+       * plugins/elements/gstidentity.c:
+       * plugins/elements/gsttypefindelement.c:
+       * tests/check/gst/gstbuffer.c:
+       * tests/check/gst/gstminiobject.c:
+       * tests/check/gst/gstutils.c:
+       * tests/check/gst/gstvalue.c:
+       * tests/check/gst/struct_x86_64.h:
+       * tools/gst-inspect.c:
+         miniobject: more boxed type fixing
+         More miniobject fixing, leaks horribly somewhere..
+
+2009-12-04 22:32:38 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * plugins/elements/gstfilesink.c:
-       * plugins/elements/gstfilesrc.c:
-       * tests/check/elements/filesrc.c:
-         filesrc, filesink: fix URI creation regression for non-absolute locations
-         Passing e.g. location=foo would lead to warnings because g_filename_to_uri()
-         wants an absolute file path and returns NULL otherwise. Use brand-new
-         gst_filename_to_uri() instead, which will try harder to create a proper
-         URI for us.
-         Also add unit test.
+       * gst/gstcaps.h:
+       * gst/gstevent.c:
+       * gst/gstmarshal.list:
+       * gst/gstmessage.c:
+       * gst/gstminiobject.c:
+       * gst/gstpad.c:
+         miniobject: make queries a boxed type
+         More minionject stuff.
 
-2011-02-24 15:18:43 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2009-12-03 20:49:30 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * docs/gst/gstreamer-sections.txt:
-       * gst/gsturi.c:
-       * gst/gsturi.h:
-       * win32/common/libgstreamer.def:
-         uri: add gst_filename_to_uri() that takes relative filenames
-         Add function that (unlike the GLib equivalent) also accepts paths that
-         aren't absolute and will clean up relative markers such as ./ and ../
-         before forming a URI.
-         Fixes warnings with e.g. filesrc location=foo ! typefind caused by the
-         recent switch to g_filename_to_uri(), but also actually creates valid
-         URIs for the first time.
-         Windows code paths could need some more work, e.g. we don't clean up
-         the relative markers there for now (because path could have \ and /
-         as separators).
-         API: gst_filename_to_uri()
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstelementfactory.c:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstmessage.c:
+         messages: make message a simple boxed type
 
-2011-02-24 16:20:01 +0200  Stefan Kost <ensonic@users.sf.net>
+2009-12-02 21:21:48 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * tests/check/gst/gstabi.c:
-       * tests/check/libs/libsabi.c:
-         tests: refix the tests (missing #endif)
+       * gst/gstbuffer.c:
+       * gst/gstbufferlist.c:
+       * gst/gstbufferlist.h:
+       * gst/gstbus.c:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstminiobject.c:
+       * gst/gstminiobject.h:
+         miniobject: work on making caps a boxed type
+         More work on making miniobject a simple allocated struct.
 
-2011-02-24 16:11:17 +0200  Stefan Kost <ensonic@users.sf.net>
+2009-11-29 00:21:24 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * tests/check/Makefile.am:
-         Makefile.am: add new abi headers to nodist_HEADERS
+       * gst/gstbuffer.c:
+       * gst/gstbuffer.h:
+       * gst/gstcaps.h:
+       * gst/gstevent.h:
+       * gst/gstmessage.h:
+       * gst/gstminiobject.h:
+       * gst/gstquery.h:
+         miniobject: make miniobject a boxed type
+         First attempt at making miniobject a simple boxed type.
 
-2011-02-21 11:24:45 +0200  Stefan Kost <ensonic@users.sf.net>
+2011-02-22 19:09:48 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * tools/gst-launch.1.in:
-       * tools/gst-launch.c:
-         gst-launch: add index support
-         When option "-i" is given, set an index object on the pipeline and compute
-         statistics for all index writers. Print a sumary when shutting down the
-         pipeline.
+       * libs/gst/base/gstadapter.h:
+       * libs/gst/base/gstbasesink.c:
+       * libs/gst/base/gstbasesink.h:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasesrc.h:
+       * libs/gst/base/gstbasetransform.h:
+       * libs/gst/base/gstdataqueue.c:
+       * libs/gst/base/gstdataqueue.h:
+         libs: cleanups for 0.11
+         Remove deprecated stuff, fix padding, rearrange methods.
 
-2011-02-24 15:12:14 +0200  Stefan Kost <ensonic@users.sf.net>
+2011-02-22 16:04:12 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * tests/check/libs/libsabi.c:
-       * tests/check/libs/struct_arm.h:
-         tests: add abi check data for ARM (libs)
+       * gst/gstbin.h:
+       * gst/gstbuffer.h:
+       * gst/gstclock.c:
+       * gst/gstclock.h:
+       * gst/gstevent.c:
+       * gst/gstevent.h:
+       * gst/gstindex.h:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstplugin.h:
+       * gst/gstregistry.h:
+       * gst/gstsegment.h:
+       * gst/gstsystemclock.c:
+       * gst/gstsystemclock.h:
+       * gst/gsttask.c:
+       * gst/gsttask.h:
+         cleanups
+         Fix padding, remove deprecated symbols.
 
-2011-02-24 15:02:37 +0200  Stefan Kost <ensonic@users.sf.net>
+2011-02-22 15:08:51 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * tests/check/gst/gstabi.c:
-       * tests/check/gst/struct_arm.h:
-         tests: add abi check data for ARM
+         Merge branch 'master' into 0.11
 
-2011-02-23 12:33:58 +0200  Stefan Kost <ensonic@users.sf.net>
+2011-02-22 14:11:59 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
-       * docs/gst/running.xml:
-         docs: tell that ORC_CODE can contain a list of flags
+         Merge branch 'master' into 0.11
+         Conflicts:
+         configure.ac
+         gst/gstelement.c
+         gst/gstelement.h
+         gst/gstpad.c
+         gst/gstutils.c
+         libs/gst/base/Makefile.am
+         libs/gst/check/Makefile.am
+         libs/gst/controller/Makefile.am
+         libs/gst/dataprotocol/Makefile.am
+         libs/gst/net/Makefile.am
+         win32/common/libgstreamer.def
 
 2011-02-14 18:05:09 -0300  Thiago Santos <thiago.sousa.santos@collabora.co.uk>
 
        * libs/gst/net/Makefile.am:
          libs: Fix GIR build for srcdir != builddir
 
+2010-12-08 17:51:10 +0100  Edward Hervey <edward.hervey@collabora.co.uk>
+
+         Merge commit '0eaa25cbf5c0e4bf86545fb67c181a0ecd2f19c7' into 0.11
+
 2010-12-08 12:17:35 +0200  Stefan Kost <ensonic@users.sf.net>
 
        * libs/gst/base/gstbasesink.c:
          docs: gst_error_get_message() returns string in UTF-8, not current locale
          We tell gettext to return everything in UTF-8 encoding.
 
+2010-12-05 20:17:08 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * gst/gstpad.c:
+         pad: register gst_pad_get_fixed_caps_func() with the debug log system
+
 2010-12-07 18:35:56 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
        * libs/gst/base/gstadapter.c:
          docs: gst: more gobject introspection annotations
          Many of these are superfluous, added for clarity.
 
-2010-12-05 20:17:08 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+2010-12-07 18:40:12 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
+       * docs/gst/gstreamer-sections.txt:
+         docs: update docs
+
+2010-12-07 18:33:51 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * win32/common/libgstcontroller.def:
+       * win32/common/libgstdataprotocol.def:
+       * win32/common/libgstreamer.def:
+         defs: update defs
+
+2010-12-07 18:32:53 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/Makefile.am:
+         check: disable ABI checks
+
+2010-12-07 18:32:34 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting document
+
+2010-12-07 18:14:38 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstcompat.h:
+       * gst/gstghostpad.c:
        * gst/gstpad.c:
-         pad: register gst_pad_get_fixed_caps_func() with the debug log system
+       * gst/gstpad.h:
+       * gst/gstutils.c:
+       * libs/gst/base/gstbasesrc.c:
+       * libs/gst/base/gstbasetransform.c:
+       * tests/check/gst/gstpad.c:
+         pad: remove get_caps_reffed variants
+         Make the _get_caps functions behave like the _get_caps_reffed variants and
+         remove the _reffed variants. This means that _get_caps doesn't return a writable
+         caps anymore and an explicit _make_writable() is needed before modifying the
+         caps.
+
+2010-12-07 18:12:53 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: update porting doc
+
+2010-12-07 16:52:47 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+         pad: Clean up .h file
+
+2010-12-07 15:53:56 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+         Merge branch 'master' into 0.11
+
+2010-12-07 15:33:04 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * gst/gstbin.c:
+       * gst/gstcompat.h:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstelementdetails.h:
+       * gst/gstelementfactory.c:
+       * gst/gstelementfactory.h:
+       * gst/gstelementmetadata.h:
+       * gst/gstpipeline.c:
+       * gst/gstregistrychunks.c:
+       * tests/check/gst/struct_x86_64.h:
+       * tools/gst-inspect.c:
+       * tools/gst-xmlinspect.c:
+         element: rework GstElementDetails
+         Clean up the GstElement structure
+         Replace GstElementDetails with metadata
+
+2010-12-07 15:31:27 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstplugin.h:
+       * tests/check/gst/gstplugin.c:
+         plugin: remove deprecated methods
+         Remove more deprecated methods and fix unit test.
+
+2010-12-07 15:21:06 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/libs/gdp.c:
+         check: remove deprecated tests
+
+2010-12-07 15:20:12 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * tests/check/gst/gstobject.c:
+         check: fix object unit test
+
+2010-12-07 15:19:34 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * gst/gstobject.c:
+       * gst/gstobject.h:
+         object: fix docs
 
 2010-12-07 13:19:10 +0100  Edward Hervey <edward.hervey@collabora.co.uk>
 
        * docs/random/ensonic/plugindocs.txt:
          docs: some notes about our plugin docs workflow
 
+2010-12-07 11:58:34 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * docs/random/porting-to-0.11.txt:
+       * gst/gstobject.c:
+       * gst/gstobject.h:
+       * gst/gstpadtemplate.c:
+         object: Removed deprecated fields and methods
+         Make GstObject extend from GInitiallyUnowned, remove the FLOATING flag and use
+         GObject methods for managing the floating ref.
+         Remove class lock, it was a workaround for a glib < 2.8 bug.
+         Remove the parent-set and parent-unset signals, attempt to implement with notify
+         but disabled because deadlocks in deep-notify.
+
+2010-12-06 20:03:46 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: mention removal of protocol property
+
+2010-12-06 19:40:03 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/controller/gstcontroller.c:
+       * libs/gst/controller/gstcontroller.h:
+       * libs/gst/dataprotocol/dataprotocol.c:
+       * libs/gst/dataprotocol/dataprotocol.h:
+         libs: remove deprecated code
+
+2010-12-06 19:24:30 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         docs: update porting doc
+
+2010-12-06 19:18:31 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/gst/gstreamer-sections.txt:
+       * docs/gst/gstreamer.types.in:
+       * docs/plugins/gstreamer-plugins.args:
+       * gst/Makefile.am:
+       * gst/gst.h:
+       * gst/gstbin.c:
+       * gst/gstcaps.c:
+       * gst/gstcaps.h:
+       * gst/gstconfig.h.in:
+       * gst/gstelement.c:
+       * gst/gstelement.h:
+       * gst/gstghostpad.c:
+       * gst/gstobject.c:
+       * gst/gstobject.h:
+       * gst/gstpad.c:
+       * gst/gstpad.h:
+       * gst/gstpipeline.c:
+       * gst/gstpipeline.h:
+       * gst/gstplugin.c:
+       * gst/gstplugin.h:
+       * gst/gstregistry.h:
+       * gst/gstregistrybinary.c:
+       * gst/gstutils.c:
+       * gst/gstutils.h:
+       * gst/gstxml.c:
+       * gst/gstxml.h:
+       * tools/gst-inspect.c:
+       * tools/gst-launch.c:
+       * tools/gst-xmlinspect.c:
+         remove deprecated symbols and methods
+
+2010-12-06 13:51:50 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/porting-to-0.11.txt:
+         porting: Add porting doc
+
+2010-12-06 13:48:31 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         plan: fix typo
+
+2010-11-11 10:38:57 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         plan: add something about GVariant registry
+
+2010-11-08 18:39:39 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/use-cases-0.11.txt:
+         add some use-cases
+
+2010-11-08 14:08:36 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         more updates
+
+2010-11-08 12:14:12 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         more updates
+
+2010-11-08 11:18:05 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         more updates
+
+2010-11-04 19:30:58 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * docs/random/plan-0.11.txt:
+         work on todo list for 0.11 work
+
+2010-12-06 13:21:45 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * android/base.mk:
+       * android/controller.mk:
+       * android/dataprotocol.mk:
+       * android/elements.mk:
+       * android/gst-inspect.mk:
+       * android/gst-launch.mk:
+       * android/gst-plugin-scanner.mk:
+       * android/gst.mk:
+       * android/indexers.mk:
+       * android/net.mk:
+       * configure.ac:
+       * gst/Makefile.am:
+       * libs/gst/base/Makefile.am:
+       * libs/gst/check/Makefile.am:
+       * libs/gst/controller/Makefile.am:
+       * libs/gst/dataprotocol/Makefile.am:
+       * libs/gst/net/Makefile.am:
+       * tools/gst-feedback-m.m:
+       * tools/gstreamer-completion:
+         more 0.10 -> 0.11
+
+2010-12-06 12:03:29 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
+
+       * configure.ac:
+         configure: open 0.11 branch
+
 2010-12-06 11:18:01 +0100  Wim Taymans <wim.taymans@collabora.co.uk>
 
        * gst/gstpoll.c:
index 383dfc7..f6ddc4a 100644 (file)
@@ -142,13 +142,11 @@ include $(top_srcdir)/common/coverage/lcov.mak
 
 # Do not run the check-exports test in case any option which causes the API to
 # change has been used
-if !GST_DISABLE_LOADSAVE
 if !GST_DISABLE_REGISTRY
 if !GST_DISABLE_TRACE
 CHECK_EXPORTS = check-exports
 endif
 endif
-endif
 
 check: $(CHECK_EXPORTS) check-enum-gettypes
 
diff --git a/NEWS b/NEWS
index 1149ebb..24a61f4 100644 (file)
--- a/NEWS
+++ b/NEWS
-This is GStreamer 0.10.35 "Nuclear Fission"
+This is GStreamer 0.11.1 "Sweet New Blossom"
 
-Changes since 0.10.34:
+New featues in 0.11.1:
 
-      * work around GLib atomic ops API change
-      * some minor win32/mingw fixes
-      * don't use G_CONST_RETURN in public headers
-
-Bugs fixed since 0.10.34:
-
-      * 652211 : Use const instead G_CONST_RETURN
-
-Changes since 0.10.33:
-
-      * Fix multiqueue thread-safety regression
-      * Don't set artificial 0-timestamp on first packet for TIME-based live sources
-      * Otherwise identical to the previous release (0.10.33)
-
-Bugs fixed since 0.10.33:
-
-      * 649369 : basesrc: do not set first buffer timestamp to 0 for live sources
-      * 649878 : multiqueue regression: gst_single_queue_new not MT-safe
-
-Changes since 0.10.32:
-
-      * atomicqueue: add an atomic/lock-free queue structure based
-      * bufferlist: improve _add*() performance
-      * bus: in _add_watch() honour any per-thread default main context set via g_main_thread_push_thread_default()
-      * caps: new gst_caps_intersect_full() to intersect in different modes
-      * clock: add functions to re-init existing periodic GstClockIDs
-      * event: add QoS type (overflow, underflow, throttle) for QoS events
-      * ghostpad: The internally linked pad of the proxypad is the ghostpad
-      * gstpoll: retry reading the control socket to release properly all wakeups
-      * message: new progress message API for asynchronous operations
-      * pad: unlock before freeing the pad cache to avoid deadlock
-      * pad: better handling for when parent goes away during data/query/event flow
-      * parse-launch: allow element names to begin with digits
-      * pluginloader: call gst-plugin-scanner with the right arch on OSX, fixing hangs with firefox
-      * registry: fixes elements (features) disappearing if a plugin or plugin file is renamed
-      * structure: Add "(date)" as a type abbreviation of GDate
-      * structure: Don't allow invalid GDates in all structures and don't allow NULL GDates in taglists
-      * taglist: add a new "encoded-by" tag
-      * uri: add gst_filename_to_uri() that takes relative filenames
-      * utils: add gst_element_factory_can_{src|sink}_{any|all}_caps() to replace can_{sink,src}_caps()
-      * baseparse: new GstBaseParse class for parsers
-      * basesink: improve rate, duration, and average duration calculation
-      * basesink: use new QoS types and add add "throttle-time" property
-      * basesrc: Handle tag and custom downstream events the same
-      * basesrc: keep downstream caps order when fixating, to honour downstream preferences when negotiating
-      * basesrc: Return FALSE if we don't handle an event
-      * basesrc: Send synchronized custom downstream/both events downstream from the streaming thread
-      * basetransform: Be smarter with pad allocs
-      * basetransform: Check for pad alloc caps when suggestion is not fixed
-      * basetransform: Retain caps order when getting caps, to honour downstream preferences when negotiating
-      * funnel: new N-to-1 pipe fitting element imported from farsight
-      * fakesink: print buffer flags
-      * filesink: Fix escaping of URIs
-      * file{sink,src}: Check if non-URI characters are escaped, but only for the URI not the location property
-      * filesrc, filesink: fix URI creation regression for non-absolute locations
-      * filesrc: Fix escaping of file uris
-      * inputselector: Hold the selector lock while reading properties of the active pad
-      * inputselector: Make sure that EOS is always sent downstream for the active pad
-      * inputselector: Return GST_FLOW_OK until the selected pad pushed something downstream
-      * inputselector: Stop waiting for a pad switch when the pad is flushing
-      * multiqueue: fix some potential corner-case deadlocks and some leaks
-      * multiqueue: handle arbitrary sink + source pad naming
-      * queue2: don't read beyond the end of file upstream in pull mode; leak fixes
-      * plugins: make query and event functions more thread-safe, protect against parent-pad disappearing
-      * gst-launch: add GstIndex support
-
-Bugs fixed since 0.10.32:
-
-     * 642356 : [Index] review api and add an example
-      * 402141 : gst_element_factory_can_{sink,src}_caps seems to be broken
-      * 518857 : [API] GstBaseParse: new base class for parsers
-      * 604094 : registry: do not remove features when removing a cached plugin that no longer is present
-      * 615357 : [macosx] Handle multi-arch plugin-scanner
-      * 617045 : [caps] New method for intersecting caps while retaining order
-      * 639674 : parse-launch: improve parsing resilience (for escapes at end of string)
-      * 639962 : design docs: Fix a few typos and a think
-      * 640071 : pluginloader: do not leak the description string of blacklisted plugin
-      * 640437 : design docs: fix 2 typos in part-MT-refcounting
-      * 640502 : fix a few typos
-      * 640622 : gst_element_link_pads_full function return wrong error information
-      * 640675 : high cpu-load with 0.10.32 release
-      * 640850 : GstElement: Fix warning with GCC 4.6
-      * 641212 : gst-uninstalled: use $GST_PREFIX variable
-      * 641928 : gst_pad_push fast path races with pad deactivation
-      * 642071 : Incorrect comparing of number of source and sink links when parsing a launch string
-      * 642130 : [basetransform] Check for pad alloc caps when suggestion is not fixed
-      * 642271 : crash in gst_caps_structure_intersect, encoder_match_media_type
-      * 642373 : [basetransform] Avoid too may pad allocs
-      * 642393 : [filesrc] Fails setting the same uri it's setting in the uri queries.
-      * 642504 : [mingw/cygwin build] correctly export plugin description
-      * 642522 : gstvalue.c does not include a deserialize function for uchar
-      * 642869 : gst_index_new: documentation typo
-      * 643301 : Adding a buffer to a buffer list iterates the list
-      * 643455 : [regression] Lots of dropouts in Empathy voip calls
-      * 644935 : [inputselector] During switching of streams it can happen that all pads returned not-linked last
-      * 645022 : GstTask: typo in GST_TASK_BROADCAST - g_cond_breadcast should probably be g_cond_broadcast
-      * 645267 : build: fix build with -Werror with GCC 4.6.0
-      * 645595 : bytereader, bytewriter: fix warnings when using inline functions with g++
-      * 645746 : [gstpoll] Regression causes 100% cpu usage in multifdsink
-      * 645877 : commit 14d7db1 causes cpu spinning and other bus weirdness
-      * 645931 : [gstmultiqueue] fix arbitrary sink + source pad naming
-      * 646118 : [gstmultiqueue] if arbitrary sink number is specified by caller, use this as single queue id
-      * 646341 : [baseparse] Add a queued flow return so parsers can keep frames in a queue
-      * 646531 : GST_BOILERPLATE: don't use " type " as both a variable name and a macro argument
-      * 646566 : Protect against Pad-Parent disappearing
-      * 646569 : poll: don't call WSAWaitForMultipleEvents with no events
-      * 646624 : GstBin: regression: creating too many bins fails, exhausting allowed file descriptor limit
-      * 646811 : baseparse: deadlock in gst_base_parse_set_index
-      * 646971 : iterator: resync to avoid infinite loop
-      * 647005 : GstBus: Only create the socketpair for async message delivery if required
-      * 647131 : recent multiqueue changes break DVD playback (again)
-      * 647293 : Fix pad callbacks so they handle when parent goes away
-      * 647763 : [bus] Bus is leaked if a watch is installed in the default main context
-      * 647844 : baseparse: Remove unused but set variable
-      * 647922 : [introspection] Needs to call gst_init() before anything else
-      * 648199 : pad: potential deadlock / crash when freeing cache
-      * 648215 : basetransform: unref in wrong place
-      * 648220 : Regression: videoscale fails to negotiate for PAR transformation
-      * 648297 : [bus] regression: critical assertion failure
-      * 649195 : [miniobject] Fix dup_mini_object function to handle NULL gvalues
-      * 635718 : [basesrc] custom, non-OOB events aren't pushed downstream
-      * 625396 : gst_debug_remove_log_function doesn't remove default log handler
-      * 640771 : amarok doesn't start with new phonon gstreamer
-      * 646972 : queue2: Fixes memory leak on out_flushing error in gst_queue2_create_read
-      * 640665 : basesink: drops too many buffers when there's no duration
-
-API additions since 0.10.32:
-
-      * gst_atomic_queue_length()
-      * gst_atomic_queue_new()
-      * gst_atomic_queue_peek()
-      * gst_atomic_queue_pop()
-      * gst_atomic_queue_push()
-      * gst_atomic_queue_ref()
-      * gst_atomic_queue_unref()
-      * gst_buffer_list_iterator_get_type()
-      * gst_caps_intersect_full()
-      * gst_caps_intersect_mode_get_type()
-      * gst_clock_periodic_id_reinit()
-      * gst_element_factory_can_sink_all_caps()
-      * gst_element_factory_can_sink_any_caps()
-      * gst_element_factory_can_src_all_caps()
-      * gst_element_factory_can_src_any_caps()
-      * gst_event_new_qos_full()
-      * gst_event_parse_qos_full()
-      * gst_filename_to_uri()
-      * gst_message_new_progress()
-      * gst_message_parse_progress()
-      * gst_parse_context_get_type()
-      * gst_progress_type_get_type()
-      * gst_qos_type_get_type()
-      * GST_TAG_ENCODED_BY
-      * gst_base_parse_add_index_entry()
-      * gst_base_parse_convert_default()
-      * gst_base_parse_frame_free()
-      * gst_base_parse_frame_get_type()
-      * gst_base_parse_frame_init()
-      * gst_base_parse_frame_new()
-      * gst_base_parse_get_type()
-      * gst_base_parse_push_frame()
-      * gst_base_parse_set_average_bitrate()
-      * gst_base_parse_set_duration()
-      * gst_base_parse_set_frame_rate()
-      * gst_base_parse_set_has_timing_info()
-      * gst_base_parse_set_min_frame_size()
-      * gst_base_parse_set_passthrough()
-      * gst_base_parse_set_syncable()
-      * gst_base_sink_get_throttle_time()
-      * gst_base_sink_set_throttle_time()
-
-API deprecated since 0.10.32:
-
-      * gst_element_factory_can_src_caps()
-      * gst_element_factory_can_sink_caps()
-
-Changes since 0.10.31:
-
-      * GLib requirement is now >= 2.22
-      * New core element: valve (moved from -bad)
-      * New core element: input-selector (N.B. without "select-all" property,
-        use fsfunnel instead) (moved from -bad)
-      * New core element: output-selector (N.B. with different negotiation
-        behaviour by default, set pad-negotiation-mode=active for previous
-        behaviour) (moved from -bad)
-      * Performance improvements for many heavily-used code paths: GstPad,
-        GstPoll, GstClock, GstTask, basesink, basesrc, queue2, multiqueue
-      * gobject-introspection: add annotations for most core API
-      * clock: make sync clock wait lockfree
-      * fdsrc/fdsink: reenable on MSVC
-      * registry: fix GStatBuf definition for win32 when building against older
-        glib (fixes unnecessary rescanning of plugins at start-up)
-      * element: add a more flexible way to get request pads from elements
-      * multiqueue: return upon input when already eos
-      * object: fix creation of default name (when creating more than 100000 elements)
-      * pluginloader: fix hangs on OSX
-      * poll: fixes for (p)select backend (used e.g. on OSX)
-      * poll: refactor and make more lockfree; fixes for win32 and OSX (pselect backend)
-      * registry: don't replace valid existing plugins by blacklisted ones
-      * tags: don't produce duplicated entries when merging same value twice
-      * basesink: preroll fixes for async=false case
-      * basesink: rework position reporting code
-      * basetransform: handle downstream giving a buffer with new caps but invalid size
-
-Bugs fixed since 0.10.31:
-
-      * 635785 : basesrc: fix deadlock
-      * 638599 : GST_PTR_FORMAT causes crashes if GLib-internal printf is used but system provides register_printf_specifier
-      * 503592 : gstpad.c does many ref/unref of peer pad in dataflow
-      * 564056 : Protect against umask(0177)
-      * 607513 : input-selector segfaults in g_object_notify()
-      * 632168 : [gsttask] MSVC thread names for task debugging
-      * 632447 : reduce static memory allocated by the registry
-      * 632557 : [macros] Define restrict keyword if not available
-      * 632778 : Optimisations to GstBaseSink
-      * 632779 : gstdataqueue: Only emit g_cond_signal when needed
-      * 632780 : queue: Remove useless checks from e406f7
-      * 633918 : [fakesink] [PATCH] print sink-message events like a  message and its structure
-      * 634965 : sinks render buffers in state PAUSED when async is FALSE
-      * 635001 : basesink: fix position reporting in PAUSED
-      * 636268 : configure test fails on FreeBSD
-      * 636455 : basesrc: Avoid taking object locks for just checking tag presence
-      * 637057 : [plugin-scanner] gstpoll fails with select backend
-      * 637300 : [API] request pad based on caps
-      * 637549 : build fails: ./.libs/libgstbase-0.10.so: undefined reference to `gst_clock_single_shot_id_reinit'
-      * 637776 : merging the same tag values again produces lists containing duplicates
-      * 638381 : {input,output}-selector: double-check API before release
-      * 638399 : a few typos in GStreamer
-      * 638900 : [GstPoll] Doesn't compile with MinGW
-      * 638941 : registry scan/loading race and inconsistency
-
-API additions since 0.10.31:
-
-      * gst_clock_single_shot_id_reinit()
-      * gst_element_request_pad()
-      * GstElementClass::request_new_pad_full()
-      * gst_poll_get_read_gpollfd()
-      * gst_value_list_merge()
-      * GST_CLOCK_DONE
-
-Changes since 0.10.30:
-
-      * bin: add "message-forward" property to force forwarding of messages that would usually be filtered such as ASYNC_DONE or EOS
-      * bin: improve tracking of source elements for more efficient event dispatch
-      * bufferlist: add function to add a list of buffers
-      * clock: fix racy shutdown clock id leak
-      * element: add support for arbitrary element class / factory details
-      * element: link_many should activate pads if needed
-      * gst: add math-compat.h header
-      * datetime: add GstDateTime API
-      * elementfactory: add utility functions to filter features by type
-      * plugin: load the gst-python plugin loader with G_MODULE_BIND_LAZY
-      * query: add buffering ranges API to retrieve informations about the areas of the stream currently buffered
-      * value: add int64 range type
-      * info: write debugging output to file if GST_DEBUG_FILE environment variable is set
-      * pad: use more efficient g_object_notify_by_pspec() for caps notifies if compiling against new-enough GLib
-      * pipeline: If the currently used clock gets lost update it the next time when going from PAUSED to playing
-      * plugin: add release datetime field to GstPluginDesc and set it if GST_PACKAGE_RELEASE_DATETIME is defined
-      * utils: speed up pad linking utility functions by not trying pads that will never work
-      * adapter: add function to get a list of buffers; support 0-sized buffers
-      * adapter: optimize gst_adapter_take() and gst_adapter_peek() a little
-      * basesink: only answer the SEGMENT query in pull mode
-      * basesrc: return values in stream time for the POSITION query
-      * basetransform: allow the subclass to add new fields to caps when getting new caps from downstream
-      * basetransform: avoid useless memcpy
-      * basetransform: upstream caps-renegotiation fixes
-      * bitreader: add inlined and unchecked versions of the most important functions
-      * bytewriter: add inline and unchecked variants of all important functions
-      * bytewriter: fix possible infinite loop caused by an overflow
-      * queue: add "silent" property to suppress signal emission (for better performance)
-      * queue: avoid unnecessary g_cond_signal() (for better performance)
-      * queue: push newsegment event when linking in PLAYING
-      * queue2: extend ring buffer to support RAM mode
-      * queue2: in download mode, prevent range corruption due to race
-      * queue2: don't send seeks beyond the end of the file upstream in pull mode (fixes apple trailers and youtube/html5 playback in webkit)
-      * multiqueue: flush the data queue if downstream return WRONG_STATE too
-      * gst-inspect: print GST_PARAM_MUTABLE_* property flags
-
-Bugs fixed since 0.10.30:
-
-      * 396774 : Make GstElementDetails extensible
-      * 482147 : [queue] Issue with current time level if source task is not started
-      * 579127 : gst-launch: disable CLOCK_LOST message handling
-      * 594504 : Need a GType of " Date AND Time AND Timezone "
-      * 600004 : underrun signal emits when i tested queue overrun test case from file /gstreamerXXXX/tests/check/element/queue.c
-      * 610366 : [gstcollectpads][doc] Add a reminder for 'data' doc
-      * 611918 : leaky queue might not push newsegment event
-      * 618919 : Registry/Plugin Loading Memory Leak
-      * 619522 : basetransform fix for upstream caps-renegotiation
-      * 621299 : make simple queues faster
-      * 621332 : BaseTransform should disable proxy alloc if downstream changes caps
-      * 622740 : GstPad: Do not call gst_pad_accept_caps() when caps change
-      * 623040 : Add release_datetime field to GstPluginDesc
-      * 623121 : [queue2] downloaded areas of the media are not exposed
-      * 623491 : make *_get_type() thread safe
-      * 623541 : [basetransform] Implement POSITION query
-      * 623622 : [basesink/basesrc] Should return values in stream time for POSITION query
-      * 623806 : [pipeline] Doesn't update the clock if the currently used one gets lost and the start time did not change
-      * 623875 : gstregistrybinary.c compatibility with glib > = 2.25.0
-      * 624203 : gstutils: Make gst_pad_proxy_getcaps() return empty caps if it's what the other side has
-      * 625239 : FTBFS: ./gstreamer-decl.txt:9461: warning: GstTagList has multiple definitions.
-      * 625295 : [info] regression: doesn't flush output stream after every debug print any longer
-      * 625368 : gstdatetime.c doesn't compile in VS 2008
-      * 625862 : [docs] unused symbol GST_CAT_LEVEL_LOG_valist breaks the build
-      * 626027 : [tag] Add GST_TAG_APPLICATION_NAME
-      * 626181 : GstElementFactory: add listing/filtering API
-      * 626651 : [tag] Photography/capture settings tags
-      * 626784 : element: link_many might assert elements are in paused or playing
-      * 627438 : gst: Add a gst_is_initialized() API
-      * 627826 : GstInt64Range type
-      * 627910 : Warnings emitted when -Wcast-qual used
-      * 627959 : [queue2] on-disk buffering failing for AVI container
-      * 628014 : Deprecate GST_FLOW_IS_FATAL/GST_FLOW_IS_SUCCESS
-      * 628174 : New gstvalue checks cause trouble in thoggen
-      * 628176 : [basetransform] Problems with buffer handling in inplace mode
-      * 628408 : Use GDateTime that has been released
-      * 629241 : Build broken with introspection using gobject-introspection from master
-      * 629410 : GstBaseTransform: position query refers to sink pad, not source pad
-      * 629494 : Latest gst-launch.c doesn't build in Visual Studio 2008
-      * 629553 : GstAdapter: timestamp not updated when empty buffer is pushed
-      * 629831 : [API] add gst_structure_take_value() and gst_structure_id_take_value()
-      * 629946 : Enumerations have incorrect names of enum values (GEnumValue.value_name)
-      * 630257 : GST_DEBUG_DUMP_DOT_DIR not working anymore
-      * 630436 : basesink: renderdelay needs to be subtracted in adjust_time()
-      * 630437 : basetransform: Make a WARNING into a DEBUG statement
-      * 630439 : clock: fix racy shutdown clock id leak
-      * 631755 : Fix build with glib 2.21.3
-      * 631853 : [queue2] deadlock when using temp-location and dispatch-properties
-      * 632236 : [gst-inspect] unhelpful uri handler output
-      * 632433 : [basesink] hangs/drops going to PLAYING following flushing step in PAUSED
-      * 632977 : [queue2] qtdemux causes soup to request seeks past the end of the range
-      * 633147 : Simple reverse negotiation pipeline is broken.
-      * 633886 : Visual Studio emits warnings about double defined _USE_MATH_DEFINES
-      * 635031 : [datetime] Fix unix epoch handling
-      * 635389 : Include information on exported packages in GIRs
-      * 635869 : GST_BOILERPLATE_FULL causes warnings in user C++ code
-      * 633176 : recent multiqueue changes break DVD playback
-
-API additions since 0.10.30:
-
-      * gst_is_initialized
-      * gst_buffer_list_iterator_add_list
-      * GstBin:message-forward
-      * GST_TYPE_DATE_TIME
-      * gst_date_time_get_day
-      * gst_date_time_get_hour
-      * gst_date_time_get_microsecond
-      * gst_date_time_get_minute
-      * gst_date_time_get_month
-      * gst_date_time_get_second
-      * gst_date_time_get_time_zone_offset
-      * gst_date_time_get_type
-      * gst_date_time_get_year
-      * gst_date_time_new
-      * gst_date_time_new_from_unix_epoch_local_time
-      * gst_date_time_new_from_unix_epoch_utc
-      * gst_date_time_new_local_time
-      * gst_date_time_new_now_local_time
-      * gst_date_time_new_now_utc
-      * gst_date_time_ref
-      * gst_date_time_unref
-      * gst_tag_list_get_date_time
-      * gst_tag_list_get_date_time_index
-      * GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR
-      * GST_TAG_APPLICATION_DATA
-      * GST_TAG_APPLICATION_NAME
-      * GST_TAG_DATE_TIME
-      * GST_ELEMENT_IS_SOURCE
-      * gst_element_class_set_documentation_uri
-      * gst_element_class_set_icon_name
-      * gst_element_factory_get_documentation_uri
-      * gst_element_factory_get_icon_name
-      * gst_element_factory_list_filter
-      * gst_element_factory_list_get_elements
-      * gst_element_factory_list_is_type
-      * GstElementFactoryListType
-      * GST_ELEMENT_FACTORY_TYPE_ANY
-      * GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS
-      * GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER
-      * GST_ELEMENT_FACTORY_TYPE_DECODABLE
-      * GST_ELEMENT_FACTORY_TYPE_DECODER
-      * GST_ELEMENT_FACTORY_TYPE_DEMUXER
-      * GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER
-      * GST_ELEMENT_FACTORY_TYPE_ENCODER
-      * GST_ELEMENT_FACTORY_TYPE_FORMATTER
-      * GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO
-      * GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY
-      * GST_ELEMENT_FACTORY_TYPE_MUXER
-      * GST_ELEMENT_FACTORY_TYPE_PARSER
-      * GST_ELEMENT_FACTORY_TYPE_PAYLOADER
-      * GST_ELEMENT_FACTORY_TYPE_SINK
-      * GST_ELEMENT_FACTORY_TYPE_SRC
-      * GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER
-      * GST_ELEMENT_FACTORY_KLASS_DECODER
-      * GST_ELEMENT_FACTORY_KLASS_ENCODER
-      * GST_ELEMENT_FACTORY_KLASS_SINK
-      * GST_ELEMENT_FACTORY_KLASS_SRC
-      * GST_ELEMENT_FACTORY_KLASS_MUXER
-      * GST_ELEMENT_FACTORY_KLASS_DEMUXER
-      * GST_ELEMENT_FACTORY_KLASS_PARSER
-      * GST_ELEMENT_FACTORY_KLASS_PAYLOADER
-      * GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER
-      * GST_ELEMENT_FACTORY_KLASS_FORMATTER
-      * GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO
-      * GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO
-      * GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE
-      * GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE
-      * GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA
-      * gst_plugin_feature_list_debug
-      * gst_plugin_feature_rank_compare_func
-      * gst_query_add_buffering_range
-      * gst_query_get_n_buffering_ranges
-      * gst_query_parse_nth_buffering_range
-      * gst_structure_get_date_time
-      * gst_structure_id_take_value
-      * gst_structure_take_value
-      * GST_TYPE_INT64_RANGE
-      * gst_int64_range_get_type
-      * gst_util_fraction_compare
-      * gst_value_get_int64_range_max
-      * gst_value_get_int64_range_min
-      * gst_value_set_int64_range
-      * GST_VALUE_HOLDS_DATE_TIME
-      * gst_adapter_take_list
-      * gst_bit_reader_skip_unchecked
-      * gst_bit_reader_skip_to_byte_unchecked
-      * gst_bit_reader_get_bits_uint16_unchecked
-      * gst_bit_reader_get_bits_uint32_unchecked
-      * gst_bit_reader_get_bits_uint64_unchecked
-      * gst_bit_reader_get_bits_uint8_unchecked
-      * gst_bit_reader_peek_bits_uint16_unchecked
-      * gst_bit_reader_peek_bits_uint32_unchecked
-      * gst_bit_reader_peek_bits_uint64_unchecked
-      * gst_bit_reader_peek_bits_uint8_unchecked
-      * gst_byte_writer_put_int8_unchecked
-      * gst_byte_writer_put_int16_be_unchecked
-      * gst_byte_writer_put_int16_le_unchecked
-      * gst_byte_writer_put_int24_be_unchecked
-      * gst_byte_writer_put_int32_be_unchecked
-      * gst_byte_writer_put_int32_le_unchecked
-      * gst_byte_writer_put_int64_be_unchecked
-      * gst_byte_writer_put_int64_le_unchecked
-      * gst_byte_writer_put_uint8_unchecked
-      * gst_byte_writer_put_uint16_be_unchecked
-      * gst_byte_writer_put_uint16_le_unchecked
-      * gst_byte_writer_put_uint24_be_unchecked
-      * gst_byte_writer_put_uint24_le_unchecked
-      * gst_byte_writer_put_uint32_be_unchecked
-      * gst_byte_writer_put_uint32_le_unchecked
-      * gst_byte_writer_put_uint64_be_unchecked
-      * gst_byte_writer_put_uint64_le_unchecked
-      * gst_byte_writer_put_float32_be_unchecked
-      * gst_byte_writer_put_float32_le_unchecked
-      * gst_byte_writer_put_float64_be_unchecked
-      * gst_byte_writer_put_float64_le_unchecked
-      * gst_byte_writer_put_data_unchecked
-      * gst_byte_writer_fill_unchecked
-
-API deprecated since 0.10.30:
-
-      * GST_FLOW_IS_FATAL
-      * GST_FLOW_IS_SUCCESS
-
-Changes since 0.10.29:
-
-      * GLib requirement was bumped to 2.20, automake requirement to 1.10
-      * bin: unlock gst_element_get_state() on error, instead of hanging forever if no timeout is given
-      * clock: fix refcounting bug in gst_clock_set_master
-      * caps: make sure _normalize() is applied on all structures
-      * info: add new TRACE log level and move refcounting there from LOG level
-      * pad: don't check twice for changed caps per push
-      * pad: fix iterator aggregation of all pads in the internal links fallback
-      * tagsetter: protect tagsetter operations with a lock
-      * value: support short fourccs (esp. serialisation/deserialisation)
-      * adapter: fix _try_to_merge_up(); optimize progressive masked scans
-      * basesink: implement percentage position and duration queries
-      * basesink: fix segment query return value
-      * basetransform: add accept_caps vmethod
-      * basetransform: re-evaluate proxy_alloc when reconfigured
-      * basetransform: assume in_size equals out_size if there's no transform_size/get_unit_size vfunc
-      * fdsink, filesink: make sync property work correctly
-      * typefind: make sure buffers' metadata is writable before setting caps on them
-      * queue2: fix merging of ranges
-      * queue2: don't wait for data when EOS
-      * queue2: don't ignore failure to open the temporary file location
-      * tools: make gst-launch print things correctly to stderr/stdout and make --quiet work correctly
-      * introspection: add many more gobject-introspection annotations
-      * xml: serialisation/deserialisation to/from XML has been deprecated, since it's always been broken
-        for all but the most trivial pipelines, and will likely never be fixed
-
-Bugs fixed since 0.10.29:
-
-      * 623586 : gst/tagsetter check fails
-      * 463435 : Skip #include < libxml/parser.h > in gstconfig.h.in when  not needed
-      * 505770 : gst_element_get_state() should unblock if element posts an error
-      * 615820 : implement percentage position and duration queries
-      * 615941 : [tags] Add GST_TAG_DEVICE_MANUFACTURER and GST_TAG_DEVICE_MODEL
-      * 616586 : Use GObject's boxed type for GError
-      * 617223 : [tags] Add tags for direction of capture and movement
-      * 617625 : Commandline utility wrappers (gst-run) don't work on Windows
-      * 618644 : gst_pad_get_caps() Return pad template if parent element is in GST_STATE_NULL
-      * 619508 : [tag] Add image orientation tag
-      * 619815 : GST_PLUGIN_LOADING_WHITELIST env var for unit tests
-      * 619828 : [API] adapter: add masked_scan_uint32_peek
-      * 620460 : info: add new TRACE log level and move refcounting there from LOG level
-      * 620490 : [basesink] segment query unconditionally returns FALSE
-      * 621006 : Deprecate unused gst_object_{get|set}_name_prefix()
-      * 621282 : Display of short fourccs is in hex instead of text
-      * 621332 : BaseTransform should disable proxy alloc if downstream changes caps
-      * 621334 : GstBaseTransform should not require a transform_size function
-      * 621505 : Disable memory poisoning by default for releases
-      * 621527 : gstcaps: New gst_caps_steal_structure() method
-      * 621530 : filesink ignores sync=true
-      * 621595 : --quiet doesnt make gst-launch be completely quiet, also messages should not go to stdout
-      * 621773 : Add introspection annotations
-      * 621867 : gst-launch: rename new --no-play command line option
-      * 621896 : [API][taglist] Add gst_tag_list_peek_string_index
-      * 622504 : [GstPad] Provide more fine-grained linking methods
-      * 622546 : distcheck fails in docs/plugins/
-      * 622685 : [GstXml] Deprecate GstXml
-      * 622967 : [queue2] Problems with progressive downloading
-      * 623301 : gst_caps_normalize : doesn't normalize completely
-      * 623589 : Fix races/refcounting bugs with slave clocks
-      * 624113 : [tags] wrong behaviour in merge function for strings
-      * 622025 : Can't build gstreamer due to Gst-0.10.gir: error: Can't resolve type 'PadIntLinkFunction' for field Gst.Pad.intlinkfunc
-
-API additions since 0.10.29:
-
-      * gst_caps_steal_structure()
-      * gst_clock_id_wait_async_full()
-      * gst_element_link_pads_full()
-      * GstPadLinkCheck
-      * gst_pad_link_check_get_type()
-      * gst_pad_link_full()
-      * gst_structure_fixate_field_string()
-      * GST_TAG_DEVICE_MANUFACTURER
-      * GST_TAG_DEVICE_MODEL
-      * GST_TAG_IMAGE_ORIENTATION
-      * GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION
-      * GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION
-      * GST_TAG_GEO_LOCATION_MOVEMENT_SPEED
-      * gst_tag_list_peek_string_index()
-      * GST_TRACE
-      * GST_TRACE_OBJECT
-      * GST_CAT_TRACE
-      * GST_CAT_TRACE_OBJECT
-      * GST_LEVEL_TRACE
-      * gst_adapter_masked_scan_uint32_peek
-      * GstBaseSink::enable-last-buffer
-      * gst_base_sink_is_last_buffer_enabled()
-      * gst_base_sink_set_last_buffer_enabled()
-      * GstBaseTransform::accept_caps()
-
-API deprecated since 0.10.29:
-
-      * gst_object_get_name_prefix()
-      * gst_object_set_name_prefix()
-      * gst_caps_load_thyself()
-      * gst_caps_save_thyself()
-      * gst_class_signal_emit_by_name()
-      * gst_object_save_thyself()
-      * gst_object_restore_thyself()
-      * gst_pad_load_and_link()
-      * gst_xml_get_element()
-      * gst_xml_get_topelements()
-      * gst_xml_get_type()
-      * gst_xml_make_element()
-      * gst_xml_new()
-      * gst_xml_parse_doc()
-      * gst_xml_parse_file()
-      * gst_xml_parse_memory()
-      * gst_xml_write()
-      * gst_xml_write_file()
-
-Changes since 0.10.28:
-
-      * improve plugin loading robustness: do not ever unload a plugin after
-        calling into it: should fix mystery crashers during registry loading
-        when a plugin init function returns FALSE (e.g. when some supporting
-        library fails to initialise or a wrapper plugin found no features to
-        wrap and wrongly returned FALSE)
-      * configurable memory alignment for GstBuffers
-      * add QoS message to inform apps of lost data, dropped frames etc.
-      * basesink, basetransform: add support for new QoS message
-      * basetransform: accept non-fixed caps suggestions
-      * basesrc: fix gst_base_src_new_seamless_segment()
-      * GstController fixes and optimisations
-      * set thread name for pad tasks on Linux
-      * pipeline, bin: fix refcount issue when removing elements during a state change
-      * queue2: implement seeking in download mode
-      * queue2: implement flushing in download buffering
-      * queue2: improve buffer level measurement in download mode
-      * fdsrc: allow specifying the size in bytes on the uri
-      * build fixes: better checks for uint128_t, inline assembly on OSX, compilation
-        if HAVE_REGISTER_PRINTF_SPECIFIER is undefined, gobject-introspection
-      * two symbols were removed that had been exported but never been used or been
-        declared in any header file: gst_element_default_error and gst_element_request_compatible_pad
-
-Bugs fixed since 0.10.28:
-
-      * 576234 : [basetransform] Suggesting non-fixed caps or no size doesn't work for upstream negotiation
-      * 520697 : [API] Add GST_TAG_USER_RATING
-      * 590718 : docs build failures with -jN: cp: cannot create regular file `build/image.entities': File exists
-      * 595958 : Position not updated after a backwards gst_event_new_step()
-      * 596832 : configurable buffer alignment
-      * 600718 : autoconf fails with gobject-introspection
-      * 600877 : [uridecodebin] Needs to disable download buffering for non-fast-start files
-      * 603710 : Can't compile with introspection support
-      * 603831 : build with libtool 1.x.y only works if --disable-shave is used
-      * 609046 : basetransform now ignores suggestions from capsfilter
-      * 609170 : basesrc pushes two newsegment
-      * 610256 : Use G_VALUE_COLLECT_INIT if available
-      * 611075 : Typo in debug_dump_pad function
-      * 611911 : Set thread names on pipeline threads
-      * 612370 : gstutils.c inline asm typo, compilation fails
-      * 612410 : [API][tags] add new geo tags
-      * 612733 : Build fails because HAVE_REGISTER_PRINTF_SPECIFIER is undefined
-      * 612881 : [utils] gst_pad_proxy_setcaps() doesn't handler iterator resyncs
-      * 613215 : delayed set in gst-launch are not recursive
-      * 613593 : git-update.sh script does not work on fresh git repository clones
-      * 614167 : gstinfo: no previous prototype for 'xxx' when buildign with --disable-gst-debug
-      * 614629 : utils: Use G_GNUC_CONST instead of G_GNUC_PURE for conversion functions
-      * 614767 : libgstreamer build failure on OS X x86_64
-      * 614833 : out of srcdir build fails for libs/gst/check
-      * 615698 :  " warning: cast increases required alignment of target type " with gcc 4.2.1 on arm
-      * 615756 : [bin] refcount issue when removing element in error
-      * 615880 : Add some more custom flow returns
-      * 615881 : [LFOControlSource] Use correct setter for double GValues
-      * 616846 : Crash in gst_interpolation_control_source_find_control_point_iter
-
-API additions since 0.10.28:
-
-      * GST_MESSAGE_QOS
-      * gst_message_new_qos()
-      * gst_message_parse_qos()
-      * gst_message_parse_qos_stats()
-      * gst_message_parse_qos_values()
-      * gst_message_set_qos_stats()
-      * gst_message_set_qos_values()
-      * GST_FLOW_CUSTOM_SUCCESS_1
-      * GST_FLOW_CUSTOM_SUCCESS_2
-      * GST_FLOW_CUSTOM_ERROR_1
-      * GST_FLOW_CUSTOM_ERROR_2
-      * GST_TAG_USER_RATING
-      * GST_TAG_GEO_LOCATION_COUNTRY
-      * GST_TAG_GEO_LOCATION_CITY
-      * GST_TAG_GEO_LOCATION_SUBLOCATION
-
-API deprecated since 0.10.28:
-
-      * gst_element_class_set_details()
-
-Changes since 0.10.27:
-
-     * parse "1/MAX" fraction strings
-     * no material changes compared to 0.10.27, this release is mostly to
-       keep core/base version numbers in sync
-
-Changes since 0.10.26:
-
-      * basesrc: protect segment values from concurrent access from different threads
-      * typefind: protect internal fields from concurrent changes from different threads
-      * typefind: fix pad activation corner-case with have-type already having been emitted
-      * typefind: reset the working mode when going to READY/NULL, fixes re-use from
-        READY state as with decodebin2
-      * gstpoll: fix crash when logging is enabled for GST_POLL
-      * bytewriter: expose gst_byte_writer_put_{float32|float64}_*() properly in header
-      * basesink: fix emergency rendering timestamp tracking
-      * fdsink, fdsrc: fix compilation with MSVC
-      * memindex: avoid busy loop when doing EXACT lookup
-
-Bugs fixed since 0.10.26:
-
-      * 610366 : [gstcollectpads][doc] Add a reminder for 'data' doc
-      * 605189 : gst_element_get_state has wrong introspection
-      * 607771 : [API] Add gst_byte_writer_fill
-      * 608036 : [typefind] deadlock when upstream puts caps on buffers on pull mode
-      * 608877 : [typefind] Access to internal fields not threadsafe
-      * 609941 : GStreamer-WARNING **: External plugin loader failed.
-      * 610210 : [PATCH] Fix compilation of fdsink and fdsrc with MSVC
-      * 610246 : [optimization] Speed up _get_range()
-      * 610367 : [memindex] might busy loop upon EXACT lookup
-      * 610444 : [controller] Interpolation control source passes NULL pointers to GSequence API
-      * 611087 : [basesink] emergency rendering of late buffers fails after resuming from PAUSE
-      * 611719 : GST_DEBUG_OBJECT macros not fed with GObject* in gstpoll.c
-
-API additions since 0.10.26:
-
-      * gst_byte_writer_fill()
-
-Changes since 0.10.25:
-
-      * registry: do plugin scanning (on *nix) using an external helper binary
-      * lots of performance improvements all over the place (ghostpads,
-        multiqueue, pad construction, superfluous type checks, registry loading)
-      * add GstByteWriter, a simple generic byte writer
-      * filesink: Use _wfopen on win32 to open files with non-ascii filenames correctly.
-      * queue2: add option to remove the temp-file (enabled by default)
-      * it is now allowed to use gst_caps_set_simple() on non-simple caps
-      * queue2: move from gst-plugins-base into the coreelements plugin in core
-        (this means you may need to remove libgstqueue2.so manually if you
-        installed from source and don't do make uninstall before upgrading, or
-        combine an older -base with a newer core)
-      * multiqueue: add support for buffering mode where we post BUFFERING
-        messages based on the level of the queues
-      * typefind: speed up typefinding a lot by first trying the typefinder for
-        the file's extension
-      * buffer: remove private/internal subbuffer subclass and keep track of
-        the parent buffer directly in the GstBuffer structure (this removes
-        quite a bit of special-casing and will allow for future improvements/
-        extensions that are harder to do if there's a separate subbuffer class.
-      * collectpads: add ability to install clipping functions
-      * new tags for TV/Radio shows/episodes, lyrics, composer sortname and
-        grouping
-      * miniobject: avoid race when recycling buffers
-      * basesrc: fix race in PLAYING->PAUSED->PLAYING
-
-Bugs fixed since 0.10.25:
-
-      * 476514 : [multiqueue] Doesn't forward EOS event in all cases
-      * 590941 : API: add gst_pad_get_caps() variant that avoids unneeded caps copies
-      * 595602 : g_child_proxy_get_valist doesn't initialize GValue correctly
-      * 535069 : basesrc no longer support non-flushing seeks on itself
-      * 560442 : GNOME Goal: Remove deprecated GLib symbols
-      * 595511 : Annotations for gst_element_query_{position,duration}
-      * 595886 : gst_pad_fixate_caps() does not return fixed caps in case of multiple structures
-      * 595964 : [multiqueue] can hang pipeline during startup
-      * 596366 : proxy_getcaps reverses direction of getcaps
-      * 597407 : GstPipeline calculates base_time incorrectly when a new clock appears during PAUSED state
-      * 597550 : basesrc: sometimes no buffers produced after PLAYING - PAUSED - PLAYING
-      * 597690 : Improve caps setters API
-      * 598297 : make check fails when any --disable option which changes the API has been used
-      * 598526 : bytewriter: fails to compile with gcc 4.2.4 on Ubuntu Hardy 64 bits
-      * 598700 : scripts: Parallelise git-update.sh build script
-      * 598895 : [GstRegistry] Use hash table for feature lookups
-      * 598896 : [GstRegistry] Cache lists of ElementFactory and TypeFindFactory
-      * 599147 : typefind : Avoid having to re-sort the typefind factory list
-      * 599759 : [qtdemux] Add support for more tags
-      * 600313 : Visualisations stop updating after seek
-      * 600922 : gst-launch: wake up less often to check for Ctrl-C
-      * 601587 : MiniObject race condition
-      * 601668 : [gstregistry] gstregistry.c uses a variable from gst.c
-      * 601669 : [tests] tests/examples/manual depends on libgstcheck
-      * 602093 : libgstcheck fails to export some symbols when built under et_EE locale
-      * 602275 : [API] Add new sink-message event
-      * 602419 : [basesink] Regression with position reporting
-      * 603059 : Totem crashes when DVD is encrypted but libdvdcss isn't available
-      * 603787 : [registry] Doesn't use GMappedFile
-      * 604091 : tee: cleanup requestpads in dispose
-      * 604093 : gst-inspect/launch: move gst_tools_print_version to avoid glib warning
-      * 605251 : tee causes segfault if there is no source pad
-      * 605930 : [shave] common/shave not existing yet when configure checks need it
-      * 606435 : gsttee not threadsafe
-      * 607283 : segfaults and/or miniobject warnings with GLib > = 2.23.2
-      * 607317 : [PATCH] fix unaligned detection for x86-64 when cross compiling
-      * 607431 : update common modules before freeze
-      * 607481 : Should define G_THREADS_MANDATORY everywhere
-      * 607739 : [queue2] Temporary file is removed although code claims the opposite
-      * 607842 : Audio comes out with short breaks after resume pipeline (paused- > playing)
-      * 608136 : multiqueue handles UNEXPECTED flowreturn wrongly
-      * 608398 : Initializing the glib thread system seems not to work
-      * 608442 : [filesrc] typo in warning message
-      * 608726 : bytewriter: mistake in .h/.c function naming
-      * 609166 : Buffer list docs ascii art
-      * 590669 : [API] need GstByteWriter or GstChunkWriter
-      * 601698 : Rename new plugin-scanner helper executable before release
-      * 604565 : [gstcheck] Update check to 0.9.8
-      * 596877 : New internal libcheck breaks the Solaris build
-
-API additions since 0.10.25:
-
-      * GST_DEBUG_REGISTER_FUNCPTR()
-      * gst_base_src_new_seamless_segment()
-      * gst_event_new_sink_message()
-      * gst_event_parse_sink_message()
-      * gst_util_fraction_add()
-      * gst_util_fraction_multiply()
-      * gst_util_greatest_common_divisor()
-      * gst_util_double_to_fraction()
-      * gst_util_fraction_to_double()
-      * gst_registry_get_feature_list_cookie()
-      * gst_default_registry_get_feature_list_cookie()
-      * gst_pad_get_caps_reffed()
-      * gst_pad_peer_get_caps_reffed()
-      * gst_structure_id_has_field()
-      * gst_structure_id_has_field_typed()
-      * gst_plugin_feature_list_copy()
-      * gst_caps_set_value()
-      * gst_byte_writer_ensure_free_space()
-      * gst_byte_writer_free()
-      * gst_byte_writer_free_and_get_buffer()
-      * gst_byte_writer_free_and_get_data()
-      * gst_byte_writer_get_remaining()
-      * gst_byte_writer_init()
-      * gst_byte_writer_init_with_buffer()
-      * gst_byte_writer_init_with_data()
-      * gst_byte_writer_init_with_size()
-      * gst_byte_writer_new()
-      * gst_byte_writer_new_with_buffer()
-      * gst_byte_writer_new_with_data()
-      * gst_byte_writer_new_with_size()
-      * gst_byte_writer_put_data()
-      * gst_byte_writer_put_float32_be()
-      * gst_byte_writer_put_float32_le()
-      * gst_byte_writer_put_float64_be()
-      * gst_byte_writer_put_float64_le()
-      * gst_byte_writer_put_int16_be()
-      * gst_byte_writer_put_int16_le()
-      * gst_byte_writer_put_int24_be()
-      * gst_byte_writer_put_int24_le()
-      * gst_byte_writer_put_int32_be()
-      * gst_byte_writer_put_int32_le()
-      * gst_byte_writer_put_int64_be()
-      * gst_byte_writer_put_int64_le()
-      * gst_byte_writer_put_int8()
-      * gst_byte_writer_put_string_utf16()
-      * gst_byte_writer_put_string_utf32()
-      * gst_byte_writer_put_string_utf8()
-      * gst_byte_writer_put_uint16_be()
-      * gst_byte_writer_put_uint16_le()
-      * gst_byte_writer_put_uint24_be()
-      * gst_byte_writer_put_uint24_le()
-      * gst_byte_writer_put_uint32_be()
-      * gst_byte_writer_put_uint32_le()
-      * gst_byte_writer_put_uint64_be()
-      * gst_byte_writer_put_uint64_le()
-      * gst_byte_writer_put_uint8()
-      * gst_byte_writer_reset()
-      * gst_byte_writer_reset_and_get_buffer()
-      * gst_byte_writer_reset_and_get_data()
-      * gst_bit_reader_get_size()
-      * gst_byte_reader_get_size()
-      * gst_data_queue_new_full()
-      * gst_collect_pads_set_clip_function()
-      * gst_type_find_helper_get_range_ext()
-
-Changes since 0.10.24:
-    
-      * Improve the byte-reader API
-      * GObject introspection support
-      * Improve clock accuracy on win32
-      * Optimisations in capabilities checking
-      * Optimisations and fixes in the basetransform base class
-      * new 64-bit scaling utility function variants
-      * Various bug-fixes and improvements (see ChangeLog and bugs list below)
-
-Bugs fixed since 0.10.24:
-     
-      * 583999 : [basetransform] caps refcounting problem causing GST_IS_CAPS assertion failures
-      * 566881 : [GstIndex] support/caching in GstBin
-      * 588472 : [basetransform] problems in reverse-negotiating
-      * 589173 : macros cause spurious semicolon warnings
-      * 589314 : [basetransform] clears GAP flag in passthrough mode
-      * 589524 : gst_base_transform_acceptcaps() could provide more verbose debugging output
-      * 589849 : [segment] Clipping fails to handle start=stop < segment_start correctly
-      * 589991 : [queue] limited error handling might cause pipeline appearing to hang
-      * 590045 : Query position fails when pipeline is paused and format is not time
-      * 590430 : Add support for " album artist " tags
-      * 590841 : configure script check for libxml2 is incorrect
-      * 590919 : gst_util_uint64_scale_int() and friends don't round
-      * 591045 : [basesrc] Leaking GstTask instances
-      * 591318 : ghostpad : core dump : on_src_target_notify called with an invalid ghostpad
-      * 591441 : append mode for filesink
-      * 592209 : [GstPad] Deprecated markers missing in the header for internal links function related things
-      * 592314 : core/tests/examples/streams/ does not link to pthread
-      * 593460 : Broken win32-specific systemclock code
-      * 593719 : regression: segfault when using gstrtpbin and certain video codecs
-      * 594107 : [gstbin] : use of freed message : valgrind Invalid read
-      * 594225 : [API] [bytereader] add _unchecked() variants and inline most common functions
-      * 594990 : [introspection] pkg-config file madness and another bug
-      * 595130 : checks fail
-      * 595133 : gst/gstutils check fails
-      * 595209 : Fix out-of-tree build
-      * 368536 : bin_change_state makes children go through unnecessary state changes
-
-API additions since 0.10.24:
-    
-      * gst_caps_can_intersect()
-      * gst_util_uint64_scale_int_round()
-      * gst_util_uint64_scale_int_ceil()
-      * gst_util_uint64_scale_round()
-      * gst_util_uint64_scale_ceil()
-      * gst_iterator_new_single()
-      * gst_byte_reader_skip_unchecked()
-      * gst_byte_reader_peek_*_unchecked()
-      * gst_byte_reader_get_*_unchecked()
-      * gst_byte_reader_{peek,get,dup}_data_unchecked()
-      * gst_byte_reader_get_float*_unchecked()
-
-Changes since 0.10.23:
-    
-      * Fully support nested structures in caps
-      * Support frame-by-frame stepping in sinks
-      * Add support for buffer-lists to pass around groups of buffers
-      * Use TaskPools for managing worker threads
-      * New stream-status API for finer thread control
-      * Code optimisations
-      * Many other bug-fixes and enhancements
-
-Bugs fixed since 0.10.23:
-     
-      * 580579 : crash in Volume Control: aucunes idées désolé.
-      * 527488 : [GstXML] can't load elements with request pads from XML
-      * 570233 : allow plugins caching data in the registry
-      * 584389 : don't recreate plugin feature and element factories on fi...
-      * 534208 : [API] add gst_structure_get()
-      * 545787 : [API] add gst_plugin_register_static_full() for bindings
-      * 554460 : thumbnailer crash in gst_fake_sink_event() on FLUSH_START...
-      * 559643 : Don't allow empty or NULL strings in taglists
-      * 560345 : gst_tag_list_get_string() may return NULL or empty string
-      * 560442 : GNOME Goal: Remove deprecated GLib symbols
-      * 572285 : Buffer Lists
-      * 577926 : Remove old xml registry
-      * 578908 : [fdsink] implement seeking on seekable fds
-      * 580177 : glibc 2.10 deprecates register_printf_function
-      * 580716 : race condition in gst_element_lost_state
-      * 581198 : [tags] Add gst_tag_setter_add_tag_value() and gst_tag_lis...
-      * 581281 : [GstURIHandler] Doesn't use get_type_full() at all
-      * 582010 : audiotestsrc is-live=1 ! pulsesink unreliable
-      * 582564 : [controller] Use ordered GSequence instead of GList in th...
-      * 582588 : [API] Add a way to get the pad corresponding to a taglist
-      * 582878 : [GstClock] ABI breakage in GIT on x86
-      * 583187 : [API] add gst_adapter_masked_scan_uint32() and gst_adapte...
-      * 583419 : Bad translatable string in gst-launch.c
-      * 583456 : framestep functionality
-      * 583554 : Slow down or lock if date time is changed to the past
-      * 584835 : MSVC compiler fails with 'static inline' function
-      * 584838 : basesrc: confusing QUERY_SEEKING handling
-      * 585039 : rtpool-test can't find pthreads
-      * 585075 : Compilation with MSVC fails for files including config.h ...
-      * 585137 : gst_xml_write_file() fails serialising GstStructure property
-      * 585592 : [API] add gst_byte_reader_masked_scan_uint32()
-      * 585733 : Wrong #include order in gstsegment.c
-      * 585748 : [API] add gst_tag_list_new_full() to create taglist with ...
-      * 586566 : Add GAP Flag support to gstcapsfilter
-      * 586568 : [bytereader] add misc. string functions and gst_byte_read...
-      * 587973 : use G_DIR_SEPARATOR_S instead of " /' " 
-      * 587976 : Fix for gst-inspect and gst-launch when option parsing is...
-      * 588744 : [check] Stream consistency checker utility
-      * 588745 : [basesrc] Serialize tags in the dataflow
-      * 589127 : gsttask leaks the pool
-      * 590056 : [collectpads] race resulting in double flush-stop being o...
-      * 590622 : [bytereader] buffer size checks subject to wrap-around ov...
-      * 579177 : GstInfo: maintain ABI compatibility
-      * 581321 : typefind element leaks force-caps property
-      * 584118 : [gstadapter][doc] Improve documentation of gst_adapter_ma...
-      * 585433 : [queue] Can lock down if min-threshold conflicts with max...
-      * 585569 : rtsp/rtp streaming fails when skipping explicit PAUSED st...
-      * 585834 : Support for GstBufferList in ghostpads
-      * 585960 : Support for GstBufferList in gstbasesink
-      * 587052 : [filesink.c] Support for files > 4GB on windows makes file...
-
-API added since 0.10.23:
-     
-      * GST_DEBUG_CATEGORY_GET() macro
-      * gst_byte_reader_dup_data
-      * gst_byte_reader_dup_string
-      * gst_byte_reader_dup_string_utf8
-      * gst_byte_reader_dup_string_utf16
-      * gst_byte_reader_dup_string_utf32
-      * gst_byte_reader_skip_string
-      * gst_byte_reader_skip_string_utf8
-      * gst_byte_reader_skip_string_utf16
-      * gst_byte_reader_skip_string_utf32
-      * gst_byte_reader_peek_string
-      * gst_byte_reader_peek_string_utf8
-      * gst_byte_reader_get_string
-      * gst_byte_reader_get_string_utf8
-      * add gst_tag_list_new_full()
-      * add gst_tag_list_new_full_valist()
-      * add gst_byte_reader_masked_scan_uint32()
-      * add gst_plugin_get_cache_data, gst_plugin_set_cache_data
-      * gst_structure_get()
-      * gst_structure_id_get()
-      * gst_structure_get_valist()
-      * gst_structure_id_get_valist()
-      * GstSegment::gst_segment_set_running_time()
-      * Add GST_MESSAGE_SRC_NAME() macro
-      * GstSegment::gst_segment_to_position()
-      * GstEvent::gst_event_new_step()
-      * GstEvent::gst_event_parse_step()
-      * GstMessage::gst_message_new_step_done()
-      * GstMessage::gst_message_parse_step_done()
-      * gst_structure_id_new()
-      * Add gst_message_{new,parse}_tag_full() to get/set the source pad
-      * GstAdapter::gst_adapter_masked_scan_uint32()
-      * GstElement::gst_element_lost_state_full()
-      * GstAdapter::gst_adapter_prev_timestamp()
-      * gst_plugin_register_static_full()
-      * gst_tag_list_add_value()
-      * gst_tag_setter_add_tag_value()
-      * add GST_TAG_CONTAINER_FORMAT tag
-      * GstTask::gst_task_set_state()
-      * GstObject::gst_object_ref_sink()
-
-Changes since 0.10.22:
-      * Support files > 4GB on Windows
-      * Controller interpolation fixes
-      * Add timer support to GstPoll and use it for clocking
-      * Attempt to typefind contents from the file extension if all else fails
-      * GStreamer revision control switched to Git
-      * Many other bug fixes and improvements
-
-Bugs fixed since 0.10.22:
-     
-      * 579177 : GstInfo: maintain ABI compatibility
-      * 163577 : [RFC] Interlaced/progressive media support in GStreamer.
-      * 574160 : collectpads does not reliably eos when last pad is removed
-      * 575598 : hierarchical pipelines accumulate segment-done wrongly
-      * 575922 : disabling subsystems cause API break
-      * 576842 : loading a broken registry file can crash
-      * 555978 : [ladspa] no elements exposed/found on Cygwin
-      * 565607 : Broken macros in gsturi.h and gstinterface.h
-      * 566936 : [ghostpads] unlink function wrongly called on target
-      * 567692 : gstinfo.h header not compatible with C++
-      * 567725 : [qtdemux] stopping at a time sometimes shows a different ...
-      * 568289 : gst_pad_template_new() leaks caps it's supposed to take o...
-      * 568438 : gst_poll_wait calling read() on control socket
-      * 568481 : GStreamer linking failures.
-      * 568632 : __MSVCRT_VERSION__ not defined with mingw, causing " stora...
-      * 568678 : filesrc doesn't logs offsets
-      * 570910 : Removing the target of a ghostpad does not re-target the ...
-      * 571227 : Add home page tag
-      * 571559 : [API] add GST_PARAM_MUTABLE_PLAYING etc. to indicate vali...
-      * 572480 : unref and copy functions should not be macros
-      * 573623 : [API] Array binary search utility function
-      * 574024 : [GstAdapter] gst_adapter_push should not accept empty buf...
-      * 574211 : gst_poll_*_control always returns FALSE on Windows
-      * 574213 : [gstcheck] fix for libcheck > 0.9.6
-      * 574241 : gst_tag_list_add and gst_tag_list_add_values behave incon...
-      * 574484 : [patch] Make caps in DOT debug graphs more readable
-      * 574623 : [dot_file_with_ts] ':' not a valid character for a filename
-      * 574805 : [capsfilter] Doesn't reset the internal suggestion with A...
-      * 575695 : build fails on OpenSolaris due to incorrect header file i...
-      * 575814 : flag for EOS on gst-launch when exiting with ctrl-c
-      * 576381 : [basesink] QoS: emergency rendering not always done
-      * 576563 : pidgin crashes on exit in gst_plugin_ext_dep_free()
-      * 576582 : A patch to enable the use of 'name' in Enum parameters
-      * 577887 : Missing GST_DISABLE_GST_DEBUG in gstregistrybinary.c
-      * 577891 : add alloc-pad property on tee
-      * 578114 : API: add two new log levels: FIXME and MEMDUMP
-      * 578201 : _gst_plugin_fault_handler_is_setup undefined under HAVE_W...
-      * 579127 : gst-launch: disable CLOCK_LOST message handling
-      * 580121 : race condition in GStreamer state changes causes problems...
-      * 361155 : Add monotonic clock
-      * 517231 : threadsafe/colored windows logging
-      * 572591 : Another batch of " differs in signedness " warnings
-      * 573823 : pad block callback if it is re-blocked while the previous...
-      * 574163 : Fix gst_pad_activate_pull deactivation with unlinked element
-      * 575682 : Add gst_pad_is_compatible()
-      * 575988 : On Windows filesink can't write files longer than 2-4 GiB...
-
-API additions since 0.10.22:
-    
-      * New FIXME and MEMDUMP debug levels
-      * gst_tag_list_get_buffer() and gst_tag_list_get_buffer_index()
-      * New tags: GST_TAG_SUBTITLE_CODEC, GST_TAG_HOMEPAGE
-      * gst_util_array_binary_search()
-      * gst_message_new_request_state(), gst_message_parse_request_state(), GST_MESSAGE_REQUEST_STATE
-      * GstPoll::gst_poll_new_timer()
-      * GstPoll::gst_poll_write_control()
-      * GstPoll::gst_poll_read_control()
-
-Changes since 0.10.21:
-
-      * GstController improvements
-      * Extensions to the latency setting behaviours
-      * Ability for plugins to register dependencies to trigger re-scanning
-      * Optimisations in some common operations on caps and values and elsewhere
-      * Add sequence numbers to events so dependent events can be associated with
-        the event that caused them
-      * New macros for reading and writing float values
-      * Many improvements in the basesink base class
-      * Support non-default main contexts for GstBus watches
-      * Improvements in pull-mode scheduling of sinks
-      * Fixes for alignment issues on sparc
-      * Ghost pad fixes
-      * New bit-reader assistance API
-      * Many other bug fixes and improvements
-      
-Bugs fixed since 0.10.21:
-
-      * 567002 : --gst-disable-registry-update also skips registry creation
-      * 350477 : [Registry] Provide a way for plugins to delegate the 'cha...
-      * 510354 : post GST_MESSAGE_STRUCTURE_CHANGE when linking and unlink...
-      * 526044 : Crash if there is more than one watcher for a GstBus
-      * 539108 : gst_ghost_pad_new() does more than call g_object_new()
-      * 544003 : [parse] Links to wrong pad if no padtemplate name is given
-      * 544293 : rtspsrc / gstpoll regression
-      * 545714 : GST_READ_UINT_* and GST_WRITE_UINT_* are not always safe ...
-      * 548786 : [win32] search for plugins based on location of DLL
-      * 551676 : Small Memleak fix in gst_pad_link_check_compatible_unlocked
-      * 552778 : add free_func in gstbuffer instances
-      * 553554 : [base] Add a generic bit reader
-      * 553874 : query_position broken during seek
-      * 555196 : Move floating point endian conversion macros into core
-      * 555307 : Need to push latency event into the pipeline
-      * 555631 : Banshee crashes; gstreamer GST_CAPS GST_IS_CAPS warnings
-      * 556091 : libtool-2.2 and old gettext don't mix
-      * 556900 : a copy & paste bug in helloworld example
-      * 557154 : Allow totem to run without write-access to home directory
-      * 557300 : libgstnet needs to link against $(WIN32_LIBS)
-      * 557438 : Gstreamer crashes when Banshee supposed to change track
-      * 557649 : GstBaseTransform can cause ivalid memory references
-      * 559250 : segments need identifiers.
-      * 560301 : Add --plugin to gst-inspect
-      * 560360 : Excessive statting when reading binary cache
-      * 560399 : Unnecessary CRC checksum for binary registry cache
-      * 560442 : GNOME Goal: Remove deprecated GLib symbols
-      * 561501 : g_type_class_ref without unref
-      * 562170 : GstBus watch doesn't work with non-default main context
-      * 562949 : [API] Add an URI query type for querying the source/sink URI
-      * 564863 : Caps are not propagated from a ghostpad's target to the g...
-      * 567225 : volatile gonce_data in BOILERPLATE not initialized to 0
-      * 566393 : [deadlock] Setting index on a pipeline
-
-API added since 0.10.21:
-
-      * Add bit reader and byte reader classes.
-      * gst_message_new_structure_change()
-      * gst_message_parse_structure_change()
-      * GST_BUFFER_FREE_FUNC()
-      * Add GST_READ_UINT24_(LE|BE) and GST_WRITE_UINT24_(LE|BE).
-      * GstBaseSrc::gst_base_src_set_blocksize()
-      * GstBaseSrc::gst_base_src_get_blocksize()
-      * GstBaseSink::gst_base_sink_set_blocksize()
-      * GstBaseSink::gst_base_sink_get_blocksize()
-      * GstBaseSink::blocksize
-      * GstBaseSink::gst_base_sink_do_preroll()
-      * Add gst_byte_reader_get_data and gst_byte_reader_peek_data 
-      * Move float endianness conversion macros from libgstfloatcast to core
-      * gst_util_seqnum_next, gst_util_seqnum_compare
-      * gst_event_get_seqnum, gst_event_set_seqnum
-      * gst_message_get_seqnum, gst_message_set_seqnum
-      * GstSeekFlags::GST_SEEK_FLAG_SKIP 
-      * gst_bin_recalculate_latency()
-      * GstBin::do-latency
-      * gst_tag_setter_reset_tags()
-      * gst_query_new_uri, gst_query_set_uri, gst_query_parse_uri
-      * add gst_plugin_add_dependency()
-      * add gst_plugin_add_dependency_simple()
-
-
-Changes since 0.10.20:
-
-      * Basetransform rework
-      * Basesink synchronisation extensions
-      * New documentation
-      * Many bug fixes, enhancements and optimisations
-
-Bugs fixed since 0.10.20:
-
-      * 481169 : [tag] add support for geo tags (gps location etc.)
-      * 520694 : adding GST_TAG_KEYWORDS
-      * 538201 : deleting the control point at ts=0 does not lower the con...
-      * 544855 : fakesrc and fakesink should call super::event()
-      * 339795 : [GstBaseTransform] Reverse negotiation issues in passthro...
-      * 348114 : [PPC64?] [gcc-4.1.2?] GST_BUFFER_IN_CAPS flag should have...
-      * 361718 : [basetransform] needs API to force renegotiation
-      * 533856 : gst_buffer_join() documentation is unclear
-      * 536978 : GTKDOC_CFLAGS should include CFLAGS
-      * 537804 : [multiqueue] wrongly reporting that the queue is full.
-      * 537812 : [check] add api to setup a pad by name
-      * 538568 : Add GST_TAG_ATTACHMENT
-      * 539772 : gst_pad_template_new() does more than call g_object_new()
-      * 542175 : gst-inspect --gst-plugins-path fails with multiple direct...
-      * 543444 : gst_base_sink_get_position can return 0 unexpectedly
-      * 543853 : Bison version check failure on OSX 10.4 Tiger
-      * 544174 : [basesrc] allow dynamic value of the seekable value.
-      * 544776 : [win32] binary registry may fail if glib is using a diffe...
-      * 545352 : gsturi is too restrictive
-      * 545603 : gst-inspect: don't print uri handler when compiled withou...
-      * 545605 : gstelementfactory: don't use uri handler code without uri...
-      * 545607 : gst: include gstconfig when using macros defined therein
-      * 545853 : [basetransform] rewrite
-      * 546328 : fractions with G_MAXINT cause failure for fixation
-      * 546822 : gstreamer doesn't tell gettext to output its translations...
-      * 547277 : filesrc detect if a file is seekable using SEEK_SET and n...
-      * 547728 : [basetransform] fail on buffer_alloc 
-      * 548394 : basesink should ignore EOS during flushing
-      * 548652 : [Inconsistency] GST_TAG_LOCATION is used for different me...
-      * 549504 : Thread-safe version of gst_pad_get_internal_links()
-      * 551952 : Need 'check' package when compile
-      * 551978 : Memleak in gst_element_sync_state_with_paren
-      * 547835 : tee release_request_pad while buffer_alloc racyness
-      * 538628 : Patch: added a timeout property to fdsrc used in gst_poll...
-      * 546883 : [basetransform] ximagesink fails when resizing video window
-      * 551509 : gst_base_transform_prepare_output_buffer: assertion faile...
-
-API added since 0.10.20:
-
-      * Add GST_TAG_ATTACHMENT for generic file attachments to streams.
-      * Add gst_base_sink_set_render_delay()
-      * Add gst_base_sink_get_render_delay()
-      * Add gst_check_setup_src_pad_by_name
-      * Add gst_check_setup_sink_pad_by_name
-      * Add gst_check_teardown_pad_by_name
-      * Add GstBaseTransform::gst_base_transform_suggest()
-      * GstBaseTransform::gst_base_transform_reconfigure()
-      * GstPad::gst_pad_set_iterate_internal_links_function()
-      * GstPad::GstPadIterIntLinkFunction
-      * GstPad::gst_pad_iterate_internal_links()
-      * GstPad::gst_pad_iterate_internal_links_default()
-
-API deprecated since 0.10.20:
-
-      * gst_pad_get_internal_links()
-      * gst_pad_set_internal_link_function()
-      * gst_pad_get_internal_links_default()
-
-Changes since 0.10.19:
-
-      * Add the Presets interface
-      * Use the binary registry by default
-      * Deprecate gst_element_get_pad and don't use it anywhere any more.
-      * Reverse playback fixes
-      * API to get missing element messages from parse_launch parsing.
-      * Fixes in latency calculations
-      * BaseTransform negotiation fixes
-      * New Buffering query and messages
-      * Fix multiqueue deadlocks when changing limits
-      * Remove pre-generated parser hacks and require newer flex/bison
-      * Use GSlice in more places
-      * Use static strings in property declarations everywhere to save memory
-        allocations
-      * Fix unaligned memory accesses with the binary registry and add CRC
-        checks
-      * Lots of other bug fixes
-
-Bugs fixed since 0.10.19:
-
-      * 535069 : basesrc no longer support non-flushing seeks on itself
-      * 522882 : Add a configure option to enable/disable OPTION_PARSING i...
-      * 396779 : Preset interface for elements
-      * 359653 : GStreamer Binary Registry patch
-      * 401456 : [API] Rename gst_bin_find_unconnected_pad to gst_bin_find...
-      * 446763 : [identity] leaks events in single segment mode
-      * 459862 : typefinding coud be more efficient
-      * 461253 : Crash when gst_base_transform_prepare_output_buffer is se...
-      * 489269 : valgrind option parameter invalid for valgrind 2.2 
-      * 508070 : gstreamer crashes whilst trying to read .so files in .deb...
-      * 512577 : GstTagMergeMode doc has slightly incorrect explanation
-      * 512578 : gst_tag_setter_merge_tags can mess up with KEEP_ALL merge...
-      * 514507 : gst-xmlinspect outputs text instead of xml for plugins
-      * 518022 : [libgstnet] MSVC 6.0 compile error due to socklen_t
-      * 518932 : Expose gst_segment_copy() to facilitate wrapping of GstSe...
-      * 520468 : Add a Env to enable/disable scan_and_update_registry for ...
-      * 522326 : use of 'char*' instead of 'const char*' in gst_caps_set_s...
-      * 523798 : [API] Some GstMiniObject enhancements
-      * 523806 : Should use G_PARAM_STATIC_(NAME|NICK|BLURB) when possible
-      * 523978 : Documentation fixes. 
-      * 523985 : [PATCH] [identity] meta-writes buffers without meta-writa...
-      * 524659 : Add specific error code for encrypted streams (e.g. WMA/A...
-      * 525532 : [fakesink/fakesrc/identity] Uses GObject marshallers for ...
-      * 526042 : [identity] check-imperfect-timestamp doesn't handle new s...
-      * 526236 : mingw32 gstpoll compilation fix
-      * 526247 : Actually build dlls when cross-compiling with mingw32
-      * 526705 : GstIndexResolver uses nickname field as description field
-      * 526768 : Basetransform bufferalloc passing through too easily
-      * 526814 : [API] add gst_pad_add_{data,event,buffer}_probe_full() wi...
-      * 527967 : gst_gerror_get_type is not thread safe
-      * 528187 : Get missing elements from gst_parse_launch()
-      * 528868 : URI schemes/protocols should be handled case insensitive
-      * 529148 : Make gstqueue give the right min latency
-      * 530317 : GType registration error - race condition when parallel c...
-      * 530637 : queue leak on capacity change
-      * 531538 : Race between gst_bus_set_flushing and async bus watches
-      * 533490 : gst_message_new_warning() should take const gchar*
-      * 533635 : gst_event_new_tag() documentation should say it takes own...
-      * 533740 : [API] add gst_typefind_suggest_simple()
-      * 533865 : gst_element_get_pad() should really be deprecated
-      * 534258 : basesink not accumulated time in some cases.
-      * 535218 : gst_base_src_send_event will block if basesrc is blocking...
-      * 536723 : Misspelled word in error string
-      * 536744 : Must link to libdl if dladdr() is used
-      * 536780 : gcc 4.3.0 compile warnings
-      * 536857 : DATADIR definition conflicts with windows headers
-      * 525961 : Build fails on darwin
-      * 535285 : Correct reference to GST_URI_UNKNOWN in gst_element_facto...
-
-API added since 0.10.19:
-
-      * Add GST_IS_PARAM_SPEC_MINI_OBJECT, GST_PARAM_SPEC_MINI_OBJECT
-        GST_TYPE_PARAM_MINI_OBJECT and gst_value_dup_mini_object
-      * typefind::force-caps
-      * gst_message_set_buffering_stats()
-      * gst_message_parse_buffering_stats()
-      * GST_QUERY_BUFFERING
-      * GstBufferingMode
-      * gst_query_new_buffering()
-      * gst_query_set_buffering_percent()
-      * gst_query_parse_buffering_percent()
-      * gst_query_set_buffering_stats()
-      * gst_query_parse_buffering_stats()
-      * gst_query_set_buffering_range()
-      * gst_query_parse_buffering_range()
-      * GST_STREAM_ERROR_DECRYPT
-      * GST_STREAM_ERROR_DECRYPT_NOKEY
-      * gst_segment_copy()
-      * gst_pad_add_data_probe_full()
-      * gst_pad_add_buffer_probe_full()
-      * gst_pad_add_event_probe_full()
-      * GstEvent::gst_event_has_name()
-      * GstFakeSrc:format
-      * gst_type_find_suggest_simple()
-      * GstBaseSink::gst_base_sink_wait_clock()
-      * gst_parse_launch_full()
-      * gst_parse_launchv_full()
-      * gst_parse_bin_from_description_full()
-      * gst_parse_context_new()
-      * gst_parse_context_free()
-      * gst_parse_context_get_missing_elements()
-      * gst_bin_find_unlinked_pad()
-      * GstPreset interface
-
-API deprecated since 0.10.19:
-
-      * gst_element_get_pad -
-        use gst_element_get_static_pad or gst_element_get_request_pad
-      * gst_atomic_int_set() - g_atomic_int_set from GLib
-      * gst_bin_find_unconnected_pad()
-
-Changes since 0.10.18:
-
-      * Fix a regression in raw fd handling
-
-Bugs fixed since 0.10.18:
-     
-      * 524041 : gstfdsrc broken in 0.10.18
-
-Changes since 0.10.17:
-        
-      * New GstPoll abstraction simplifies operations on multiple fd's/sockets
-      * Various bug fixes and corrections
-      
-Bugs fixed since 0.10.17:
-      
-      * 516187 : adding gst_collect_pads_read_buffer () collectpads
-      * 516395 : gst_buffer_create_sub does not copy flags
-      * 520756 : different registry backend configurations cause build errors
-      * 498222 : configure improvements
-      * 499127 : [multiqueue] has no documentation
-      * 505417 : Add GstPoll to core
-      * 509559 : [gstinfo]_gst_debug_init() memory leak
-      * 510194 : segmentation fault when trying to link elements.
-      * 511783 : [API] [check] add gst_check_element_push_buffer_list() etc.
-      * 513964 : [GstPad] gst_pad_get_caps don't return a copy of the caps
-      * 515469 : patch to add gst_index_set_resolver_full
-      * 519584 : gst_element_implements_interface() segfaults with 'filesr...
-      * 519698 : g_free/xmlFree mismatches in gstregistryxml
-      * 520152 : Core uses non-portable size_t and ssize_t
-      * 520671 : GstPoll needs to be ported to Windows
-      * 520808 : GstPoll's API could need some changes for Windows
-      * 520877 : registrybinary.c doesn't build cleanly on Windows/MSVC
-      * 521740 : libgstreamer.def exports not up to date
-      * 522741 : regression: gst_index_entry_free() frees string it does n...
-
-Changes since 0.10.16:
-
-      * Fix compilation on environments that have POSIX timers but not
-        monotonic clocks
-
-Bugs fixed since 0.10.16:
-      
-      * 512715 : gst/gstutils.c and HAVE_MONOTONIC_CLOCK
-
-Changes since 0.10.15:
-
-      * Monotonic/Posix clock support
-      * Dumping of dot-file graph descriptions for debugging
-      * Clean-up of exported symbols
-      * Many bug-fixes and enhancements
-
-Bugs fixed since 0.10.15:
-
-      * 497859 : --disable-gst-debug option fails compilation
-      * 339279 : [gst.URIHandler] interfaces with class-global virtual met...
-      * 498694 : Patches to avoid g_signal_emit(SIGNAL_HANDOFF) on identit...
-      * 498746 : basesink is forwarding downstream events
-      * 498767 : Hangs after end of tracks since 0.10.15
-      * 498924 : deprecate GST_PLUGIN_DEFINE_STATIC because it's not portable
-      * 499007 : [gst-plot-timeline] more options
-      * 499140 : Add check to ensure .def files are kept up-to-date
-      * 500143 : Some small improvements (limiting realloc and CPU usage )
-      * 500150 : [filesink] add property to enable buffering via setvbuf()
-      * 501560 : gst_(caps|structure)_from_string() crash if structure nam...
-      * 503131 : g_intern_string SUSE 10.2
-      * 503231 : Change to GST_BUFFER_FLAG_GAP meaning can break with base...
-      * 503417 : Build failure due uninitialized variable in function 'gst...
-      * 503590 : gstreamer-0.10.15 fails tests on ppc64
-      * 503675 : broken registry files written to disk
-      * 504499 : Messages from check no longer contain the test case name
-      * 505799 : iSight camera does not work in gstreamer
-      * 506643 : crash in fixate_value/gst_value_init_and_copy on empty li...
-      * 507957 : clean-up incomplete function declarations
-      * 508175 : GST_TIMEVAL_TO_TIME() and GST_TIMESPEC_TO_TIME() need to ...
-      * 510187 : gst_plugin_register_static() API review and GST_PLUGIN_DE...
-      * 510747 : Use $(MAKE) instead of make to fix the build if GNU make ...
-      * 511750 : Configure of prereleases 15.2-15.4 fail in OpenEmbedded M...
-
-API additions since 0.10.15:
-
-* GstIdentity::signal-handoffs
-* gst_util_get_timestamp()
-* gst_base_transform_set_gap_aware()
-* GstFileSink::buffer-mode
-* GstFileSink::buffer-size
-* gst_plugin_register_static()
-
-API deprecated since 0.10.15:
-
-* GST_PLUGIN_DEFINE_STATIC()
-
-Changes since 0.10.14:
-
-      * Changes for asynchronous sink management
-      * New ts-offset property on basesink for adjusting clock synchronisation
-      * New GstController LFO feature
-      * Fixes and improvements in latency measurement for live pipelines
-      * Additional documentation and docs fixes
-      * Faster typefinding
-      * More tag types added
-      * Improvements in various core elements and parent classes
-      * New unit tests
-      * Allow dumping pipelines as dot graphs
-      * GstStructures now support nesting
-      * URIHandler interface can now be implemented in bindings
-      * Many other bug-fixes and improvements
-
-Bugs fixed since 0.10.14:
-
-      * 496722 : DSP/DSW files in win32/vs6 directory are in unix format
-      * 476514 : [queue] Doesn't forward EOS event in all cases
-      * 456573 : allow dumping pipelines as dot graphs
-      * 475723 : cleanup static caps correctly
-      * 480341 : Memory leak at fakesink (regression in cvs)
-      * 349410 : Problems with type handling
-      * 414539 : [API] Support more GST_TAG*_SORTNAME and remove MusicBrai...
-      * 459717 : [Controller] Add GstLFOControlSource that provides values...
-      * 459809 : [API] add GST_TAG_COMPOSER
-      * 461598 : Commit Hungarian translations from TP
-      * 461599 : Some files missing from POTFILES.in
-      * 464366 : program including gst/gstbuffer.h does not compile with -...
-      * 466595 : gst_index_add_association generates corrupted entries
-      * 469402 : File uri handling on windows broken
-      * 473846 : Deadlock if sink is unable to send first buffer
-      * 474371 : Can't build libsgtcontroller with VS6
-      * 474823 : tee unit test failure
-      * 478347 : GST_STATIC_PAD_TEMPLATE macro causes warnings with g++-4.2
-      * 478401 : gstbasesrc.c ref count bug
-      * 479784 : GST_PLUGIN_DEFINE() doesn't accept BSD and MIT/X11 licences
-      * 485343 : Implement a wait_eos function in basesink
-      * 487969 : allow nested GstStructures
-      * 492077 : Build issues on Windows/MSVC
-      * 493134 : Wrong GstObject signals registration
-      * 493983 : Build issues on Windows
-      * 494343 : pre-release vs6 patch
-      * 480858 : gstqueue code cleaning
-      * 486758 : queue element fails to re-negotiate caps upstream when si...
-      * 488201 : gst_segment_set_newsegment does not accumulate correctly
-      * 492729 : PAUSED- > PLAYING returns ASYNC when triggered from bus han...
-      * 494245 : [basesink] doesn't sync correctly if segment is in BYTES ...
-
-API added since 0.10.14:
-
-      * gst_base_sink_get_last_buffer()
-      * GstBaseSink::last-buffer
-      * GstURIHandlerInterface::get_type_full
-      * GstURIHandlerInterface::get_protocols_full
-      * New tag: GST_TAG_ARTIST_SORTNAME
-      * New tag: GST_TAG_ALBUM_SORTNAME
-      * New tag: GST_TAG_TITLE_SORTNAME
-      * New tag: GST_TAG_COMPOSER
-      * gst_value_set_structure()
-      * gst_value_get_structure()
-      * GST_VALUE_HOLDS_STRUCTURE macro
-      * gst_bus_pop_filtered()
-      * gst_bus_timed_pop_filtered()
-      * gst_base_sink_wait_eos()
-      * gst_pad_peer_query()
-      * GstBaseSrc::do-timestamp
-      * gst_base_src_set_do_timestamp()
-      * gst_base_src_get_do_timestamp()
-      * GstBaseSink::ts-offset property
-      * gst_base_sink_set_ts_offset()
-      * gst_base_sink_get_ts_offset()
-      * GstBaseSink::async property
-      * gst_base_sink_set_async_enabled()
-      * gst_base_sink_is_async_enabled()
-      * gst_structure_get_uint()
-      * GstLFOControlSource and functions
-
-Changes since 0.10.13:
-
-      * State change handling improvements
-      * New improved GstController API
-      * Multi-queue fixes and enhancements
-      * Fewer dynamic library relocations
-      * Various other fixes and improvements
-      * Parallel installability with 0.8.x series
-      * Threadsafe design and API
-
-Bugs fixed since 0.10.13:
-
-      * 457322 : registry is read twice on startup
-      * 406632 : pkgconfigify the check for Check in configure.ac
-      * 423700 : [multiqueue] leaks memory when flushing
-      * 437457 : saving relocations for GstElementDetails
-      * 444648 : [API] add GstParamSpecFraction
-      * 444820 : build error with grammar.tab.c
-      * 448794 : state changes are racy with decodebin after rewrite for 0...
-      * 449197 : [capsfilter] Should set src pad caps on buffer
-      * 449226 : Incomplete ghostpads in xml session save
-      * 449493 : minor quoting fix in gst-feature.m4 macro
-      * 450711 : [GstController] Improve extensibility by providing a GstC...
-      * 451939 : [API] add GST_TAG_LICENSE_URI and GST_TAG_COPYRIGHT_URI
-      * 459501 : gst_registry_lookup_feature_locked is slow
-      * 462558 : Regression in async state change handling
-      * 462752 : make gst_element_class_set_details_simple args const
-      * 430682 : multiqueue doesn't output data on unlinked pads properly
-      * 462085 : registry feature hash can access invalid memory
-      * 357959 : buffer_alloc is not proxied through tee
-      * 374639 : GstTee doesn't handle pad list resyncs properly
-      * 449414 : [capsfilter] Copy of passed GstCaps taken instead of refe...
-      * 453732 : [PATCH] multiqueue returns wrong internally linked pads
-
-API added since 0.10.13:
-
-      * Add GstParamSpecFraction, so elements can have fraction
-        properties without lots of painful string parsing (#444648).
-      * Add fail_unless_equals_float() and assert_equals_float()
-      * Add gst_type_register_static_full
-      * Add gst_element_class_set_details_simple
-      * Refactor GstController into the core controller which can take
-        a GstControlSource for providing actual values for timestamps.
-      * add GST_TAG_LICENSE_URI and GST_TAG_COPYRIGHT_URI (#451939)
-      * gst_element_factory_has_interface()
-
-Changes since 0.10.12:
-
-      * Latency handling infrastructure for live playback scenarios
-      * State change handling changes
-      * GstController property handling improved
-      * Various bug fixes and improvements
-      * Parallel installability with 0.8.x series
-      * Threadsafe design and API
-
-Bugs fixed since 0.10.12: 
-
-      * 440682 : gst/gstsystemclock unit test occasionally fails
-      * 342564 : Configure options causing compilation to fail
-      * 378255 : Swedish translation updated
-      * 392804 : [API] add GST_CORE_ERROR_DISABLED
-      * 412648 : [filesink] reports wrong (byte) position after seeking
-      * 413123 : No XML dependency patch
-      * 415394 : [identity] post message for imperfect streams if check-pe...
-      * 417992 : Quickly playing/pausing messes up synchronization
-      * 420106 : [basetransform] race on shutdown: setcaps func called aft...
-      * 420206 : Collectpads causes a segv. when stopping after a pad remove
-      * 421480 : Make it possible to build without libxml2 with --disable-...
-      * 421543 : [GstPad] Doesn't check if pad accepts caps after caps change
-      * 422295 : GstController crashes with quadratic and cubic interpolat...
-      * 425400 : Multiqueue leaks memory when releasing sink pads
-      * 431150 : compilation fails with flex 2.5.4
-      * 431940 : [API] add gst_buffer_try_new_and_alloc()
-      * 432876 : current time level in queue
-      * 434926 : Multilib conflicts with gst-launch-0.10 man page
-      * 435880 : [GstBin] Property to allow bins to handle child async cha...
-      * 437563 : URIs with upper-case protocol don't play
-      * 440463 : gstbin unit test sometimes hangs waiting for ASYNC_DONE m...
-      * 441159 : Regression in state change handling
-      * 349180 : gst_parse_launch is not reentrant (or recursively callable)
-      * 414986 : Don't start the async thread for the system clock until n...
-      * 393099 : GstBuffer copy vfunc broken?
-      * 419851 : pad-added and pad-removed signals parameter type incorrect
-      * 420133 : gst_element_sync_state_with_parent should look at pending...
-      * 421177 : Possible deadlock if pad eventfunc is not specified
-
-API additions since 0.10.12:
-
-      * gst_element_change_state()
-      * GST_STATE_TARGET
-      * GST_BASE_TRANSFORM_LOCK/UNLOCK
-      * GstClock::gst_clock_unadjust_unlocked()
-      * fakesink::num-buffers property
-      * GST_CORE_ERROR_DISABLED
-      * basesrc::prepare_seek_segment vmethod
-      * gst_buffer_try_new_and_alloc()
-      * gst_buffer_copy_metadata()
-      * GstBufferCopyFlags enum
-      * GST_BUFFER_COPY_ALL flag
-      * gst_uri_protocol_is_supported()
-      * gst_base_src_query_latency()
-      * GstQueue::pushing
-      * gst_controller_suggest_next_sync()
-      * gst_object_suggest_next_sync()
-      * basesrc::unlock_stop
-      * basesink::unlock_stop
-      * GstBin::async-handling property
-      * gst_message_new_async_start()
-      * gst_message_parse_async_start()
-      * gst_message_new_async_done()
-      * GST_MESSAGE_ASYNC_START
-      * GST_MESSAGE_ASYNC_DONE
-
-Changes since 0.10.11:
-
-      * Add a warning if GLib threading support is not properly initialised
-      * Add support for binary registry serialisation
-      * Preliminary support for pull-mode scheduling of entire chains
-      * Add support for HPPA 
-      * Collectpads fixes
-      * Lots of bug fixes
-
-Bugs fixed since 0.10.11:
-     
-      * 378931 : Bison version check doesn't work on Solaris 9
-      * 399875 : [multiqueue] dynamic growth not implemented.
-      * 339326 : pads not set to FLUSHING when created
-      * 380129 : gst_plugin_feature_load doesn't consistently ref a return...
-      * 381301 : [patch] Make GstBus watch work with any GMainContext
-      * 383382 : Removing pads from collectpads not threadsafe
-      * 383506 : Disallow CLOCK_TIME_NONE as periodic clock id interval
-      * 387073 : gst-launch videotestsrc ! ffmpegcolorspace ! ximagesink d...
-      * 387866 : [docs] Small fix for GstCollectPads docs
-      * 391278 : g_thread_init() called too late, possibly causing memory ...
-      * 391296 : [API] add gst_update_registry() to rescan registry at run...
-      * 391777 : GStreamer does not reset SEGV trap handler
-      * 391909 : Fix compilation with MinGW
-      * 399094 : gst_pad_start_task: small doc typo
-      * 401381 : GstRegistry signals documentation is missing
-      * 401781 : [API] add GST_ROUND_DOWN_* macros
-      * 402393 : [API][GstCollectPads] Allow elements to specify destroy n...
-      * 405284 : Changing state of pipeline can lock up with preroll queue...
-      * 400656 : [PATCH] filesrc seekability detection fix (NFS and 2GB+ f...
-      * 403172 : [filesrc] doesn't handle localhost file locations
-      * 404569 : [filesrc] Unexpected end of file
-      * 161922 : script to provide plugin installation info
-      * 391915 : adapter test doesn't compile with mingw
-      * 395554 : gst_tag_setter_merge_tags works at most once
-      * 403597 : [API] Add ReplayGain reference level tag
-      * 405288 : Configure checks use pkg-config directly
-      * 381492 : [SystemClock] ClockID wait_async notification broken
-      * 382592 : Multiple wait()ers break periodic clock ids
-      * 385084 : endless ghost pad pull/push activate recursion until crash
-      * 388201 : [API] add gst_adapter_copy()
-
-API additions since 0.10.11:
-
-      * gst_update_registry()
-      * gst_adapter_copy()
-      * GST_ROUND_DOWN_* macros
-      * GstCollectDataDestroyNotify
-      * gst_query_new_latency()
-      * gst_query_set_latency()
-      * gst_query_parse_latency()
-      * gst_message_new_lost_preroll()
-      * gst_message_parse_lost_preroll()
-      * gst_message_new_prerolled()
-      * gst_message_new_latency()
-      * gst_event_new_latency()
-      * gst_event_parse_latency()
-      * GST_TAG_REFERENCE_LEVEL
-      * gst_base_sink_query_latency()
-      * gst_base_sink_get_latency()
-      * gst_bus_timed_pop()
-      * gst_message_new_info()
-      * gst_message_parse_info()
-
-Bugs fixed since 0.10.10:
-
-      * 363095 : [BaseTransform] Outputs empty buffers
-      * 353301 : aborts in _get_element_by_uri(), probably due to buggy el...
-      * 344639 : Separate threadsafe queuing functionnality in a separate ...
-      * 347785 : [multiqueue] New multiple input-output queue
-      * 352827 : re-negotiation issues with dynamic pipelines and level or...
-      * 357180 : [libs] gst_controller_new* functions don't increase refco...
-      * 318031 : gstreamer should use gmodule-no-export in its .pc file
-      * 340878 : Registry doesn't discard removed plugin features
-      * 345496 : No GstPadDirection in files created by GstXml
-      * 356910 : Basesrc gst_base_src_activate_push not calling base_src_s...
-      * 357593 : Generated gst-element-check.m4 installed from $(srcdir)
-      * 358436 : #include is missing in gstghostpad.c and gstquery.c
-      * 358999 : [PATCH] [GstPad] Flushing on blocked pads not handled cor...
-      * 359850 : Compiling issues on sparc with Forte
-      * 360151 : Fixes compiling with forte: disable warning as error for ...
-      * 360173 : Fixes compiling with forte: warning clean up (part 1)
-      * 360467 : [API] add gst_tag_list_is_empty ()
-      * 360860 : Fixes compiling with forte: warning clean up (part 2)
-      * 361675 : Allow applications to use libxml2 and GStreamer even if  ...
-      * 361720 : grammar project: error generating gstmarshal.c and gstmar...
-      * 361730 : wrong source file list in VC8 project
-      * 361732 : " win32\common\libgstreamer.def " lacks 'gst_caps_merge' entry
-      * 361769 : Deadlock in gstpad.c 
-      * 364388 : size variable is not always initialized in gst_base_src_s...
-      * 366321 : GST_SEGMENT_FORMAT not defined on windows
-      * 370865 : [basesrc] update segment duration in gst_base_src_update_...
-      * 371493 : Incomplete change of printf conversion specifiers in gstr...
-      * 374475 : [PATCH] minor doc typo
-      * 377332 : [PATCH] Warning with check > = 0.9.4
-      * 357617 : [libs] gst_controller_set_from_list can return without un...
-      * 358737 : _gst_event_copy sets the wrong parent_refcount on the chi...
-      * 366212 : Fix some misspellings in gstreamer core
-      * 369366 : MacOSX printf fixes for CVS
-      * 371894 : tests/examples/typefind is broken  
-      * 355499 : ensure_current_registry_forking()  fails if zombie alread...
-      * 352345 : Small race condition in the queue element
-      * 357432 : [libs] GstController needs to keep controlled objects alive
-      * 358613 : sink- > file is never reset for filesink elements, even tho...
-      * 366286 : [PATCH] fix compilation on Windows
-      * 366572 : Bad declaration in headerfile
-      * 367677 : [fdsrc] skips the first byte
-      * 369942 : [PATCH] unblocking blocked pad does not release all block...
-
-API added since 0.10.10:
-
-      * gst_element_state_change_return_get_name
-      * gst_tag_list_is_empty
-      * gst_pad_is_blocking()
-      * GST_PAD_IS_BLOCKING() macro
-      * GST_PAD_BLOCKING GstPadFlag
-      * gst_base_src_wait_playing
-      * gst_base_sink_wait_preroll
-      * gst_message_new_buffering
-      * gst_message_parse_buffering
-
-Bugs fixed since 0.10.9:
-     
-      * 349180 : gst_parse_launch is not reentrant (or recursively callable)
-      * 348455 : [filesrc] should not use mmap() by default, since it migh...
-      * 340674 : marry gst-debugs & plot-timeline.py
-      * 350449 : [GstBaseTransform] buffer_alloc should alway try downstream
-      * 352580 : implement proper caps merging
-      * 345444 : Linking to an audioconvert (pad-added callback) multiple ...
-      * 347293 : GstValueList comparison is flawed
-      * 347311 : element_unlink leaks its iterator wich will leak the src ...
-      * 348179 : gst_parse_lauch is not reentrant
-      * 348354 : failure in bison version detection breaks build
-      * 350419 : API: GST_SEGMENT_FORMAT printf extension for GstSegments
-      * 350879 : [init] Mark gstreamer as being initialized during registr...
-      * 350935 : API: add GST_TAG_EXTENDED_COMMENT
-      * 353976 : asssertion about element sanity in gst_registry_xml_write...
-      * 350432 : micro-optimising quarks
-      * 341029 : Ghostpads internal and target should be linked from the b...
-      * 345295 : [PATCH] gstreamer/libs/gst/net for Windows
-      * 347756 : Allow --disable-trace without --disable-parse
-      * 347794 : Do not reset SIGSEGV handler when --gst-disable-segtrap i...
-      * 348918 : application should decide whether or not to use fork() to...
-      * 349943 : [QOS] documentation/code mismatch
-      * 351768 : Unwanted concurent buffer modifications
-      * 352958 : pad_alloc_buffer and stream lock
-      * 353121 : gst_query_new_segment should initialize all structure fields
-      * 353122 : gst_element_get_bus refs the bus unconditionally
-      * 347385 : [ghostpad] gst_ghost_pad_new_from_template() method
-      * 348677 : Upgrade to 0.10.9 breaks existing applications (failed se...
-
-API added since 0.10.9:
-     
-      * gst_segtrap_is_enabled
-      * gst_segtrap_set_enabled
-      * gst_registry_fork_is_enabled
-      * gst_registry_fork_set_enabled
-      * gst_ghost_pad_new_from_template
-      * gst_ghost_pad_new_no_target_from_template
-      * gst_caps_merge
-      * GST_TAG_EXTENDED_COMMENT
-      * GstClockCLass:wait_jitter
-      * GST_SEGMENT_FORMAT
-      * gst_structure_id_set
-      * gst_structure_id_set_valist
-
-Changes since 0.10.8:
-
-      * The testsuite can now generate coverage information
-      * Better support for non-linear editing
-      * Removed Glib 2.6 compatibility
-      * Performance improvements on cpus that support branch hints
-      * Bug fixes
-
-Bugs fixed since 0.10.8:
-
-      * 346730 : some warnings about enums and macros
-      * 341029 : Ghostpads internal and target should be linked from the b...
-      * 346192 : [PATCH] Pad blocking on events
-      * 347384 : [ghostpad] padtemplates shouldn't be set automatically
-      * 344115 : [patch] make more internal data const
-      * 324176 : gst-element-check-0.x.m4 should use versioned gst-inspect
-      * 330379 : Bogus commits to basesink, basetransform, collectpads
-      * 341667 : restore_from_xml breaks pad links again after creating them
-      * 344642 : tools/gst-inspect.c does not compile if --disable-nls is ...
-      * 344748 : Fails with non-writable registry
-      * 344849 : GstController doesn't handle float properties correct
-      * 345086 : [gst-feedback] calls un-versioned tools
-      * 346097 : SIGSEGV when using --gst-plugin-load
-      * 347337 : GDP does not correctly deserialize events without a struc...
-      * 347408 : basesrc causes regressions in pull with 0 bytes
-      * 345720 : Bad performance playing files off CD
-      * 331727 : make probes and Ghostpads more elegant
-      * 343196 : basetransform not handles ro/rw buffer flagging for trans...
-      * 346663 : Segmentation error with fakesrc, fakesink and a filter
-
-Changes since 0.10.7:
-    
-      * Important fix for registry update causing applets not to load
-
-Bugs fixed since 0.10.7:
-    
-      * 344474 : Gnome Mixer Applet doesn't want to load
-
-Changes since 0.10.6:
-    
-      * Registry cache updating is now done in a fork, so no plugins are left
-        opened
-      * New version of data protocol now serializes events
-      * queue fixes
-      * win32 fixes
-
-Bugs fixed since 0.10.6:
-    
-      * 338335 : [patch] memleak in gst-utils.c (leak pads from iterator)
-      * 343598 : undefined symbol in coreindexers when using --disable-loa...
-      * 336929 : GstCollectPads does not clear/reset segment info after fl...
-      * 337100 : [fakesink] add " preroll-handoff " signal
-      * 339918 : GstTagSetter merge-mode description unclear, and implemen...
-      * 340501 : [filesrc] give primary rank
-      * 341662 : gst-launch print_tags() fix
-      * 342238 : API: gst_element_seek_simple
-      * 342321 : GST_QUERY_POSITION fails if GstBaseSrc in get_range mode
-      * 342777 : rebuilding the registry leaves all plugins in memory
-      * 342820 : gstnetclientclock.c(453): servaddr used before set
-      * 343057 : gst-launch-0.10 segfaults when passed gst-plugin-path and...
-      * 343341 : [API] add GST_TAG_PREVIEW_IMAGE
-      * 343827 : leak in gst_index_gtype_resolver
-      * 343929 : Use of // in public header
-      * 343988 : data protocol needs extending to handle events better
-      * 341479 : Too many plugins loaded even for up-to-date registry
-      * 343334 : GstCollectPads testsuite and fixes
-      * 343538 : GstCollectPads doesn't reset EOS fields when stopped
-
-API added since 0.10.6:
-
-      * gst_element_seek_simple()
-      * GST_FLOW_CUSTOM_SUCCESS
-      * GST_FLOW_CUSTOM_ERROR
-      * GST_FLOW_IS_SUCCESS
-      * gst_collect_pads_set_flushing()
-      * GST_TAG_PREVIEW_IMAGE
-      * gst_dp_crc()
-      * GstDPPacketizer
-      * GstDPVersion
-      * GstFakeSink::preroll-handoff
-      * GstFakeSink::use-mmap
-
-Changes since 0.10.5:
-
-      * Fixes for the collectpads helper
-      * Support for proper time recording on server-trickmode streams
-        via the applied_rate parameter of the NewSegment event
-      * Many bug fixes
-
-Bugs fixed since 0.10.5:
-
-      * 339808 : [patch] mem-leak of bin in gstbin.c
-      * 338339 : [patch] registry cache is always written
-      * 339843 : [patch] fdsink should not handle short writes and non fat...
-      * 340016 : does not build on opensolaris, must always include config...
-      * 340079 : gst-launch wrapper fails with 'No version of tool gst-lau...
-      * 340174 : locking problem in gstbasesink
-      * 340460 : gst-launch no longer supports --version
-      * 340508 : remove glib pre 2.8 hacks and compat stuff
-      * 340604 : gst_mini_object_ref () docs make no mention of writeability
-      * 340608 : leaking caps in padtemplate
-      * 340697 : gstsystemclock hangs when outputting to stdout via fdsink 
-      * 340721 : API: add GST_TAG_IMAGE
-      * 340772 : [qtdemux] bails out on Meet The Robinsons trailer
-      * 341556 : gst-launch: print image tags in a human readable form
-      * 339821 : [patch] serializing a GValue with a NULL buffer crashes
-
-API added since 0.10.5:
-
-      * gst_adapter_take_buffer()
-      * GST_TAG_IMAGE tag added.
-      * gst_event_new_new_segment_full()
-      * gst_event_parse_new_segment_full()
-      * GstSegment::applied_rate field
-      * gst_segment_set_newsegment_full()
-
-Changes since 0.10.4:
-
-      * QoS in BaseTransform
-      * gcc 4.1 fixes
-      * BaseTransform reworked
-      * Bus reworked; signal API added
-
-Bugs fixed since 0.10.4:
-    
-      * 131079 : [PATCH] [api] loading a class leaves elementfactory blank
-      * 317048 : gstreamer Cygwin build fixes
-      * 325599 : Build fails with GCC 4.1
-      * 327315 : GStreamer CVS head files to build with GCC 4.1
-      * 331248 : [basesink] filesink spews warnings when used with flacenc
-      * 332151 : xml registry loader should use mmap() where possible
-      * 332390 : [GstQueue/GstPad] queue pauses immediately when linked, p...
-      * 332986 : Something wrong in caps checking...
-      * 334109 : pkg-config files must link with the same check library th...
-      * 334303 : Stale libgnomeui check in configure
-      * 334434 : Missing functions in def files for dlls
-      * 335195 : GST_BOILERPLATE_FULL etc isn' optimised
-      * 335480 : start with debugging disabled
-      * 335513 : totem goes (and stays) out of sync when running bittorrent
-      * 336336 : [queue] Queue might block in EOS
-      * 336945 : [filesink] throws error when writing 0 bytes
-      * 337103 : small cleanup in gstplugin.c
-      * 337386 : Pipeline bus is not initially flushing
-      * 338711 : Internal data flow error with latest updates for FC5 with...
-      * 326311 : basesink does not call the PAUSED- > PLAYING change_state f...
-      * 326998 : GstBaseSrc's send_event handler ignores seek requests aft...
-
-API added since 0.10.4:
-
-      * gst_controller_unset_all()
-      * gst_pad_query_peer_position()
-      * gst_pad_query_peer_duration()
-      * gst_pad_query_peer_convert()
-      * GstBaseSink::async_play()
-      * GstBaseSrc::qos
-      * gst_base_sink_set_qos_enabled()
-      * gst_base_sink_is_qos_enabled()
-      * gst_base_transform_update_qos()
-      * gst_base_transform_set_qos_enabled()
-      * gst_base_transform_is_qos_enabled()
-      * gst_pipeline_get_delay()
-      * gst_pipeline_set_delay()
-
-Changes since 0.10.3:
-    
-      * Parallel installability with 0.8.x series
-      * Threadsafe design and API
-      * 33% of library size removed by parse change
-      * (Experimental) QoS features (use max-lateness on BaseSink subclasses to enable)
-
-Bugs fixed since 0.10.3:
-    
-      * 323542 : GStreamer 0.10 hangs at EOS for all songs
-      * 320340 : triggering a gst_task_join from the streaming task can de...
-      * 322628 : document thread-unsafety of gst_value_foo() + gst_value_r...
-      * 324186 : Smarter (deterministic!) typefind decisions
-      * 324398 : varargs/valist functions aren't bindable
-      * 328873 : only one gst_bin_recalc_state allowed at a time
-      * 330899 : CVS directory in make dist tarball
-      * 330906 : API: add GST_QUERY_TYPE_NAME and GST_MESSAGE_TYPE_NAME
-      * 330996 : basesrc emits EOS unconditionally when going to READY
-      * 331255 : Shrinking gst_parse_launch bloat
-      * 331898 : Basetranform is not reusable
-      * 332045 : API: GstPipeline needs API to disable  flushing of its bu...
-      * 332277 : [filesrc] seek does not correct read position in non-mmap...
-      * 332611 : [basesrc] needs way to prevent expensive start/stop in ch...
-      * 332723 : New API: gst_type_find_helper_for_buffer
-      * 333042 : New API: gst_type_find_helper_get_range
-      * 333266 : Registry file writing rewrite
-      * 333272 : tests should set G_SLICE=always-malloc now
-      * 333417 : GST_BOILERPLATE_WITH_INTERFACE can't be used in C++ code
-      * 333669 : Add pad accessor defines for GstBaseTransform
-      * 333779 : New API: add gst_uri_has_protocol
-      * 324818 : gst_registry_get_default doesn't sink newly created registry
-      * 330125 : _pad_send_event does not check flushing correctly
-      * 330684 : Add ability to emit sync-message without messing with the...
-API added since 0.10.3:
-    
-      * gst_pipeline_set_auto_flush_bus()
-      * gst_pipeline_get_auto_flush_bus()
-      * gst_uri_has_protocol()
-      * gst_pipeline_set_max_lateness()
-      * gst_pipeline_get_max_lateness()
-      * gst_pipeline_get_sync()
-      * gst_pipeline_do_sync()
-      * GST_BASE_TRANSFORM_SRC_PAD()
-      * GST_BASE_TRANSFORM_SINK_PAD()
-      * GstBaseSrc::check_get_range()
-      * GstBaseSink::max-lateness
-      * gst_type_find_helper_get_range()
-      * gst_type_find_helper_for_buffer()
-      * GST_MESSAGE_TYPE_NAME()
-      * GST_QUERY_TYPE_NAME()
-      * gst_bus_enable_sync_message_emission()
-      * gst_bus_disable_sync_message_emission()
-
-Changes since 0.10.2:
-
-      * Documentation updates
-      * Bug fixes
-      * Base class improvements
-      * Extra utility API
-      * More elements ported from 0.8
-      * Fixes for win32 build.
-
-Changes since 0.10.1:
-    
-      * documentation updates
-      * bug fixes
-
-Bugs fixed since 0.10.1:
-    
-      * 325429 : GST_BOILERPLATE_FULL can't be used when compiling with -W...
-      * 316086 : MinGW compilation: fileindexer depends on mmap
-
-Changes since 0.10.0:
-    
-      * element factory leak fixes
-      * tests cleanup
-      * BaseSrc seeking in other format than BYTES
-      * collectpad fixes
-
-Bugs fixed since 0.10.0:
-    
-      * 322441 : getcontext() in common/m4/gst-mcsc.m4 uses incorrect stac...
-      * 323041 : [BASESRC] basesrc does not handle a seek to non-bytes for...
-      * 323870 : [tools] gst-feedback needs updating for 0.9/0.10
-      * 323882 : gst-launch manpage needs updates
-      * 323905 : use return val of g_list_append
-
-API added since 0.10.0:
-     
-      * GST_TYPE_STATIC_CAPS
-      * GST_TYPE_STATIC_PAD_TEMPLATE
-      * GstNetTimeProvider::active
-      * gst_base_src_set_format
-
-Changes from the 0.8 series to 0.10 series:
-
-      * Refcounting and API revised for thread safety, see rules in
-        docs/design/part-MT-refcounting.txt
-
-      * Scheduling is now done by the elements, they start/stop
-        processing threads themselves. This removes the need for 
-        a separate scheduler.
-
-      * State changes now happen from sink to source. This makes sure
-        that downstream elements are ready to process data when upstream
-        starts producing.
-
-      * EOS/ERROR/... does not change the state of elements anymore. This
-        means that when the application sets the state on an element, it
-        remains in this state.
-
-      * GMainLoop integration. Information on the state of the pipeline
-        is now received in the mainloop via the GstBus.
-
-      * Events move separate from the datastream, this allows for both
-        in and out of sync delivery of events.
-
-      * Generic _pull() replaced by _pull_region() so that random access
-        can be made faster.
-
-      * data passing happens from PAUSED, called the preroll phase. In this
-        state no data is rendered but it is queued in the sinks.
-
-      * negotiation simplified. Caps are now attached to buffers and travel
-        along with the datastream. 
-
-      * GstBuffer is now subclassable.
-
-      * Ghostpads now look and feel like real pads.
-
-      * New Seeking/flushing policy.
-
-      * Addition of base classes and helper functions in the core to abstract
-        away the harder parts of plugin development.
-
-Changes since 0.9.7:
-
-      * added Traditional Chinese translation
-
-Bugs fixed since 0.9.7:
-    
-      * 322874 : [PAD] pad_alloc_buffer should not call set_caps
-      * 323222 : GStreamer 0.9.7 still checks in dirs containing 0.9
-      * 323250 : [collectpads] debug category should be called 'collectpad...
-
-Changes since 0.9.6:
-    
-      * bumped major/minor to 0.10
-      * API cleanup
-      * PluginFeature and TypeFind leak fixes
-      * cleaned up source tree
-      * added plugin documentation for core elements
-      * fixes for stripped core
-
-Bugs fixed since 0.9.6:
-    
-      * 320529 : [API] gst_event_new_segment mentions " stream_time " as an ...
-      * 321917 : quicktime with two video tracks and extra foo, makes tote...
-      * 322257 : Fix gstnet library name
-      * 322427 : gst-compprep aborts with 'double free or corruption'
-      * 322429 : Filesink seeking problem
-      * 322626 : Strings in gst-launch.c adn gstdebug.c are horrid
-      * 322708 : gst_plugin_load_file leaks a reference to a GstPlugin
-      * 322751 : gst_ghost_pad_get_target borks on pads without target
-      * 322842 : GStreamer-CRITICAL in GstBaseSink and GstBaseTransform
-
-Changes since 0.9.5:
-    
-      * API changes and clean-up
-      * Extensive documentation updates
-      * remove GLib 2.4 compatibility
-      * added clock selection
-      * added network clocking
-      * added fd:// URI handler
-      * added more fraction functionality
-
-Bugs fixed since 0.9.5:
-    
-      * 143472 : [api] gst_tag_list_foreach() takes a non-const GstTagList*
-      * 156633 : [API] don't use same API for arrays as for normal lists
-      * 164168 : circular pipeline fails to negotiate
-      * 165650 : [API] gst_value_deserialize doesn't work correctly for NU...
-      * 168438 : [API] GstIndexFilter doesn't receive user_data
-      * 168494 : [API] gst_index_add_object() does nothing
-      * 305291 : Obnoxious bug-filing request
-      * 311489 : Possible gstghostpad locking problems
-      * 319178 : [API] finish filler events and support them in GstCollect...
-      * 319388 : 0.9 API changes tracker
-      * 319389 : state change updates obsolete some functions
-      * 319392 : GstEventType is not bindings-friendly
-      * 319395 : Macro name/visibility API bugs
-      * 319940 : Use GLIB macros for GCC extensions
-      * 320060 : add a CORE error category for missing ELEMENTS/PLUGINS
-      * 320097 : GST_BUFFER_FLAG_ORIGINAL should die
-      * 320113 : [API] duration message changes
-      * 320299 : gst_pad_send_event should take stream lock for serialized...
-      * 320324 : [API] GST_FOURCC_FORMAT should drop leading '%'
-      * 320423 : [API] padding for GstCollectData
-      * 320766 : [API] collect pads API changes
-      * 321061 : GstURI not used
-      * 321235 : [API] GST_PAD_IS_USABLE should be removed
-      * 321386 : [SEGFAULT] basetransform when doing reverse caps negotiation
-      * 321452 : GstPad's " template " property is b0rked
-      * 321528 : capsfilter: assertion `caps != NULL' failed
-      * 321595 : GstBin doesn't clean the message queue when changing stat...
-      * 321638 : Don't use // style comments in headers
-      * 321648 : Wrong type check in gst_message_parse_clock_lost
-      * 321710 : GstClock resolution functions should take a GstClockTime
-      * 321712 : GstClock adjust function changes
-      * 321875 : gst_plugin_check_file disappeared
-      * 321950 : gst_registry_scan_paths lacks implementation
-      * 321962 : [easyfix] gst_value_is_fixed uses gst_value_list_* on GST...
-      * 322027 : [API] Rename gst_caps_structure_fixate_* to gst_structure...
-      * 322034 : Elements should be updated not to take the stream lock in...
-      * 322069 : Names of GstTagSetter methods should be more descriptive
-      * 322134 : API master/slave clocks
-      * 322139 : our elements are confused about GEnumValue and which is t...
-  
-Changes since 0.9.4:
-    
-      * gst_bus_poll and signal watch now see the same messages
-      * clock sync in BaseSrc class
-      * API documentation updates
-      * Bus reworked; signal API added
-
-Bugs fixed since 0.9.4:
-    
-      * 317341 : after linking ghost pads, one target pad does not have a ...
-      * 320774 : basesrc commit broke typefinding
-
-Changes since 0.9.3:
-
-      * state lock redefined
-      * Extensive documentation updates
-      * BaseTransform reworked
-      * Bus reworked; signal API added
-
-Bugs fixed since 0.9.3:
-
-      * 111146 : new GstThread fails on pipeline with errors
-      * 169772 : [PATCH] GOption command-line parsing
-      * 170777 : use GST_TYPE_DATE for GST_TAG_DATE
-      * 315050 : [API] consider using GstClockTime instead of GTimeVal in ...
-      * 315126 : filesrc + forced caps should be possible
-      * 315383 : gst-launch shouldn't run broken pipelines
-      * 317041 : GstObject flags should be made real flags
-      * 318447 : gst_bin_iterate_sorted: Invalid call to gst_iterator_new
-
-Changes since 0.9.2:
-
-      * gst-register has been removed
-      * Extensive documentation updates
-      * BaseTransform reworked
-      * Bus reworked; signal API added
-
-Bugs fixed since 0.9.2:
-
-      * 102980 : support incremental gst-register/compprep updates
-      * 313897 : [0.9] registry rewrite
-      * 314710 : gst_buffer_create_sub doesn't copy the GST_BUFFER_FLAGS
-      * 315895 : gst_pad_query_convert src_val check
-      * 316155 : MinGW compilation: glib-mkenums root path subtitution pro...
-      * 316157 : MinGW compilation: Plugin exports
-
-This is GStreamer 0.9.2, "South".
-
-Bugs fixed since 0.9.1:
-
-      * 121015 : [api] gst_clock_entry_new() seems broken
-      * 134227 : [api] gst_clock_id_wait_async, wrong return code for defa...
-      * 142209 : [build] Large file support broken
-      * 154785 : Clock does not run if audio stream lacks data for a short...
-      * 305256 : [API] Change gst_element_seek to not mix enum/flags types
-      * 309253 : GST_DEBUG_FUNCPTR macro does illegal casting from functio...
-      * 311004 : ghostpad bugginess
-      * 311009 : valgrind shows undesired messages
-      * 311848 : Renegotiation broken
-      * 314708 : filesrc doesn't set GST_BUFFER_FLAG_READONLY on mmaped bu...
+      * Parallel installability with 0.10.x series
+      * Remove negotiation from state change in GstBaseSrc
+      * Removed our custom FOURCC type
+      * Updates to the base classes
diff --git a/RELEASE b/RELEASE
index f089617..dc1c808 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,20 +1,20 @@
 
-Release notes for GStreamer 0.10.35 "Nuclear Fission"
+Release notes for GStreamer 0.11.1 "Sweet New Blossom"
         
 
 
 The GStreamer team is proud to announce a new release
-in the 0.10.x stable series of the
+in the 0.11.x unstable series of the
 core of the GStreamer streaming media framework.
 
 
-The 0.10.x series is a stable series targeted at end users.
-It is not API or ABI compatible with the stable 0.8.x series.
-It is, however, parallel installable with the 0.8.x series.
+The 0.11.x series is an unstable series targeted at developers
+It is not API or ABI compatible with the stable 0.10.x series.
+It is, however, parallel installable with the 0.10.x series.
 
 
-The 0.10.x series has been reworked for threadsafety.  It also features
-various feature additions and enhancements.
+The 0.11.x series has improved memory management and features
+various cleanups and enhancements.
 
 
 This module, gstreamer, only contains core functionality.
@@ -37,13 +37,12 @@ contains a set of less supported plug-ins that haven't passed the
 
 Features of this release
     
-      * work around GLib atomic ops API change
-      * some minor win32/mingw fixes
-      * don't use G_CONST_RETURN in public headers
-
-Bugs fixed in this release
-     
-      * 652211 : Use const instead G_CONST_RETURN
+      * Parallel installability with 0.10.x series
+      * Remove negotiation from state change in GstBaseSrc
+      * Removed our custom FOURCC type
+      * Updates to the base classes
+There were no bugs fixed in this release
+    
 
 Download
 
@@ -70,14 +69,30 @@ will create more lists as necessary.
         
 Applications
 
-Applications ported to GStreamer 0.10 include Totem, RhythmBox, Sound-Juicer,
-Gnome Media, Flumotion, Amarok, Jamboree, Pitivi, Istanbul, AnnoAmp, Elisa, and others.
-Let us know if you want to be added to this list.
+No applications are ported to 0.11 as of yet. We are looking for more people to
+port plugins and applications.
 
   
 Contributors to this release
     
       * David Schleef
-      * Javier Jardón
-      * Руслан Ижбулатов
+      * Edward Hervey
+      * Fabrizio (Misto) Milo
+      * Guillaume Desmottes
+      * Josep Torra
+      * Mark Nauwelaerts
+      * Nicolas Dufresne
+      * Peteris Krisjanis
+      * Piotr Fusik
+      * Raimo Järvi
+      * Sebastian Dröge
+      * Shaun Hoopes
+      * Sjoerd Simons
+      * Stas Sergeev
+      * Stefan Kost
+      * Stefan Sauer
+      * Thomas Vander Stichele
+      * Tim-Philipp Müller
+      * Vincent Penquerc'h
+      * Wim Taymans
  
\ No newline at end of file
diff --git a/common b/common
index 17fa4ab..c463bc0 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 17fa4abf49d31cf5dcc2994bdbaa86e45a3fb69f
+Subproject commit c463bc0b05e14a0eec30558fd08bb109f789d7c8
index 90daf07..18e1fdd 100644 (file)
@@ -3,7 +3,7 @@ AC_PREREQ(2.60)
 dnl initialize autoconf
 dnl when going to/from release please set the nano (fourth number) right !
 dnl releases only do Wall, git and prerelease does Werror too
-AC_INIT(GStreamer, 0.10.35.1,
+AC_INIT(GStreamer, 0.11.1.1,
     http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer,
     gstreamer)
 AG_GST_INIT
@@ -37,7 +37,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],
 dnl our libraries and install dirs use major.minor as a version
 GST_MAJORMINOR=$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR
 dnl we override it here for release candidates for a new series
-GST_MAJORMINOR=0.10
+GST_MAJORMINOR=0.11
 AC_SUBST(GST_MAJORMINOR)
 AC_DEFINE_UNQUOTED(GST_MAJORMINOR, "$GST_MAJORMINOR",
   [library major.minor version])
@@ -48,7 +48,7 @@ dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
 dnl - interfaces added -> increment AGE
 dnl - interfaces removed -> AGE = 0
 dnl sets GST_LT_LDFLAGS
-AS_LIBTOOL(GST, 29, 0, 29)
+AS_LIBTOOL(GST, 31, 0, 0)
 
 dnl FIXME: this macro doesn't actually work;
 dnl the generated libtool script has no support for the listed tags.
@@ -80,16 +80,6 @@ dnl subsystems - can influence other decisions so needs to be high up
 dnl we need to AM_CONDITIONAL them here for automake 1.6.x compatibility
 AG_GST_CHECK_SUBSYSTEM_DISABLE(GST_DEBUG,[debugging subsystem])
 AM_CONDITIONAL(GST_DISABLE_GST_DEBUG, test "x$GST_DISABLE_GST_DEBUG" = "xyes")
-AG_GST_CHECK_SUBSYSTEM_DISABLE(LOADSAVE,[pipeline XML load/save])
-AM_CONDITIONAL(GST_DISABLE_LOADSAVE, test "x$GST_DISABLE_LOADSAVE" = "xyes")
-dnl define a substitution to use in docs/gst/gstreamer.types
-if test "x$GST_DISABLE_LOADSAVE" = "xyes"
-then
-  GST_LOADSAVE_DOC_TYPES="%"
-else
-  GST_LOADSAVE_DOC_TYPES=
-fi
-AC_SUBST(GST_LOADSAVE_DOC_TYPES)
 AG_GST_CHECK_SUBSYSTEM_DISABLE(PARSE,[command-line parser])
 AM_CONDITIONAL(GST_DISABLE_PARSE, test "x$GST_DISABLE_PARSE" = "xyes")
 if test "x$GST_DISABLE_PARSE" = xyes; then
@@ -116,8 +106,6 @@ else
   GST_REGISTRY_DOC_TYPES=
 fi
 AC_SUBST(GST_REGISTRY_DOC_TYPES)
-AG_GST_CHECK_SUBSYSTEM_DISABLE(NET,[network distribution])
-AM_CONDITIONAL(GST_DISABLE_NET, test "x$GST_DISABLE_NET" = "xyes")
 AG_GST_CHECK_SUBSYSTEM_DISABLE(PLUGIN,[plugin])
 AM_CONDITIONAL(GST_DISABLE_PLUGIN, test "x$GST_DISABLE_PLUGIN" = "xyes")
 
@@ -256,7 +244,7 @@ AC_PATH_PROG(VALGRIND_PATH, valgrind, no)
 AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno")
 
 dnl check for gobject-introspection
-GOBJECT_INTROSPECTION_CHECK([0.6.8])
+GOBJECT_INTROSPECTION_CHECK([1.31.1])
 
 dnl check for documentation tools
 AG_GST_DOCBOOK_CHECK
@@ -522,50 +510,16 @@ AC_CHECK_LIB(dl, dladdr,
    LIBS="$LIBS -ldl")
 CFLAGS="$save_cflags"
 
-dnl *** checks for socket and nsl libraries ***
-AC_CHECK_FUNC(socket,,[AC_CHECK_LIB(socket,socket)])
-AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
-
-dnl check for inet_aton()
-save_libs="$LIBS"
-AC_CHECK_FUNC(inet_aton, ,
-   AC_CHECK_LIB(nsl, inet_aton, ,
-      AC_CHECK_LIB(socket, inet_aton, ,
-         AC_CHECK_LIB(resolv, inet_aton, ,[AC_DEFINE(NO_INET_ATON, 1, [Define if you have no native inet_aton() function.])]))))
-INET_ATON_LIBS=$LIBS
-AC_SUBST(INET_ATON_LIBS)
-LIBS="$save_libs"
-
 dnl *** checks for dependency libraries ***
 
 dnl GLib
-GLIB_REQ=2.24
-
+GLIB_REQ=2.31.10
 AG_GST_GLIB_CHECK([$GLIB_REQ])
 
-dnl FIXME: 0.11: Guess we need to keep this around until 0.11
-GST_HAVE_GLIB_2_8_DEFINE="#define GST_HAVE_GLIB_2_8 1"
-AC_SUBST(GST_HAVE_GLIB_2_8_DEFINE)
-
-dnl Check for glib2 without extra fat, useful for the unversioned tool frontends
-PKG_CHECK_MODULES(GLIB_ONLY, glib-2.0 >= $GLIB_REQ)
-
 dnl Check for documentation xrefs
 GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
 AC_SUBST(GLIB_PREFIX)
 
-dnl libxml2 is only needed for xml loading/saving of pipelines these days
-if test "x$GST_DISABLE_LOADSAVE" = "xyes"
-then
-  AC_MSG_NOTICE([XML registry and load/save are disabled, not checking for libxml2])
-  GST_DISABLE_XML_DEFINE="#define GST_DISABLE_XML 1"
-else
-  dnl check for libxml2 with minimum req version
-  AG_GST_LIBXML2_CHECK(2.4.9)
-  GST_DISABLE_XML_DEFINE="/* #undef GST_DISABLE_XML */"
-fi
-AC_SUBST(GST_DISABLE_XML_DEFINE)
-
 dnl building of unit test libraries
 AC_ARG_ENABLE(check,
   AC_HELP_STRING([--disable-check], [disable building unit test libraries]),
@@ -586,22 +540,22 @@ dnl bit of a misnomer, but keep the conditional named like this so we don't
 dnl have to change too much elsewhere
 AM_CONDITIONAL(HAVE_CHECK, test "x$BUILD_CHECK" = "xyes")
 
-dnl configure the desired buffer alignment
-AC_ARG_WITH([buffer-alignment],
-  AS_HELP_STRING([--with-buffer-alignment],[8,N,malloc,pagesize (default is 32)]),
+dnl configure the desired memory alignment
+AC_ARG_WITH([memory-alignment],
+  AS_HELP_STRING([--with-memory-alignment],[8,N,malloc,pagesize (default is 32)]),
   [
     if test "x$withval" = "xyes"
     then
-      AC_DEFINE(BUFFER_ALIGNMENT, 32, [Buffer alignment to use])
+      AC_DEFINE(MEMORY_ALIGNMENT, 32, [Memory alignment to use])
     else
       case "${withval}" in
-        malloc) AC_DEFINE(BUFFER_ALIGNMENT_MALLOC, 1, [Buffer alignment by malloc default]) ;;
-        pagesize)  AC_DEFINE(BUFFER_ALIGNMENT_PAGESIZE, 1, [Buffer alignment by pagesize]) ;;
-        *)   AC_DEFINE_UNQUOTED(BUFFER_ALIGNMENT, ${withval}, [Buffer alignment to use]) ;;
+        malloc) AC_DEFINE(MEMORY_ALIGNMENT_MALLOC, 1, [Memory alignment by malloc default]) ;;
+        pagesize)  AC_DEFINE(MEMORY_ALIGNMENT_PAGESIZE, 1, [Memory alignment by pagesize]) ;;
+        *)   AC_DEFINE_UNQUOTED(MEMORY_ALIGNMENT, ${withval}, [Memory alignment to use]) ;;
       esac
     fi
   ], [
-    AC_DEFINE(BUFFER_ALIGNMENT_MALLOC, 1, [Buffer alignment by malloc default]) 
+    AC_DEFINE(MEMORY_ALIGNMENT_MALLOC, 1, [Memory alignment by malloc default]) 
   ]
 )
 
@@ -637,7 +591,6 @@ AC_DEFINE_UNQUOTED(GST_DATADIR, "$DATADIR", [data dir])
 dnl set location of plugin directory
 AG_GST_SET_PLUGINDIR
 
-dnl FIXME: add LIBXML_PKG here if we use it
 GST_PKG_DEPS="glib-2.0, gobject-2.0, gmodule-no-export-2.0, gthread-2.0"
 AC_SUBST(GST_PKG_DEPS)
 
@@ -685,13 +638,14 @@ dnl every flag in GST_OPTION_CFLAGS can be overridden at make time via e.g.
 dnl make DEPRECATED_CFLAGS=''
 GST_OPTION_CFLAGS="\$(WARNING_CFLAGS) \$(DEBUG_CFLAGS) \$(PROFILE_CFLAGS) \$(GCOV_CFLAGS) \$(OPT_CFLAGS) \$(DEPRECATED_CFLAGS)"
 GST_OPTION_CXXFLAGS="\$(WARNING_CXXFLAGS) \$(ERROR_CXXFLAGS) \$(DEBUG_CFLAGS) \$(PROFILE_CFLAGS) \$(GCOV_CFLAGS) \$(OPT_CFLAGS) \$(DEPRECATED_CFLAGS)"
+GST_OPTION_CFLAGS="$GST_OPTION_CFLAGS -DGST_USE_UNSTABLE_API"
+GST_OPTION_CXXFLAGS="$GST_OPTION_CXXFLAGS -DGST_USE_UNSTABLE_API"
 AC_SUBST(GST_OPTION_CFLAGS)
 AC_SUBST(GST_OPTION_CXXFLAGS)
 
 dnl GST_ALL_*
 dnl vars common to for all internal objects (core libs, elements, applications)
 dnl CFLAGS:
-dnl - XML needs to be added because xmlPtr is used in core
 dnl - src and build dirs need to be added because every piece that gets built
 dnl   will need the GStreamer source and generated headers
 dnl LIBS: XML doesn't need to be added because we don't explicitly use symbols
@@ -718,7 +672,7 @@ AC_SUBST(GST_ALL_LDFLAGS)
 dnl GST_LIB_LDFLAGS
 dnl linker flags shared by all libraries
 dnl LDFLAGS modifier defining exported symbols from built libraries
-GST_LIB_LDFLAGS="-export-symbols-regex \^[_]*\(gst_\|Gst\|GST_\).*"
+GST_LIB_LDFLAGS="-export-symbols-regex \^[_]?\(gst_\|Gst\|GST_\).*"
 AC_SUBST(GST_LIB_LDFLAGS)
 
 dnl GST_OBJ_*
@@ -759,11 +713,9 @@ libs/gst/check/Makefile
 libs/gst/check/libcheck/Makefile
 libs/gst/check/libcheck/check.h
 libs/gst/controller/Makefile
-libs/gst/dataprotocol/Makefile
 libs/gst/helpers/Makefile
 libs/gst/net/Makefile
 plugins/Makefile
-plugins/indexers/Makefile
 plugins/elements/Makefile
 po/Makefile.in
 tests/Makefile
@@ -807,8 +759,6 @@ pkgconfig/gstreamer-check.pc
 pkgconfig/gstreamer-check-uninstalled.pc
 pkgconfig/gstreamer-controller.pc
 pkgconfig/gstreamer-controller-uninstalled.pc
-pkgconfig/gstreamer-dataprotocol.pc
-pkgconfig/gstreamer-dataprotocol-uninstalled.pc
 pkgconfig/gstreamer-net.pc
 pkgconfig/gstreamer-net-uninstalled.pc
 gst-element-check.m4
@@ -830,7 +780,6 @@ sed \
     -e 's/.* HAVE_CPU_I386$/#define HAVE_CPU_I386 1/' \
     -e 's/.* HAVE_FGETPOS$/#define HAVE_FGETPOS 1/' \
     -e 's/.* HAVE_FSETPOS$/#define HAVE_FSETPOS 1/' \
-    -e 's/.* HAVE_LIBXML2$/#define HAVE_LIBXML2 1/' \
     -e 's/.* HAVE_PROCESS_H$/#define HAVE_PROCESS_H 1/' \
     -e 's/.* HAVE_STDLIB_H$/#define HAVE_STDLIB_H 1/' \
     -e 's/.* HAVE_STRING_H$/#define HAVE_STRING_H 1/' \
@@ -839,7 +788,7 @@ sed \
     -e 's/.* HAVE_WIN32$/#define HAVE_WIN32 1/' \
     -e 's/.* HAVE_WINSOCK2_H$/#define HAVE_WINSOCK2_H 1/' \
     -e 's/.* HOST_CPU$/#define HOST_CPU "i686"/' \
-    -e 's/.* BUFFER_ALIGNMENT_MALLOC/#define BUFFER_ALIGNMENT_MALLOC 1/' \
+    -e 's/.* MEMORY_ALIGNMENT_MALLOC/#define MEMORY_ALIGNMENT_MALLOC 1/' \
     -e 's/.* LIBDIR$/#ifdef _DEBUG\n#  define LIBDIR PREFIX "\\\\debug\\\\lib"\n#else\n#  define LIBDIR PREFIX "\\\\lib"\n#endif/' \
     -e 's/.* LOCALEDIR$/#define LOCALEDIR PREFIX "\\\\share\\\\locale"/' \
     -e 's/.* PACKAGE$/#define PACKAGE "gstreamer"/' \
@@ -848,7 +797,7 @@ sed \
     -e "s/.* PACKAGE_STRING$/#define PACKAGE_STRING \"$PACKAGE_STRING\"/" \
     -e 's/.* PACKAGE_TARNAME$/#define PACKAGE_TARNAME "'$PACKAGE_TARNAME'"/' \
     -e 's/.* PACKAGE_VERSION$/#define PACKAGE_VERSION "'$PACKAGE_VERSION'"/' \
-    -e 's/.* PLUGINDIR$/#ifdef _DEBUG\n#  define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.10"\n#else\n#  define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.10"\n#endif/' \
+    -e 's/.* PLUGINDIR$/#ifdef _DEBUG\n#  define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.11"\n#else\n#  define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.11"\n#endif/' \
     -e 's/.* GST_PLUGIN_SCANNER_INSTALLED$/#define GST_PLUGIN_SCANNER_INSTALLED LIBDIR "\\\\gst-plugin-scanner"/' \
     -e 's/.* VERSION$/#define VERSION "'$VERSION'"/' \
     config.h.in >win32/common/config.h-new
@@ -857,14 +806,12 @@ AC_OUTPUT
 
 dnl negate for output
 if test "x${GST_DISABLE_GST_DEBUG}" = "xno"; then enable_gst_debug="yes"; fi
-if test "x${GST_DISABLE_LOADSAVE}" = "xno"; then enable_loadsave="yes"; fi
 if test "x${GST_DISABLE_PARSE}" = "xno"; then enable_parse="yes"; fi
 if test "x${GST_DISABLE_OPTION_PARSING}" = "xno"; then enable_option_parsing="yes"; fi
 if test "x${GST_DISABLE_TRACE}" = "xno"; then enable_trace="yes"; fi
 if test "x${GST_DISABLE_ALLOC_TRACE}" = "xno"; then enable_alloc_trace="yes"; fi
 if test "x${GST_DISABLE_PLUGIN}" = "xno"; then enable_plugin="yes"; fi
 if test "x${GST_DISABLE_REGISTRY}" = "xno"; then enable_registry="yes"; fi
-if test "x${GST_DISABLE_NET}" = "xno"; then enable_net="yes"; fi
 
 echo "
 
@@ -880,14 +827,12 @@ Configuration
        Documentation (API)        : ${enable_gtk_doc}
 
        Debug Logging              : ${enable_gst_debug}
-       Pipeline XML load/save     : ${enable_loadsave}
        Command-line parser        : ${enable_parse}
        Option parsing in gst_init : ${enable_option_parsing}
        Tracing subsystem          : ${enable_trace}
        Allocation tracing         : ${enable_alloc_trace}
        Plugin registry            : ${enable_registry}
        Plugin support             : ${enable_plugin}
-       Network support            : ${enable_net}
        Unit testing support       : ${BUILD_CHECK}
 
        Debug                      : ${USE_DEBUG}
index b313c9d..64875c9 100644 (file)
@@ -1,13 +1,11 @@
 
 EXTRA_DIST = \
-       draft-buffer2.txt \
        draft-klass.txt \
        draft-push-pull.txt \
        draft-tagreading.txt \
        part-activation.txt \
        part-block.txt \
        part-buffering.txt \
-       part-bufferlist.txt \
        part-caps.txt \
        part-clocks.txt \
        part-conventions.txt \
diff --git a/docs/design/draft-buffer2.txt b/docs/design/draft-buffer2.txt
deleted file mode 100644 (file)
index 8aa465e..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-GstBuffer^2
------------
-
-This draft document describes a possible design for arbitrary per-buffer
-metadata.
-
-The proposed changes in this document are not ABI/API compatible with the 0.10
-version of GStreamer and should thus only be considered for upcoming unstable
-versions.
-
-Buffer metadata typically includes properties that give more information about
-the buffer contents. These properties are usually not negotiated and are thus
-not inside the caps.
-
-Some examples of metadata:
-
- - timestamp, duration
- - offset, offset_end
- - interlacing information
- - video alignment, cropping, panning information
- - extra container information such as granulepos, ...
- - extra global buffer properties
-
-
-Requirements
-~~~~~~~~~~~~
-
- - It must be fast
-    * allocation, free, low fragmentation
-    * access to the metadata fields, preferably not much slower than directly
-      accessing a C structure field
- - It must be extensible. Elements should be able to add new arbitrary metadata
-   without requiring much effort. Also new metadata fields should not break API
-   or ABI.
- - It plays nice with subbuffers. When a subbuffer is created, the various
-   buffer metadata should be copied/updated correctly.
- - We should be able to pass metadata in pad_alloc() and get_range() functions
-   to specify extra allocation parameters.
- - We should be able to attach statically allocated metadata to a buffer. This
-   is for metadata that does not change much.
-
-
-GstMiniObject
-~~~~~~~~~~~~~
-
-We make GstMiniObject a simple refcounted C structure and also a GLib boxed
-type. The following fields will be in the structure:
-
-struct _GstMiniObject {
-  GType type;
-
-  /*< public >*/ /* with COW */
-  /* refcounting */
-  gint       refcount;
-  guint      flags;
-
-  GstMiniObjectCopyFunction copy;
-  GstMiniObjectFreeFunction free;
-}
-
-We will use the regular GSlice allocator or custom object pooling for allocating
-instances of the mini object.
-
-We use the well known refcounting mechanisms to manage the lifetime of the
-objects.
-
-
-GstEvent, GstCaps, GstQuery, GstMessage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Have the new GstMiniObject be the first field in these objects. They will probably
-also replace the copy and free functions with their own implementations.
-
-Allocation of the objects will use the regular gst_*_new() functions that will
-allocate and initialize a parent GstMiniObject of the required size and setting up
-the custom functions.
-
-
-GstBuffer
-~~~~~~~~~
-
-A GstMiniObject will be the parent instance of the GstBuffer object, which is a
-regular C structure.
-
-struct _GstBuffer {
-  GstMiniObject          mini_object;
-
-  gsize                  free_size;
-
-  GstCaps               *caps;
-  GstBuffer             *parent;
-
-  gpointer _gst_padding[10];
-};
-
-The Buffer object will contain a pointer to the parent buffer to allow for subbuffers
-as a first class feature of a GstBuffer.
-
-Allocation of the GstBuffer structure will result in the allocation of a memory region
-of a customizable size (512 bytes). Only the first sizeof (GstBuffer) bytes of this
-region will initially be used. The remaining bytes will be part of the free metadata
-region of the buffer. The size of the free region is kept in the free_size field.
-
-Buffers point to a GstCaps structure that contains the caps of the buffer data.
-
-
-GstBufferMeta
-~~~~~~~~~~~~~
-
-A GstBufferMeta is a structure as follows:
-
-  struct _GstBufferMeta {
-    GstBufferMetaInfo *info;  /* tag and info for the meta item */
-    GstBufferMeta     *next;  /* pointer to the next item */
-  }
-
-The purpose of the this structure is to serve as a common header for all metadata
-information that we can attach to a buffer. Specific metadata, such as timing metadata,
-will have this structure as the first field. For example:
-
-  struct _GstBufferMetaTiming {
-    GstBufferMeta  meta;        /* common meta header */
-    GstClockTime   dts;         /* decoding timestamp */
-    GstClockTime   pts;         /* presentation timestamp */
-    GstClockTime   duration;    /* duration of the data */
-    GstClockTime   clock_rate;  /* clock rate for the above values */
-  };
-
-Or another example for the buffer memory region
-
-  struct _GstBufferMetaMemory {
-    GstBufferMeta      meta;
-   
-    /* pointer to data and its size */
-    guint8            *data;
-    guint              size;
-    guint8            *malloc_data;
-    GFreeFunc          data_free;
-    gpointer           data_user;
-  };
-
-GstBufferMetaInfo will point to more information about the metadata and looks like this:
-
-  struct _GstBufferMetaInfo {
-    GQuark                     tag;       /* tag name */
-    gsize                      size;      /* size of the structure */
-
-    GstMetaInitFunction        init_func;
-    GstMetaFreeFunction        free_func;
-    GstMetaCopyFunction        copy_func;
-    GstMetaSubFunction         sub_func;
-    GstMetaSerializeFunction   serialize_func
-    GstMetaDeserializeFunction deserialize_func
-    GstMetaConvFunction        conv_func;
-  }
-
-Tag will contain a GQuark of the metadata name. We will be able to refer to specific
-metadata by name or by its (cached) GQuark.  A repository of registered MetaInfo
-will be maintained by the core. We will register some common metadata structures
-in core and some media specific info for audio/video/text in -base. Plugins can
-register additional custom metadata.
-
-Along with the metadata description we will have functions to initialize/free (and/or refcount)
-a specific GstBufferMeta instance. We also have the possibility to add a custom subbuffer
-function that can be used to modify the metadata when a subbuffer is taken.
-
-We also add serialize and deserialize function for the metadata in case we need special
-logic for reading and writing the metadata. This is needed for GDP payloading of the
-metadata.
-
-We add a conv function to the Info structure that will be called when a buffer
-should be converted to an old-style buffer for backward compatibility.
-
-The purpose of the separate MetaInfo is to not have to carry the free/init functions in
-each buffer instance but to define them globally. We still want quick access to the info
-so we need to make the buffer metadata point to the info.
-
-Technically we could also specify the field and types in the MetaInfo and
-provide a generic API to retrieve the metadata fields without the need for a
-header file. We will not do this yet.
-The complete buffer with metadata would then look as follows:
-
-                         +-------------------------------------+
-GstMiniObject            |     GType (GstBuffer)               |
-                         |     refcount, flags, copy/free      |
-                         +-------------------------------------+
-GstBuffer                |     caps, parent, subfunc           |
-                         +.....................................+
-                      +- |     info                           ------> GstBufferMetaInfo
-GstBufferMetaTiming   |  |     next                           ---+
-                      |  |                                     | |
-                      |  |     dts                             | |
-                      |  |     pts                             | |
-                      |  |     duration                        | |
-                      +- |     clock_rate                      | |
-                         + . . . . . . . . . . . . . . . . . . + |
-                      +- |     info                           <--+ -> GstBufferMetaInfo
-GstBufferMetaMemory   |  |     next                           ---+
-                      |  |                                     | |
-                      |  |     data                            | |
-                      |  |     size                            | |
-                      |  |     mallocdata                      | |
-                      |  |     data_free                       | |
-                      +- |     data_user                       | |
-                         + . . . . . . . . . . . . . . . . . . + .
-                         .                                       .
-
-API examples
-~~~~~~~~~~~~
-
-Buffers are created using the normal gst_buffer_new functions. The standard fields
-are initialized as usual. A memory area that is bigger than the structure size
-is allocated for the buffer metadata. The remaining free area is stored in the
-free_size field.
-
-  gst_buffer_new ();
-
-After creating a buffer, the application can set caps. and add other metadata
-information. 
-
-In order to modify metadata, a reference to the MetaInfo should be obtained.
-This can be done like this:
-
-  GstBufferMetaInfo *info;
-
-  info = gst_buffer_meta_get_info (GQuark tag);
-
-Usually the info will be obtained only once in order to avoid lock contention on
-the global pool of meta info. The core will also provide convenience functions
-for the core metainfo.
-
-Once a reference to the info has been obtained, the associated metadata can be
-added or modified on a buffer.
-
-For example, to modify the timing info on a buffer, one could use the following
-sequence:
-
-  GstBufferMetaInfo *info;
-  GstBufferMetaTiming *timing;
-
-  info = gst_buffer_meta_get_info (GST_META_TIMING_QUARK);
-  
-  timing = gst_buffer_get_meta (buffer, info, TRUE); /* TRUE = create if absent */
-  timing->timestamp = 0;
-  timing->duration = 20 * GST_MSECOND;
-
-The _get_meta() function returns a pointer to the metadata structure associated
-with the GST_META_TIMING_QUARK info.
-
-For the core meta info, we will provide convenience code that uses the cached
-GstBufferMetaInfo, making the above code a little more simple.
-
-  GstBufferMetaTiming *timing;
-
-  timing = gst_buffer_get_meta_timing (buffer, TRUE); /* TRUE = create if absent */
-  timing->timestamp = 0;
-  timing->duration = 20 * GST_MSECOND;
-Note that for each of the metadata that we will add to buffers, we need a struct
-definition and a registered MetaInfo. 
-
-
-We will also provide an API to iterate the different metainfo structures. A
-possible simple API would look like this:
-
- GstBufferMeta *current = NULL;
-
- /* passing NULL gives the first entry */ 
- current = gst_buffer_meta_get_next (buffer, current);
-
- /* passing a GstBufferMeta returns the next */
- current = gst_buffer_meta_get_next (buffer, current);
-
-
-
-Memory management
-~~~~~~~~~~~~~~~~~
-
-* allocation
-
-  We will initially allocate a reasonable sized GstBuffer structure (say 512
-  bytes) and we will set the free_size to the maximum amount of metadata we can
-  store.
-
-  Since the complete buffer structure, including a large area for metadata, is
-  allocated in one go, we can reduce the number of memory allocations while still
-  providing dynamic metadata.
-
-  When adding metadata, we need to call the init function of the associated
-  metadata info structure. Since adding the metadata requires the caller to pass
-  a handle to the info, this operation does not require table lookups.
-
-  Per-metadata memory initialisation is needed because not all metadata is
-  initialized in the same way. We need to, for example, set the timestamps to
-  NONE in the MetaTiming structures.
-
-  The init/free functions can also be used to implement refcounting for a metadata
-  structure. This can be useful when a structure is shared between buffers.
-
-  When the free_size of the GstBuffer is exhausted, we will allocate new memory
-  for each newly added BufferMeta and use the next pointers to point to this. It
-  is expected that this does not occur often and we might be able to optimize
-  this transparently in the future.
-
-* free
-
-  When a GstBuffer is freed, we potentially might have to call a custom free
-  function on the metadata info. In the case of the Memory metadata, we need to
-  call the associated free function to free the memory.
-  
-  When freeing a GstBuffer, the custom buffer free function will iterate all of
-  the metadata in the buffer and call the associated free functions in the
-  MetaInfo associated with the entries. Usually, this function will be NULL.
-
-
-Subbuffers
-~~~~~~~~~~
-
-Subbuffers are a first class feature of the GstBuffer. 
-
-Creating a subbuffer from a GstBuffer will allocate a new GstBuffer and ref the
-parent buffer. It will then iterate all of the metadata entries for the parent
-buffer and call the associated sub_func in the MetaInfo.
-
-This allows each metadata structure to implement the actions needed to update
-the metadata of the subbuffer. 
-
-A pointer to the old and new memory location of the metadata is passed to the
-sub_func. The default implementation will simply copy the metadata. Custom
-implementations can adjust the values. For example, when making a subbuffer, the
-timing metadata needs to be reset to NONE when the start offset is different.
-
-
-Serialization
-~~~~~~~~~~~~~
-
-When buffer should be sent over the wire or be serialized in GDP, we need a way
-to perform custom serialization and deserialization on the metadata.
-
-For this we add the serialize and deserialize functions to the metadata info.
-Possible use cases are to make sure we write out the fields with a specific size
-and endianness.
-
-
-Transformations
-~~~~~~~~~~~~~~~
-
-After certain transformations, the metadata on a buffer might not be relevant
-anymore.
-
-Consider, for example, metadata that lists certain regions of interest
-on the video data. If the video is scaled or rotated, the coordinates might not
-make sense anymore. A transform element should be able to adjust or remove the
-associated metadata when it becomes invalid. 
-
-We can make the transform element aware of the metadata so that it can adjust or
-remove in an intelligent way. Since we allow arbitrary metadata, we can't do
-this for all metadata and thus we need some other way.
-
-One proposition is to tag the metadata type with keywords that specify what it
-functionally refers too. We could, for example, tag the metadata for the regions
-of interest with a tag that notes that the metadata refers to absolute pixel
-positions. A transform could then know that the metadata is not valid anymore
-when the position of the pixels changed (due to rotation, flipping, scaling and
-so on).
-
-
-Other use cases
-~~~~~~~~~~~~~~~
-
-Making the GstBufferMetaMemory (for making the buffer point to the associated
-memory region) as metadata on a GstBuffer, as opposed to making it an integral
-part of GstBuffer, allows for some more interesting ways to transfer data.
-
-We could for example make a new GstBufferMetaIOVec metadata structure like this:
-
-  struct _GstBufferMetaIOVec {
-    GstBufferMeta  meta;
-   
-    /* pointer to data and its size */
-    GFreeFunc       data_free;
-    gpointer        data_user;
-    guint           len;
-    struct iovec   *iov;
-  };
-
-This would allow us to transfer data in a scatter/gather array. Since the fields
-in the buffer metadata are now explicit, elements that don't support this kind
-of metadata can gracefully degrade.
-
-Another use case for not having the Memory metadata in the buffers would be for
-_pad_alloc() and get_range(). We can pass a GstBuffer with the requested
-metadata fields to those functions and have the _get_range() or pad_alloc()
-implementations add (or use, in the case of a file reader) the memory metadata. 
-
-
-Relationship with GstCaps
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The difference between GstCaps, used in negotiation, and the metadata is not
-clearly defined. 
-
-We would like to think of the GstCaps containing the information needed to
-functionally negotiate the format between two elements. The Metadata should then
-only contain variables that can change between each buffer.
-
-For example, for video we would have width/height/framerate in the caps but then
-have the more technical details, such as stride, data pointers, pan/crop/zoom
-etc in the metadata.
-
-A scheme like this would still allow us to functionally specify the desired
-video resolution while the implementation details would be inside the metadata.
-
-
-Compatibility
-~~~~~~~~~~~~~
-
-We need to make sure that elements exchange metadata that they both understand,
-This is particulary important when the metadata describes the data layout in
-memory (such as strides).
-
-Currently the only way to communicate buffer formats between elements is by
-using caps. We would like to use the caps system to negotiate the metadata that
-will be put on buffers.
-
-We would like to add to the caps on the buffer (and pad) an array of metadata
-structures (as strings) that is on the buffer. This way, an element can
-quickly know what metadata to look for.
-
-In order to remain compatibility with older plugins we need to convert buffers
-that use metadata to specify a non-standard data layout to the old format. We
-need to do this before handing buffers to old elements. We will require elements
-that are metadata aware to set a flag on their pads; any buffer passed on that
-pad will be converted to the old layout when the flag is not set.
-
-
-Notes
-~~~~~
-
-Some structures that we need to be able to add to buffers.
-
-* Clean Aperture
-* Arbitrary Matrix Transform
-* Aspect ratio
-* Pan/crop/zoom
-* Video strides
-
-Some of these overlap, we need to find a minimal set of metadata structures that
-allows us to define all use cases.
-
-
-
-
diff --git a/docs/design/draft-bufferpool.txt b/docs/design/draft-bufferpool.txt
deleted file mode 100644 (file)
index 72d3a61..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-Bufferpool
-----------
-
-This document details a possible design for how buffers can be allocated
-and managed in pools.
-
-Bufferpools should increase performance by reducing allocation overhead and
-improving possibilities to implement zero-copy memory transfer.
-
-
-Current Situation
------------------
-
- - elements can choose to implement a pool of buffers. These pools
-   can contain buffers for both source and sink pad buffers.
-
- - elements can provide buffers to upstream elements when the upstream element
-   requests a buffer with gst_pad_alloc_buffer().
-
- - The buffer pool can preallocate a certain amount of buffers to avoid
-   runtime allocation. pad_alloc_buffer() is allowed to block the upstream
-   element until buffers are recycled in the pool.
-
- - the pad_alloc_buffer function call can be passed downstream to the sink
-   that actually will perform the allocation. A fallback option exists to use
-   a default memory bufferpool whe there is no alloc_buffer function installed
-   on a pad.
-
- - Upstream renegotiation is performed by making the pad_alloc_buffer function
-   return a buffer with new caps.
-
-
-Problems
---------
-
- - There is currently no helper base class to implement efficient buffer pools
-   meaning that each element has to implement its own version.
-
- - There is no negotiation between elements about their buffer requirements.
-   Upstream elements that decide to use pad_alloc_buffer() can find that the
-   buffer they received is not appropriate at all. The most common problem
-   is that the buffers don't have the right alignment or insufficient padding.
-
- - There is no negotiation of minimum and maximum amounts of preallocated
-   buffers. In order to not avoid deadlocks, this means that buffer pool
-   implementations should be able to allocate unlimited amounts of buffers and
-   are never allowed to block in pad_alloc_buffer()
-
-
-Requirements
-------------
-
- - maintain and reuse a list of buffers in a reusable base GstBufferPool
-   object
-
- - negotiate allocation configuration between source and sink pad.
-   - have minimum and maximum amount of buffers with the option of 
-     preallocating buffers.
-   - alignment and padding support
-   - arbitrary extra options
-
- - integrate with dynamic caps renegotiation
-
- - dynamically change bufferpool configuration based on pipeline changes.
-
- - allow the application to control buffer allocation
-
-
-GstBufferPool
--------------
-
- The bufferpool object manages a list of buffers with the same properties such
- as size, padding and alignment.
-
- The bufferpool has two states: flushing and non-flushing. In the flushing
- state, the bufferpool can be configured with the required allocation
- preferences. In the non-flushing state, buffers can be retrieved from and
- returned to the pool.
-
- The default implementation of the bufferpool is able to allocate buffers
- from main memory with arbitrary alignment and padding/prefix.
-
- Custom implementations of the bufferpool can override the allocation and
- free algorithms of the buffers from the pool. This should allow for
- different allocation strategies such as using shared memory or hardware
- mapped memory.
-
- The bufferpool object is also used to perform the negotiation of configuration
- between elements.
-
-
-GstPad
-------
-
- The GstPad has a method to query a GstBufferPool and its configuration.
-
-   GstBufferPool * gst_pad_query_bufferpool (GstPad * pad);
-
- This function can return a handle to a bufferpool object or NULL when no
- bufferpool object can be provided by the pad.
-
- This function should return a bufferpool object with the
- GstBufferPoolConfig set to the desired parameters of the buffers that will be
- handled by the given pad. This function can only be called on a sinkpad and
- will usually be called by the peer srcpad with the convenience method:
-
-   GstBufferPool * gst_pad_peer_query_bufferpool (GstPad * pad);
- There is also a new function to configure a bufferpool on a pad and its peer
- pad:
-
-   gboolean gst_pad_set_bufferpool (GstPad * pad, GstBufferPool *pool);
- This function is to inform a pad and its peer pad that a bufferpool should
- be used for allocation (on source pads) and that bufferpool is used by the
- upstream element (on sinkpads).
-
- The currently configured bufferpool can be retrieved with:
-
-   GstBufferPool * gst_pad_get_bufferpool (GstPad * pad);
-
- New functions exist to configure these bufferpool functions on pads:
- gst_pad_set_querybufferpool_function and gst_pad_set_setbufferpool_function.
-
-negotiating pool and config
----------------------------
-
-Since upstream needs to allocate buffers from a buffer pool, it should first
-negotiate a buffer pool with the downstream element. We propose a simple
-scheme where a sink can propose a bufferpool and some configuration and where
-the source can choose to use this allocator or use its own.
-
-The algorithm for doing this is rougly like this:
-
-
-   /* srcpad knows media type and size of buffers and is ready to
-    * prepare an output buffer but has no pool yet */
-
-   /* first get the pool from the downstream peer */
-   pool = gst_pad_peer_query_bufferpool (srcpad);
-
-   if (pool != NULL) {
-     GstBufferPoolConfig config;
-
-     /* clear the pool so that we can reconfigure it */
-     gst_buffer_pool_set_flushing (pool, TRUE);
-
-     do {
-       /* get the config */
-       gst_buffer_pool_get_config (pool, &config);
-
-       /* check and modify the config to match our requirements */
-       if (!tweak_config (&config)) {
-         /* we can't tweak the config any more, exit and fail */
-         gst_object_unref (pool);
-         pool = NULL;
-         break;
-       } 
-     }
-     /* update the config */
-     while (!gst_buffer_pool_set_config (pool, &config));
-
-     /* we managed to update the config, all is fine now */
-     /* set the pool to non-flushing to make it allocate things */
-     gst_buffer_pool_set_flushing (pool, FALSE);
-   }
-
-   if (pool == NULL) {
-     /* still no pool, we create one ourself with our ideal config */
-     pool = gst_buffer_pool_new (...);
-   }
-
-   /* now set the pool on this pad and the peer pad */
-   gst_pad_set_bufferpool (pad, pool);
-
-
-Negotiation is the same for both push and pull mode. In the case of pull
-mode scheduling, the srcpad will perform the negotiation of the pool
-when it receives the first pull request.
-
-
-Allocating from pool
---------------------
-
- Buffers are allocated from the pool of a pad:
-
-  res = gst_buffer_pool_acquire_buffer (pool, &buffer, &params);
-
- convenience functions to automatically get the pool from a pad can be made:
-  
-  res = gst_pad_acquire_buffer (pad, &buffer, &params);
-
- Buffers are refcounted in te usual way. When the refcount of the buffer
- reaches 0, the buffer is automatically returned to the pool. This is achieved
- by setting and reffing the pool as a new buffer member.
-
- Since all the buffers allocated from the pool keep a reference to the pool,
- when nothing else is holding a refcount to the pool, it will be finalized
- when all the buffers from the pool are unreffed. By setting the pool to
- the flushing state we can drain all buffers from the pool. 
-
-
-Renegotiation
--------------
-
-Renegotiation of the bufferpool might need to be performed when the
-configuration of the pool changes. Changes can be in the buffer size (because
-of a caps change), alignment or number of buffers. 
-
-* downstream
-
-  When the upstream element wants to negotiate a new format, it might need
-  to renegotiate a new bufferpool configuration with the downstream element.
-  This can, for example, happen when the buffer size changes.
-
-  We can not just reconfigure the existing bufferpool because there might
-  still be outstanding buffers from the pool in the pipeline. Therefore we
-  need to create a new bufferpool for the new configuration while we let the
-  old pool drain.
-
-  Implementations can choose to reuse the same bufferpool object and wait for
-  the drain to finish before reconfiguring the pool.
-
-  The element that wants to renegotiate a new bufferpool uses exactly the same
-  algorithm as when it first started.
-  
-* upstream 
-
-  When a downstream element wants to negotiate a new format, it will send a 
-  RECONFIGURE event upstream. This instructs upstream to renegotiate both
-  the format and the bufferpool when needed.
-
-  A pipeline reconfiguration is when new elements are added or removed from
-  the pipeline or when the topology of the pipeline changes. Pipeline
-  reconfiguration also triggers possible renegotiation of the bufferpool and
-  caps.
-
-  A RECONFIGURE event tags each pad it travels on as needing reconfiguration.
-  The next buffer allocation will then require the renegotiation or
-  reconfiguration of a pool.
-
-  If downstream has specified a RENEGOTIATE flag, it must be prepared to
-  received NOT_NEGOTIATED results when allocating buffers, which instructs
-  it to start caps and bufferpool renegotiation. When using this flag, 
-  upstream can more quickly react to downstream format or size changes.
-
-
-Shutting down
--------------
-
- In push mode, a source pad is responsible for setting the pool to the
- flushing state when streaming stops. The flush will unblock any pending
- allocations so that the element can shut down.
-
- In pull mode, the sink element should set the pool to the flushing state when
- shutting down so that the peer _get_range() function can unblock.
-
- In the flushing state, all the buffers that are returned to the pool will
- be automatically freed by the pool and new allocations will fail.
-
-
-
-Use cases
----------
-
-1)  videotestsrc ! xvimagesink
-
- Before videotestsrc can output a buffer, it needs to negotiate caps and
- a bufferpool with the downstream peer pad.
-
- First it will negotiate a suitable format with downstream according to the
- normal rules.
-
- Then it does gst_pad_peer_query_bufferpool() which triggers the querybufferpool
- function installed on the xvimagesink pad. This bufferpool is currently in
- the flushing state and thus has no buffers allocated.
-
- videotestsrc gets the configuration of the bufferpool object. This
- configuration lists the desired configuration of the xvimagesink, which can
- have specific alignment and/or min/max amount of buffers.
-
- videotestsrc updates the configuration of the bufferpool, it will likely
- set the min buffers to 1 and the size of the desired buffers. It then
- updates the bufferpool configuration with the new properties.
-
- When the configuration is successfully updated, videotestsrc sets the 
- bufferpool on its source pad, this will also set the pool on the peer 
- sinkpad.
-
- It then sets the bufferpool to the non-flushing state. This preallocates
- the buffers in the pool (if needed). This operation can fail when there
- is not enough memory available. Since the bufferpool is provided by
- xvimagesink, it will allocate buffers backed by an XvImage and pointing
- to shared memory with the X server.
-
- If the bufferpool is successfully activated, videotestsrc can acquire a
- buffer from the pool, set the caps on it, fill in the data and push it
- out to xvimagesink.
-
- xvimagesink can know that the buffer originated from its pool by following
- the pool member or checking the specific GType of it GstBuffer subclass.
- It might need to get the parent buffer first in case of subbuffers.
-
- when shutting down, videotestsrc will set the pool to the flushing state,
- this will cause further allocations to fail and currently allocated buffers
- to be freed. videotestsrc will then free the pool and stop streaming.
-
-
-2) videotestsrc ! queue ! myvideosink
-
- In this second use case we have a videosink that can at most allocate
- 3 video buffers.
-
- Again videotestsrc will have to negotiate a bufferpool with the peer 
- element. For this it will perform gst_pad_peer_query_bufferpool() which
- queue will proxy to its downstream peer element.
-
- The bufferpool returned from myvideosink will have a max_buffers set to 3.
- queue and videotestsrc can operate with this upper limit because none of
- those elements require more than that amount of buffers for temporary
- storage.
-
- The bufferpool of myvideosink will then be configured with the size of the
- buffers for the negotiated format and according to the padding and alignment
- rules. When videotestsrc sets the pool to non-flushing, the 3 video
- buffers will be preallocated in the pool.
-
- The pool will then be configured on the src of videotestsrc and the
- sinkpad of the queue. The queue will proxy the setbufferpool method to
- its srcpad, which finally configures the pool all the way to the sink.
-
- videotestsrc acquires a buffer from the configured pool on its srcpad and
- pushes this into the queue. When the videotestsrc has acquired and pushed
- 3 frames, the next call to gst_buffer_pool_acquire_buffer() will block
- (assuming the GST_BUFFER_POOL_FLAG_WAIT is specified).
-
- When the queue has pushed out a buffer and the sink has rendered it, the
- refcount of the buffer reaches 0 and the buffer is recycled in the pool.
- This will wake up the videotestsrc that was blocked, waiting for more
- buffers and will make it produce the next buffer. 
-
- In this setup, there are at most 3 buffers active in the pipeline and
- the videotestsrc is rate limited by the rate at which buffers are recycled
- in the bufferpool.
-
- When shutting down, videotestsrc will first set the bufferpool on the srcpad
- to flushing. This causes any pending (blocked) acquire to return with a 
- WRONG_STATE result and causes the streaming thread to pause.
-
-3) .. ! myvideodecoder ! queue ! fakesink 
-
- In this case, the myvideodecoder requires buffers to be aligned to 128
- bytes and padded with 4096 bytes. The pipeline starts out with the
- decoder linked to a fakesink but we will then dynamically change the
- sink to one that can provide a bufferpool.
-
- When it negotiates the size with the downstream element fakesink, it will
- receive a NULL bufferpool because fakesink does not provide a bufferpool.
- It will then select it own custom bufferpool to start the datatransfer.
-
- At some point we block the queue srcpad, unlink the queue from the 
- fakesink, link a new sink, set the new sink to the PLAYING state and send
- the right newsegment event to the sink. Linking the new sink would 
- automatically send a RENEGOTIATE event upstream and, through queue, inform
- myvideodecoder that it should renegotiate its bufferpool because downstream
- has been reconfigured.
-
- Before pushing the next buffer, myvideodecoder would renegotiate a new
- bufferpool. To do this, it performs the usual bufferpool negotiation
- algorithm. If it can obtain and configure a new bufferpool from downstream,
- it sets its own (old) pool to flushing and unrefs it. This will eventually
- drain and unref the old bufferpool.
-
- The new bufferpool is set as the new bufferpool for the srcpad and sinkpad
- of the queue and set to the non-flushing state.
-
-
-4) .. ! myvideodecoder ! queue ! myvideosink 
-
- myvideodecoder has negotiated a bufferpool with the downstream myvideosink
- to handle buffers of size 320x240. It has now detected a change in the 
- video format and need to renegotiate to a resolution of 640x480. This
- requires it to negotiate a new bufferpool with a larger buffersize.
-
- When myvideodecoder needs to get the bigger buffer, it starts the 
- negotiation of a new bufferpool. It queries a bufferpool from downstream,
- reconfigures it with the new configuration (which includes the bigger buffer
- size), it sets the bufferpool to non-flushing and sets the bufferpool as
- the new pool for the srcpad and its peer. This automatically flushes the
- old pool and unrefs it, which causes the old format to drain.
-
- It then uses the new bufferpool for allocating new buffers of the new 
- dimension.
-
- If at some point, the decoder wants to switch to a lower resolution again,
- it can choose to use the current pool (which has buffers that are larger
- than the required size) or it can choose to renegotiate a new bufferpool.
-
-
-5) .. ! myvideodecoder ! videoscale ! myvideosink 
-
- myvideosink is providing a bufferpool for upstream elements and wants to
- change the resolution.
-
- myvideosink sends a RENEGOTIATE event upstream to notify upstream that a
- new format is desirable. upstream elements try to negotiate a new format
- and bufferpool before pushing out a new buffer. The old bufferpools are
- drained in the regular way.
-
-
-
index 00524b7..9cb8f0c 100644 (file)
@@ -10,8 +10,7 @@ API/ABI
   keyframe, after the seek you want to get the new stream time that will
   actually be used to update the slider bar.
 
-- make gst_pad_push_event() return a GstFlowReturn so that we can resend
-  NEWSEGMENT and other events.
+- make gst_pad_push_event() return a GstFlowReturn
 
 - GstEvent, GstMessage register like GstFormat or GstQuery.
 
@@ -22,13 +21,15 @@ API/ABI
 
 - rethink how we handle dynamic replugging wrt segments and other events that
   already got pushed and need to be pushed again. Might need GstFlowReturn from
-  gst_pad_push_event().
+  gst_pad_push_event(). FIXED in 0.11 with sticky events.
 
 - Optimize negotiation. We currently do a get_caps() call when we link pads,
   which could potentially generate a huge list of caps and all their
   combinations, we need to avoid generating these huge lists by generating them
+  We also need to incrementally return intersections etc, for this. somewhat
   incrementally when needed. We can do this with a gst_pad_iterate_caps() call.
   We also need to incrementally return intersections etc, for this.
+  FIXED in 0.11 with a filter on getcaps functions.
 
 - Elements in a bin have no clue about the final state of the parent element
   since the bin sets the target state on its children in small steps. This
@@ -50,6 +51,7 @@ API/ABI
     and another a push, the push might be busy while the block callback is done.
   * maybe this name is overloaded. We need to look at some more use cases before
     trying to fix this.
+  FIXED in 0.11 with BLOCKING probes. Not everything is implemented yet, though.
 
 - rethink the way we do upstream renegotiation. Currently it's done with
   pad_alloc but this has many issues such as only being able to suggest 1 format
@@ -57,8 +59,7 @@ API/ABI
   as capsfilter only know about the format, not the size). We would ideally like
   to let upstream renegotiate a new format just like it did when it started.
   This could, for example, easily be triggered with a RENEGOTIATE event.
-
-- Remove the XML serialisation stuff.
+  FIXED in 0.11 with RECONFIGURE events.
 
 - Remove the result format value in queries.
 
@@ -75,8 +76,6 @@ IMPLEMENTATION
 
 - implement BUFFERSIZE.
 
-- implement pad_block with probes? see above.
-
 
 DESIGN
 ~~~~~~
index 854951d..deaedbf 100644 (file)
@@ -157,19 +157,3 @@ as well, so that there is a generic method for both PAUSED and PLAYING.
 The same flow works as well for any chain of multiple elements and might 
 be implemented with a helper function in the future.
 
-
-Issues
-~~~~~~
-
-When an EOS event has passed a pad and the pad is set to blocked, the block will
-never happen because no data is going to flow anymore. One possibility is to
-keep track of the pad's EOS state and make the block succeed immediately. This is
-not yet implemenented.
-
-When dynamically reconnecting pads, some events (like NEWSEGMENT, EOS,
-TAGS, ...) are not yet retransmitted to the newly connected element. It's
-unclear if this can be done by core automatically by caching those events and
-resending them on a relink. It might also be possible that this needs a
-GstFlowReturn value from the event function, in which case the implementation
-must be delayed for after 0.11, when we can break API/ABI.
-
diff --git a/docs/design/part-buffer.txt b/docs/design/part-buffer.txt
new file mode 100644 (file)
index 0000000..b6568ed
--- /dev/null
@@ -0,0 +1,154 @@
+GstBuffer
+---------
+
+This document describes the design for buffers.
+
+A GstBuffer is the object that is passed from an upstream element to a
+downstream element and contains memory and metadata information.
+
+Requirements
+~~~~~~~~~~~~
+
+ - It must be fast
+    * allocation, free, low fragmentation
+ - Must be able to attach multiple memory blocks to the buffer
+ - Must be able to attach artibtrary metadata to buffers
+ - efficient handling of subbuffer, copy, span, trim
+
+Writability
+-----------
+
+The Buffers is writable when the refcount is 1. This means that:
+
+ - metadata can be added/removed and the metadata can be changed
+ - GstMemory blocks can be added/removed
+
+The individual memory blocks have their own refcounting and READONLY flags
+that might influence their writability.
+
+Buffers can be made writable with gst_buffer_make_writable(). This will copy the
+buffer with the metadata and will ref the memory in the buffer. This means that
+the memory is not automatically copied when copying buffers.
+
+
+Managing GstMemory
+------------------
+
+A GstBuffer contains an array of pointers to GstMemory objects. 
+
+When the buffer is writable, gst_buffer_take_memory() can be used to add a
+new GstMemory object to the buffer. When the array of memory is full, memory
+will be merged to make room for the new memory object.
+
+gst_buffer_n_memory() is used to get the amount of memory blocks on the
+GstBuffer.
+
+With gst_buffer_peek_memory(), memory can be retrieved from the memory array.
+The desired access pattern for the memory block should be specified so that
+appropriate checks can be made and, in case of GST_MAP_WRITE, a writable copy
+can be constructed when needed.
+
+gst_buffer_remove_memory_range() and gst_buffer_remove_memory() can be used to
+remove memory from the GstBuffer.
+
+
+Subbuffers
+----------
+
+Subbuffers are made by copying only a region of the memory blocks and copying
+all of the metadata.
+
+
+Span
+----
+
+Spanning will merge together the data of 2 buffers into a new buffer
+
+
+Data access
+-----------
+
+ Accessing the data of the buffer can happen by retrieving the individual
+ GstMemory objects in the GstBuffer or my using the gst_buffer_map() and
+ gst_buffer_unmap() function.
+
+ The _map and _unmap function will always return the memory of all blocks as one
+ large contiguous region of memory. Using the _map and _unmap function might be
+ more convenient that accessing the individual memory blocks at the expense of
+ being more expensive because it might perform memcpy operations.
+
+ For buffers with only one GstMemory object (the most common case), _map and
+ _unmap have no performance penalty at all.
+
+
+* Read access with 1 memory block
+
+  The memory block is accessed and mapped for read access.
+  The memory block is unmapped after usage
+
+* write access with 1 memory block
+
+  The buffer should be writable or this operation will fail..
+  The memory block is accessed. If the memory block is readonly, a copy is made
+  and the original memory block is replaced with this copy. then the memory
+  block is mapped in write mode.
+  The memory block is unmapped after usage.
+
+* Read access with multiple memory blocks
+
+  The memory blocks are combined into one large memory block. If the buffer is
+  writable, The memory blocks are replace with this new memory block. If the
+  buffer is not writable, the memory is returned as is.
+  The memory block is then mapped in read mode.
+
+  When the memory is unmapped after usage and the buffer has multiple memory
+  blocks, this means that the map operation was not able to store the combined
+  buffer and it thus returned memory that should be freed. Otherwise, the memory
+  is unmapped.
+
+* Write access with multiple memory blocks
+
+  The buffer should be writable or the operation fails. The memory blocks are
+  combined into one large memory block and the existing blocks are replaced with
+  this new block. The memory is then mapped in write mode.
+  The memory is unmapped after usage.
+
+
+Use cases
+---------
+
+Generating RTP packets from h264 video
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+We receive as input a GstBuffer with an encoded h264 image and we need to
+create RTP packets containing this h264 data as the payload. We typically need
+to fragment the h264 data into multiple packets, each with their own RTP and
+payload specific header.
+
+                       +-------+-------+---------------------------+--------+
+  input H264 buffer:   | NALU1 | NALU2 |  .....                    | NALUx  |
+                       +-------+-------+---------------------------+--------+
+                             |
+                             V
+  array of             +-+ +-------+  +-+ +-------+            +-+ +-------+
+  output buffers:      | | | NALU1 |  | | | NALU2 |   ....     | | | NALUx |
+                       +-+ +-------+  +-+ +-------+            +-+ +-------+
+                       :           :  :           :
+                       \-----------/  \-----------/
+                         buffer 1        buffer 2
+
+The output buffer array consists of x buffers consisting of an RTP payload header
+and a subbuffer of the original input H264 buffer. Since the rtp headers and
+the h264 data don't need to be contiguous in memory, they are added to the buffer
+as separate GstMemory blocks and we can avoid to memcpy the h264 data into
+contiguous memory.
+
+A typical udpsink will then use something like sendmsg to send the memory regions
+on the network inside one UDP packet. This will further avoid having to memcpy
+data into contiguous memory.
+
+Using bufferlists, the complete array of output buffers can be pushed in one
+operation to the peer element.
+
+
+
diff --git a/docs/design/part-bufferlist.txt b/docs/design/part-bufferlist.txt
deleted file mode 100644 (file)
index 527d1e8..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-Buffer Lists
-------------
-
-GstBuffer provides a datastructure to manage:
-
- - a continuous region of memory
- - functions to copy/free the memory
- - metadata associated with that memory such as timestamps and caps.
-
-It is the primary means of transfering data between pads and elements.
-
-GstBufferList expands on GstBuffer to allow multiple GstBuffers (conceptually 
-organized in a list) to be treated as a multiple groups of GstBuffers. This allows
-for the following extra functionality:
-
- - A logical GstBuffer (called a group) can consist of disjoint memory each with
-   their own copy/free and metadata. Logically the group should be treated as
-   one single GstBuffer.
- - Multiple groups can be put into one bufferlist. This allows for a single
-   method call to pass multiple (logical) buffers downstream.
-
-
-Use cases
-~~~~~~~~~
-
-A typical use case for multimedia pipelines is to append or remove 'headers'
-from packets of data.
-
-Generating RTP packets from h264 video
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-We receive as input a GstBuffer with an encoded h264 image and we need to
-create RTP packets containing this h264 data as the payload. We typically need
-to fragment the h264 data into multiple packets, each with their own RTP and
-payload specific header.
-
-                       +-------+-------+---------------------------+--------+
-  input H264 buffer:   | NALU1 | NALU2 |  .....                    | NALUx  |
-                       +-------+-------+---------------------------+--------+
-                             |
-                             V
-                       +-+ +-------+  +-+ +-------+            +-+ +-------+
-  output bufferlist:   | | | NALU1 |  | | | NALU2 |   ....     | | | NALUx |
-                       +-+ +-------+  +-+ +-------+            +-+ +-------+
-                       :           :  :           :
-                       \-----------/  \-----------/
-                         group 1        group 2 
-
-The output bufferlist consists of x groups consisting of an RTP payload header
-and a subbuffer of the original input H264 buffer. Since the rtp headers and
-the h264 data don't need to be contiguous in memory, we can avoid to memcpy the
-h264 data into the rtp packets.
-
-Since we can generate a bufferlist with multiple groups, we can push all the
-RTP packets for the input data to the next element in one operation.
-
-A typical udpsink will then use something like sendmsg to send the groups on
-the network inside one UDP packet. This will further avoid having to memcpy
-data into contiguous memory.
-
-
-API
-~~~
-
-The GstBufferList is an opaque data structure and is operated on using an
-iterator. It derives from GstMiniObject so that it has basic refcounting and
-copy/free functions.
-
-The bufferlist is writable when its refcount is 1 and it's not marked as
-readonly. A writable bufferlist means that elements can be added and removed
-form the list but it does not mean that the actual buffers in the list are
-writable.
-
-To modify the data in the buffers of the bufferlist, both the list and the
-buffer must be writable.
-
-Methods exist for navigating the groups in the list and the buffers inside a
-group. 
-
-
-Metadata
-~~~~~~~~
-
-Each of the buffers inside the bufferlist can have metadata associated with it.
-
-The metadata of the bufferlist is always the metadata of the first buffer of the
-first group in the bufferlist. This means that:
-
-  - Before pushing the list to a pad, negotiation happens with (only) the caps of
-    the first buffer in the list. Caps of other buffers is ignore.
-
-  - synchronisation happens on the timestamp of the first buffer in the list.
-
-This allows for efficient (re)timestamping and re-typing (caps) of a group of
-buffers without having to modify each of the buffer's metadata.
-
diff --git a/docs/design/part-bufferpool.txt b/docs/design/part-bufferpool.txt
new file mode 100644 (file)
index 0000000..b4254dc
--- /dev/null
@@ -0,0 +1,344 @@
+Bufferpool
+----------
+
+This document details the design of how buffers are be allocated and
+managed in pools.
+
+Bufferpools increases performance by reducing allocation overhead and
+improving possibilities to implement zero-copy memory transfer.
+
+Together with the ALLOCATION query, elements can negotiate allocation properties
+and bufferpools between themselves. This also allows elements to negotiate
+buffer metadata between themselves.
+
+Requirements
+------------
+
+ - Provide a GstBufferPool base class to help the efficient implementation of a
+   list of reusable GstBuffer objects.
+
+ - Let upstream elements initiate the negotiation of a bufferpool and it
+   configuration. Allow downstream elements provide bufferpool properties and/or
+   a bufferpool. This includes the following properties:
+
+    * have minimum and maximum amount of buffers with the option of 
+      preallocating buffers.
+    * alignment and padding support
+    * buffer metadata
+    * arbitrary extra options
+
+ - Integrate with dynamic caps renegotiation.
+
+ - Notify upstream element of new bufferpool availability. This is important
+   when a new element, that can provide a bufferpool, is dynamically linked
+   downstream.
+
+
+GstBufferPool
+-------------
+
+ The bufferpool object manages a list of buffers with the same properties such
+ as size, padding and alignment.
+
+ The bufferpool has two states: active and inactive. In the in-active
+ state, the bufferpool can be configured with the required allocation
+ preferences. In the active state, buffers can be retrieved from and
+ returned to the pool.
+
+ The default implementation of the bufferpool is able to allocate buffers
+ from main memory with arbitrary alignment and padding/prefix.
+
+ Custom implementations of the bufferpool can override the allocation and
+ free algorithms of the buffers from the pool. This should allow for
+ different allocation strategies such as using shared memory or hardware
+ mapped memory.
+
+
+Negotiation
+-----------
+
+ After a particular media format has been negotiated between two pads (using the
+ CAPS event), they must agree on how to allocate buffers.
+
+ The srcpad will always take the initiative to negotiate the allocation
+ properties. It starts with creating a GST_QUERY_ALLOCATION with the negotiated
+ caps.
+
+ The srcpad can set the need-pool flag to TRUE in the query to optionally make the
+ peer pad allocate a bufferpool.
+
+ It will then inspect the returned results and configure the returned pool or
+ create a new pool with the returned properties when needed.
+
+ Buffers are then allocated by the srcpad from the negotiated pool and pushed to
+ the peer pad as usual.
+
+ The allocation query can also return an allocator name when the buffers are of
+ different sizes and can't be allocated from a pool.
+
+
+Allocation query
+----------------
+
+ The allocation query has the following fields:
+
+  (in) "caps", GST_TYPE_CAPS
+        - the caps that was negotiated
+
+  (in) "need-pool", G_TYPE_BOOLEAN
+        - if a GstBufferPool is requested
+
+  (out) "size", G_TYPE_UINT
+        - the total size of the buffer memory. This size is set to 0 when the 
+          buffers are of variable size.
+
+  (out) "min-buffers", G_TYPE_UINT
+        - the minimum amount of buffers to allocate
+
+  (out) "max-buffers", G_TYPE_UINT
+        - the maximum amount of buffers to allocate
+
+  (out) "prefix", G_TYPE_UINT
+        - the prefix of the buffer memory
+
+  (out) "align", G_TYPE_UINT
+        - the aligment of the memory in the buffers, the alignment will be applied
+          to the prefix. The aligment is expressed as a value ((1 << N) - 1).
+          Alignment will be done on multiples of (1 << N).
+
+  (out) "pool", GST_TYPE_BUFFER_POOL
+        - a buffer pool when need-pool was TRUE and the peer can provide a pool.
+          This pool is inactive and can be configured when needed.
+
+  (out) "metadata", G_TYPE_VALUE_ARRAY of G_TYPE_STRING
+        - an array of metadata API strings that can be accepted.
+
+  (out) "allocator", G_TYPE_VALUE_ARRAY of G_TYPE_STRING
+        - an array of allocators that can be used.
+
+
+Allocating from pool
+--------------------
+
+ Buffers are allocated from the pool of a pad:
+
+  res = gst_buffer_pool_acquire_buffer (pool, &buffer, &params);
+
+ A GstBuffer that is allocated from the pool will always be writable (have a
+ refcount of 1) and it will also have its pool member point to the GstBufferPool
+ that created the buffer.
+
+ Buffers are refcounted in the usual way. When the refcount of the buffer
+ reaches 0, the buffer is automatically returned to the pool.
+
+ Since all the buffers allocated from the pool keep a reference to the pool,
+ when nothing else is holding a refcount to the pool, it will be finalized
+ when all the buffers from the pool are unreffed. By setting the pool to
+ the inactive state we can drain all buffers from the pool. 
+
+ When the pool is in the inactive state, gst_buffer_pool_acquire_buffer() will
+ return GST_FLOW_WRONG_STATE immediately.
+
+ Extra parameters can be given to the gst_buffer_pool_acquire_buffer() method to
+ influence the allocation decision. GST_BUFFER_POOL_FLAG_KEY_UNIT and
+ GST_BUFFER_POOL_FLAG_DISCONT serve as hints.
+
+ When the bufferpool is configured with a maximum number of buffers, allocation
+ will block when all buffers are outstanding until a buffer is returned to the
+ pool. This behaviour can be changed by specifying the
+ GST_BUFFER_POOL_FLAG_DONTWAIT flag in the parameters. With this flag set,
+ allocation will return GST_FLOW_UNEXPECTED when the pool is empty.
+
+
+Renegotiation
+-------------
+
+Renegotiation of the bufferpool might need to be performed when the
+configuration of the pool changes. Changes can be in the buffer size (because
+of a caps change), alignment or number of buffers. 
+
+* downstream
+
+  When the upstream element wants to negotiate a new format, it might need
+  to renegotiate a new bufferpool configuration with the downstream element.
+  This can, for example, happen when the buffer size changes.
+
+  We can not just reconfigure the existing bufferpool because there might
+  still be outstanding buffers from the pool in the pipeline. Therefore we
+  need to create a new bufferpool for the new configuration while we let the
+  old pool drain.
+
+  Implementations can choose to reuse the same bufferpool object and wait for
+  the drain to finish before reconfiguring the pool.
+
+  The element that wants to renegotiate a new bufferpool uses exactly the same
+  algorithm as when it first started. It will negotiate caps first then use the
+  ALLOCATION query to get and configure the new pool.
+  
+* upstream 
+
+  When a downstream element wants to negotiate a new format, it will send a 
+  RECONFIGURE event upstream. This instructs upstream to renegotiate both
+  the format and the bufferpool when needed.
+
+  A pipeline reconfiguration is when new elements are added or removed from
+  the pipeline or when the topology of the pipeline changes. Pipeline
+  reconfiguration also triggers possible renegotiation of the bufferpool and
+  caps.
+
+  A RECONFIGURE event tags each pad it travels on as needing reconfiguration.
+  The next buffer allocation will then require the renegotiation or
+  reconfiguration of a pool.
+
+
+Shutting down
+-------------
+
+ In push mode, a source pad is responsible for setting the pool to the
+ inactive state when streaming stops. The inactive state will unblock any pending
+ allocations so that the element can shut down.
+
+ In pull mode, the sink element should set the pool to the inactive state when
+ shutting down so that the peer _get_range() function can unblock.
+
+ In the inactive state, all the buffers that are returned to the pool will
+ automatically be freed by the pool and new allocations will fail.
+
+Use cases
+---------
+
+1)  videotestsrc ! xvimagesink
+
+ Before videotestsrc can output a buffer, it needs to negotiate caps and
+ a bufferpool with the downstream peer pad.
+
+ First it will negotiate a suitable format with downstream according to the
+ normal rules. It will send a CAPS event downstream with the negotiated
+ configuration.
+
+ Then it does an ALLOCATION query. It will use the returned bufferpool or
+ configures its own bufferpool with the returned parameters. The bufferpool is
+ initially in the inactive state.
+
+ The ALLOCATION query lists the desired configuration of the downstream 
+ xvimagesink, which can have specific alignment and/or min/max amount of
+ buffers.
+
+ videotestsrc updates the configuration of the bufferpool, it will likely
+ set the min buffers to 1 and the size of the desired buffers. It then
+ updates the bufferpool configuration with the new properties.
+
+ When the configuration is successfully updated, videotestsrc sets the
+ bufferpool to the active state. This preallocates the buffers in the pool
+ (if needed). This operation can fail when there is not enough memory
+ available. Since the bufferpool is provided by xvimagesink, it will allocate
+ buffers backed by an XvImage and pointing to shared memory with the X server.
+
+ If the bufferpool is successfully activated, videotestsrc can acquire a
+ buffer from the pool, fill in the data and push it out to xvimagesink.
+
+ xvimagesink can know that the buffer originated from its pool by following
+ the pool member.
+
+ when shutting down, videotestsrc will set the pool to the inactive state,
+ this will cause further allocations to fail and currently allocated buffers
+ to be freed. videotestsrc will then free the pool and stop streaming.
+
+
+2) videotestsrc ! queue ! myvideosink
+
+ In this second use case we have a videosink that can at most allocate
+ 3 video buffers.
+
+ Again videotestsrc will have to negotiate a bufferpool with the peer 
+ element. For this it will perform the ALLOCATION query which
+ queue will proxy to its downstream peer element.
+
+ The bufferpool returned from myvideosink will have a max_buffers set to 3.
+ queue and videotestsrc can operate with this upper limit because none of
+ those elements require more than that amount of buffers for temporary
+ storage.
+
+ The bufferpool of myvideosink will then be configured with the size of the
+ buffers for the negotiated format and according to the padding and alignment
+ rules. When videotestsrc sets the pool to active, the 3 video
+ buffers will be preallocated in the pool.
+
+ videotestsrc acquires a buffer from the configured pool on its srcpad and
+ pushes this into the queue. When the videotestsrc has acquired and pushed
+ 3 frames, the next call to gst_buffer_pool_acquire_buffer() will block
+ (assuming the GST_BUFFER_POOL_FLAG_DONTWAIT is not specified).
+
+ When the queue has pushed out a buffer and the sink has rendered it, the
+ refcount of the buffer reaches 0 and the buffer is recycled in the pool.
+ This will wake up the videotestsrc that was blocked, waiting for more
+ buffers and will make it produce the next buffer. 
+
+ In this setup, there are at most 3 buffers active in the pipeline and
+ the videotestsrc is rate limited by the rate at which buffers are recycled
+ in the bufferpool.
+
+ When shutting down, videotestsrc will first set the bufferpool on the srcpad
+ to inactive. This causes any pending (blocked) acquire to return with a 
+ WRONG_STATE result and causes the streaming thread to pause.
+
+3) .. ! myvideodecoder ! queue ! fakesink 
+
+ In this case, the myvideodecoder requires buffers to be aligned to 128
+ bytes and padded with 4096 bytes. The pipeline starts out with the
+ decoder linked to a fakesink but we will then dynamically change the
+ sink to one that can provide a bufferpool.
+
+ When it negotiates the size with the downstream element fakesink, it will
+ receive a NULL bufferpool because fakesink does not provide a bufferpool.
+ It will then select its own custom bufferpool to start the datatransfer.
+
+ At some point we block the queue srcpad, unlink the queue from the 
+ fakesink, link a new sink and set the new sink to the PLAYING state.
+ Linking the new sink would automatically send a RECONFIGURE event upstream
+ and, through queue, inform myvideodecoder that it should renegotiate its
+ bufferpool because downstream has been reconfigured.
+
+ Before pushing the next buffer, myvideodecoder would renegotiate a new
+ bufferpool. To do this, it performs the usual bufferpool negotiation
+ algorithm. If it can obtain and configure a new bufferpool from downstream,
+ it sets its own (old) pool to inactive and unrefs it. This will eventually
+ drain and unref the old bufferpool.
+
+ The new bufferpool is set as the new bufferpool for the srcpad and sinkpad
+ of the queue and set to the active state.
+
+
+4) .. ! myvideodecoder ! queue ! myvideosink 
+
+ myvideodecoder has negotiated a bufferpool with the downstream myvideosink
+ to handle buffers of size 320x240. It has now detected a change in the 
+ video format and need to renegotiate to a resolution of 640x480. This
+ requires it to negotiate a new bufferpool with a larger buffersize.
+
+ When myvideodecoder needs to get the bigger buffer, it starts the 
+ negotiation of a new bufferpool. It queries a bufferpool from downstream,
+ reconfigures it with the new configuration (which includes the bigger buffer
+ size) and it then sets the bufferpool to active. The old pool is inactivated
+ and unreffed, which causes the old format to drain.
+
+ It then uses the new bufferpool for allocating new buffers of the new 
+ dimension.
+
+ If at some point, the decoder wants to switch to a lower resolution again,
+ it can choose to use the current pool (which has buffers that are larger
+ than the required size) or it can choose to renegotiate a new bufferpool.
+
+
+5) .. ! myvideodecoder ! videoscale ! myvideosink 
+
+ myvideosink is providing a bufferpool for upstream elements and wants to
+ change the resolution.
+
+ myvideosink sends a RECONFIGURE event upstream to notify upstream that a
+ new format is desirable. upstream elements try to negotiate a new format
+ and bufferpool before pushing out a new buffer. The old bufferpools are
+ drained in the regular way.
+
index 3df28ba..ac04b75 100644 (file)
@@ -12,9 +12,6 @@ Caps are exposed on the element pads using the _get_caps() pad function.
 This function describes the possible types that the pad can handle or
 produce (see part-pads.txt and part-negotiation.txt).
 
-Caps are also attached to buffers to describe to content of the data
-pointed to be the buffer.
-
 Various methods exist to work with the media types such as subtracting
 or intersecting.
 
diff --git a/docs/design/part-controller.txt b/docs/design/part-controller.txt
new file mode 100644 (file)
index 0000000..1a2f23e
--- /dev/null
@@ -0,0 +1,40 @@
+Controller
+----------
+
+The controller subsystem allows to automate element property changes. It works
+so that all parameter changes are time based and elements request property
+updates at processing time.
+
+Element view
+~~~~~~~~~~~~
+Elements don't need to do much. They need to:
+- mark object properties that can be changed while processing with
+  GST_PARAM_CONTROLLABLE
+- call gst_object_sync_values (self, timestamp) in the processing function
+  before accessing the parameters.
+  
+All ordered property types can be automated (int, double, boolean, enum). 
+
+Application view
+~~~~~~~~~~~~~~~~
+Applications need to setup the property automation. For that they need to create
+a GstControlSource and attach it to a property using GstControlBinding. Various
+control-sources and control-bindings exist. All control sources produce control
+value sequences in the form of gdouble values. The control bindings map them to
+the value range and type of the bound property.
+
+One control-source can be attached to one or more properties at the same time.
+If it is attached multiple times, then each control-binding will scale and
+convert the control values to the target property type and range.
+
+One can create complex control-curves by using a GstInterpolationControlSource.
+This allows the classic user editable control-curve (often seen in audio/video
+editors). Another way is to use computed control curves. GstLFOControlSource can
+generate various repetitive signals. Those can be made more complex by chaining
+the control sources. One can attach another control-source to e.g. modulate the
+frequency of the first GstLFOControlSource.
+
+In most cases GstControlBindingDirect will be the binding to be used. Other
+control bindings are there to handle special cases, such as having 1-4 control-
+sources and combine their values into a single guint to control a rgba-color
+property. 
index aecd5fb..e3c11b8 100644 (file)
@@ -99,8 +99,7 @@ Negotiation
 Typical (re)negotiation of the transform element in push mode always goes from
 sink to src, this means triggers the following sequence:
  
-  - the sinkpad receives a buffer with new caps, this triggers the setcaps
-    function on the sinkpad before handing the buffer to transform.
+  - the sinkpad receives a new caps event.
   - the transform function figures out what it can convert these caps to.
   - try to see if we can configure the caps unmodified on the peer. We need to
     do this because we prefer to not do anything.
@@ -111,10 +110,10 @@ sink to src, this means triggers the following sequence:
 We call this downstream negotiation (DN) and it goes roughly like this:
 
                sinkpad              transform               srcpad
-     setcaps()    |                    |                      |
+     CAPS event   |                    |                      |
      ------------>|  find_transform()  |                      |
                   |------------------->|                      |
-                  |                    |       setcaps()      |
+                  |                    |       CAPS event     |
                   |                    |--------------------->|
                   | <configure caps> <-|                      |
 
@@ -148,8 +147,7 @@ assume nothing is going to write to the buffer and we don't enforce a writable
 buffer for the transform_ip function, when present.
 
 One common function that we need for the transform element is to find the best
-transform from one format (src) to another (dest). Since the function is
-bidirectional, we will use the src->dest negotiation. Some requirements of this
+transform from one format (src) to another (dest). Some requirements of this
 function are:
 
    - has a fixed src caps
@@ -198,18 +196,14 @@ state. We can identify these steady states:
       - in-place: buffers are modified in-place, this means that the input
        buffer is modified to produce a new output buffer. This requires the
        input buffer to be writable. If the input buffer is not writable, a new
-       buffer has to be allocated with pad-alloc. (SCI)
+       buffer has to be allocated from the bufferpool. (SCI)
 
                sinkpad              transform               srcpad
        chain()    |                    |                      |
      ------------>|   handle_buffer()  |                      |
                   |------------------->|                      |
                   |                    |   [!writable]        |
-                  |                    |     pad-alloc()      |
-                  |                    |--------------------->|
-                  |  [caps-changed]  .-|  [caps-changed]      |
-                  |   <reconfigure>  | |     setcaps()        |
-                  |                  '>|--------------------->|
+                  |                    |   alloc buffer       |
                   |                  .-|                      |
                   |  <transform_ip>  | |                      |
                   |                  '>|                      |
@@ -217,18 +211,15 @@ state. We can identify these steady states:
                   |                    |--------------------->|
                   |                    |                      |
 
-      - copy transform: a new output buffer is allocated with pad-alloc and data
-        from the input buffer is transformed into the output buffer. (SCC)
+      - copy transform: a new output buffer is allocate from the bufferpool
+        and data from the input buffer is transformed into the output buffer.
+        (SCC)
 
                sinkpad              transform               srcpad
        chain()    |                    |                      |
      ------------>|   handle_buffer()  |                      |
                   |------------------->|                      |
-                  |                    |     pad_alloc()      |
-                  |                    |--------------------->|
-                  |  [caps-changed]  .-|   [caps-changed]     |
-                  |   <reconfigure>  | |      setcaps()       |
-                  |                  '>|--------------------->|
+                  |                    |     alloc buffer     |
                   |                  .-|                      |
                   |     <transform>  | |                      |
                   |                  '>|                      |
@@ -250,11 +241,7 @@ state. We can identify these steady states:
      ------------>|   handle_buffer()  |                      |
                   |------------------->|                      |
                   |                    | [!writable || !size] |
-                  |                    |     pad-alloc        |
-                  |                    |--------------------->|
-                  |  [caps-changed]  .-|  [caps-changed]      |
-                  |   <reconfigure>  | |     setcaps()        |
-                  |                  '>|--------------------->|
+                  |                    |     alloc buffer     |
                   |                  .-|                      |
                   |  <transform_ip>  | |                      |
                   |                  '>|                      |
@@ -267,146 +254,41 @@ state. We can identify these steady states:
        the same as the case with the same-caps negotiation. (DCC)
  
 We can immediately observe that the copy transform states will need to
-allocate a buffer from a downstream element using pad-alloc. When the transform
-element is receiving a non-writable buffer in the in-place state, it will also
-need to perform a pad-alloc. There is no reason why the passthrough state would
-perform a pad-alloc. This is important because upstream re-negotiation can only
-happen when the transform uses pad-alloc for all outgoing buffers.
+allocate a new buffer from the bufferpool. When the transform element is
+receiving a non-writable buffer in the in-place state, it will also
+need to perform an allocation. There is no reason why the passthrough state would
+perform an allocation.
 
 This steady state changes when one of the following actions occur:
 
   - the sink pad receives new caps, this triggers the above downstream
     renegotation process, see above for the flow.
-  - the src pad is instructed to produce new caps because of new caps from
-    pad-alloc, this only happens when the transform calls pad-alloc on the
-    srcpad in order to produce a new output buffer.
   - the transform element wants to renegotiate (because of changed properties,
     for example). This essentially clears the current steady state and
-    triggers the downstream and upstream renegotiation process.
-
-Parallel to the downstream negotiation process there is an upstream negotiation
-process. The handling and proxy of buffer-alloc is the most comple part of the
-transform element. This upstream negotiation process has 3 cases: (UN)
-
-  - upstream calls the buffer-alloc function of the transform sinkpad and this
-    call is proxied downstream (UNP)
-  - upstream calls the buffer-alloc function of the transform sinkpad, the
-    transform does not proxy the call but returns a buffer itself (UNU)
-  - the transform calls the pad-alloc function downstream to allocate a new
-    output buffer (but not because of a proxied buffer-alloc) (UNA)
-
-The case where the pad-alloc is called because an output buffer must be
-generated in the chain function is handled above in the copy-transform and the
-in-place transform when the input buffer is not writable or the input buffer
-size is smaller than the output size.
-
-We are left with the last case (proxy an incoming pad-alloc or not). We have 2
-possibilities here:
-
-   - pad-alloc is called with the same caps as are currently being handled by
-     the transform on the sinkcaps. Note that this will only be true when the
-     transform element is completely negotiated because of data processing, see
-     above. Then the element is not yet negotiated, we proceed with the case
-     where sinkcaps are different from thos in the buffer-alloc.
-     
-     * If the transform is using copy-transform, we don't need to proxy because
-       we will call pad-alloc when generating an output buffer. 
-
-               sinkpad              transform               srcpad
-   buffer_alloc() |                    |                      |
-  --------------->|                    |                      |
-                  |                    |                      |
-                  |-. [same caps &&    |                      |
-   return default | |  copy-trans]     |                      |
-     <------------|<'                  |                      |
-                  |                    |                      |
-
-     * If the transform is using in-place and insize < outsize, we proxy
-       the pad-alloc with the srccaps. If the caps are unmodified, we proxy
-       the buffer after changing the caps and size. 
-
-               sinkpad              transform               srcpad
-   buffer_alloc() |                    |                      |
-  --------------->|                    |                      |
-                  |   [same caps &&    |                      |
-                  |    in-place]       |                      |
-                  |------------------->|    pad_alloc()       |
-                  |                    |--------------------->|
-                  | [caps unchanged]   |                      |
-      return      |  adjust_buffer     |                      |
-    <----------------------------------|                      |
-                  |                    |                      |
-                  |                    |                      |
-
-     * If the transform is using in-place and insize < outsize, we proxy
-       the pad-alloc with the srccaps. If the caps are modified find the best
-       transform from these new caps and return a buffer of this size/caps
-       instead. 
-
-               sinkpad              transform               srcpad
-   buffer_alloc() |                    |                      |
-  --------------->|                    |                      |
-                  |   [same caps &&    |                      |
-                  |    in-place]       |    pad-alloc()       |
-                  |------------------------------------------>|
-                  | [caps changed]   .-|                      |
-                  | find_transform() | |                      |
-      return      |                  '>|                      |
-    <----------------------------------|                      |
-                  |                    |                      |
+    triggers the downstream and upstream renegotiation process. This situation
+    also happens when a RECONFIGURE event was received on the transform srcpad.
 
-     * If the transform is using in-place and insize >= outsize, we cannot proxy
-       the pad-alloc because the resulting buffer would be too small to return
-       anyway. 
 
-     * If the transform is using passthrough, we can proxy the pad-alloc to the
-       source pad. If the caps change, find the best transform and return a
-       buffer of those caps and size instead.
+Allocation
+~~~~~~~~~~
 
-               sinkpad              transform               srcpad
-   buffer_alloc() |                    |                      |
-  --------------->| [same caps &&      |                      |
-                  |  passtrough]       |     pad-alloc()      |
-                  |------------------------------------------>|
-                  | [caps changed]   .-|                      |
-                  | find_transform() | |                      |
-      return      |                  '>|                      |
-    <----------------------------------|                      |
-                  |                    |                      |
+After the transform element is configured with caps, a bufferpool needs to be
+negotiated to perform the allocation of buffers. We habe 2 cases:
 
-   - pad-alloc is called with different caps than are currently being handled by
-     the transform on the sinkcaps we have to try to negotiate a new
-     configuration for the transform element.
+  - The element is operating in passthrough we don't need to allocate a buffer
+    in the transform element.
+  - The element is not operating in passthrough and needs to allocation an
+    output buffer.
 
-      * we perform the standard way to finding a best transform using
-        find_transform() and we call the pad-alloc function with these caps.
-       If we get different caps from pad-alloc, we find the best format to
-       transform these to and return those caps instead.
+In case 1, we don't query and configure a pool. We let upstream decide if it
+wants to use a bufferpool and then we will proxy the bufferpool from downstream
+to upstream.
 
+In case 2, we query and set a bufferpool on the srcpad that will be used for
+doing the allocations.
 
-               sinkpad              transform               srcpad
-   buffer_alloc() |                    |                      |
-  --------------->|                    |                      |
-                  |  find_transform()  |                      |
-                  |------------------->|                      |
-                  |                    |  pad-alloc()         |
-                  |                    |--------------------->|
-      return      | [caps unchanged]   |                      |
-    <----------------------------------|                      |
-                  |                    |                      |
-                  | [caps changed]   .-|                      |
-                  | find_transform() | |                      |
-      return      |                  '>|                      |
-    <----------------------------------|                      |
-                  |                    |                      |
-
-In order to perform passthrough buffer-alloc or pad-alloc, we need to be able
-to get the size of the output buffer after the transform.
-
-For passthrough buffer-alloc, this is trivial: the input size equals the output
-size.
-
-For the copy transform or the in-place transform we need additional function to
+In order to perform allocation, we need to be able to get the size of the
+output buffer after the transform.  We need additional function to
 retrieve the size. There are two functions:
 
   - transform_size()
@@ -424,62 +306,3 @@ retrieve the size. There are two functions:
 
  For performance reasons, the mapping between caps and size is kept in a cache.
 
-
-Issues
-~~~~~~
-
-passthrough and in-place transforms (with writable buffers) never need to
-perform a pad-alloc on the srcpad. This means that if upstream negotiation
-happens, the transform element will never know about it.
-
-The transform element will keep therefore track of the allocation pattern of
-the peer elements. We can see the following cases:
-
-- upstream peer calls buffer-alloc on the sinkpad of the transform. In some
-  cases (see above) this call gets proxied or not.
-
-- upstream peer does never call buffer-alloc.
-
-We will keeps state about this allocation pattern and perform the following in
-each case respectively:
-
-- Upstream calls buffer-alloc: In passthrough and (some) in-place we proxy
-  this call onto the downstream element. If the caps are changed, we mark
-  a flag that we will require a new pad-alloc for the output of the next
-  output buffer.
-
-- upstream peer does not call buffer-alloc: We always perform a pad-alloc
-  when processing buffers. We can further optimize by only looking at the
-  returned caps instead of doing a full, needless buffer copy.
-
-
-Use cases
-~~~~~~~~~
-
- videotestsrc ! ximagesink
-  
-   - resizing happens because videotestsrc performs pad-alloc.
-
- videotestsrc peer-alloc=0 ! ximagesink
-
-   - resizing cannot happen because videotestsrc never performs pad-alloc.
-
- videotestsrc ! videoscale ! ximagesink
-  
-   - videoscale is initially configured in passthrough mode, pad-alloc from
-     videotestsrc is proxied through videoscale.
-   - pad-alloc will renegotiate a new size in videotestsrc.
-
- videotestsrc peer-alloc=0 ! videoscale ! ximagesink
-  
-   - videoscale is initially configured in passthrough mode.
-   - videoscale performs pad-alloc because no buffer-alloc is called on the
-     sinkpad
-   - resizing the videosink makes videoscale perform the scaling.
-   
-Problematic
-~~~~~~~~~~~
-
-    filesrc location=~/media/moveyourfeet.mov ! decodebin !
-    ffmpegcolorspace ! videoscale ! ffmpegcolorspace ! ximagesink -v
-
index b79ed05..3193698 100644 (file)
@@ -12,20 +12,63 @@ Different types of events exist to implement various functionalities.
 
   GST_EVENT_FLUSH_START:   data is to be discarded
   GST_EVENT_FLUSH_STOP:    data is allowed again
-  GST_EVENT_EOS:          no more data is to be expected on a pad.
-  GST_EVENT_NEWSEGMENT:    A new group of buffers with common start time  
+  GST_EVENT_CAPS:          Format information about the following buffers
+  GST_EVENT_SEGMENT:       Timing information for the following buffers
   GST_EVENT_TAG:           Stream metadata.
   GST_EVENT_BUFFERSIZE:    Buffer size requirements
+  GST_EVENT_SINK_MESSAGE:  An event turned into a message by sinks
+  GST_EVENT_EOS:          no more data is to be expected on a pad.
   GST_EVENT_QOS:           A notification of the quality of service of the stream
   GST_EVENT_SEEK:          A seek should be performed to a new position in the stream
   GST_EVENT_NAVIGATION:    A navigation event.
   GST_EVENT_LATENCY:       Configure the latency in a pipeline
+  GST_EVENT_STEP:          Stepping event
+  GST_EVENT_RECONFIGURE:   stream reconfigure event
 
   * GST_EVENT_DRAIN:       Play all data downstream before returning.
 
 * not yet implemented, under investigation, might be needed to do still frames
   in DVD.
 
+
+src pads
+--------
+
+A gst_pad_push_event() on a srcpad will first store the event in the sticky
+array before sending the event to the peer pad. If there is no peer pad, the
+gst_pad_push_event() function returns NOT_LINKED.
+
+Note that the behaviour is not influenced by a flushing pad.
+
+FLUSH_START and FLUSH_STOP events are dropped on blocked pads.
+
+sink pads
+---------
+
+A gst_pad_send_event() on a sinkpad will check the new event against the
+existing event. If they are different, the new event is stored as a pending
+event. If the events are the same, nothing changes.
+
+When the pad is flushing, the _send_event() function returns WRONG_STATE
+immediately.
+
+The event function is then called for all pending events. If the function
+returns success, the pending event is copied to the active events, else the
+pending event is removed and the current active event is unchanged.
+
+This ensures that the event function is never called for flushing pads and that
+the sticky array only contains events for which the event function returned
+success.
+
+
+pad link
+--------
+
+When linking pads, all the sticky events from the srcpad are copied to the
+pending array on the sinkpad. The pending events will be sent to the event
+function of the sinkpad on the next event or buffer.
+
+
 FLUSH_START/STOP
 ~~~~~~~~~~~~~~~~
 
@@ -57,11 +100,9 @@ For elements that use the pullrange function, they send both flush events to
 the upstream pads in the same way to make sure that the pullrange function
 unlocks and any pending buffers are cleared in the upstream elements.
 
-A FLUSH_STOP event will also clear any configured synchronisation information
-like NEWSEGMENT events. After a FLUSH_STOP, any element that performs
-synchronisation to the clock will therefore need a NEWSEGMENT event (which makes
-the running_time start from 0 again) and will therefore also need a new
-base_time (see part-clocks.txt and part-synchronisation.txt).
+A FLUSH_START may instruct the pipeline to distribute a new base_time to
+elements so that the running_time is reset to 0. 
+(see part-clocks.txt and part-synchronisation.txt).
 
 
 EOS
@@ -106,43 +147,38 @@ goes to PLAYING.
 A FLUSH_STOP event on an element flushes the EOS state and all pending EOS messages.
 
 
-NEWSEGMENT
-~~~~~~~~~~
+SEGMENT
+~~~~~~~
 
-A newsegment event is sent downstream by an element to indicate that the following
+A segment event is sent downstream by an element to indicate that the following
 group of buffers start and end at the specified positions. The newsegment event
 also contains the playback speed and the applied rate of the stream.
 
 Since the stream time is always set to 0 at start and after a seek, a 0
 point for all next buffer's timestamps has to be propagated through the
-pipeline using the NEWSEGMENT event.
+pipeline using the SEGMENT event.
 
-Before sending buffers, an element must send a NEWSEGMENT event. An element is
-free to refuse buffers if they were not preceeded by a NEWSEGMENT event.
+Before sending buffers, an element must send a SEGMENT event. An element is
+free to refuse buffers if they were not preceeded by a SEGMENT event.
 
-Elements that sync to the clock should store the NEWSEGMENT start and end values
+Elements that sync to the clock should store the SEGMENT start and end values
 and subtract the start value from the buffer timestamp before comparing
 it against the stream time (see part-clocks.txt).
 
-An element is allowed to send out buffers with the NEWSEGMENT start time already
+An element is allowed to send out buffers with the SEGMENT start time already
 subtracted from the timestamp. If it does so, it needs to send a corrected
-NEWSEGMENT downstream, ie, one with start time 0.
+SEGMENT downstream, ie, one with start time 0.
 
-A NEWSEGMENT event should be generated as soon as possible in the pipeline and
+A SEGMENT event should be generated as soon as possible in the pipeline and
 is usually generated by a demuxer or source. The event is generated before 
 pushing the first buffer and after a seek, right before pushing the new buffer.
 
-The NEWSEGMENT event should be sent from the streaming thread and should be
+The SEGMENT event should be sent from the streaming thread and should be
 serialized with the buffers.
 
 Buffers should be clipped within the range indicated by the newsegment event
 start and stop values. Sinks must drop buffers with timestamps out of the
-indicated newsegment range.
-
-If a newsegment arrives at an element not preceeded by a flush event, the 
-streamtime of the pipeline will not be reset to 0 so any element that syncs
-to the clock must use the stop times of the previous newsegment events to
-make the buffer timestamps increasing (part-segments.txt).
+indicated segment range.
 
 
 TAG
index 5b7036e..a01ffc6 100644 (file)
@@ -39,7 +39,7 @@ These pads are stored in a single GList within the Element.  Several counters
 are kept in order to allow quicker determination of the type and properties of
 a given Element.
 
-Pads may be added to an element with _add_pad.  Retrieval is via _get_pad(),
+Pads may be added to an element with _add_pad.  Retrieval is via _get_static_pad(),
 which operates on the name of the Pad (the unique key).  This means that all
 Pads owned by a given Element must have unique names.
 A pointer to the GList of pads may be obtained with _iterate_pads. 
index b846072..473dc7f 100644 (file)
@@ -89,12 +89,3 @@ Flags
 
 Each object in the GStreamer object hierarchy can have flags associated with it,
 which are used to describe a state or a feature of the object.
-GstObject has flags to mark its lifecycle: FLOATING and DISPOSING.
-
-
-Class signals
-~~~~~~~~~~~~~
-
-It is possible to know when a new object is loaded by connecting to the
-GstObjectClass signal. This feature is not very much used and might be removed
-at some point.
index 1090d3a..7b58b10 100644 (file)
@@ -195,13 +195,11 @@ capture pipelines.
   prerolled.
 
 
-State Changes revised
-~~~~~~~~~~~~~~~~~~~~~
+State Changes
+~~~~~~~~~~~~~
 
-As a first step in a generic solution we propose to modify the state changes so
-that no sink is set to PLAYING before it is prerolled.
-
-In order to do this, the pipeline (at the GstBin level) keeps track of all
+A Sink is never set to PLAYING before it is prerolled. In order to do this, the
+pipeline (at the GstBin level) keeps track of all
 elements that require preroll (the ones that return ASYNC from the state
 change). These elements posted a ASYNC_START message without a matching
 ASYNC_DONE message.
@@ -221,18 +219,12 @@ NO_PREROLL element to PLAYING. This operation has to be performed in the
 separate async state change thread (like the one currently used for going from
 PAUSED->PLAYING in a non-live pipeline).
 
-implications:
-
- - the current async_play vmethod in basesink can be deprecated since we now
-   always call the state change function when going from PAUSED->PLAYING. We
-   keep this method however to remain backward compatible.
-
 
 Latency compensation
 ~~~~~~~~~~~~~~~~~~~~
 
-As an extension to the revised state changes we can perform latency calculation
-and compensation before we proceed to the PLAYING state. 
+Latency calculation and compensation is performed before the pipeline proceeds to
+the PLAYING state. 
 
 When the pipeline collected all ASYNC_DONE messages it can calculate the global
 latency as follows:
@@ -279,8 +271,8 @@ the same for all sinks, all sinks will render data relatively synchronised.
 Flushing a playing pipeline
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Using the new state change mechanism we can implement resynchronisation after an
-uncontrolled FLUSH in (part of) a pipeline. Indeed, when a flush is performed on
+We can implement resynchronisation after an uncontrolled FLUSH in (part of) a
+pipeline in the same way. Indeed, when a flush is performed on
 a PLAYING live element, a new base time must be distributed to this element.
 
 A flush in a pipeline can happen in the following cases:
diff --git a/docs/design/part-memory.txt b/docs/design/part-memory.txt
new file mode 100644 (file)
index 0000000..981616c
--- /dev/null
@@ -0,0 +1,156 @@
+GstMemory
+---------
+
+This document describes the design of the memory objects.
+
+GstMemory objects are usually added to GstBuffer objects and contain the
+multimedia data passed around in the pipeline.
+
+Requirements
+~~~~~~~~~~~~
+
+ - It must be possible to have different memory allocators
+ - It must be possible to efficiently share memory objects, copy, span
+   and trim.
+
+
+Allocators
+~~~~~~~~~~
+
+ GstMemory objects are created by allocators. Allocators are registered to the
+ memory system with a set of methods contained in a GstMemoryInfo structure.
+
+  struct _GstMemoryInfo {
+    GstMemoryAllocFunction    alloc;
+    GstMemoryGetSizesFunction get_sizes;
+    GstMemoryResizeFunction   resize;
+    GstMemoryMapFunction      map;
+    GstMemoryUnmapFunction    unmap;
+    GstMemoryFreeFunction     free;
+
+    GstMemoryCopyFunction     copy;
+    GstMemoryShareFunction    share;
+    GstMemoryIsSpanFunction   is_span;
+
+    gpointer user_data;
+  };
+
+ After an allocator is registerd, new GstMemory can be created with 
+
+   GstMemory * gst_allocator_alloc (const GstAllocator * allocator,
+                                    gsize maxsize, gsize align);
+
+ The GstMemory object is a refcounted object that must be freed with
+ gst_memory_unref ().
+
+ It is also possible to create a new GstMemory object that wraps existing
+ memory with:
+  
+   GstMemory * gst_memory_new_wrapped  (GstMemoryFlags flags, gpointer data,
+                                        GFreeFunc free_func, gsize maxsize,
+                                        gsize offset, gsize size);
+
+Lifecycle
+~~~~~~~~~
+
+GstMemory objects are refcounted. When the GstMemory object is first created, it
+has a refcount of 1. 
+
+Each variable holding a reference to the GstMemory object is responsible for
+updating the refcount.
+
+The refcount determines the writability of the object. If the refcount > 1, it is
+by definition used by multipled objects and thus cannot be safely written to.
+
+When the refcount reaches 0, and thus no objects hold a reference anymore, we
+can free the memory. The GstMemoryFreeFunction of the allocator will be called
+to cleanup the memory.
+
+
+Memory layout
+~~~~~~~~~~~~~
+
+ GstMemory manages a memory region. The accesible part of the managed region is
+ defined by an offset relative to the start of the region and a size. This
+ means that the managed region can be larger than what is visible to the user of
+ GstMemory API.
+
+ Schematically, GstMemory has a pointer to a memory region of _maxsize_. The area
+ starting from _offset_ and _size_ is accessible.
+
+               memory
+    GstMemory  ->*----------------------------------------------------*
+                 ^----------------------------------------------------^ 
+                                   maxsize
+                      ^--------------------------------------^         
+                     offset            size
+
+ The current properties of the accessible memory can be retrieved with:
+
+   gsize       gst_memory_get_sizes  (GstMemory *mem, gsize *offset, gsize *maxsize);
+
+ The offset and size can be changed with:
+
+   void        gst_memory_resize     (GstMemory *mem, gssize offset, gsize size);
+
+ The memory object is always readable. The memory block is writable when:
+
+  - the refcount is exactly 1
+  - the memory object has no parent, or if it has a parent, the parent is
+    writable.
+  - the memory object is not marked as READONLY.
+
+
+Data Access
+~~~~~~~~~~~
+
+ Access to the memory region is always controlled with a map and unmap method
+ call. This allows the implementation to monitor the access patterns or set up
+ the required memory mappings when needed.
+
+ Mapping a memory region requires the caller to specify the access method: READ
+ and/or WRITE. For write access, the GstMemory object must be writable.
+
+ After the data has been accessed in the object, the unmap call must be
+ performed. The call will update the new memory size with the specified size.
+
+ It is allowed to map multiple times with different access modes. for each of
+ the map calls, an corresponding unmap call needs to be made. WRITE-only memory
+ cannot be mapped in READ mode and READ-only memory cannot be mapped in WRITE
+ mode.
+ The memory pointer returned from the map call is guaranteed to remain valid in
+ the requested mapping mode until the corresponding unmap call is performed on
+ the pointer.
+ When multiple map operations are nested and return the same pointer, the pointer
+ is valid until the last unmap call is done.
+
+ When the final reference on a memory object is dropped, all outstanding
+ mappings are automatically unmapped.
+
+ Resizing a GstMemory does not influence any current mappings an any way. Note
+ however that the unmap call can resize the buffer again.
+
+
+Copy
+~~~~
+
+ A GstMemory copy can be made with the gst_memory_copy() call. Normally,
+ allocators will implement a custom version of this function to make a copy of
+ the same kind of memory as the original one.
+
+ This is what the fallback version of the copy function will do, albeit slower
+ than what as custom implementation could do.
+
+ The copy operation is only required to copy the visible range of the memory
+ block.
+
+
+Share
+~~~~~
+
+ A memory region can be shared between GstMemory object with the
+ gst_memory_share() operation. 
+
+
index f952dd4..6e23d5b 100644 (file)
@@ -134,3 +134,16 @@ GST_MESSAGE_REQUEST_STATE:
   are in. A typical use case would be an audio sink that requests the pipeline
   to pause in order to play a higher priority stream.
 
+GST_MESSAGE_STEP_START:
+
+  A Stepping operation has started.
+
+GST_MESSAGE_QOS:
+
+  A buffer was dropped or an element changed its processing strategy for
+  Quality of Service reasons.
+
+GST_MESSAGE_PROGRESS:
+
+  A progress message was posted. Progress messages inform the application about
+  the state of asynchronous operations.
diff --git a/docs/design/part-meta.txt b/docs/design/part-meta.txt
new file mode 100644 (file)
index 0000000..797c315
--- /dev/null
@@ -0,0 +1,389 @@
+GstMeta
+-------
+
+This document describes the design for arbitrary per-buffer metadata.
+
+Buffer metadata typically describes the lowlevel properties of the buffer
+content. These properties are typically not negotiated with caps but they are
+negotiated in the bufferpools.
+
+Some examples of metadata:
+
+ - timestamp, duration
+ - offset, offset_end
+ - interlacing information
+ - video alignment, cropping, panning information
+ - extra container information such as granulepos, ...
+ - extra global buffer properties
+
+
+Requirements
+~~~~~~~~~~~~
+
+ - It must be fast
+    * allocation, free, low fragmentation
+    * access to the metadata fields, preferably not much slower than directly
+      accessing a C structure field
+ - It must be extensible. Elements should be able to add new arbitrary metadata
+   without requiring much effort. Also new metadata fields should not break API
+   or ABI.
+ - It plays nice with subbuffers. When a subbuffer is created, the various
+   buffer metadata should be copied/updated correctly.
+ - We should be able to negotiate metadata between elements
+
+Use cases
+---------
+
+ * Video planes
+
+ Video data is sometimes allocated in non-contiguous planes for the Y and the UV
+ data. We need to be able to specify the data on a buffer using multiple
+ pointers in memory. We also need to be able to specify the stride for these
+ planes.
+
+ * Extra buffer data
+
+ Some elements might need to store extra data for a buffer. This is typically
+ done when the resources are allocated from another subsystem such as OMX or
+ X11. 
+
+ * Processing information
+
+ Pan and crop information can be added to the buffer data when the downstream
+ element can understand and use this metadata. An imagesink can, for example,
+ use the pan and cropping formation when it blits the image on the screen
+ with little overhead.
+
+
+GstMeta
+~~~~~~~
+
+A GstMeta is a structure as follows:
+
+  struct _GstMeta {
+    const GstMetaInfo *info;    /* tag and info for the meta item */
+  };
+
+The purpose of the this structure is to serve as a common header for all metadata
+information that we can attach to a buffer. Specific metadata, such as timing metadata,
+will have this structure as the first field. For example:
+
+  struct _GstMetaTiming {
+    GstMeta        meta;        /* common meta header */
+    GstClockTime   dts;         /* decoding timestamp */
+    GstClockTime   pts;         /* presentation timestamp */
+    GstClockTime   duration;    /* duration of the data */
+    GstClockTime   clock_rate;  /* clock rate for the above values */
+  };
+
+Or another example for the video memory regions that consists of both fields and
+methods.
+
+
+ #define GST_VIDEO_MAX_PLANES 4
+
+ struct GstMetaVideo {
+   GstMeta       meta;
+
+   GstBuffer         *buffer;
+
+   GstVideoFlags      flags;
+   GstVideoFormat     format;
+   guint              width;
+   guint              height;
+
+   guint              n_planes;
+   gsize              offset[GST_VIDEO_MAX_PLANES];   /* offset in the buffer memory region of the
+                                                       * first pixel. */
+   gint               stride[GST_VIDEO_MAX_PLANES];   /* stride of the image lines. Can be negative when
+                                                       * the image is upside-down */
+
+   gpointer (*map)    (GstMetaVideo *meta, guint plane, gint *stride,
+                       GstMapFlags flags);
+   gboolean (*unmap)  (GstMetaVideo *meta, guint plane, gpointer data);
+ };
+
+ gpointer gst_meta_video_map   (GstMetaVideo *meta, guint plane, gint *stride,
+                                GstMapflags flags);
+ gboolean gst_meta_video_unmap (GstMetaVideo *meta, guint plane, gpointer data);
+
+GstMeta derived structures define the API of the metadata. The API can consist of
+fields and/or methods. It is possible to have different implementations for the
+same GstMeta structure.
+
+The implementation of the GstMeta api would typically add more fields to the
+public structure that allow it to implement the API.
+
+GstMetaInfo will point to more information about the metadata and looks like this:
+
+  struct _GstMetaInfo {
+    GQuark                     api;       /* api name */
+    GType                      type;      /* implementation type */
+    gsize                      size;      /* size of the structure */
+
+    GstMetaInitFunction        init_func;
+    GstMetaFreeFunction        free_func;
+    GstMetaCopyFunction        copy_func;
+    GstMetaTransformFunction   transform_func;
+  };
+
+api will contain a GQuark of the metadata api. A repository of registered MetaInfo
+will be maintained by the core. We will register some common metadata structures
+in core and some media specific info for audio/video/text in -base. Plugins can
+register additional custom metadata.
+
+For each implementation of api, there will thus be a unique GstMetaInfo. In the
+case of metadata with a well defined API, the implementation specific init
+function will setup the methods in the metadata structure. A unique GType will
+be made for each implementation and stored in the type field.
+
+Along with the metadata description we will have functions to initialize/free (and/or refcount)
+a specific GstMeta instance. We also have the possibility to add a custom
+transform function that can be used to modify the metadata when a transformation
+happens.
+
+There are no explicit methods to serialize and deserialize the metadata. Since
+each type has a GType, we can reuse the GValue transform functions for this.
+
+The purpose of the separate MetaInfo is to not have to carry the free/init functions in
+each buffer instance but to define them globally. We still want quick access to the info
+so we need to make the buffer metadata point to the info.
+
+Technically we could also specify the field and types in the MetaInfo and
+provide a generic API to retrieve the metadata fields without the need for a
+header file. We will not do this yet.
+
+Allocation of the GstBuffer structure will result in the allocation of a memory region
+of a customizable size (512 bytes). Only the first sizeof (GstBuffer) bytes of this
+region will initially be used. The remaining bytes will be part of the free metadata
+region of the buffer. Different implementations are possible and are invisible
+in the API or ABI.
+
+The complete buffer with metadata could, for example, look as follows:
+
+                         +-------------------------------------+
+GstMiniObject            |     GType (GstBuffer)               |
+                         |     refcount, flags, copy/disp/free |
+                         +-------------------------------------+
+GstBuffer                |     caps, parent, pool              |
+                         +.....................................+
+                         |     next                           ---+
+                      +- |     info                           ------> GstMetaInfo
+GstMetaTiming         |  |                                     | |
+                      |  |     dts                             | |
+                      |  |     pts                             | |
+                      |  |     duration                        | |
+                      +- |     clock_rate                      | |
+                         + . . . . . . . . . . . . . . . . . . + |
+                         |     next                           <--+
+GstMetaVideo       +- +- |     info                           ------> GstMetaInfo
+                   |  |  |                                     | |
+                   |  |  |     flags                           | |
+                   |  |  |     n_planes                        | |
+                   |  |  |     planes[]                        | |
+                   |  |  |     map                             | |
+                   |  |  |     unmap                           | |
+                   +- |  |                                     | |
+                      |  |     private fields                  | |
+GstMetaVideoImpl      |  |     ...                             | |
+                      |  |     ...                             | |
+                      +- |                                     | |
+                         + . . . . . . . . . . . . . . . . . . + .
+                         .                                       .
+
+
+API examples
+~~~~~~~~~~~~
+
+Buffers are created using the normal gst_buffer_new functions. The standard fields
+are initialized as usual. A memory area that is bigger than the structure size
+is allocated for the buffer metadata.
+
+  gst_buffer_new ();
+
+After creating a buffer, the application can set caps and add metadata
+information. 
+
+To add or retrieve metadata, a handle to a GstMetaInfo structure needs to be
+obtained. This defines the implementation and API of the metadata. Usually, a
+handle to this info structure can be obtained by calling a public _get_info()
+method from a shared library (for shared metadata).
+
+The following defines can usually be found in the shared .h file.
+
+  GstMetaInfo * gst_meta_timing_get_info();
+  #define GST_META_TIMING_INFO  (gst_meta_timing_get_info())
+
+Adding metadata to a buffer can be done with the gst_buffer_add_meta() call.
+This function will create new metadata based on the implementation specified by
+the GstMetaInfo. It is also possible to pass a generic pointer to the add_meta()
+function that can contain parameters to initialize the new metadata fields.
+
+Retrieving the metadata on a buffer can be done with the
+gst_buffer_meta_get() method. This function retrieves an existing metadata
+conforming to the API specified in the given info. When no such metadata exists,
+the function will return NULL.
+
+  GstMetaTiming *timing;
+
+  timing = gst_buffer_get_meta (buffer, GST_META_TIMING_INFO);
+
+Once a reference to the info has been obtained, the associated metadata can be
+added or modified on a buffer.
+
+  timing->timestamp = 0;
+  timing->duration = 20 * GST_MSECOND;
+
+Other convenience macros can be made to simplify the above code:
+
+ #define gst_buffer_get_meta_timing(b) \
+    ((GstMetaTiming *) gst_buffer_get_meta ((b), GST_META_TIMING_INFO)
+
+This makes the code look like this:
+
+  GstMetaTiming *timing;
+
+  timing = gst_buffer_get_meta_timing (buffer);
+  timing->timestamp = 0;
+  timing->duration = 20 * GST_MSECOND;
+To iterate the different metainfo structures, one can use the
+gst_buffer_meta_get_next() methods.
+
+ GstMeta *current = NULL;
+
+ /* passing NULL gives the first entry */ 
+ current = gst_buffer_meta_get_next (buffer, current);
+
+ /* passing a GstMeta returns the next */
+ current = gst_buffer_meta_get_next (buffer, current);
+
+
+Memory management
+~~~~~~~~~~~~~~~~~
+
+* allocation
+
+  We initially allocate a reasonable sized GstBuffer structure (say 512 bytes).
+
+  Since the complete buffer structure, including a large area for metadata, is
+  allocated in one go, we can reduce the number of memory allocations while still
+  providing dynamic metadata.
+
+  When adding metadata, we need to call the init function of the associated
+  metadata info structure. Since adding the metadata requires the caller to pass
+  a handle to the info, this operation does not require table lookups.
+
+  Per-metadata memory initialisation is needed because not all metadata is
+  initialized in the same way. We need to, for example, set the timestamps to
+  NONE in the MetaTiming structures.
+
+  The init/free functions can also be used to implement refcounting for a metadata
+  structure. This can be useful when a structure is shared between buffers.
+
+  When the free_size of the GstBuffer is exhausted, we will allocate new memory
+  for each newly added Meta and use the next pointers to point to this. It
+  is expected that this does not occur often and we might be able to optimize
+  this transparently in the future.
+
+* free
+
+  When a GstBuffer is freed, we potentially might have to call a custom free
+  function on the metadata info. In the case of the Memory metadata, we need to
+  call the associated free function to free the memory.
+  
+  When freeing a GstBuffer, the custom buffer free function will iterate all of
+  the metadata in the buffer and call the associated free functions in the
+  MetaInfo associated with the entries. Usually, this function will be NULL.
+
+
+Serialization
+~~~~~~~~~~~~~
+
+When buffer should be sent over the wire or be serialized in GDP, we need a way
+to perform custom serialization and deserialization on the metadata.
+
+for this we can use the GValue transform functions.
+
+
+Transformations
+~~~~~~~~~~~~~~~
+
+After certain transformations, the metadata on a buffer might not be relevant
+anymore.
+
+Consider, for example, metadata that lists certain regions of interest
+on the video data. If the video is scaled or rotated, the coordinates might not
+make sense anymore. A transform element should be able to adjust or remove the
+associated metadata when it becomes invalid. 
+
+We can make the transform element aware of the metadata so that it can adjust or
+remove in an intelligent way. Since we allow arbitrary metadata, we can't do
+this for all metadata and thus we need some other way.
+
+One proposition is to tag the metadata type with keywords that specify what it
+functionally refers too. We could, for example, tag the metadata for the regions
+of interest with a tag that notes that the metadata refers to absolute pixel
+positions. A transform could then know that the metadata is not valid anymore
+when the position of the pixels changed (due to rotation, flipping, scaling and
+so on).
+
+
+Subbuffers
+~~~~~~~~~~
+
+Subbuffers are implemented with a generic copy. Parameters to the copy
+are the offset and size. This allows each metadata structure to implement the
+actions needed to update the metadata of the subbuffer. 
+
+It might not make sense for some metadata to work with subbuffers. For example
+when  we take a subbuffer of a buffer with a video frame, the GstMetaVideo
+simply becomes invalid and is removed from the new subbuffer.
+
+
+Relationship with GstCaps
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The difference between GstCaps, used in negotiation, and the metadata is not
+clearly defined. 
+
+We would like to think of the GstCaps containing the information needed to
+functionally negotiate the format between two elements. The Metadata should then
+only contain variables that can change between each buffer.
+
+For example, for video we would have width/height/framerate in the caps but then
+have the more technical details, such as stride, data pointers, pan/crop/zoom
+etc in the metadata.
+
+A scheme like this would still allow us to functionally specify the desired
+video resolution while the implementation details would be inside the metadata.
+
+
+Compatibility
+~~~~~~~~~~~~~
+
+We need to make sure that elements exchange metadata that they both understand,
+This is particulary important when the metadata describes the data layout in
+memory (such as strides).
+
+We would like to use the bufferpool negotiation system to negotiate the possible
+metadata that can be exchanged between elements.
+
+When deciding the allocation properties, we will also negotiate the buffer
+metadata structures that we can exchange.
+
+
+Notes
+~~~~~
+
+Some structures that we need to be able to add to buffers.
+
+* Clean Aperture
+* Arbitrary Matrix Transform
+* Aspect ratio
+* Pan/crop/zoom
+* Video strides
+
+Some of these overlap, we need to find a minimal set of metadata structures that
+allows us to define all use cases.
index 11c296b..2a5f4be 100644 (file)
@@ -26,32 +26,18 @@ negotiation.
 
 The basics of negotiation are as follows:
 
- - GstCaps (see part-caps.txt) are refcounted before they
-   are attached to a buffer to describe the contents of the buffer.
-   It is possible to add a NULL caps to a buffer, this means that the
-   buffer type did not change relative to the previous buffer. If no
-   previous buffer was received by a downstream element, it is free to
-   discard the buffer.
-
- - Before receiving a buffer, an element must check if the datatype of
-   the buffer has changed. The element should reconfigure itself to the
-   new format before processing the buffer data. If the data type on
-   the buffer is not acceptable, the element should refuse the buffer by 
+ - GstCaps (see part-caps.txt) are refcounted before they are pushed as
+   an event to describe the contents of the following buffer.
+
+ - An element should reconfigure itself to the new format received as a CAPS
+   event before processing the following buffers. If the data type in the
+   caps event is not acceptable, the element should refuse the buffer by 
    returning an appropriate GST_FLOW_NOT_NEGOTIATED return value from the
    chain function.
-   The core will automatically call the set_caps function for this purpose
-   when it is installed on the sink or source pad.
-
- - When requesting a buffer from a bufferpool, the preferred type should
-   be passed to the buffer allocation function. After receiving a buffer
-   from a bufferpool, the datatype should be checked again.
-
- - A bufferpool allocation function should try to allocate a buffer of the
-   preferred type. If there is a good reason to choose another type, the
-   alloc function should see if that other type is accepted by the other
-   element, then allocate a buffer of that type and attach the type to the
-   buffer before returning it.
 
+ - Downstream elements can request a format change of the stream by sending a
+   RECONFIGURE event upstream. Upstream elements will renegotiate a new format
+   when they receive a RECONFIGURE event.
 
 The general flow for a source pad starting the negotiation.
 
@@ -60,30 +46,24 @@ The general flow for a source pad starting the negotiation.
               |  accepts?       |
   type A      |---------------->|
               |      yes        |
-              |<----------------|
+              |< - - - - - - - -|
               |                 |
get buffer   |  alloc_buf      |
- from pool    |---------------->| 
with type A  |                 | Create buffer of type A.
             |  send_event()   |
+ send CAPS    |---------------->| Receive type A, reconfigure to
event A      |                 | process type A.
               |                 |
- check type   |<----------------|
- and use A    |                 |
               |  push           |
- push buffer  |---------------->| Receive type A, reconfigure to
- with new type|                 | process type A.
+ push buffer  |---------------->| Process buffer of type A
               |                 |
 
  One possible implementation in pseudo code:
 
  [element wants to create a buffer]
  if not format
-   # see what the peer can do
-   peercaps = gst_pad_peer_get_caps (srcpad)
    # see what we can do
    ourcaps = gst_pad_get_caps (srcpad)
-
-   # get common formats
-   candidates = gst_caps_intersect (peercaps, ourcaps)
+   # see what the peer can do filtered against our caps
+   candidates = gst_pad_peer_get_caps (srcpad, ourcaps)
 
    foreach candidate in candidates
      # make sure the caps is fixed
@@ -93,20 +73,16 @@ The general flow for a source pad starting the negotiation.
      if gst_pad_peer_accept_caps (srcpad, fixedcaps)
        # store the caps as the negotiated caps, this will
        # call the setcaps function on the pad
-       gst_pad_set_caps (srcpad, fixedcaps)
+       gst_pad_push_event (srcpad, gst_event_new_caps (fixedcaps))
        break
      endif
    done
  endif
 
- # if the type is different, the buffer will have different caps from
- # the src pad -- setcaps will get called on the pad_push
- buffer = gst_pad_alloc_buffer (srcpad, 0, size, GST_PAD_CAPS (fixedcaps));
- if buffer
-   [fill buffer and push]
- elseif
-   [no buffer, either no peer or no acceptable format found]
- endif
+ #negotiate allocator/bufferpool with the ALLOCATION query
+
+ buffer = gst_buffer_new_allocate (NULL, size, 0);
+ # fill buffer and push
 
 
 The general flow for a sink pad starting a renegotiation.
@@ -116,21 +92,27 @@ The general flow for a sink pad starting a renegotiation.
               |  accepts?       |
               |<----------------| type B
               |      yes        |
-              |---------------->|
+              |- - - - - - - - >|-.
+              |                 | | suggest B caps next
+              |                 |<'
+              |                 |
+              |   push_event()  |
+  mark      .-|<----------------| send RECONFIGURE event
+ renegotiate| |                 |
+            '>|                 |
+              |   get_caps()    |
+ renegotiate  |---------------->| 
+              |  suggest B      |
+              |< - - - - - - - -|
               |                 |
get buffer   |  alloc_buf      |
- from pool    |---------------->| 
with type A  |                 | Create buffer of new type B.
             |  send_event()   |
+ send CAPS    |---------------->| Receive type B, reconfigure to
event B      |                 | process type B.
               |                 |
- check type   |<----------------|
- and          |                 |
- reconfigure  |                 |
               |  push           |
- push buffer  |---------------->| Receive type B, reconfigure to
- with new type|                 | process type B.
+ push buffer  |---------------->| Process buffer of type B
               |                 |
 
-             
 
 Use case:
 
@@ -146,25 +128,30 @@ videotestsrc ! xvimagesink
 
   2) When does negotiation happen?
    - before srcpad does a push, it figures out a type as stated in 1), then 
-     it calls the pad alloc function with the type. The sinkpad has to 
-     create a buffer of that type, src fills the buffer and sends it to sink.
+     it pushes a caps event with the type. The sink checks the media type and
+     configures itself for this type.
+   - the source then usually does an ALLOCATION query to negotiate a bufferpool
+     with the sink. It then allocates a buffer from the pool and pushes it to
+     the sink. since the sink accepted the caps, it can create a pool for the
+     format.
    - since the sink stated in 1) it could accept the type, it will be able to
-     create a buffer of the type and handle it.
-   - sink checks media type of buffer and configures itself for this type.
+     handle it.
      
   3) How can sink request another format?
    - sink asks if new format is possible for the source.
-   - sink returns buffer with new type in allocfunction.
-   - src receives buffer with new type, reconfigures and pushes.
-   - sink can always select something it can create and handle since it takes
-     the initiative. src should be able to handle the new type since it said
-     it could accept it.
+   - sink pushes RECONFIGURE event upstream
+   - src receives the RECONFIGURE event and marks renegotiation
+   - On the next buffer push, the source renegotiates the caps and the
+     bufferpool. The sink will put the new new prefered format high in the list
+     of caps it returns from its getcaps function.
 
 videotestsrc ! queue ! xvimagesink
 
-  - queue implements an allocfunction, proxying all calls to its srcpad peer.
   - queue proxies all accept and getcaps to the other peer pad.
-  - queue contains buffers with different types.
+  - queue proxies the bufferpool
+  - queue proxies the RECONFIGURE event
+  - queue stores CAPS event in the queue. This means that the queue can contain
+    buffers with different types.
 
    
 Pull-mode negotiation
@@ -232,7 +219,7 @@ deadlines.
 The pull thread is usually started in the PAUSED->PLAYING state change. We must
 be able to complete the negotiation before this state change happens.
 
-The time to do capsnego, then, is after _check_pull_range() has succeeded,
+The time to do capsnego, then, is after the SCHEDULING query has succeeded,
 but before the sink has spawned the pulling thread.
 
 
@@ -240,7 +227,7 @@ Mechanism
 ^^^^^^^^^
 
 The sink determines that the upstream elements support pull based scheduling by
-calling gst_pad_check_pull_range().
+doing a SCHEDULING query.
 
 The sink initiates the negotiation process by intersecting the results
 of gst_pad_get_caps() on its sink pad and its peer src pad. This is the
@@ -250,8 +237,7 @@ intersection of calling get_allowed_caps() on all of its sink pads. In
 this way the sink element knows the capabilities of the entire pipeline.
 
 The sink element then fixates the resulting caps, if necessary,
-resulting in the flow caps. It notifies the pipeline of the caps by
-calling gst_pad_set_caps() on its sink pad. From now on, the getcaps function
+resulting in the flow caps.  From now on, the getcaps function
 of the sinkpad will only return these fixed caps meaning that upstream elements
 will only be able to produce this format.
 
@@ -269,11 +255,3 @@ function. The state will commit to PAUSED when the first buffer is received in
 the sink. This is needed to provide a consistent API to the applications that
 expect ASYNC return values from sinks but it also allows us to perform the
 remainder of the negotiation outside of the context of the pulling thread.
-
-During dataflow, gst_pad_pull_range() checks the caps on the pulled
-buffer. If they are different from the sink pad's caps, it will return
-GST_FLOW_NOT_NEGOTIATED. Because of the low-latency requirements,
-changing caps in an activate pull-mode pipeline is not supported, as it
-might require e.g. the sound card to reconfigure its hardware buffers,
-and start capsnego again.
-
index e292150..a51471a 100644 (file)
@@ -195,10 +195,9 @@ includes:
   - offset of the data: a media specific offset, this could be samples for audio or
       frames for video.
   - the duration of the data in time.
-  - the media type of the data described with caps, these are key/value pairs that
-      describe the media type in a unique way.
   - additional flags describing special properties of the data such as 
     discontinuities or delta units.
+  - additional arbitrary metadata
 
 When an element whishes to send a buffer to another element is does this using one
 of the pads that is linked to a pad of the other element. In the push model, a 
@@ -208,13 +207,13 @@ is pulled from the peer with the gst_pad_pull_range() function.
 Before an element pushes out a buffer, it should make sure that the peer element
 can understand the buffer contents.  It does this by querying the peer element
 for the supported formats and by selecting a suitable common format. The selected
-format is then attached to the buffer with gst_buffer_set_caps() before pushing
-out the buffer.
+format is then first sent to the peer element with a CAPS event before pushing
+the buffer.
 
-When an element pad receives a buffer, if has to check if it understands the media
-type of the buffer before starting processing it. The GStreamer core does this
-automatically and will call the gst_pad_set_caps() function of the element before
-sending the buffer to the element.
+
+When an element pad receives a CAPS event, it has to check if it understand the
+media type. The element must refuse following buffers if the media type
+preceeding it was not accepted.
 
 Both gst_pad_push() and gst_pad_pull_range() have a return value indicating whether
 the operation succeeded. An error code means that no more data should be sent
@@ -222,12 +221,11 @@ to that pad. A source element that initiates the data flow in a thread typically
 pauses the producing thread when this happens.
 
 A buffer can be created with gst_buffer_new() or by requesting a usable buffer
-from the peer pad using gst_pad_alloc_buffer(). Using the second method, it is
-possible for the peer element to suggest the element to produce data in another 
-format by attaching another media type caps to the buffer.
+from a buffer pool using gst_buffer_pool_acquire_buffer(). Using the second
+method, it is possible for the peer element to implement a custom buffer
+allocation algorithm.
 
-The process of selecting a media type and attaching it to the buffers is called
-caps negotiation.
+The process of selecting a media type is called caps negotiation.
 
 
 Caps
@@ -349,14 +347,18 @@ it accepts the data from filesrc on the sinkpad and starts decoding the compress
 data to raw audio samples.
 
 The mp3 decoder figures out the samplerate, the number of channels and other audio
-properties of the raw audio samples, puts the decoded samples into a Buffer,  
-attaches the media type caps to the buffer and pushes this buffer to the next
+properties of the raw audio samples and sends out a caps event with the media type.
+
+Alsasink then receives the caps event, inspects the caps and reconfigures
+itself to process the media type.
+
+mp3dec then puts the decoded samples into a Buffer and pushes this buffer to the next
 element.
 
-Alsasink then receives the buffer, inspects the caps and reconfigures itself to process
-the buffer. Since it received the first buffer of samples, it completes the state change
-to the PAUSED state. At this point the pipeline is prerolled and all elements have
-samples. Alsasink is now also capable of providing a clock to the pipeline.
+Alsasink receives the buffer with samples. Since it received the first buffer of
+samples, it completes the state change to the PAUSED state. At this point the
+pipeline is prerolled and all elements have samples. Alsasink is now also
+capable of providing a clock to the pipeline.
 
 Since alsasink is now in the PAUSED state it blocks while receiving the first buffer. This
 effectively blocks both mp3dec and filesrc in their gst_pad_push().
@@ -488,7 +490,7 @@ element performs the following steps.
      always stop because of step 1).
   3) perform the seek operation
   4) send a FLUSH done event to all downstream and upstream peer elements.
-  5) send NEWSEGMENT event to inform all elements of the new position and to complete
+  5) send SEGMENT event to inform all elements of the new position and to complete
      the seek.
 
 In step 1) all downstream elements have to return from any blocking operations
@@ -512,8 +514,8 @@ Since the pipeline is still PAUSED, this will preroll the next media sample in t
 sinks. The application can wait for this preroll to complete by performing a 
 _get_state() on the pipeline.
 
-The last step in the seek operation is then to adjust the stream time of the pipeline
-to 0 and to set the pipeline back to PLAYING.
+The last step in the seek operation is then to adjust the stream running_time of
+the pipeline to 0 and to set the pipeline back to PLAYING.
 
 The sequence of events in our mp3 playback example.
 
@@ -533,8 +535,8 @@ The sequence of events in our mp3 playback example.
              | 2) stop streaming
              | 3) perform seek
               --------------------------> 4) FLUSH done event
-              --------------------------> 5) NEWSEGMENT event
+              --------------------------> 5) SEGMENT event
   
-                                      | e) update stream time to 0
+                                      | e) update running_time to 0
                                      | f) PLAY pipeline
 
diff --git a/docs/design/part-probes.txt b/docs/design/part-probes.txt
new file mode 100644 (file)
index 0000000..1857709
--- /dev/null
@@ -0,0 +1,281 @@
+Probes
+------
+
+ Probes are callbacks that can be installed by the application and will notify
+ the application about the states of the dataflow.
+
+
+Requirements
+------------
+
+Applications should be able to monitor and control the dataflow on pads. We
+identify the following types:
+
+ - be notified when the pad is/becomes idle and make sure the pad stays idle.
+   This is essential to be able to implement dynamic relinking of elements
+   without breaking the dataflow.
+
+ - be notified when data or events are pushed or sent on a pad. It should also
+   be possible to inspect and modify the data.
+ - be able to drop, pass and block on data based on the result of the callback.
+
+ - be able to drop, pass data on blocking pads based on methods performed by
+   the application thread.
+
+
+Overview
+--------
+
+ The function gst_pad_add_probe() is used to add a probe to a pad. It accepts a
+ probe type mask and a callback.
+
+   gulong  gst_pad_add_probe    (GstPad *pad,
+                                 GstPadProbeType mask,
+                                 GstPadProbeCallback callback,
+                                 gpointer user_data,
+                                 GDestroyNotify destroy_data);
+
+ The function returns a gulong that uniquely identifies the probe and that can
+ be used to remove the probe with gst_pad_remove_probe():
+
+   void    gst_pad_remove_probe (GstPad *pad, gulong id);
+
+ The mask parameter is a bitwise or of the following flags:
+  
+    typedef enum
+    {
+      GST_PAD_PROBE_TYPE_INVALID          = 0,
+
+      /* flags to control blocking */
+      GST_PAD_PROBE_TYPE_IDLE             = (1 << 0),
+      GST_PAD_PROBE_TYPE_BLOCK            = (1 << 1),
+
+      /* flags to select datatypes */
+      GST_PAD_PROBE_TYPE_BUFFER           = (1 << 2),
+      GST_PAD_PROBE_TYPE_BUFFER_LIST      = (1 << 3),
+      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM = (1 << 4),
+      GST_PAD_PROBE_TYPE_EVENT_UPSTREAM   = (1 << 5),
+
+      /* flags to select scheduling mode */
+      GST_PAD_PROBE_TYPE_PUSH             = (1 << 6),
+      GST_PAD_PROBE_TYPE_PULL             = (1 << 7),
+
+    } GstPadProbeType;
+
+ When adding a probe with the IDLE or BLOCK flag, the probe will become a
+ blocking probe (see below). Otherwise the probe will be a DATA probe.
+
+ The datatype and scheduling selector flags are used to select what kind of
+ datatypes and scheduling modes should be allowed in the callback.
+ The blocking flags must match the triggered probe exactly.
+
+ The probe callback is defined as:
+
+   GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info,
+                                          gpointer user_data);
+
+ A probe info structure is passed as an argument and its type is guaranteed
+ to match the mask that was used to register the callback. The data item in the
+ info contains type specific data, which is usually the data item that is blocked
+ or NULL when no data item is present.  
+ The probe can return any of the following return values:
+
+   typedef enum
+   {
+     GST_PAD_PROBE_DROP,
+     GST_PAD_PROBE_OK,
+     GST_PAD_PROBE_REMOVE,
+     GST_PAD_PROBE_PASS,
+   } GstPadProbeReturn;
+
+ GST_PAD_PROBE_OK is the normal return value.  DROP will drop the item that is
+ currently being probed. GST_PAD_PROBE_REMOVE the currently executing probe from the
+ list of probes. 
+ GST_PAD_PROBE_PASS is relevant for blocking probes and will temporarily unblock the
+ pad and let the item trough, it will then block again on the next item.
+
+
+Blocking probes
+---------------
+
+  Blocking probes are probes with BLOCK or IDLE flags set. They will always
+  block the dataflow and trigger the callback according to the following rules:
+
+  When the IDLE flag is set, the probe callback is called as soon as no data is
+  flowing over the pad. If at the time of probe registration, the pad is idle,
+  the callback will be called immediately from the current thread. Otherwise,
+  the callback will be called as soon as the pad becomes idle in the streaming
+  thread.
+
+  The IDLE probe in useful to perform dynamic linking, it allows to wait for for
+  a safe moment when an unlink/link operation can be done. Since the probe is a
+  blocking probe, it will also make sure that the pad stays idle until the probe
+  is removed.
+
+  When the BLOCK flag is set, the probe callback will be called when new data
+  arrives on the pad and right before the pad goes into the blocking state. This
+  callback is thus only called when there is new data on the pad.
+
+  The blocking probe is removed with gst_pad_remove_probe() or when the probe
+  callback return GST_PAD_PROBE_REMOVE. In both cases, and if this was the last
+  blocking probe on the pad, the pad is unblocked and dataflow can continue.
+
+
+Non-Blocking probes
+--------------------
+
+  Non-blocking probes or DATA probes are probes triggered when data is flowing
+  over the pad. The are called after the blocking probes are run and always with
+  data.
+
+
+Push dataflow
+-------------
+
+Push probes have the GST_PAD_PROBE_TYPE_PUSH flag set in the callbacks.
+
+In push based scheduling, the blocking probe is called first with the data item.
+Then the data probes are called before the peer pad chain or event function is
+called.
+
+The data probes are called before the peer pad is checked. This allows for
+linking the pad in either the BLOCK or DATA probes on the pad.
+
+Before the peerpad chain or event function is called, the peer pad block and
+data probes are called.
+
+Finally, the IDLE probe is called on the pad after the data was sent to the
+peer pad.
+
+The push dataflow probe behavior is the same for buffers and bidirectional events.
+
+
+                     pad                           peerpad
+                      |                               |
+ gst_pad_push() /     |                               |
+ gst_pad_push_event() |                               |
+ -------------------->O                               |
+                      O                               | 
+        flushing?     O                               | 
+        WRONG_STATE   O                               |
+        < - - - - - - O                               | 
+                      O-> do BLOCK probes             | 
+                      O                               | 
+                      O-> do DATA probes              | 
+         no peer?     O                               |
+        NOT_LINKED    O                               | 
+        < - - - - - - O                               |
+                      O   gst_pad_chain() /           | 
+                      O   gst_pad_send_event()        | 
+                      O------------------------------>O
+                      O                   flushing?   O 
+                      O                 WRONG_STATE   O 
+                      O< - - - - - - - - - - - - - - -O 
+                      O                               O-> do BLOCK probes
+                      O                               O 
+                      O                               O-> do DATA probes
+                      O                               O 
+                      O                               O---> chainfunc /
+                      O                               O     eventfunc
+                      O< - - - - - - - - - - - - - - -O 
+                      O                               |
+                      O-> do IDLE probes              | 
+                      O                               | 
+        < - - - - - - O                               | 
+                      |                               | 
+
+
+Pull dataflow
+-------------
+
+Pull probes have the GST_PAD_PROBE_TYPE_PULL flag set in the callbacks.
+
+The gst_pad_pull_range() call will first trigger the BLOCK probes without a DATA
+item. This allows the pad to be linked before the peer pad is resolved. It also
+allows the callback to set a data item in the probe info.
+
+After the blocking probe and the getrange function is called on the peer pad
+and there is a data item, the DATA probes are called.
+
+When control returns to the sinkpad, the IDLE callbacks are called. The IDLE
+callback is called without a data item so that it will also be called when there
+was an error.
+
+If there is a valid DATA item, the DATA probes are called for the item.
+
+
+                 srcpad                          sinkpad
+                   |                               |
+                   |                               | gst_pad_pull_range()
+                   |                               O<---------------------
+                   |                               O
+                   |                               O  flushing?
+                   |                               O  WRONG_STATE
+                   |                               O - - - - - - - - - - >
+                   |             do BLOCK probes <-O
+                   |                               O   no peer?
+                   |                               O  NOT_LINKED
+                   |                               O - - - - - - - - - - >
+                   |          gst_pad_get_range()  O
+                   O<------------------------------O
+                   O                               O
+                   O flushing?                     O
+                   O WRONG_STATE                   O
+                   O- - - - - - - - - - - - - - - >O
+ do BLOCK probes <-O                               O
+                   O                               O
+  getrangefunc <---O                               O
+                   O  flow error?                  O
+                   O- - - - - - - - - - - - - - - >O
+                   O                               O
+  do DATA probes <-O                               O
+                   O- - - - - - - - - - - - - - - >O
+                   |                               O 
+                   |              do IDLE probes <-O               
+                   |                               O   flow error?
+                   |                               O - - - - - - - - - - >
+                   |                               O
+                   |              do DATA probes <-O  
+                   |                               O - - - - - - - - - - >
+                   |                               |
+
+
+Queries
+-------
+
+Query probes have the GST_PAD_PROBE_TYPE_QUERY_* flag set in the callbacks.
+
+
+                     pad                           peerpad
+                      |                               |
+ gst_pad_peer_query() |                               |
+ -------------------->O                               |
+                      O                               | 
+                      O-> do BLOCK probes             | 
+                      O                               | 
+                      O-> do QUERY | PUSH probes      | 
+         no peer?     O                               |
+           FALSE      O                               | 
+        < - - - - - - O                               |
+                      O   gst_pad_query()             | 
+                      O------------------------------>O
+                      O                               O-> do BLOCK probes
+                      O                               O 
+                      O                               O-> do QUERY | PUSH probes
+                      O                               O 
+                      O                               O---> queryfunc
+                      O                    error      O 
+        <- - - - - - - - - - - - - - - - - - - - - - -O 
+                      O                               O 
+                      O                               O-> do QUERY | PULL probes
+                      O< - - - - - - - - - - - - - - -O 
+                      O                               |
+                      O-> do QUERY | PULL probes      | 
+                      O                               | 
+        < - - - - - - O                               | 
+                      |                               | 
+
index 815216e..2633072 100644 (file)
@@ -52,6 +52,45 @@ The getrange function
 The getrange function is called when a peer pad performs a _pull_range() on the pad. This
 downstream pad can be a pulling element or another _pull_range() based element.
 
+
+Scheduling Query
+~~~~~~~~~~~~~~~~
+
+A sinkpad can ask the upstream srcpad for its scheduling attributes. It does
+this with the SCHEDULING query.
+
+
+ (out) "modes", G_TYPE_VALUE_ARRAY (default NULL)
+       - an array of GST_TYPE_PAD_MODE enums. Contains all the supported
+         scheduling modes.
+
+ (out) "flags", GST_TYPE_SCHEDULING_FLAGS (default 0)
+
+     typedef enum {
+       GST_SCHEDULING_FLAG_SEEKABLE      = (1 << 0),
+       GST_SCHEDULING_FLAG_SEQUENTIAL    = (1 << 1)
+     } GstSchedulingFlags;
+
+   _SEEKABLE:
+       - the offset of a pull operation can be specified, if this flag is false,
+         the offset should be -1,
+   _SEQUENTIAL:
+       - suggest sequential access to the data. If _SEEKABLE is specified,
+         seeks are allowed but should be avoided. This is common for network
+         streams.
+
+ (out) "minsize", G_TYPE_INT (default 1)
+       - the suggested minimum size of pull requests
+
+ (out) "maxsize", G_TYPE_INT (default -1, unlimited)
+       - the suggested maximum size of pull requests
+
+ (out) "align", G_TYPE_INT (default 0)
+       - the suggested alignment for the pull requests.
+
+
+
 Plug-in techniques
 ~~~~~~~~~~~~~~~~~~
 
index 992edb3..38bb33c 100644 (file)
@@ -127,7 +127,7 @@ When a seek to a certain position is requested, the demuxer/parser will
 do two things (ignoring flushing and segment seeks, and simplified for
 illustration purposes):
 
- - send a newsegment event with a new start position
+ - send a segment event with a new start position
 
  - start pushing data/buffers again
 
@@ -136,15 +136,15 @@ can actually be decoded, a demuxer or parser needs to start pushing data
 from a keyframe/keyunit at or before the requested seek position.
 
 Unless requested differently (via the KEY_UNIT flag), the start of the
-newsegment event should be the requested seek position.
+segment event should be the requested seek position.
 
 So by default a demuxer/parser will then start pushing data from
-position DATA and send a newsegment event with start position SEG_START,
+position DATA and send a segment event with start position SEG_START,
 and DATA <= SEG_START.
 
 If DATA < SEG_START, a well-behaved video decoder will start decoding frames
 from DATA, but take into account the segment configured by the demuxer via
-the newsegment event, and only actually output decoded video frames from
+the segment event, and only actually output decoded video frames from
 SEG_START onwards, dropping all decoded frames that are before the
 segment start and adjusting the timestamp/duration of the buffer that
 overlaps the segment start ("clipping"). A not-so-well-behaved video decoder
index d5b7e76..e05ec5b 100644 (file)
@@ -22,8 +22,8 @@ on the stream. The seek has a start time, a stop time and a processing rate.
 
 
 The playback of a segment starts with a source or demuxer element pushing a
-newsegment event containing the start time, stop time and rate of the segment.
-The purpose of this newsegment is to inform downstream elements of the 
+segment event containing the start time, stop time and rate of the segment.
+The purpose of this segment is to inform downstream elements of the 
 requested segment positions. Some elements might produce buffers that fall
 outside of the segment and that might therefore be discarded or clipped.
 
@@ -46,8 +46,8 @@ Use case: FLUSHING seek
     upstream and downstream.
 
     When avidemux starts playback of the segment from second 1 to 5, it pushes
-    out a newsegment with 1 and 5 as start and stop times. The stream_time in
-    the newsegment is also 1 as this is the position we seek to.
+    out a segment with 1 and 5 as start and stop times. The stream_time in
+    the segment is also 1 as this is the position we seek to.
 
     The video decoder stores these values internally and forwards them to the
     next downstream element (videosink, which also stores the values)
@@ -64,7 +64,7 @@ Use case: FLUSHING seek
     When it reaches timestamp 5, it does not decode and push frames anymore.
 
     The video sink receives a frame of timestamp 1. It takes the start value of 
-    the previous newsegment and aplies the folowing (simplified) formula:
+    the previous segment and aplies the folowing (simplified) formula:
 
         render_time = BUFFER_TIMESTAMP - segment_start + element->base_time
 
index 4770e90..269faa5 100644 (file)
@@ -8,7 +8,7 @@ In 0.8, there was some support for Sparse Streams through the use of
 FILLER events. These were used to mark gaps between buffers so that downstream
 elements could know not to expect any more data for that gap. 
 
-In 0.10, segment information conveyed through NEWSEGMENT events can be used
+In 0.10, segment information conveyed through SEGMENT events can be used
 for the same purpose.
 
 Use cases
@@ -45,9 +45,9 @@ Details
   The main requirement here is to avoid stalling the pipeline between sub-title
   packets, and is effectively updating the minimum-timestamp for that stream.
   
-  A demuxer can do this by sending an 'update' NEWSEGMENT with a new start time
+  A demuxer can do this by sending an 'update' SEGMENT with a new start time
   to the subtitle pad. For example, every time the SCR in MPEG data 
-  advances more than 0.5 seconds, the MPEG demuxer can issue a NEWSEGMENT with
+  advances more than 0.5 seconds, the MPEG demuxer can issue a SEGMENT with
    (update=TRUE, start=SCR ). Downstream elements can then be aware not to 
    expect any data older than the new start time.
 
@@ -57,7 +57,7 @@ Details
    
   This technique can also be used, for example, to represent a stream of 
   MIDI events spaced to a clock period. When there is no event present for 
-  a clock time, a NEWSEGMENT update can be sent in its place.
+  a clock time, a SEGMENT update can be sent in its place.
   
 2) Still frame/menu support
   Still frames in DVD menus are not the same, in that they do not introduce
@@ -74,7 +74,7 @@ Details
       if necessary due to an intervening activity (such as a user navigation)
     * FLUSH the pipeline using a normal flush sequence (FLUSH_START, 
       chain-lock, FLUSH_STOP)
-    * Send a NEWSEGMENT to restart playback with the next timestamp in the 
+    * Send a SEGMENT to restart playback with the next timestamp in the 
       stream.
   
   The upstream element performing the wait must only do so when in the PLAYING 
@@ -90,7 +90,7 @@ Details
   arriving late at the sink, and they will be discarded instead of played.
 
 3) For audio, 3) is the same case as 1) - there is a 'gap' in the audio data 
-   that needs to be presented, and this can be done by sending a NEWSEGMENT 
+   that needs to be presented, and this can be done by sending a SEGMENT 
    update that moves the start time of the segment to the next timestamp when 
    data will be sent.
    
index 1274ae0..119921d 100644 (file)
@@ -11,7 +11,7 @@ Stream objects
 The following objects are to be expected in the streaming thread:
 
  - events
-    - NEW_SEGMENT      (NS)
+    - SEGMENT           (S)
     - EOS              (EOS)  *
     - TAG               (T)
  - buffers              (B)    *
@@ -23,25 +23,27 @@ and live sources.
 Typical stream
 ~~~~~~~~~~~~~~
 
- A typical stream starts with a newsegment event that marks the
+ A typical stream starts with a segment event that marks the
  buffer timestamp range. After that buffers are sent one after the
  other. After the last buffer an EOS marks the end of the stream. No
  more buffers are to be processed after the EOS event.
 
-  +--+ +-++-+     +-+ +---+
-  |NS| |B||B| ... |B| |EOS|
-  +--+ +-++-+     +-+ +---+
+  +-+ +-++-+     +-+ +---+
+  |S| |B||B| ... |B| |EOS|
+  +-+ +-++-+     +-+ +---+
 
-  1) NEW_SEGMENT, rate, start/stop, time
+  1) SEGMENT, rate, start/stop, time
      - marks valid buffer timestamp range (start, stop)
      - marks stream_time of buffers (time). This is the stream time of buffers
        with a timestamp of NS.start.
      - marks playback rate (rate). This is the required playback rate.
      - marks applied rate (applied_rate). This is the already applied playback
        rate. (See also part-trickmodes.txt)
+     - marks running_time of buffers. This is the time used to synchronize
+       against the clock.
 
   2) N buffers
-     - displayable buffers are between start/stop of the NEW_SEGMENT. Buffers
+     - displayable buffers are between start/stop of the SEGMENT. Buffers
        outside the segment range should be dropped or clipped.
 
      - running_time: 
index 07d87c8..68ac0f0 100644 (file)
@@ -8,7 +8,7 @@ Synchronisation in a GstPipeline is achieved using the following 3 components:
 
  - a GstClock, which is global for all elements in a GstPipeline.
  - Timestamps on a GstBuffer.
- - the NEW_SEGMENT event preceding the buffers.
+ - the SEGMENT event preceding the buffers.
 
 
 A GstClock
@@ -68,7 +68,7 @@ This value is monotonically increasing at the rate of the clock.
 Timestamps
 ~~~~~~~~~~
  
-The GstBuffer timestamps and the preceeding NEW_SEGMENT event (See
+The GstBuffer timestamps and the preceeding SEGMENT event (See
 part-streams.txt) define a transformation of the buffer timestamps to
 running_time as follows:
 
@@ -77,13 +77,13 @@ The following notation is used:
  B: GstBuffer 
   - B.timestamp = buffer timestamp (GST_BUFFER_TIMESTAMP)
 
- NS:  NEWSEGMENT event preceeding the buffers.
-  - NS.start: start field in the NEWSEGMENT event
-  - NS.stop: stop field in the NEWSEGMENT event
-  - NS.rate: rate field of NEWSEGMENT event
-  - NS.abs_rate: absolute value of rate field of NEWSEGMENT event
-  - NS.time: time field in the NEWSEGMENT event
-  - NS.accum: total accumulated time of all previous NEWSEGMENT events. This
+ NS:  SEGMENT event preceeding the buffers.
+  - NS.start: start field in the SEGMENT event
+  - NS.stop: stop field in the SEGMENT event
+  - NS.rate: rate field of SEGMENT event
+  - NS.abs_rate: absolute value of rate field of SEGMENT event
+  - NS.time: time field in the SEGMENT event
+  - NS.accum: total accumulated time of all previous SEGMENT events. This
               field is kept in the GstSegment structure.
 
 Valid buffers for synchronisation are those with B.timestamp between NS.start
@@ -97,7 +97,7 @@ The following transformation to running_time exist:
     else
       B.running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum
 
-We write B.running_time as the running_time obtained from the NEWSEGMENT event
+We write B.running_time as the running_time obtained from the SEGMENT event
 and the buffers of that segment.
 
 The first displayable buffer will yield a value of 0 (since B.timestamp ==
@@ -120,7 +120,7 @@ As we have seen, we can get a running_time:
 
     C.running_time = absolute_time - base_time
 
- - using the buffer timestamp and the preceeding NEWSEGMENT event as (assuming
+ - using the buffer timestamp and the preceeding SEGMENT event as (assuming
    positive playback rate):
 
     B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
@@ -154,9 +154,9 @@ the sink (See also part-clocks.txt).
 For multiple streams this means that buffers with the same running_time are to
 be displayed at the same time. 
 
-A demuxer must make sure that the NEWSEGMENT it emits on its output pads yield
+A demuxer must make sure that the SEGMENT it emits on its output pads yield
 the same running_time for buffers that should be played synchronized. This
-usually means sending the same NEWSEGMENT on all pads and making sure that the
+usually means sending the same SEGMENT on all pads and making sure that the
 synchronized buffers have the same timestamps.
 
 
@@ -172,7 +172,7 @@ It is the stream time that is used for:
   - the position used in seek events/queries
   - the position used to synchronize controller values
 
-Stream time is calculated using the buffer times and the preceeding NEWSEGMENT
+Stream time is calculated using the buffer times and the preceeding SEGMENT
 event as follows:
 
     stream_time = (B.timestamp - NS.start) * NS.abs_applied_rate + NS.time
index e188ee2..f1bc40e 100644 (file)
@@ -72,12 +72,12 @@ One element will actually perform the seek, this is usually the demuxer or
 source element. For more information on how to perform the different seek
 types see part-seeking.txt.
 
-For client side trickmode a NEW_SEGMENT event will be sent downstream with
+For client side trickmode a SEGMENT event will be sent downstream with
 the new rate and start/stop positions. All elements prepare themselves to
-handle the rate (see below). The applied rate of the NEW_SEGMENT event will
+handle the rate (see below). The applied rate of the SEGMENT event will
 be set to 1.0 to indicate that no rate adjustment has been done.
 
-for server side trick mode a NEW_SEGMENT event is sent downstream with a
+for server side trick mode a SEGMENT event is sent downstream with a
 rate of 1.0 and the start/stop positions. The elements will configure themselves
 for normal playback speed since the server will perform the rate conversions.
 The applied rate will be set to the rate that will be applied by the server. This
@@ -137,16 +137,16 @@ playback speed or direction.
 client side forward trickmodes 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The seek happens as stated above. a NEW_SEGMENT event is sent downstream with a rate
-different from 1.0. Plugins receiving the NEW_SEGMENT can decide to perform the 
+The seek happens as stated above. a SEGMENT event is sent downstream with a rate
+different from 1.0. Plugins receiving the SEGMENT can decide to perform the 
 rate conversion of the media data (retimestamp video frames, resample audio, ...).
 
-If a plugin decides to resample or retimestamp, it should modify the NEW_SEGMENT with
+If a plugin decides to resample or retimestamp, it should modify the SEGMENT with
 a rate of 1.0 and update the applied rate so that downstream elements don't resample
 again but are aware that the media has been modified.
 
 The GStreamer base audio and video sinks will resample automatically if they receive
-a NEW_SEGMENT event with a rate different from 1.0. The position reporting in the
+a SEGMENT event with a rate different from 1.0. The position reporting in the
 base audio and video sinks will also depend on the applied rate of the segment
 information.
 
@@ -162,10 +162,10 @@ client side backwards trickmode
 
 For backwards playback the following rules apply:
 
- - the rate in the NEW_SEGMENT is less than 0.0.
- - the NEW_SEGMENT start position is less than the stop position, playback will
+ - the rate in the SEGMENT is less than 0.0.
+ - the SEGMENT start position is less than the stop position, playback will
    however happen from stop to start in reverse.
- - the time member in the NEW_SEGMENT is set to the stream time of the start
+ - the time member in the SEGMENT is set to the stream time of the start
    position.
 
 For plugins the following rules apply:
@@ -181,12 +181,12 @@ For plugins the following rules apply:
    forward continuous with the previous buffer.
 
  - A video decoder decodes and accumulates all decoded frames. If a buffer with
-   a DISCONT, accumulate NEWSEGMENT or EOS is received, all accumulated frames
-   are sent downsteam in reverse.
+   a DISCONT, SEGMENT or EOS is received, all accumulated frames are sent
+   downsteam in reverse.
 
  - An audio decoder decodes and accumulates all decoded audio. If a buffer with
-   a DISCONT, accumulate NEWSEGMENT or EOS is received, all accumulated audio
-   is sent downstream in reverse order. Some audio codecs need the previous
+   a DISCONT, SEGMENT or EOS is received, all accumulated audio is sent
+   downstream in reverse order. Some audio codecs need the previous
    data buffer to decode the current one, in that case, the previous DISCONT
    buffer needs to be combined with the last non-DISCONT buffer to generate the
    last bit of output.
@@ -201,7 +201,7 @@ For plugins the following rules apply:
  - for transcoding, audio and video resamplers can be used to reverse, resample
    and retimestamp the buffers. Any rate adjustments performed on the media must
    be added to the applied_rate and subtracted from the rate members in the
-   NEWSEGMENT event.
+   SEGMENT event.
 
  In SKIP mode, the same algorithm as for forward SKIP mode can be used.
 
index 395f6b8..4ee7eed 100644 (file)
@@ -154,19 +154,6 @@ how you installed GStreamer (from git, source, packages, which ?)</para></listit
 </itemizedlist>
         </para>
         <para>
-It also is useful for us if you attach output of
-the gst-feedback command to your bug report.
-If you're having problem with a specific application (either one of ours,
-somebody else's, or your own), please also provide a log of gst-mask by
-running
-<programlisting>
-myapp --gst-mask=-1 > mask.log 2>&amp;1
-gzip mask.log
-</programlisting>
-(interrupting the program if it doesn't stop by itself)
-and attach mask.log.gz to your bug report.
-        </para>
-        <para>
 If the application you are having problems with is segfaulting, then
 provide us with the necessary gdb output.  See
 <xref linkend="troubleshooting-segfault" endterm="troubleshooting-segfault"/>
index ca969a1..e350970 100644 (file)
@@ -61,24 +61,26 @@ Windows.  It is released under the GNU Library General Public License
     <xi:include href="xml/gstbin.xml" />
     <xi:include href="xml/gstbuffer.xml" />
     <xi:include href="xml/gstbufferlist.xml" />
+    <xi:include href="xml/gstbufferpool.xml" />
     <xi:include href="xml/gstbus.xml" />
     <xi:include href="xml/gstcaps.xml" />
+    <xi:include href="xml/gstsample.xml" />
     <xi:include href="xml/gstchildproxy.xml" />
     <xi:include href="xml/gstclock.xml" />
     <xi:include href="xml/gstconfig.xml" />
+    <xi:include href="xml/gstcontrolbinding.xml" />
+    <xi:include href="xml/gstcontrolsource.xml" />
     <xi:include href="xml/gstdatetime.xml" />
     <xi:include href="xml/gstelement.xml" />
     <xi:include href="xml/gstelementfactory.xml" />
     <xi:include href="xml/gsterror.xml" />
     <xi:include href="xml/gstevent.xml" />
-    <xi:include href="xml/gstfilter.xml" />
     <xi:include href="xml/gstformat.xml" />
     <xi:include href="xml/gstghostpad.xml" />
-    <xi:include href="xml/gstimplementsinterface.xml" />
-    <xi:include href="xml/gstindex.xml" />
-    <xi:include href="xml/gstindexfactory.xml" />
     <xi:include href="xml/gstiterator.xml" />
+    <xi:include href="xml/gstmemory.xml" />
     <xi:include href="xml/gstmessage.xml" />
+    <xi:include href="xml/gstmeta.xml" />
     <xi:include href="xml/gstminiobject.xml" />
     <xi:include href="xml/gstobject.xml" />
     <xi:include href="xml/gstpad.xml" />
@@ -105,7 +107,6 @@ Windows.  It is released under the GNU Library General Public License
     <xi:include href="xml/gstutils.xml" />
     <xi:include href="xml/gstvalue.xml" />
     <xi:include href="xml/gstversion.xml" />
-    <xi:include href="xml/gstxml.xml" />
 
   </chapter>
 
index 58be88d..8fffedf 100644 (file)
@@ -81,7 +81,6 @@ gst_bin_recalculate_latency
 gst_bin_add_many
 gst_bin_remove_many
 gst_bin_find_unlinked_pad
-gst_bin_find_unconnected_pad
 
 <SUBSECTION>
 GstBinFlags
@@ -158,25 +157,22 @@ GstBusPrivate
 <FILE>gstbuffer</FILE>
 <TITLE>GstBuffer</TITLE>
 GstBuffer
-GstBufferFlag
+GstBufferFlags
 GstBufferCopyFlags
 GST_BUFFER_FLAGS
 GST_BUFFER_FLAG_IS_SET
 GST_BUFFER_FLAG_SET
 GST_BUFFER_FLAG_UNSET
 
-GST_BUFFER_DATA
-GST_BUFFER_MALLOCDATA
-GST_BUFFER_FREE_FUNC
-GST_BUFFER_SIZE
-GST_BUFFER_TIMESTAMP
+GST_BUFFER_PTS
+GST_BUFFER_DTS
 GST_BUFFER_DURATION
-GST_BUFFER_CAPS
 GST_BUFFER_OFFSET
 GST_BUFFER_OFFSET_END
 GST_BUFFER_OFFSET_NONE
 GST_BUFFER_DURATION_IS_VALID
-GST_BUFFER_TIMESTAMP_IS_VALID
+GST_BUFFER_PTS_IS_VALID
+GST_BUFFER_DTS_IS_VALID
 GST_BUFFER_OFFSET_IS_VALID
 GST_BUFFER_OFFSET_END_IS_VALID
 GST_BUFFER_IS_DISCONT
@@ -184,101 +180,163 @@ GST_BUFFER_TRACE_NAME
 
 gst_buffer_new
 gst_buffer_new_and_alloc
-gst_buffer_try_new_and_alloc
+gst_buffer_new_allocate
+gst_buffer_new_wrapped
+gst_buffer_new_wrapped_full
 
 gst_buffer_ref
 gst_buffer_unref
 
-gst_buffer_set_data
-gst_buffer_copy
+gst_buffer_get_sizes
+gst_buffer_get_size
+gst_buffer_resize
+gst_buffer_set_size
+
+gst_buffer_n_memory
+gst_buffer_take_memory
+gst_buffer_peek_memory
+gst_buffer_remove_memory
+gst_buffer_remove_memory_range
+
+gst_buffer_join
+gst_buffer_merge
 
+gst_buffer_map
+gst_buffer_unmap
+
+gst_buffer_memcmp
+gst_buffer_extract
+gst_buffer_fill
+gst_buffer_memset
+
+GST_BUFFER_COPY_METADATA
 GST_BUFFER_COPY_ALL
-gst_buffer_copy_metadata
+gst_buffer_copy
+gst_buffer_copy_into
+gst_buffer_copy_region
+
 gst_buffer_is_writable
 gst_buffer_make_writable
-gst_buffer_is_metadata_writable
-gst_buffer_make_metadata_writable
 gst_buffer_replace
 
-gst_buffer_set_qdata
-gst_buffer_get_qdata
-
-gst_buffer_get_caps
-gst_buffer_set_caps
-
-gst_buffer_create_sub
 gst_buffer_is_span_fast
 gst_buffer_span
 
-gst_buffer_stamp
-gst_buffer_join
-gst_buffer_merge
+gst_buffer_get_meta
+gst_buffer_add_meta
+gst_buffer_remove_meta
+gst_buffer_iterate_meta
 
 <SUBSECTION Standard>
 GstBufferClass
 GST_BUFFER
-GST_BUFFER_CLASS
-GST_BUFFER_GET_CLASS
 GST_IS_BUFFER
-GST_IS_BUFFER_CLASS
 GST_TYPE_BUFFER
-GST_TYPE_BUFFER_FLAG
+GST_TYPE_BUFFER_FLAGS
 GST_TYPE_BUFFER_COPY_FLAGS
 GST_BUFFER_CAST
 <SUBSECTION Private>
 gst_buffer_get_type
-gst_buffer_flag_get_type
+gst_buffer_flags_get_type
 gst_buffer_copy_flags_get_type
 </SECTION>
 
 <SECTION>
+<FILE>gstmeta</FILE>
+<TITLE>GstMeta</TITLE>
+GstMeta
+GstMetaFlags
+GST_META_FLAGS
+GST_META_FLAG_IS_SET
+GST_META_FLAG_SET
+GST_META_FLAG_UNSET
+GstMetaInfo
+GstMetaInitFunction
+GstMetaFreeFunction
+GstMetaCopyFunction
+GstMetaTransformFunction
+gst_meta_register
+gst_meta_get_info
+<SUBSECTION Standard>
+GST_META_CAST
+GST_META_TRACE_NAME
+<SUBSECTION Private>
+GST_TYPE_META_FLAGS
+gst_meta_flags_get_type
+</SECTION>
+
+
+<SECTION>
+<FILE>gstbufferpool</FILE>
+<TITLE>GstBufferPool</TITLE>
+GstBufferPool
+GstBufferPoolClass
+GstBufferPoolFlags
+GST_BUFFER_POOL_IS_FLUSHING
+GstBufferPoolParams
+gst_buffer_pool_new
+
+gst_buffer_pool_config_get
+gst_buffer_pool_config_set
+
+gst_buffer_pool_config_add_option
+gst_buffer_pool_config_get_option
+gst_buffer_pool_config_has_option
+gst_buffer_pool_config_n_options
+gst_buffer_pool_get_options
+gst_buffer_pool_has_option
+
+gst_buffer_pool_get_config
+gst_buffer_pool_set_config
+
+gst_buffer_pool_set_active
+gst_buffer_pool_is_active
+
+gst_buffer_pool_acquire_buffer
+gst_buffer_pool_release_buffer
+<SUBSECTION Standard>
+GST_BUFFER_POOL_CLASS
+GST_BUFFER_POOL_CAST
+GST_BUFFER_POOL_TRACE_NAME
+GstBufferPoolPrivate
+GST_BUFFER_POOL
+GST_IS_BUFFER_POOL
+GST_TYPE_BUFFER_POOL
+gst_buffer_pool_get_type
+GST_TYPE_BUFFER_POOL_FLAGS
+gst_buffer_pool_flags_get_type
+GST_IS_BUFFER_POOL_CLASS
+GST_BUFFER_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
 <FILE>gstbufferlist</FILE>
 <TITLE>GstBufferList</TITLE>
 GstBufferList
-GstBufferListIterator
-GstBufferListDoFunction
 
 gst_buffer_list_new
+gst_buffer_list_new_sized
+gst_buffer_list_length
+gst_buffer_list_add
+gst_buffer_list_insert
+gst_buffer_list_remove
+
 gst_buffer_list_ref
 gst_buffer_list_unref
 gst_buffer_list_copy
 gst_buffer_list_is_writable
 gst_buffer_list_make_writable
 
-gst_buffer_list_n_groups
-
-GstBufferListItem
 GstBufferListFunc
 gst_buffer_list_foreach
 gst_buffer_list_get
 
-gst_buffer_list_iterate
-gst_buffer_list_iterator_free
-gst_buffer_list_iterator_n_buffers
-gst_buffer_list_iterator_add
-gst_buffer_list_iterator_add_group
-gst_buffer_list_iterator_add_list
-gst_buffer_list_iterator_next
-gst_buffer_list_iterator_next_group
-gst_buffer_list_iterator_remove
-gst_buffer_list_iterator_steal
-gst_buffer_list_iterator_take
-gst_buffer_list_iterator_do
-gst_buffer_list_iterator_merge_group
 <SUBSECTION Standard>
-GstBufferListClass
 GST_BUFFER_LIST
-GST_BUFFER_LIST_CLASS
-GST_BUFFER_LIST_GET_CLASS
 GST_IS_BUFFER_LIST
-GST_IS_BUFFER_LIST_CLASS
 GST_TYPE_BUFFER_LIST
 GST_BUFFER_LIST_CAST
-GST_TYPE_BUFFER_LIST_ITEM
-GST_TYPE_BUFFER_LIST_ITERATOR
 <SUBSECTION Private>
-gst_buffer_list_item_get_type
-gst_buffer_list_iterator_get_type
 gst_buffer_list_get_type
 </SECTION>
 
@@ -297,17 +355,22 @@ GST_CAPS_REFCOUNT_VALUE
 GST_STATIC_CAPS_ANY
 GST_STATIC_CAPS_NONE
 GST_CAPS_IS_SIMPLE
-GST_DEBUG_CAPS
 GST_STATIC_CAPS
+GST_CAPS_FLAGS
+GST_CAPS_FLAG_IS_SET
+GST_CAPS_FLAG_SET
+GST_CAPS_FLAG_UNSET
 
 gst_caps_new_empty
 gst_caps_new_any
 gst_caps_new_simple
 gst_caps_new_full
 gst_caps_new_full_valist
+gst_caps_is_writable
 gst_caps_copy
 gst_caps_copy_nth
 gst_static_caps_get
+gst_static_caps_cleanup
 gst_caps_append
 gst_caps_merge
 gst_caps_append_structure
@@ -333,8 +396,6 @@ gst_caps_intersect_full
 gst_caps_union
 gst_caps_normalize
 gst_caps_do_simplify
-gst_caps_save_thyself
-gst_caps_load_thyself
 gst_caps_replace
 gst_caps_to_string
 gst_caps_from_string
@@ -342,6 +403,7 @@ gst_caps_subtract
 gst_caps_make_writable
 gst_caps_ref
 gst_caps_truncate
+gst_caps_fixate
 gst_caps_unref
 <SUBSECTION Standard>
 GST_CAPS
@@ -349,6 +411,7 @@ GST_IS_CAPS
 GST_TYPE_CAPS
 GST_TYPE_CAPS_FLAGS
 GST_TYPE_CAPS_INTERSECT_MODE
+GST_CAPS_CAST
 <SUBSECTION Private>
 gst_caps_flags_get_type
 gst_caps_get_type
@@ -356,6 +419,29 @@ gst_caps_intersect_mode_get_type
 </SECTION>
 
 <SECTION>
+<FILE>gstsample</FILE>
+<TITLE>GstSample</TITLE>
+GstSample
+gst_sample_get_buffer
+gst_sample_get_caps
+gst_sample_get_info
+gst_sample_get_segment
+gst_sample_new
+gst_sample_ref
+gst_sample_unref
+gst_value_get_sample
+gst_value_set_sample
+gst_value_take_sample
+<SUBSECTION Standard>
+GST_SAMPLE_TRACE_NAME
+GST_IS_SAMPLE
+GST_SAMPLE
+GST_TYPE_SAMPLE
+gst_sample_get_type
+GST_SAMPLE_CAST
+</SECTION>
+
+<SECTION>
 <FILE>gstchildproxy</FILE>
 <TITLE>GstChildProxy</TITLE>
 GstChildProxy
@@ -472,21 +558,26 @@ gst_clock_return_get_type
 <FILE>gstcompat</FILE>
 <TITLE>GstCompat</TITLE>
 <SUBSECTION Standard>
+gst_element_class_set_details_simple
+gst_element_factory_get_author
+gst_element_factory_get_description
+gst_element_factory_get_documentation_uri
+gst_element_factory_get_icon_name
+gst_element_factory_get_klass
+gst_element_factory_get_longname
 <SUBSECTION Private>
 </SECTION>
 
+
 <SECTION>
 <FILE>gstconfig</FILE>
 GST_DISABLE_GST_DEBUG
-GST_DISABLE_LOADSAVE
 GST_DISABLE_PARSE
 GST_DISABLE_TRACE
 GST_DISABLE_ALLOC_TRACE
 GST_DISABLE_REGISTRY
 GST_DISABLE_PLUGIN
-GST_DISABLE_XML
 <SUBSECTION Private>
-GST_DISABLE_LOADSAVE_REGISTRY
 GST_HAVE_GLIB_2_8
 GST_PTR_FORMAT
 GST_SEGMENT_FORMAT
@@ -498,6 +589,51 @@ GST_PADDING_INIT
 GST_USING_PRINTF_EXTENSION
 </SECTION>
 
+
+<SECTION>
+<FILE>gstcontrolbinding</FILE>
+<TITLE>GstControlBinding</TITLE>
+GstControlBinding
+GstControlBindingClass
+GstControlBindingConvert
+gst_control_binding_sync_values
+gst_control_binding_get_value
+gst_control_binding_get_value_array
+gst_control_binding_set_disabled
+gst_control_binding_is_disabled
+<SUBSECTION Standard>
+GST_CONTROL_BINDING
+GST_IS_CONTROL_BINDING
+GST_CONTROL_BINDING_CLASS
+GST_IS_CONTROL_BINDING_CLASS
+GST_CONTROL_BINDING_GET_CLASS
+GST_TYPE_CONTROL_BINDING
+<SUBSECTION Private>
+gst_control_binding_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gstcontrolsource</FILE>
+<TITLE>GstControlSource</TITLE>
+GstControlSource
+GstControlSourceClass
+GstControlSourceGetValue
+GstControlSourceGetValueArray
+GstTimedValue
+gst_control_source_get_value
+gst_control_source_get_value_array
+<SUBSECTION Standard>
+GST_CONTROL_SOURCE
+GST_IS_CONTROL_SOURCE
+GST_CONTROL_SOURCE_CLASS
+GST_IS_CONTROL_SOURCE_CLASS
+GST_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_CONTROL_SOURCE
+<SUBSECTION Private>
+gst_control_source_get_type
+</SECTION>
+
+
 <SECTION>
 <FILE>gstelement</FILE>
 <TITLE>GstElement</TITLE>
@@ -532,19 +668,23 @@ GST_ELEMENT_WARNING
 GST_ELEMENT_INFO
 GST_ELEMENT_IS_LOCKED_STATE
 
+GST_ELEMENT_METADATA_AUTHOR
+GST_ELEMENT_METADATA_DESCRIPTION
+GST_ELEMENT_METADATA_DOC_URI
+GST_ELEMENT_METADATA_ICON_NAME
+GST_ELEMENT_METADATA_KLASS
+GST_ELEMENT_METADATA_LONGNAME
+
 <SUBSECTION element-construction>
 gst_element_class_add_pad_template
 gst_element_class_get_pad_template
 gst_element_class_get_pad_template_list
 gst_element_class_install_std_props
-gst_element_class_set_details
-gst_element_class_set_details_simple
-gst_element_class_set_documentation_uri
-gst_element_class_set_icon_name
+gst_element_class_set_metadata
+gst_element_class_add_metadata
 
 <SUBSECTION element-pads>
 gst_element_add_pad
-gst_element_get_pad
 gst_element_create_all_pads
 gst_element_get_compatible_pad
 gst_element_get_compatible_pad_template
@@ -570,6 +710,7 @@ gst_element_link_pads_filtered
 gst_element_link_filtered
 
 <SUBSECTION element-properties>
+gst_element_class_get_metadata
 gst_element_set_base_time
 gst_element_get_base_time
 gst_element_set_start_time
@@ -577,19 +718,14 @@ gst_element_get_start_time
 gst_element_set_bus
 gst_element_get_bus
 gst_element_get_factory
-gst_element_set_index
-gst_element_get_index
-gst_element_is_indexable
 gst_element_set_name
 gst_element_get_name
 gst_element_set_parent
 gst_element_get_parent
 
 <SUBSECTION element-clocks>
-gst_element_requires_clock
 gst_element_set_clock
 gst_element_get_clock
-gst_element_provides_clock
 gst_element_provide_clock
 
 <SUBSECTION element-states>
@@ -600,22 +736,16 @@ gst_element_is_locked_state
 gst_element_abort_state
 gst_element_continue_state
 gst_element_lost_state
-gst_element_lost_state_full
 gst_element_state_get_name
 gst_element_state_change_return_get_name
 gst_element_sync_state_with_parent
 gst_element_change_state
 
-<SUBSECTION element-tags>
-gst_element_found_tags
-gst_element_found_tags_for_pad
-
 <SUBSECTION element-messages>
 gst_element_message_full
 gst_element_post_message
 
 <SUBSECTION element-query>
-gst_element_get_query_types
 gst_element_query
 gst_element_query_convert
 gst_element_query_position
@@ -661,26 +791,16 @@ gst_state_change_return_get_type
 <FILE>gstelementfactory</FILE>
 <TITLE>GstElementFactory</TITLE>
 GstElementFactory
-GstElementDetails
-GST_ELEMENT_DETAILS
-GST_IS_ELEMENT_DETAILS
 gst_element_register
 gst_element_factory_find
 gst_element_factory_get_element_type
-gst_element_factory_get_longname
-gst_element_factory_get_klass
-gst_element_factory_get_description
-gst_element_factory_get_author
-gst_element_factory_get_documentation_uri
-gst_element_factory_get_icon_name
+gst_element_factory_get_metadata
 gst_element_factory_get_num_pad_templates
 gst_element_factory_get_uri_type
 gst_element_factory_get_uri_protocols
 gst_element_factory_has_interface
 gst_element_factory_create
 gst_element_factory_make
-gst_element_factory_can_sink_caps
-gst_element_factory_can_src_caps
 gst_element_factory_can_sink_all_caps
 gst_element_factory_can_src_all_caps
 gst_element_factory_can_sink_any_caps
@@ -754,13 +874,11 @@ GST_STREAM_ERROR
 GST_ERROR_SYSTEM
 gst_error_get_message
 <SUBSECTION Standard>
-GST_TYPE_G_ERROR
 GST_TYPE_CORE_ERROR
 GST_TYPE_LIBRARY_ERROR
 GST_TYPE_RESOURCE_ERROR
 GST_TYPE_STREAM_ERROR
 <SUBSECTION Private>
-gst_g_error_get_type
 gst_core_error_get_type
 gst_library_error_get_type
 gst_resource_error_get_type
@@ -788,10 +906,12 @@ GST_EVENT_TRACE_NAME
 GST_EVENT_TYPE
 GST_EVENT_TYPE_NAME
 GST_EVENT_TIMESTAMP
-GST_EVENT_SRC
+GST_EVENT_SEQNUM
+
 GST_EVENT_IS_UPSTREAM
 GST_EVENT_IS_DOWNSTREAM
 GST_EVENT_IS_SERIALIZED
+GST_EVENT_IS_STICKY
 
 gst_event_type_get_flags
 gst_event_type_get_name
@@ -801,7 +921,12 @@ gst_event_ref
 gst_event_unref
 gst_event_replace
 gst_event_copy
+gst_event_steal
+gst_event_take
 
+gst_event_is_writable
+gst_event_make_writable
+gst_event_writable_structure
 
 gst_event_new_custom
 gst_event_get_structure
@@ -812,13 +937,13 @@ gst_event_set_seqnum
 
 gst_event_new_flush_start
 gst_event_new_flush_stop
+gst_event_parse_flush_stop
 
 gst_event_new_eos
 
-gst_event_new_new_segment
-gst_event_new_new_segment_full
-gst_event_parse_new_segment
-gst_event_parse_new_segment_full
+gst_event_new_segment
+gst_event_parse_segment
+gst_event_copy_segment
 
 gst_event_new_tag
 gst_event_parse_tag
@@ -828,9 +953,7 @@ gst_event_parse_buffer_size
 
 GstQOSType
 gst_event_new_qos
-gst_event_new_qos_full
 gst_event_parse_qos
-gst_event_parse_qos_full
 
 GstSeekType
 GstSeekFlags
@@ -847,6 +970,11 @@ gst_event_parse_step
 
 gst_event_new_sink_message
 gst_event_parse_sink_message
+
+gst_event_new_reconfigure
+
+gst_event_new_caps
+gst_event_parse_caps
 <SUBSECTION Standard>
 GstEventClass
 GST_EVENT
@@ -863,6 +991,11 @@ GST_TYPE_QOS_TYPE
 GST_TYPE_EVENT_TYPE_FLAGS
 <SUBSECTION Private>
 GST_EVENT_TYPE_SHIFT
+GST_EVENT_MAX_STICKY
+GST_EVENT_NUM_SHIFT
+GST_EVENT_STICKY_IDX
+GST_EVENT_STICKY_IDX_TYPE
+GST_EVENT_STICKY_SHIFT
 FLAG
 gst_event_get_type
 gst_event_type_get_type
@@ -872,15 +1005,6 @@ gst_qos_type_get_type
 gst_event_type_flags_get_type
 </SECTION>
 
-
-<SECTION>
-<FILE>gstfilter</FILE>
-<TITLE>GstFilter</TITLE>
-GstFilterFunc
-gst_filter_run
-</SECTION>
-
-
 <SECTION>
 <FILE>gstformat</FILE>
 <TITLE>GstFormat</TITLE>
@@ -919,30 +1043,20 @@ gst_ghost_pad_get_target
 
 gst_ghost_pad_construct
 
-gst_ghost_pad_setcaps_default
 gst_ghost_pad_unlink_default
 gst_ghost_pad_link_default
-gst_ghost_pad_activate_pull_default
-gst_ghost_pad_activate_push_default
+gst_ghost_pad_activate_mode_default
 
-gst_ghost_pad_internal_activate_push_default
-gst_ghost_pad_internal_activate_pull_default
+gst_ghost_pad_internal_activate_mode_default
 
 gst_proxy_pad_get_internal
 
-gst_proxy_pad_query_type_default
 gst_proxy_pad_event_default
 gst_proxy_pad_query_default
 gst_proxy_pad_iterate_internal_links_default
-gst_proxy_pad_bufferalloc_default
 gst_proxy_pad_chain_default
 gst_proxy_pad_chain_list_default
 gst_proxy_pad_getrange_default
-gst_proxy_pad_checkgetrange_default
-gst_proxy_pad_getcaps_default
-gst_proxy_pad_acceptcaps_default
-gst_proxy_pad_fixatecaps_default
-gst_proxy_pad_setcaps_default
 gst_proxy_pad_unlink_default
 <SUBSECTION Standard>
 GstGhostPadClass
@@ -967,102 +1081,6 @@ gst_ghost_pad_get_type
 
 
 <SECTION>
-<FILE>gstindex</FILE>
-<TITLE>GstIndex</TITLE>
-GstIndex
-GstIndexEntry
-GstIndexGroup
-GstIndexCertainty
-GstIndexEntryType
-GstIndexLookupMethod
-GST_INDEX_NASSOCS
-GST_INDEX_ASSOC_FLAGS
-GST_INDEX_ASSOC_FORMAT
-GST_INDEX_ASSOC_VALUE
-GstIndexAssociation
-GstAssocFlags
-GST_INDEX_FORMAT_FORMAT
-GST_INDEX_FORMAT_KEY
-GST_INDEX_ID_INVALID
-GST_INDEX_ID_DESCRIPTION
-GstIndexFilter
-GstIndexResolverMethod
-GstIndexResolver
-GstIndexFlags
-GST_INDEX_IS_READABLE
-GST_INDEX_IS_WRITABLE
-gst_index_new
-gst_index_commit
-gst_index_get_group
-gst_index_new_group
-gst_index_set_group
-gst_index_set_certainty
-gst_index_get_certainty
-gst_index_set_filter
-gst_index_set_filter_full
-gst_index_set_resolver
-gst_index_set_resolver_full
-gst_index_get_writer_id
-gst_index_add_format
-gst_index_add_association
-gst_index_add_associationv
-gst_index_add_object
-gst_index_add_id
-gst_index_get_assoc_entry
-gst_index_get_assoc_entry_full
-gst_index_entry_copy
-gst_index_entry_free
-gst_index_entry_assoc_map
-<SUBSECTION Standard>
-GstIndexClass
-GST_INDEX
-GST_IS_INDEX
-GST_TYPE_INDEX
-GST_INDEX_CLASS
-GST_IS_INDEX_CLASS
-GST_INDEX_GET_CLASS
-GST_TYPE_INDEX_ENTRY
-GST_TYPE_ASSOC_FLAGS
-GST_TYPE_INDEX_CERTAINTY
-GST_TYPE_INDEX_ENTRY_TYPE
-GST_TYPE_INDEX_FLAGS
-GST_TYPE_INDEX_LOOKUP_METHOD
-GST_TYPE_INDEX_RESOLVER_METHOD
-<SUBSECTION Private>
-gst_index_get_type
-gst_assoc_flags_get_type
-gst_index_certainty_get_type
-gst_index_entry_get_type
-gst_index_entry_type_get_type
-gst_index_flags_get_type
-gst_index_lookup_method_get_type
-gst_index_resolver_method_get_type
-</SECTION>
-
-
-<SECTION>
-<FILE>gstindexfactory</FILE>
-<TITLE>GstIndexFactory</TITLE>
-GstIndexFactory
-gst_index_factory_new
-gst_index_factory_destroy
-gst_index_factory_find
-gst_index_factory_create
-gst_index_factory_make
-<SUBSECTION Standard>
-GstIndexFactoryClass
-GST_INDEX_FACTORY
-GST_IS_INDEX_FACTORY
-GST_INDEX_FACTORY_CLASS
-GST_IS_INDEX_FACTORY_CLASS
-GST_INDEX_FACTORY_GET_CLASS
-GST_TYPE_INDEX_FACTORY
-<SUBSECTION Private>
-gst_index_factory_get_type
-</SECTION>
-
-
-<SECTION>
 <FILE>gstinfo</FILE>
 <TITLE>GstInfo</TITLE>
 GstDebugLevel
@@ -1162,27 +1180,6 @@ gst_debug_graph_details_get_type
 GST_CAT_LEVEL_LOG_valist
 </SECTION>
 
-
-<SECTION>
-<FILE>gstimplementsinterface</FILE>
-<TITLE>GstImplementsInterface</TITLE>
-GstImplementsInterface
-gst_element_implements_interface
-gst_implements_interface_cast
-gst_implements_interface_check
-<SUBSECTION Standard>
-GstImplementsInterfaceClass
-GST_IMPLEMENTS_INTERFACE
-GST_IS_IMPLEMENTS_INTERFACE
-GST_IMPLEMENTS_INTERFACE_GET_CLASS
-GST_TYPE_IMPLEMENTS_INTERFACE
-GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST
-GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE
-<SUBSECTION Private>
-gst_implements_interface_get_type
-</SECTION>
-
-
 <SECTION>
 <FILE>gstiterator</FILE>
 <TITLE>GstIterator</TITLE>
@@ -1191,13 +1188,13 @@ GstIterator
 GstIteratorItem
 GstIteratorResult
 
-GstIteratorDisposeFunction
+GstIteratorCopyFunction
 GstIteratorNextFunction
 GstIteratorItemFunction
 GstIteratorResyncFunction
 GstIteratorFreeFunction
+GstIteratorForeachFunction
 GstIteratorFoldFunction
-GstCopyFunction
 
 GST_ITERATOR
 GST_ITERATOR_LOCK
@@ -1208,9 +1205,11 @@ gst_iterator_new
 gst_iterator_new_list
 gst_iterator_new_single
 
+gst_iterator_copy
+gst_iterator_free
+
 gst_iterator_next
 gst_iterator_resync
-gst_iterator_free
 gst_iterator_push
 gst_iterator_filter
 gst_iterator_fold
@@ -1218,15 +1217,69 @@ gst_iterator_foreach
 gst_iterator_find_custom
 
 <SUBSECTION Standard>
+GST_TYPE_ITERATOR
 GST_TYPE_ITERATOR_ITEM
 GST_TYPE_ITERATOR_RESULT
 <SUBSECTION Private>
+gst_iterator_get_type
 gst_iterator_item_get_type
 gst_iterator_result_get_type
 </SECTION>
 
 
 <SECTION>
+<FILE>gstmemory</FILE>
+<TITLE>GstMemory</TITLE>
+GstMemory
+GstMemoryInfo
+GstAllocator
+GstMemoryFlags
+GstMapFlags
+GST_MAP_READWRITE
+GstMemoryAllocFunction
+GstMemoryMapFunction
+GstMemoryUnmapFunction
+GstMemoryFreeFunction
+GstMemoryCopyFunction
+GstMemoryShareFunction
+GstMemoryIsSpanFunction
+
+gst_memory_alignment
+
+gst_allocator_alloc
+gst_memory_new_wrapped
+
+gst_memory_ref
+gst_memory_unref
+
+gst_memory_get_sizes
+gst_memory_resize
+
+gst_memory_is_writable
+
+gst_memory_map
+gst_memory_unmap
+
+gst_memory_copy
+gst_memory_share
+
+gst_memory_is_span
+
+GST_ALLOCATOR_SYSMEM
+gst_allocator_find
+gst_allocator_register
+gst_allocator_set_default
+<SUBSECTION Standard>
+GST_TYPE_MEMORY
+GST_MEMORY_TRACE_NAME
+GST_TYPE_MAP_FLAGS
+GST_TYPE_MEMORY_FLAGS
+gst_map_flags_get_type
+gst_memory_flags_get_type
+gst_memory_get_type
+</SECTION>
+
+<SECTION>
 <FILE>gstmessage</FILE>
 <TITLE>GstMessage</TITLE>
 GstMessage
@@ -1234,6 +1287,7 @@ GstMessageType
 GST_MESSAGE_SRC
 GST_MESSAGE_SRC_NAME
 GST_MESSAGE_TIMESTAMP
+GST_MESSAGE_SEQNUM
 GST_MESSAGE_TYPE
 GST_MESSAGE_TYPE_NAME
 GST_MESSAGE_TRACE_NAME
@@ -1246,6 +1300,9 @@ gst_message_get_structure
 gst_message_make_writable
 gst_message_get_seqnum
 gst_message_set_seqnum
+gst_message_has_name
+gst_message_is_writable
+gst_message_replace
 
 gst_message_new_eos
 gst_message_new_error
@@ -1255,9 +1312,7 @@ gst_message_parse_warning
 gst_message_new_info
 gst_message_parse_info
 gst_message_new_tag
-gst_message_new_tag_full
 gst_message_parse_tag
-gst_message_parse_tag_full
 gst_message_new_buffering
 gst_message_parse_buffering
 gst_message_set_buffering_stats
@@ -1284,8 +1339,8 @@ gst_message_new_duration
 gst_message_parse_duration
 gst_message_new_latency
 gst_message_new_async_start
-gst_message_parse_async_start
 gst_message_new_async_done
+gst_message_parse_async_done
 gst_message_new_step_start
 gst_message_parse_step_start
 gst_message_new_qos
@@ -1345,55 +1400,45 @@ GST_MESSAGE_WAIT
 GstMiniObject
 GstMiniObjectFlags
 GstMiniObjectCopyFunction
-GstMiniObjectFinalizeFunction
+GstMiniObjectDisposeFunction
+GstMiniObjectFreeFunction
 GstMiniObjectWeakNotify
 
+GST_MINI_OBJECT_TYPE
 GST_MINI_OBJECT_FLAGS
 GST_MINI_OBJECT_FLAG_IS_SET
 GST_MINI_OBJECT_FLAG_SET
 GST_MINI_OBJECT_FLAG_UNSET
 GST_MINI_OBJECT_REFCOUNT
 GST_MINI_OBJECT_REFCOUNT_VALUE
+GST_MINI_OBJECT_SIZE
+
+GST_DEFINE_MINI_OBJECT_TYPE
+gst_mini_object_init
 
-gst_mini_object_new
 gst_mini_object_copy
 gst_mini_object_is_writable
 gst_mini_object_make_writable
 
 gst_mini_object_ref
 gst_mini_object_unref
-gst_mini_object_replace
 
 gst_mini_object_weak_ref
 gst_mini_object_weak_unref
 
-GstParamSpecMiniObject
-gst_param_spec_mini_object
-
-gst_value_set_mini_object
-gst_value_take_mini_object
-gst_value_get_mini_object
-gst_value_dup_mini_object
+gst_mini_object_replace
+gst_mini_object_steal
+gst_mini_object_take
 
 <SUBSECTION Standard>
-GstMiniObjectClass
 GST_MINI_OBJECT
-GST_IS_MINI_OBJECT
-GST_MINI_OBJECT_CLASS
-GST_IS_MINI_OBJECT_CLASS
-GST_MINI_OBJECT_GET_CLASS
-GST_TYPE_MINI_OBJECT
+GST_IS_MINI_OBJECT_TYPE
 GST_TYPE_MINI_OBJECT_FLAGS
 GST_MINI_OBJECT_CAST
 GST_MINI_OBJECT_CONST_CAST
 
-GST_IS_PARAM_SPEC_MINI_OBJECT
-GST_PARAM_SPEC_MINI_OBJECT
-GST_TYPE_PARAM_MINI_OBJECT
 <SUBSECTION Private>
-gst_mini_object_get_type
 gst_mini_object_flags_get_type
-gst_param_spec_mini_object_get_type
 </SECTION>
 
 
@@ -1409,14 +1454,8 @@ GST_OBJECT_FLAG_SET
 GST_OBJECT_FLAG_UNSET
 GST_OBJECT_NAME
 GST_OBJECT_PARENT
-GST_OBJECT_IS_DISPOSING
-GST_OBJECT_IS_FLOATING
 GST_OBJECT_REFCOUNT
 GST_OBJECT_REFCOUNT_VALUE
-GST_CLASS_GET_LOCK
-GST_CLASS_LOCK
-GST_CLASS_TRYLOCK
-GST_CLASS_UNLOCK
 GST_OBJECT_LOCK
 GST_OBJECT_TRYLOCK
 GST_OBJECT_UNLOCK
@@ -1427,22 +1466,29 @@ gst_object_get_name
 gst_object_set_parent
 gst_object_get_parent
 gst_object_unparent
-gst_object_get_name_prefix
-gst_object_set_name_prefix
 gst_object_default_deep_notify
 gst_object_default_error
 gst_object_check_uniqueness
 gst_object_has_ancestor
-gst_object_save_thyself
-gst_object_restore_thyself
 gst_object_ref
 gst_object_unref
 gst_object_ref_sink
-gst_object_sink
 gst_object_replace
 gst_object_get_path_string
-gst_class_signal_connect
-gst_class_signal_emit_by_name
+
+gst_object_suggest_next_sync
+gst_object_sync_values
+gst_object_has_active_control_bindings
+gst_object_set_control_bindings_disabled
+gst_object_set_control_binding_disabled
+gst_object_add_control_binding
+gst_object_get_control_binding
+gst_object_remove_control_binding
+gst_object_get_value
+gst_object_get_value_array
+gst_object_get_control_rate
+gst_object_set_control_rate
+
 <SUBSECTION Standard>
 GST_OBJECT
 GST_IS_OBJECT
@@ -1456,7 +1502,6 @@ GST_OBJECT_CLASS_CAST
 <SUBSECTION Private>
 gst_object_get_type
 gst_object_flags_get_type
-GstXmlNodePtr
 </SECTION>
 
 
@@ -1473,7 +1518,11 @@ GST_PAD_LINK_SUCCESSFUL
 GstPadLinkCheck
 GST_PAD_LINK_CHECK_DEFAULT
 GstFlowReturn
-GstActivateMode
+GstPadMode
+GstPadProbeReturn
+GstPadProbeType
+GST_PAD_PROBE_TYPE_BLOCKING
+GST_PAD_PROBE_TYPE_SCHEDULING
 
 <SUBSECTION Application>
 gst_pad_get_name
@@ -1488,139 +1537,112 @@ gst_pad_unlink
 gst_pad_is_linked
 gst_pad_can_link
 
-gst_pad_get_caps
-gst_pad_get_caps_reffed
 gst_pad_get_allowed_caps
-gst_pad_get_negotiated_caps
+gst_pad_get_current_caps
 gst_pad_get_pad_template_caps
 gst_pad_set_caps
 
 gst_pad_get_peer
-gst_pad_peer_get_caps
-gst_pad_peer_get_caps_reffed
 gst_pad_use_fixed_caps
+gst_pad_has_current_caps
+
+gst_pad_get_sticky_event
+GstPadStickyEventsForeachFunction
+gst_pad_sticky_events_foreach
 
 gst_pad_is_active
 
-gst_pad_set_blocked
-gst_pad_set_blocked_async
-gst_pad_set_blocked_async_full
-GstPadBlockCallback
 gst_pad_is_blocked
 gst_pad_is_blocking
 
-gst_pad_add_data_probe
-gst_pad_add_data_probe_full
-gst_pad_add_buffer_probe
-gst_pad_add_buffer_probe_full
-gst_pad_add_event_probe
-gst_pad_add_event_probe_full
-gst_pad_remove_data_probe
-gst_pad_remove_buffer_probe
-gst_pad_remove_event_probe
+GstPadProbeCallback
+gst_pad_add_probe
+gst_pad_remove_probe
 
+gst_pad_get_offset
+gst_pad_set_offset
 <SUBSECTION Element>
 gst_pad_new
 gst_pad_new_from_template
 gst_pad_new_from_static_template
 
-gst_pad_alloc_buffer
-gst_pad_alloc_buffer_and_set_caps
-gst_pad_set_bufferalloc_function
-GstPadBufferAllocFunction
-
 gst_pad_set_chain_function
+gst_pad_set_chain_function_full
 GstPadChainFunction
 
 gst_pad_set_chain_list_function
+gst_pad_set_chain_list_function_full
 GstPadChainListFunction
 
-gst_pad_set_checkgetrange_function
-GstPadCheckGetRangeFunction
-
 gst_pad_get_range
 gst_pad_set_getrange_function
+gst_pad_set_getrange_function_full
 GstPadGetRangeFunction
 
 gst_pad_set_event_function
+gst_pad_set_event_function_full
 GstPadEventFunction
 
 gst_pad_set_link_function
+gst_pad_set_link_function_full
 GstPadLinkFunction
 gst_pad_set_unlink_function
+gst_pad_set_unlink_function_full
 GstPadUnlinkFunction
 
-gst_pad_accept_caps
-gst_pad_set_acceptcaps_function
-GstPadAcceptCapsFunction
-
-gst_pad_set_getcaps_function
-GstPadGetCapsFunction
-gst_pad_proxy_getcaps
-
-gst_pad_set_setcaps_function
-GstPadSetCapsFunction
-gst_pad_proxy_setcaps
-
-gst_pad_fixate_caps
-gst_pad_set_fixatecaps_function
-GstPadFixateCapsFunction
-
-gst_pad_get_fixed_caps_func
-
-gst_pad_peer_accept_caps
+gst_pad_proxy_query_caps
+gst_pad_proxy_query_accept_caps
 
 gst_pad_set_activate_function
+gst_pad_set_activate_function_full
 GstPadActivateFunction
 
-gst_pad_set_activatepush_function
-gst_pad_set_activatepull_function
+gst_pad_set_activatemode_function
+gst_pad_set_activatemode_function_full
 GstPadActivateModeFunction
 
+gst_pad_check_reconfigure
+gst_pad_mark_reconfigure
+
 gst_pad_push
 gst_pad_push_event
 gst_pad_push_list
-gst_pad_check_pull_range
 gst_pad_pull_range
-gst_pad_activate_pull
-gst_pad_activate_push
+gst_pad_activate_mode
 gst_pad_send_event
 gst_pad_event_default
 
 gst_pad_query
 gst_pad_peer_query
+
 gst_pad_query_default
+
 gst_pad_query_position
 gst_pad_query_duration
 gst_pad_query_convert
-gst_pad_query_peer_position
-gst_pad_query_peer_duration
-gst_pad_query_peer_convert
+gst_pad_query_accept_caps
+gst_pad_query_caps
+
+gst_pad_peer_query_position
+gst_pad_peer_query_duration
+gst_pad_peer_query_convert
+gst_pad_peer_query_accept_caps
+gst_pad_peer_query_caps
+
 gst_pad_set_query_function
+gst_pad_set_query_function_full
 GstPadQueryFunction
-gst_pad_set_query_type_function
-GstPadQueryTypeFunction
-gst_pad_get_query_types
-gst_pad_get_query_types_default
-
 gst_pad_set_iterate_internal_links_function
+gst_pad_set_iterate_internal_links_function_full
 GstPadIterIntLinkFunction
 gst_pad_iterate_internal_links
 gst_pad_iterate_internal_links_default
 
-gst_pad_set_internal_link_function
-GstPadIntLinkFunction
-gst_pad_get_internal_links
-gst_pad_get_internal_links_default
-
-gst_pad_load_and_link
-
-gst_pad_dispatcher
-GstPadDispatcherFunction
-
 gst_pad_set_element_private
 gst_pad_get_element_private
 
+GstPadForwardFunction
+gst_pad_forward
 <SUBSECTION Core>
 gst_pad_chain
 gst_pad_chain_list
@@ -1631,17 +1653,10 @@ gst_pad_stop_task
 
 gst_pad_set_active
 
-GST_PAD_CAPS
-
 GST_PAD_GET_STREAM_LOCK
 GST_PAD_STREAM_LOCK
-GST_PAD_STREAM_LOCK_FULL
 GST_PAD_STREAM_TRYLOCK
 GST_PAD_STREAM_UNLOCK
-GST_PAD_STREAM_UNLOCK_FULL
-
-GST_FLOW_IS_FATAL
-GST_FLOW_IS_SUCCESS
 
 <SUBSECTION Standard>
 GstPadClass
@@ -1656,8 +1671,10 @@ GST_TYPE_PAD_FLAGS
 GST_TYPE_PAD_LINK_RETURN
 GST_TYPE_PAD_LINK_CHECK
 GST_TYPE_PAD_PRESENCE
+GST_TYPE_PAD_MODE
 GST_TYPE_FLOW_RETURN
-GST_TYPE_ACTIVATE_MODE
+GST_TYPE_PROBE_RETURN
+GST_TYPE_PROBE_TYPE
 
 <SUBSECTION Private>
 gst_pad_get_type
@@ -1667,7 +1684,9 @@ gst_pad_link_return_get_type
 gst_pad_link_check_get_type
 gst_pad_presence_get_type
 gst_flow_return_get_type
-gst_activate_mode_get_type
+gst_pad_mode_get_type
+gst_probe_return_get_type
+gst_probe_type_get_type
 
 GST_PAD_NAME
 GST_PAD_PARENT
@@ -1678,6 +1697,9 @@ GST_PAD_PEER
 GST_PAD_IS_LINKED
 GST_PAD_IS_SRC
 GST_PAD_IS_SINK
+GST_PAD_IS_FIXED_CAPS
+GST_PAD_NEEDS_EVENTS
+GST_PAD_NEEDS_RECONFIGURE
 
 GST_PAD_IS_IN_GETCAPS
 GST_PAD_MODE_ACTIVATE
@@ -1686,7 +1708,7 @@ GST_PAD_BLOCK_GET_COND
 GST_PAD_BLOCK_SIGNAL
 GST_PAD_BLOCK_WAIT
 GST_PAD_CAST
-GST_PAD_ACTIVATE_MODE
+GST_PAD_MODE
 GST_PAD_DO_BUFFER_SIGNALS
 GST_PAD_DO_EVENT_SIGNALS
 GST_PAD_IS_BLOCKED
@@ -1696,35 +1718,20 @@ GST_PAD_SET_FLUSHING
 GST_PAD_TASK
 GST_PAD_UNSET_FLUSHING
 
-GST_PAD_ACCEPTCAPSFUNC
+GST_PAD_IS_ACTIVE
 GST_PAD_ACTIVATEFUNC
-GST_PAD_ACTIVATEPULLFUNC
-GST_PAD_ACTIVATEPUSHFUNC
-GST_PAD_BUFFERALLOCFUNC
+GST_PAD_ACTIVATEMODEFUNC
+
 GST_PAD_CHAINFUNC
-GST_PAD_CHECKGETRANGEFUNC
+GST_PAD_CHAINLISTFUNC
 GST_PAD_EVENTFUNC
-GST_PAD_FIXATECAPSFUNC
-GST_PAD_GETCAPSFUNC
 GST_PAD_GETRANGEFUNC
-GST_PAD_INTLINKFUNC
 GST_PAD_ITERINTLINKFUNC
 GST_PAD_IS_FLUSHING
 GST_PAD_LINKFUNC
+GST_PAD_UNLINKFUNC
 GST_PAD_QUERYFUNC
 GST_PAD_QUERYTYPEFUNC
-GST_PAD_SETCAPSFUNC
-GST_PAD_UNLINKFUNC
-
-GST_PAD_PREROLL_BROADCAST
-GST_PAD_GET_PREROLL_COND
-GST_PAD_GET_PREROLL_LOCK
-GST_PAD_PREROLL_LOCK
-GST_PAD_PREROLL_SIGNAL
-GST_PAD_PREROLL_TIMED_WAIT
-GST_PAD_PREROLL_TRYLOCK
-GST_PAD_PREROLL_UNLOCK
-GST_PAD_PREROLL_WAIT
 </SECTION>
 
 
@@ -1835,9 +1842,6 @@ gst_pipeline_get_clock
 gst_pipeline_use_clock
 gst_pipeline_auto_clock
 
-gst_pipeline_set_new_stream_time
-gst_pipeline_get_last_stream_time
-
 gst_pipeline_set_auto_flush_bus
 gst_pipeline_get_auto_flush_bus
 
@@ -1872,7 +1876,6 @@ GstPluginDesc
 GstPluginInitFunc
 GstPluginInitFullFunc
 GST_PLUGIN_DEFINE
-GST_PLUGIN_DEFINE_STATIC
 GST_LICENSE_UNKNOWN
 GstPluginFilter
 gst_plugin_get_name
@@ -1925,12 +1928,9 @@ gst_plugin_flags_get_type
 <FILE>gstpluginfeature</FILE>
 <TITLE>GstPluginFeature</TITLE>
 GstPluginFeature
-GST_PLUGIN_FEATURE_NAME
-GstTypeNameData
 GstPluginFeatureFilter
 GstRank
 
-gst_plugin_feature_type_name_filter
 gst_plugin_feature_set_rank
 gst_plugin_feature_set_name
 gst_plugin_feature_get_rank
@@ -2029,8 +2029,11 @@ gst_query_ref
 gst_query_unref
 gst_query_copy
 gst_query_make_writable
+gst_query_is_writable
+gst_query_replace
+gst_query_writable_structure
 
-gst_query_new_application
+gst_query_new_custom
 gst_query_get_structure
 
 gst_query_new_convert
@@ -2056,8 +2059,8 @@ gst_query_parse_seeking
 gst_query_new_formats
 gst_query_set_formats
 gst_query_set_formatsv
-gst_query_parse_formats_length
-gst_query_parse_formats_nth
+gst_query_parse_n_formats
+gst_query_parse_nth_format
 
 gst_query_new_segment
 gst_query_set_segment
@@ -2078,6 +2081,22 @@ gst_query_parse_nth_buffering_range
 gst_query_new_uri
 gst_query_parse_uri
 gst_query_set_uri
+
+gst_query_new_allocation
+gst_query_parse_allocation
+gst_query_parse_allocation_params
+gst_query_parse_nth_allocation_memory
+gst_query_parse_nth_allocation_meta
+gst_query_set_allocation_params
+gst_query_add_allocation_memory
+gst_query_add_allocation_meta
+gst_query_has_allocation_meta
+gst_query_get_n_allocation_memories
+gst_query_get_n_allocation_metas
+
+gst_query_new_scheduling
+gst_query_parse_scheduling
+gst_query_set_scheduling
 <SUBSECTION Standard>
 GstQueryClass
 GST_QUERY
@@ -2101,7 +2120,7 @@ gst_buffering_mode_get_type
 <FILE>gstregistry</FILE>
 <TITLE>GstRegistry</TITLE>
 GstRegistry
-gst_registry_get_default
+gst_registry_get
 gst_registry_get_feature_list
 gst_registry_get_feature_list_cookie
 gst_registry_get_feature_list_by_plugin
@@ -2119,16 +2138,7 @@ gst_registry_scan_path
 gst_registry_lookup
 gst_registry_remove_feature
 gst_registry_add_feature
-<SUBSECTION Default Registry>
-gst_default_registry_check_feature_version
-gst_default_registry_get_path_list
-gst_default_registry_add_plugin
-gst_default_registry_add_path
-gst_default_registry_find_plugin
-gst_default_registry_find_feature
-gst_default_registry_get_plugin_list
-gst_default_registry_get_feature_list_cookie
-gst_default_registry_feature_filter
+gst_registry_check_feature_version
 <SUBSECTION Standard>
 GstRegistryClass
 GST_REGISTRY
@@ -2144,8 +2154,6 @@ GST_MAGIC_BINARY_VERSION_STR
 GST_MAGIC_BINARY_VERSION_LEN
 gst_registry_get_type
 GstRegistryPrivate
-gst_registry_xml_read_cache
-gst_registry_xml_write_cache
 </SECTION>
 
 
@@ -2153,23 +2161,23 @@ gst_registry_xml_write_cache
 <FILE>gstsegment</FILE>
 <TITLE>GstSegment</TITLE>
 GstSegment
+GstSegmentFlags
 gst_segment_clip
 gst_segment_init
 gst_segment_new
 gst_segment_copy
 gst_segment_free
-gst_segment_set_duration
-gst_segment_set_last_stop
-gst_segment_set_newsegment
-gst_segment_set_newsegment_full
-gst_segment_set_seek
+gst_segment_do_seek
 gst_segment_to_running_time
 gst_segment_to_stream_time
 gst_segment_to_position
 gst_segment_set_running_time
+gst_segment_copy_into
 <SUBSECTION Standard>
 GST_TYPE_SEGMENT
+GST_TYPE_SEGMENT_FLAGS
 gst_segment_get_type
+gst_segment_flags_get_type
 <SUBSECTION Private>
 </SECTION>
 
@@ -2180,11 +2188,11 @@ gst_segment_get_type
 GstStructure
 GstStructureForeachFunc
 GstStructureMapFunc
-gst_structure_empty_new
-gst_structure_id_empty_new
+gst_structure_new_empty
+gst_structure_new_id_empty
 gst_structure_new
 gst_structure_new_valist
-gst_structure_id_new
+gst_structure_new_id
 gst_structure_copy
 gst_structure_free
 gst_structure_get_name
@@ -2223,7 +2231,6 @@ gst_structure_id_has_field_typed
 gst_structure_get_boolean
 gst_structure_get_int
 gst_structure_get_uint
-gst_structure_get_fourcc
 gst_structure_get_double
 gst_structure_get_string
 gst_structure_get_date
@@ -2236,6 +2243,8 @@ gst_structure_nth_field_name
 gst_structure_set_parent_refcount
 gst_structure_to_string
 gst_structure_from_string
+gst_structure_fixate
+gst_structure_fixate_field
 gst_structure_fixate_field_nearest_int
 gst_structure_fixate_field_nearest_double
 gst_structure_fixate_field_nearest_fraction
@@ -2243,6 +2252,7 @@ gst_structure_fixate_field_boolean
 gst_structure_fixate_field_string
 <SUBSECTION Standard>
 GST_STRUCTURE
+GST_STRUCTURE_CAST
 GST_IS_STRUCTURE
 GST_TYPE_STRUCTURE
 <SUBSECTION Private>
@@ -2370,8 +2380,8 @@ gst_tag_get_description
 gst_tag_get_flag
 gst_tag_is_fixed
 gst_tag_list_new
-gst_tag_list_new_full
-gst_tag_list_new_full_valist
+gst_tag_list_new_empty
+gst_tag_list_new_valist
 gst_tag_list_new_from_string
 gst_tag_list_to_string
 gst_is_tag_list
@@ -2382,6 +2392,8 @@ gst_tag_list_insert
 gst_tag_list_merge
 gst_tag_list_free
 gst_tag_list_get_tag_size
+gst_tag_list_n_tags
+gst_tag_list_nth_tag_name
 gst_tag_list_add
 gst_tag_list_add_value
 gst_tag_list_add_values
@@ -2391,20 +2403,12 @@ gst_tag_list_remove_tag
 gst_tag_list_foreach
 gst_tag_list_get_value_index
 gst_tag_list_copy_value
-gst_tag_list_get_char
-gst_tag_list_get_char_index
-gst_tag_list_get_uchar
-gst_tag_list_get_uchar_index
 gst_tag_list_get_boolean
 gst_tag_list_get_boolean_index
 gst_tag_list_get_int
 gst_tag_list_get_int_index
 gst_tag_list_get_uint
 gst_tag_list_get_uint_index
-gst_tag_list_get_long
-gst_tag_list_get_long_index
-gst_tag_list_get_ulong
-gst_tag_list_get_ulong_index
 gst_tag_list_get_int64
 gst_tag_list_get_int64_index
 gst_tag_list_get_uint64
@@ -2443,7 +2447,7 @@ gst_tag_merge_mode_get_type
 <FILE>gsttagsetter</FILE>
 <TITLE>GstTagSetter</TITLE>
 GstTagSetter
-GstTagSetterIFace
+GstTagSetterInterface
 gst_tag_setter_reset_tags
 gst_tag_setter_merge_tags
 gst_tag_setter_add_tags
@@ -2457,7 +2461,7 @@ gst_tag_setter_get_tag_merge_mode
 <SUBSECTION Standard>
 GST_TAG_SETTER
 GST_IS_TAG_SETTER
-GST_TAG_SETTER_GET_IFACE
+GST_TAG_SETTER_GET_INTERFACE
 GST_TYPE_TAG_SETTER
 <SUBSECTION Private>
 gst_tag_setter_get_type
@@ -2501,7 +2505,7 @@ GST_TASK_SIGNAL
 GST_TASK_STATE
 GST_TASK_WAIT
 
-gst_task_create
+gst_task_new
 gst_task_set_lock
 gst_task_set_priority
 
@@ -2634,7 +2638,6 @@ gst_uri_handler_get_uri_type
 gst_uri_handler_get_protocols
 gst_uri_handler_get_uri
 gst_uri_handler_set_uri
-gst_uri_handler_new_uri
 <SUBSECTION Standard>
 GST_URI_HANDLER
 GST_IS_URI_HANDLER
@@ -2650,21 +2653,8 @@ gst_uri_type_get_type
 <SECTION>
 <FILE>gstutils</FILE>
 <TITLE>GstUtils</TITLE>
-GST_BOILERPLATE_WITH_INTERFACE
-GST_BOILERPLATE_FULL
-GST_BOILERPLATE
 GST_CALL_PARENT
 GST_CALL_PARENT_WITH_DEFAULT
-GDOUBLE_FROM_BE
-GDOUBLE_FROM_LE
-GDOUBLE_TO_BE
-GDOUBLE_TO_LE
-GDOUBLE_SWAP_LE_BE
-GFLOAT_FROM_BE
-GFLOAT_FROM_LE
-GFLOAT_TO_BE
-GFLOAT_TO_LE
-GFLOAT_SWAP_LE_BE
 GST_READ_UINT8
 GST_READ_UINT16_LE
 GST_READ_UINT16_BE
@@ -2703,15 +2693,24 @@ GST_ROUND_DOWN_8
 GST_ROUND_DOWN_16
 GST_ROUND_DOWN_32
 GST_ROUND_DOWN_64
+GDOUBLE_FROM_BE
+GDOUBLE_FROM_LE
+GDOUBLE_SWAP_LE_BE
+GDOUBLE_TO_BE
+GDOUBLE_TO_LE
+GFLOAT_FROM_BE
+GFLOAT_FROM_LE
+GFLOAT_SWAP_LE_BE
+GFLOAT_TO_BE
+GFLOAT_TO_LE
+
 
-gst_atomic_int_set
 gst_flow_get_name
 gst_flow_to_quark
 gst_print_element_args
 gst_print_pad_caps
 gst_guint64_to_gdouble
 gst_gdouble_to_guint64
-gst_type_register_static_full
 gst_util_dump_mem
 gst_util_uint64_scale
 gst_util_uint64_scale_round
@@ -2768,14 +2767,10 @@ gst_date_time_unref
 <TITLE>GstValue</TITLE>
 
 <SUBSECTION fourcc>
-GST_VALUE_HOLDS_FOURCC
 GST_MAKE_FOURCC
 GST_STR_FOURCC
 GST_FOURCC_FORMAT
 GST_FOURCC_ARGS
-GST_TYPE_FOURCC
-gst_value_set_fourcc
-gst_value_get_fourcc
 
 <SUBSECTION intrange>
 GST_VALUE_HOLDS_INT_RANGE
@@ -2827,12 +2822,6 @@ gst_value_get_fraction_range_min
 gst_value_get_fraction_range_max
 gst_value_set_fraction_range_full
 
-<SUBSECTION date>
-GST_VALUE_HOLDS_DATE
-GST_TYPE_DATE
-gst_value_set_date
-gst_value_get_date
-
 <SUBSECTION datetime>
 GST_VALUE_HOLDS_DATE_TIME
 
@@ -2846,9 +2835,7 @@ GST_VALUE_HOLDS_STRUCTURE
 gst_value_set_structure
 gst_value_get_structure
 
-<SUBSECTION miniobject>
-GST_VALUE_HOLDS_MINI_OBJECT
-
+<SUBSECTION buffer>
 GST_VALUE_HOLDS_BUFFER
 gst_value_get_buffer
 gst_value_set_buffer
@@ -2888,13 +2875,13 @@ gst_value_array_append_value
 gst_value_array_get_size
 gst_value_array_get_value
 gst_value_array_prepend_value
+gst_value_fixate
 
 
 <SUBSECTION Private>
 gst_date_get_type
 gst_date_time_get_type
 gst_double_range_get_type
-gst_fourcc_get_type
 gst_fraction_get_type
 gst_fraction_range_get_type
 gst_int_range_get_type
@@ -2913,29 +2900,3 @@ GST_VERSION_NANO
 GST_CHECK_VERSION
 </SECTION>
 
-
-<SECTION>
-<FILE>gstxml</FILE>
-<TITLE>GstXML</TITLE>
-GstXML
-
-gst_xml_write
-gst_xml_write_file
-gst_xml_new
-gst_xml_parse_doc
-gst_xml_parse_file
-gst_xml_parse_memory
-gst_xml_get_element
-gst_xml_get_topelements
-gst_xml_make_element
-<SUBSECTION Standard>
-GstXMLClass
-GST_XML
-GST_IS_XML
-GST_XML_CLASS
-GST_IS_XML_CLASS
-GST_XML_GET_CLASS
-GST_TYPE_XML
-<SUBSECTION Private>
-gst_xml_get_type
-</SECTION>
index 2bcd498..d01b2dc 100644 (file)
@@ -12,12 +12,11 @@ gst_bin_get_type
 gst_bus_get_type
 gst_child_proxy_get_type
 gst_clock_get_type
+gst_control_binding_get_type
+gst_control_source_get_type
 gst_element_factory_get_type
 gst_element_get_type
 gst_ghost_pad_get_type
-gst_implements_interface_get_type
-gst_index_factory_get_type
-gst_index_get_type
 gst_object_get_type
 gst_pad_get_type
 gst_pad_template_get_type
@@ -30,7 +29,6 @@ gst_tag_setter_get_type
 gst_task_get_type
 gst_type_find_factory_get_type
 gst_uri_handler_get_type
-@GST_LOADSAVE_DOC_TYPES@gst_xml_get_type
 
 % these are not GObject derived types
 % this works with gtk-doc 1.10 at least
index 0f96f96..932eb31 100644 (file)
@@ -43,7 +43,6 @@ SCANOBJ_OPTIONS=--type-init-func="g_type_init();gst_init(&argc,&argv)"
 IGNORE_HFILES = \
        gstinterpolationcontrolsourceprivate.h \
        gstlfocontrolsourceprivate.h \
-       gstcontrollerprivate.h \
        gstgetbits_inl.h \
        dp-private.h
 
index 31488e3..97387d2 100644 (file)
@@ -46,7 +46,6 @@
       <xi:include href="xml/gstcollectpads.xml" />
       <xi:include href="xml/gstcollectpads2.xml" />
       <xi:include href="xml/gsttypefindhelper.xml" />
-      <xi:include href="xml/gstdataqueue.xml" />
     </chapter>
 
     <chapter id="gstreamer-control">
         element properties over time.
       </para>
 
-      <xi:include href="xml/gstcontroller.xml" />
-      <xi:include href="xml/gstcontrolsource.xml" />
+      <xi:include href="xml/gsttimedvaluecontrolsource.xml" />
       <xi:include href="xml/gstinterpolationcontrolsource.xml" />
       <xi:include href="xml/gstlfocontrolsource.xml" />
-      <xi:include href="xml/gstcontrollergobject.xml" />
-    </chapter>
-
-    <chapter id="gstreamer-dataprotocol">
-      <title>GStreamer Data Protocol</title>
-      <xi:include href="xml/gstdataprotocol.xml" />
+      <xi:include href="xml/gsttriggercontrolsource.xml" />
     </chapter>
 
     <chapter id="gstreamer-net">
index b3e04db..6311372 100644 (file)
 # <SUBSECTION Private>
 # </SECTION>
 
-<SECTION>
-<FILE>gstdataprotocol</FILE>
-<INCLUDE>gst/dataprotocol/dataprotocol.h</INCLUDE>
-GstDPHeaderFlag
-GstDPPayloadType
-
-GST_DP_HEADER_LENGTH
-GstDPVersion
-GST_DP_VERSION_MAJOR
-GST_DP_VERSION_MINOR
-
-gst_dp_init
-
-GstDPHeaderFromBufferFunction
-GstDPPacketFromCapsFunction
-GstDPPacketFromEventFunction
-GstDPPacketizer
-gst_dp_packetizer_new
-gst_dp_packetizer_free
-
-gst_dp_crc
-
-gst_dp_header_payload_length
-gst_dp_header_payload_type
-
-gst_dp_header_from_buffer
-gst_dp_packet_from_caps
-gst_dp_packet_from_event
-
-gst_dp_buffer_from_header
-gst_dp_caps_from_packet
-gst_dp_event_from_packet
-
-gst_dp_validate_header
-gst_dp_validate_payload
-gst_dp_validate_packet
-<SUBSECTION Standard>
-GST_TYPE_DP_VERSION
-gst_dp_version_get_type
-</SECTION>
+# control source classes
 
 <SECTION>
-<FILE>gstcontroller</FILE>
-<TITLE>GstController</TITLE>
-<INCLUDE>gst/controller/gstcontroller.h</INCLUDE>
-GstController
-gst_controller_init
-gst_controller_new
-gst_controller_new_list
-gst_controller_new_valist
-gst_controller_remove_properties
-gst_controller_remove_properties_list
-gst_controller_remove_properties_valist
-gst_controller_set_disabled
-gst_controller_set_property_disabled
-gst_controller_suggest_next_sync
-gst_controller_sync_values
-gst_controller_get_control_source
-gst_controller_set_control_source
-gst_controller_get
-gst_controller_get_value_arrays
-gst_controller_get_value_array
-gst_controller_set
-gst_controller_set_from_list
-gst_controller_unset
-gst_controller_unset_all
-gst_controller_get_all
-gst_controller_set_interpolation_mode
+<FILE>gsttimedvaluecontrolsource</FILE>
+<TITLE>GstTimedValueControlSource</TITLE>
+<INCLUDE>libs/controller/gsttimedvaluecontrolsource.h</INCLUDE>
+GstTimedValueControlSource
+gst_timed_value_control_source_find_control_point_iter
+gst_timed_value_control_source_set
+gst_timed_value_control_source_set_from_list
+gst_timed_value_control_source_get_all
+gst_timed_value_control_source_unset
+gst_timed_value_control_source_unset_all
+gst_timed_value_control_source_get_count
+gst_timed_value_control_source_get_base_value_type
+gst_timed_value_control_invalidate_cache
 <SUBSECTION Standard>
-GstControllerClass
-GstControllerPrivate
-GST_CONTROLLER
-GST_IS_CONTROLLER
-GST_CONTROLLER_CLASS
-GST_IS_CONTROLLER_CLASS
-GST_CONTROLLER_GET_CLASS
-GST_TYPE_CONTROLLER
+GstTimedValueControlSourceClass
+GstTimedValueControlSourcePrivate
+GST_TIMED_VALUE_CONTROL_SOURCE
+GST_IS_TIMED_VALUE_CONTROL_SOURCE
+GST_TIMED_VALUE_CONTROL_SOURCE_CLASS
+GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS
+GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_TIMED_VALUE_CONTROL_SOURCE
 <SUBSECTION Private>
-gst_controller_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gstcontrolsource</FILE>
-<TITLE>GstControlSource</TITLE>
-<INCLUDE>libs/controller/gstcontrolsource.h</INCLUDE>
-GstControlSource
-GstControlSourceClass
-GstControlSourceBind
-GstControlSourceGetValue
-GstControlSourceGetValueArray
-GstTimedValue
-GstValueArray
-gst_control_source_bind
-gst_control_source_get_value
-gst_control_source_get_value_array
-<SUBSECTION Standard>
-GST_CONTROL_SOURCE
-GST_IS_CONTROL_SOURCE
-GST_CONTROL_SOURCE_CLASS
-GST_IS_CONTROL_SOURCE_CLASS
-GST_CONTROL_SOURCE_GET_CLASS
-GST_TYPE_CONTROL_SOURCE
-<SUBSECTION Private>
-gst_control_source_get_type
+gst_timed_value_control_source_get_type
 </SECTION>
 
 <SECTION>
@@ -124,15 +47,8 @@ gst_control_source_get_type
 <TITLE>GstInterpolationControlSource</TITLE>
 <INCLUDE>libs/controller/gstinterpolationcontrolsource.h</INCLUDE>
 GstInterpolationControlSource
-GstInterpolateMode
+GstInterpolationMode
 gst_interpolation_control_source_new
-gst_interpolation_control_source_set
-gst_interpolation_control_source_set_from_list
-gst_interpolation_control_source_set_interpolation_mode
-gst_interpolation_control_source_get_all
-gst_interpolation_control_source_unset
-gst_interpolation_control_source_unset_all
-gst_interpolation_control_source_get_count
 <SUBSECTION Standard>
 GstInterpolationControlSourceClass
 GstInterpolationControlSourcePrivate
@@ -142,8 +58,10 @@ GST_INTERPOLATION_CONTROL_SOURCE_CLASS
 GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
 GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
 GST_TYPE_INTERPOLATION_CONTROL_SOURCE
+GST_TYPE_INTERPOLATION_MODE
 <SUBSECTION Private>
 gst_interpolation_control_source_get_type
+gst_interpolation_mode_get_type
 </SECTION>
 
 <SECTION>
@@ -169,23 +87,22 @@ gst_lfo_waveform_get_type
 </SECTION>
 
 <SECTION>
-<FILE>gstcontrollergobject</FILE>
-<TITLE>GstControllerGObject</TITLE>
-<INCLUDE>libs/controller/gstcontroller.h</INCLUDE>
-gst_object_control_properties
-gst_object_uncontrol_properties
-gst_object_get_controller
-gst_object_set_controller
-gst_object_suggest_next_sync
-gst_object_sync_values
-gst_object_get_control_source
-gst_object_set_control_source
-gst_object_get_value_arrays
-gst_object_get_value_array
-gst_object_get_control_rate
-gst_object_set_control_rate
+<FILE>gsttriggercontrolsource</FILE>
+<TITLE>GstTriggerControlSource</TITLE>
+<INCLUDE>libs/controller/gsttriggercontrolsource.h</INCLUDE>
+GstTriggerControlSource
+gst_trigger_control_source_new
 <SUBSECTION Standard>
+GstTriggerControlSourceClass
+GstTriggerControlSourcePrivate
+GST_TRIGGER_CONTROL_SOURCE
+GST_IS_TRIGGER_CONTROL_SOURCE
+GST_TRIGGER_CONTROL_SOURCE_CLASS
+GST_IS_TRIGGER_CONTROL_SOURCE_CLASS
+GST_TRIGGER_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_TRIGGER_CONTROL_SOURCE
 <SUBSECTION Private>
+gst_trigger_control_source_get_type
 </SECTION>
 
 # base classes
@@ -198,7 +115,8 @@ GstAdapter
 gst_adapter_new
 gst_adapter_clear
 gst_adapter_push
-gst_adapter_peek
+gst_adapter_map
+gst_adapter_unmap
 gst_adapter_copy
 gst_adapter_flush
 gst_adapter_available
@@ -206,7 +124,8 @@ gst_adapter_available_fast
 gst_adapter_take
 gst_adapter_take_buffer
 gst_adapter_take_list
-gst_adapter_prev_timestamp
+gst_adapter_prev_pts
+gst_adapter_prev_dts
 gst_adapter_masked_scan_uint32
 gst_adapter_masked_scan_uint32_peek
 <SUBSECTION Standard>
@@ -236,6 +155,7 @@ gst_base_parse_set_passthrough
 gst_base_parse_set_syncable
 gst_base_parse_set_has_timing_info
 gst_base_parse_set_frame_rate
+gst_base_parse_set_latency
 gst_base_parse_convert_default
 gst_base_parse_add_index_entry
 
@@ -288,6 +208,7 @@ gst_base_src_get_do_timestamp
 gst_base_src_set_do_timestamp
 gst_base_src_set_dynamic_size
 gst_base_src_new_seamless_segment
+gst_base_src_set_caps
 
 GST_BASE_SRC_PAD
 <SUBSECTION Standard>
@@ -330,13 +251,22 @@ gst_base_sink_set_render_delay
 gst_base_sink_get_render_delay
 gst_base_sink_set_last_buffer_enabled
 gst_base_sink_is_last_buffer_enabled
-gst_base_sink_get_last_buffer
+gst_base_sink_get_last_sample
 gst_base_sink_set_blocksize
 gst_base_sink_get_blocksize
 gst_base_sink_get_throttle_time
 gst_base_sink_set_throttle_time
 
 GST_BASE_SINK_PAD
+GST_BASE_SINK_GET_PREROLL_COND
+GST_BASE_SINK_GET_PREROLL_LOCK
+GST_BASE_SINK_PREROLL_BROADCAST
+GST_BASE_SINK_PREROLL_LOCK
+GST_BASE_SINK_PREROLL_SIGNAL
+GST_BASE_SINK_PREROLL_TIMED_WAIT
+GST_BASE_SINK_PREROLL_TRYLOCK
+GST_BASE_SINK_PREROLL_UNLOCK
+GST_BASE_SINK_PREROLL_WAIT
 
 <SUBSECTION Standard>
 GST_BASE_SINK
@@ -401,14 +331,11 @@ gst_base_transform_get_type
 GstBitReader
 
 GST_BIT_READER_INIT
-GST_BIT_READER_INIT_FROM_BUFFER
 
 gst_bit_reader_new
-gst_bit_reader_new_from_buffer
 gst_bit_reader_free
 
 gst_bit_reader_init
-gst_bit_reader_init_from_buffer
 
 gst_bit_reader_get_pos
 gst_bit_reader_get_remaining
@@ -451,14 +378,11 @@ GST_BIT_READER
 GstByteReader
 
 GST_BYTE_READER_INIT
-GST_BYTE_READER_INIT_FROM_BUFFER
 
 gst_byte_reader_new
-gst_byte_reader_new_from_buffer
 gst_byte_reader_free
 
 gst_byte_reader_init
-gst_byte_reader_init_from_buffer
 
 gst_byte_reader_get_pos
 gst_byte_reader_get_remaining
@@ -608,12 +532,10 @@ g_memdup
 GstByteWriter
 
 gst_byte_writer_new
-gst_byte_writer_new_with_buffer
 gst_byte_writer_new_with_data
 gst_byte_writer_new_with_size
 
 gst_byte_writer_init
-gst_byte_writer_init_with_buffer
 gst_byte_writer_init_with_data
 gst_byte_writer_init_with_size
 
@@ -708,7 +630,6 @@ gst_collect_pads_new
 gst_collect_pads_set_function
 gst_collect_pads_set_clip_function
 gst_collect_pads_add_pad
-gst_collect_pads_add_pad_full
 gst_collect_pads_remove_pad
 gst_collect_pads_is_active
 gst_collect_pads_collect
@@ -719,7 +640,6 @@ gst_collect_pads_set_flushing
 gst_collect_pads_peek
 gst_collect_pads_pop
 gst_collect_pads_available
-gst_collect_pads_read
 gst_collect_pads_read_buffer
 gst_collect_pads_take_buffer
 gst_collect_pads_flush
@@ -833,44 +753,13 @@ gst_push_src_get_type
 gst_type_find_helper
 gst_type_find_helper_for_buffer
 gst_type_find_helper_for_extension
+gst_type_find_helper_for_data
 GstTypeFindHelperGetRangeFunction
 gst_type_find_helper_get_range
 gst_type_find_helper_get_range_ext
 <SUBSECTION Private>
 </SECTION>
 
-<SECTION>
-<FILE>gstdataqueue</FILE>
-<TITLE>GstDataQueue</TITLE>
-<INCLUDE>gst/base/gstdataqueue.h</INCLUDE>
-GstDataQueue
-GstDataQueueSize
-GstDataQueueCheckFullFunction
-GstDataQueueItem
-GstDataQueueEmptyCallback
-GstDataQueueFullCallback
-gst_data_queue_new
-gst_data_queue_new_full
-gst_data_queue_push
-gst_data_queue_pop
-gst_data_queue_flush
-gst_data_queue_set_flushing
-gst_data_queue_drop_head
-gst_data_queue_is_full
-gst_data_queue_is_empty
-gst_data_queue_get_level
-gst_data_queue_limits_changed
-<SUBSECTION Standard>
-GstDataQueueClass
-GST_DATA_QUEUE
-GST_IS_DATA_QUEUE
-GST_TYPE_DATA_QUEUE
-GST_DATA_QUEUE_CLASS
-GST_IS_DATA_QUEUE_CLASS
-<SUBSECTION Private>
-gst_data_queue_get_type
-</SECTION>
-
 # net
 
 <SECTION>
@@ -946,12 +835,14 @@ fail_unless_equals_int
 fail_unless_equals_float
 fail_unless_equals_string
 fail_unless_equals_uint64
+fail_unless_equals_int64
 fail_unless_message_error
 
 assert_equals_int
 assert_equals_float
 assert_equals_string
 assert_equals_uint64
+assert_equals_int64
 assert_message_error
 
 gst_check_init
@@ -966,6 +857,7 @@ gst_check_teardown_element
 gst_check_teardown_sink_pad
 gst_check_teardown_src_pad
 gst_check_drop_buffers
+gst_check_buffer_data
 gst_check_caps_equal
 gst_check_element_push_buffer_list
 gst_check_element_push_buffer
index a41e584..a75d55b 100644 (file)
@@ -18,15 +18,15 @@ gst_push_src_get_type
 
 % controller
 
-#include <gst/controller/gstcontroller.h>
-#include <gst/controller/gstcontrolsource.h>
+#include <gst/controller/gsttimedvaluecontrolsource.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
 #include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gsttriggercontrolsource.h>
 
-gst_controller_get_type
-gst_control_source_get_type
+gst_timed_value_control_source_get_type
 gst_interpolation_control_source_get_type
 gst_lfo_control_source_get_type
+gst_trigger_control_source_get_type
 
 % net
 
index 58889da..dbdb5ea 100644 (file)
@@ -314,7 +314,7 @@ init_factories (void)
 {
   /* first filter out the interesting element factories */
   factories = gst_registry_feature_filter (
-      gst_registry_get_default (),
+      gst_registry_get (),
       (GstPluginFeatureFilter) cb_feature_filter, FALSE, NULL);
 
   /* sort them according to their ranks */
@@ -344,7 +344,7 @@ cb_newpad (GstElement *element,
 {
   GstCaps *caps;
 
-  caps = gst_pad_get_caps (pad);
+  caps = gst_pad_query_caps (pad, NULL);
   try_to_plug (pad, caps);
   gst_caps_unref (caps);
 }
@@ -389,7 +389,7 @@ close_link (GstPad      *srcpad,
     switch (templ->presence) {
       case GST_PAD_ALWAYS: {
         GstPad *pad = gst_element_get_static_pad (sinkelement, templ->name_template);
-        GstCaps *caps = gst_pad_get_caps (pad);
+        GstCaps *caps = gst_pad_query_caps (pad, NULL);
 
         /* link */
         try_to_plug (pad, caps);
@@ -436,7 +436,8 @@ try_to_plug (GstPad        *pad,
   }
 
   /* can it link to the audiopad? */
-  audiocaps = gst_pad_get_caps (gst_element_get_static_pad (audiosink, "sink"));
+  audiocaps = gst_pad_query_caps (gst_element_get_static_pad (audiosink, "sink"),
+  NULL);
   res = gst_caps_intersect (caps, audiocaps);
   if (res &amp;&amp; !gst_caps_is_empty (res)) {
     g_print ("Found pad to link to audiosink - plugging is now done\n");
index 0db6e3c..60d1f72 100644 (file)
@@ -56,17 +56,23 @@ cb_have_data (GstPad    *pad,
              gpointer   u_data)
 {
   gint x, y;
-  guint16 *data = (guint16 *) GST_BUFFER_DATA (buffer), t;
+  guint16 *data, *ptr, t;
+  gsize size;
+  
+  data = gst_buffer_map (buffer, &amp;size, NULL, GST_MAP_WRITE);
 
+  ptr = data;
   /* invert data */
   for (y = 0; y &lt; 288; y++) {
     for (x = 0; x &lt; 384 / 2; x++) {
-      t = data[384 - 1 - x];
-      data[384 - 1 - x] = data[x];
-      data[x] = t;
+      t = ptr[384 - 1 - x];
+      ptr[384 - 1 - x] = ptr[x];
+      ptr[x] = t;
     }
-    data += 384;
+    ptr += 384;
   }
+  gst_buffer_unmap (buffer, data, size);
+
 
   return TRUE;
 }
@@ -282,11 +288,16 @@ cb_handoff (GstElement *fakesrc,
            gpointer    user_data)
 {
   static gboolean white = FALSE;
+  gpointer data;
+  gsize size;
+  
+  data = gst_buffer_map (buffer, &amp;size, NULL, GST_MAP_WRITE);
 
   /* this makes the image black/white */
-  memset (GST_BUFFER_DATA (buffer), white ? 0xff : 0x0,
-         GST_BUFFER_SIZE (buffer));
+  memset (data, white ? 0xff : 0x0, size);
   white = !white;
+
+  gst_buffer_unmap (buffer, data, size);
 }
 
 gint
index 5957231..1786339 100644 (file)
@@ -78,11 +78,10 @@ my_bus_message_cb (GstBus     *bus,
 static gboolean
 cb_print_position (GstElement *pipeline)
 {
-  GstFormat fmt = GST_FORMAT_TIME;
   gint64 pos, len;
 
-  if (gst_element_query_position (pipeline, &amp;fmt, &amp;pos)
-    &amp;&amp; gst_element_query_duration (pipeline, &amp;fmt, &amp;len)) {
+  if (gst_element_query_position (pipeline, GST_FORMAT_TIME, &amp;pos)
+    &amp;&amp; gst_element_query_duration (pipeline, GST_FORMAT_TIME, &amp;len)) {
     g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
             GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
   }
index bf6c7db..1981ee4 100644 (file)
@@ -253,7 +253,7 @@ cb_newpad (GstElement *decodebin,
   }
 
   /* check media type */
-  caps = gst_pad_get_caps (pad);
+  caps = gst_pad_query_caps (pad, NULL);
   str = gst_caps_get_structure (caps, 0);
   if (!g_strrstr (gst_structure_get_name (str), "audio")) {
     gst_caps_unref (caps);
index fd88bb8..1198280 100644 (file)
 <RANGE></RANGE>
 <FLAGS>rw</FLAGS>
 <NICK>Single Segment</NICK>
-<BLURB>Timestamp buffers and eat newsegments so as to appear as one segment.</BLURB>
+<BLURB>Timestamp buffers and eat segments so as to appear as one segment.</BLURB>
 <DEFAULT>FALSE</DEFAULT>
 </ARG>
 
index ea81e4a..1c36392 100644 (file)
@@ -1,44 +1,45 @@
 GObject
-  GstObject
-    GstBus
-    GstClock
-    GstElement
-      GstBaseSink
-        GstFakeSink
-        GstFdSink
-        GstFileSink
-      GstBaseSrc
-        GstFakeSrc
-        GstFileSrc
-        GstPushSrc
-          GstFdSrc
-      GstBaseTransform
-        GstCapsFilter
-        GstIdentity
-      GstBin
-        GstPipeline
-      GstFunnel
-      GstInputSelector
-      GstMultiQueue
-      GstOutputSelector
-      GstQueue
-      GstQueue2
-      GstTee
-      GstTypeFindElement
-      GstValve
-    GstIndex
-      GstMemIndex
-    GstPad
-    GstPadTemplate
-    GstPlugin
-    GstPluginFeature
-      GstElementFactory
-      GstIndexFactory
-      GstTypeFindFactory
-    GstRegistry
-    GstTask
-    GstTaskPool
-  GstSignalObject
+  GInitiallyUnowned
+    GstObject
+      GstPad
+      GstPadTemplate
+      GstPluginFeature
+        GstElementFactory
+        GstTypeFindFactory
+        GstIndexFactory
+      GstElement
+        GstBin
+          GstPipeline
+        GstBaseTransform
+          GstCapsFilter
+          GstIdentity
+        GstBaseSrc
+          GstFakeSrc
+          GstPushSrc
+            GstFdSrc
+          GstFileSrc
+        GstBaseSink
+          GstFakeSink
+          GstFdSink
+          GstFileSink
+        GstFunnel
+        GstInputSelector
+        GstOutputSelector
+        GstQueue
+        GstQueue2
+        GstTee
+        GstTypeFindElement
+        GstMultiQueue
+        GstValve
+      GstBus
+      GstTask
+      GstTaskPool
+      GstClock
+      GstPlugin
+      GstRegistry
+      GstIndex
+        GstMemIndex
+        GstFileIndex
 GInterface
   GTypePlugin
   GstChildProxy
diff --git a/docs/random/plan-0.11.txt b/docs/random/plan-0.11.txt
new file mode 100644 (file)
index 0000000..3569927
--- /dev/null
@@ -0,0 +1,141 @@
+Plan for 0.11
+=============
+
+First attempt at making a list of tasks in roughly chronological order.
+
+* General cleanup
+
+  - Remove deprecated methods
+  - Cleanup structs + PADDING
+  - ..
+  
+  This should allow us to continue expanding later in the same way that 0.10 was
+  expanded.
+
+
+* Review GstCaps fields
+
+  - go over caps fields for audio, video, compressed media-type etc
+
+  We need to express things with less fields. This would speed up caps, make
+  them less verbose and speed up some elements.
+
+
+* Add GstFlowReturn for events (and query)
+
+  This would allow us to know more precisely what went wrong.
+
+  http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=events2
+
+
+* add return structure for events and query
+
+  Make events return more information. (a seek event might want to return the
+  final position of the keyframe seek and the accuracy of the seek)
+
+  Make bindings easiers. Currently the writability of a query depends on the
+  refcount being exactly 1. If the query is not writable, it simply cannot be
+  answered.
+
+
+* Make GstMiniObject a simple boxed type
+
+  - Move copy and free function to structure
+  - convert GstBuffer, GstEvent, GstMessage, GstQuery,
+
+  We don't need to subclass miniobjects when we have arbitrary metadata. 
+
+  Allocation should be more efficient and buffer/metadata/data can be allocated
+  and pooled in one contiguous memory area.
+
+  Typechecking of various types is much more efficient when there is only
+  one class.
+
+  http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=miniobject2
+
+
+* Convert GstCaps to GstMiniObject
+
+  Currently it has its own refcounting and flags.
+
+  http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=miniobject2
+
+
+* GVariant registry
+
+  - allow for mmaped registy (tpm)
+
+* Incremental caps
+
+  - Remove array from caps ?
+  - make caps iterator or is the array the cache for iterator ?
+
+  We need to perform less caps operations when negotiating formats. One way is
+  to only handle small caps objects incrementally.
+
+  http://cgit.freedesktop.org/~ensonic/gstreamer/log/?h=lazycaps
+
+
+* Make GstBufferMetadata
+
+  - Make functions to register metadata
+  - Make common metadata: timeinfo, memory data, video data
+  - Remove GstBuffer Fields
+  - Make methods to add metadata to buffers.
+  
+  More flexible metadata for buffers.
+
+  http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=buffermeta
+
+
+* Negotiation of metadata
+
+  - figure out if we need to negotiate the metadata on the caps or if we can
+    gracefully degrade when an element doesn't understand the metadata.
+
+  We need to avoid that elements put metadata on buffers that is essential in
+  handling the buffer contents but that is then not understood by other
+  elements.
+
+
+* Rework reverse negotiation
+
+  - upstream event to notify of a downstream caps change
+  - _alloc_buffer() takes input GstBuffer prototype (or NULL)
+  - _alloc_buffer() never returns changed caps.
+
+  One of the performance problems in 0.10 is that transform elements need to
+  call gst_pad_alloc_buffer() downstream to check if the caps changed. This
+  usually also results in a useless memory allocation. 
+  
+  We would make a new upstream event to notify downstream elements that new caps
+  are possible somewhere downstream.
+
+  gst_pad_alloc_buffer() would take a GstBuffer as an input argument to make the
+  API easier, we can then use metadata to specify additional contraints for the
+  new buffer (such as strides, etc)
+  
+
+* Incremental event progation
+
+  - certain events would be sticky on a pad like for caps
+  - rules for pushing an event downstream
+     - right before pushing a buffer
+     - after link operation
+  - activate for most serialized downstream events
+
+  This would allow an application to have more control over the state of the
+  dataflow in a pipeline. 
+
+
+* GstSegment changes
+
+  - remove segment accumulation
+  - add accumulated time to the event
+  - apply segment info to pads
+  - add method on pads to get/adjust sync offset
+  - add method on pads to query current running_time 
+
+  The goal is to make the timing model more comprehensible and thus make dynamic
+  pipeline plugging easier.
+
diff --git a/docs/random/porting-to-0.11.txt b/docs/random/porting-to-0.11.txt
new file mode 100644 (file)
index 0000000..eb5b216
--- /dev/null
@@ -0,0 +1,481 @@
+The 0.11 porting guide
+----------------------
+
+* All deprecated methods were removed. Recompile against 0.10 with
+  DISABLE_DEPRECATED and fix issues before attempting to port to 0.11.
+
+* GST_BOILERPLATE is gone, use G_DEFINE_TYPE instead.
+
+* various methods take a gsize instead of a guint when talking about memory
+  sizes.
+
+* multifdsink, tcpclientsink, tcpclientsrc, tcpserversrc the protocol property
+  is removed, use gdppay and gdpdepay.
+
+* Presets and plugins moved to $XDG_DATA_HOME/gstreamer-0.11/ root
+  directory. Registry moved to $XDG_CACHE_HOME/gstreamer-0.11/.
+  XDG_CACHE_HOME usually points to $HOME/.cache and XDG_DATA_HOME
+  usually is $HOME/.local/share/.
+
+* GstObject:
+    GST_OBJECT_DISPOSING flag removed
+    GST_OBJECT_IS_DISPOSING removed
+    GST_OBJECT_FLOATING flag remove, GstObject is now GInitiallyUnowned
+    GST_OBJECT_IS_FLOATING removed, use g_object_is_floating()
+
+    GST_CLASS_GET_LOCK, GST_CLASS_LOCK, GST_CLASS_TRYLOCK, GST_CLASS_UNLOCK,
+    used to be a workaround for thread-unsafe glib < 2.8
+
+    gst_object_ref_sink() has gpointer as result to make it more like the
+    GObject version.
+
+    gst_object_sink() removed, use gst_object_ref_sink() instead.
+
+    gst_class_signal_connect() removed, was only used for XML
+
+    parent-set and parent-unset signals removed. Use notify:parent. Currently
+    still disabled because of deep notify locking issues.
+
+* GstElement:
+    GstElementDetails is removed and replaced with more generic metadata.
+
+    gst_element_class_set_details_simple() -> gst_element_class_set_metadata()
+    gst_element_class_set_documentation_uri -> gst_element_class_add_metadata
+    gst_element_class_set_icon_name -> gst_element_class_add_metadata
+    also gst_element_class_get_metadata()
+
+    gst_element_factory_get_longname -> gst_element_factory_get_metadata
+    gst_element_factory_get_klass -> gst_element_factory_get_metadata
+    gst_element_factory_get_description -> gst_element_factory_get_metadata
+    gst_element_factory_get_author -> gst_element_factory_get_metadata
+    gst_element_factory_get_documentation_uri -> gst_element_factory_get_metadata
+    gst_element_factory_get_icon_name -> gst_element_factory_get_metadata
+
+    gstelementmetadata.h contains the keys for all standard metadata.
+
+    gst_element_factory_can_{src,sink}_caps() => gst_element_factory_can_{src,sink}_{any,all}_caps()
+
+    Element metadata and pad templates are inherited from parent classes and
+    should be added in class_init instead of base_init.
+
+    gst_element_class_add_pad_template() takes ownership of the template
+
+    Elements that change the duration must post DURATION messages on the
+    bus when the duration changes in PAUSED or PLAYING.
+
+    gst_element_lost_state_full() -> gst_element_lost_state()
+    gst_element_lost_state() -> gst_element_lost_state(, TRUE)
+
+    request_new_pad_full() -> request_new_pad()
+
+    gst_element_found_tags() and gst_element_found_tags_for_pad() are gone, just
+    push the tag event.
+
+* GstPad:
+    gst_pad_get_caps() was replaced by gst_pad_query_caps(), it
+    does not return writable caps anymore and an explicit
+    gst_caps_make_writable() needs to be performed. This was the functionality
+    of gst_pad_get_caps_reffed(), which is removed now.
+
+    A similar change was done for gst_pad_peer_get_caps() and
+    gst_pad_peer_get_caps_reffed()
+
+    gst_pad_set_bufferalloc_function(), gst_pad_alloc_buffer() and
+    gst_pad_alloc_buffer_and_set_caps() are removed. Use the ALLOCATION query
+    now when negotiating formats to obtain a reference to a bufferpool object
+    that can be used to allocate buffers using gst_buffer_pool_acquire_buffer().
+
+    removed sched_private, it should not be used, use g_object_set_qdata() or
+    use element_private.
+
+    Removed GST_PAD_CAPS() use gst_pad_get_current_caps() to get a handle to the
+    currently configured caps.
+
+    GstPadGetCapsFunction, gst_pad_get_caps(), gst_pad_peer_get_caps(),
+    gst_pad_proxy_getcaps() now takes a GstCaps* parameter to inform
+    the other side about the possible caps and preferences.
+
+    gst_pad_get_pad_template_caps() and gst_pad_get_pad_template()
+    return a new reference of the caps or template now and the return
+    value needs to be unreffed after usage.
+
+    gst_pad_set_caps() now pushes a CAPS event for backward compatibility.
+    Consider sending the CAPS event yourself. It is not possible anymore to set
+    NULL caps.
+
+    gst_pad_set_checkgetrange_function() and gst_pad_check_pull_range() are
+    gone, use the SCHEDULING query now.
+
+    gst_pad_set_blocked(), gst_pad_set_blocked_async(),
+    gst_pad_set_blocked_async_full() are removed, use the gst_pad_add_probe()
+    method with the GST_PAD_PROBE_TYPE_BLOCK to get the same result as the async
+    blocking version. There is no more sync version of blocking, this is in
+    general dangerous and can be implemented using the callbacks if needed.
+
+    gst_pad_add_data_probe(), gst_pad_add_data_probe_full(),
+    gst_pad_remove_data_probe(), gst_pad_add_event_probe(),
+    gst_pad_add_event_probe_full(), gst_pad_remove_event_probe(),
+    gst_pad_add_buffer_probe(), gst_pad_add_buffer_probe_full(),
+    gst_pad_remove_buffer_probe() are removed. Use gst_pad_add_probe() and
+    gst_pad_remove_probe() for equivalent functionality.
+
+    The have-data signal was removed from pads, it was never supposed to be used
+    without calling the _add_.*_probe() methods.
+
+    The request-link signal was removed. It was never used.
+
+    gst_pad_get_negotiated_caps() -> get_pad_get_current_caps()
+
+    GST_FLOW_UNEXPECTED -> GST_FLOW_EOS
+
+    GstActivateMode -> GstPadMode, GST_ACTIVATE_* -> GST_PAD_MODE_*
+
+    The GstPadAcceptCapsFunction was removed and replaced with a
+    GST_QUERY_ACCEPT_CAPS query.
+
+    The GstPadFixateCapsFunction was removed. It has no replacement, you can
+    simply do the fixation in the element or use a vmethod from the base class
+    if appropriate.
+
+    The GstPadGetCapsFunction was removed and replaced with a GST_QUERY_CAPS
+    query.
+
+    gst_pad_proxy_getcaps() -> gst_pad_proxy_query_caps()
+    gst_pad_get_caps() -> gst_pad_query_caps()
+    gst_pad_peer_get_caps() -> gst_pad_peer_query_caps()
+    gst_pad_accept_caps() -> gst_pad_query_accept_caps()
+    gst_pad_peer_accept_caps() -> gst_pad_peer_query_accept_caps()
+    gst_pad_query_peer_*() -> gst_pad_peer_query_*()
+
+    GstPadFlags: GST_PAD_* -> GST_PAD_FLAG_*
+
+* GstPadTemplate
+    gst_pad_template_get_caps() returns a new reference of the caps
+    and the return value needs to be unreffed after usage.
+
+    gst_pad_template_new() does not take ownership of the caps anymore.
+
+    GstPadTemplate is now created with a floating ref and
+    gst_element_class_add_pad_template() takes ownership of this floating ref.
+
+    GstPadTemplate instances are considered immutable and must not be
+    changed.
+
+* GstMiniObject
+    A miniobject is now a simple refcounted structure holding the information
+    common to buffers, events, messages, queries and caps.
+
+    There is no more GST_TYPE_MINIOBJECT as the type for subclasses.
+    G_TYPE_BOXED can be used as the type of all GstMiniObject based types such
+    as buffers, events, messages, caps, etc. Signals, for example, would use the
+    boxed type if the argument include GstMiniObject derived types.
+
+    gst_mini_object_new() is removed. You would allocate memory with the the
+    methods specific for the derived type.
+
+    GstParamSpecMiniObject is removed, use boxed param spec now with the GType
+    of the specific GstMiniObject derived type. Also
+    gst_param_spec_mini_object().
+
+    gst_param_spec_mini_object() -> g_param_spec_boxed()
+
+    The specific gst_value_*_mini_object() methods are removed, used the generic
+    boxed methods instead.
+
+    gst_value_set_mini_object() -> g_value_set_boxed()
+    gst_value_take_mini_object() -> g_value_take_boxed()
+    gst_value_take_get_object() -> g_value_get_boxed()
+    gst_value_take_dup_object() -> g_value_dup_boxed()
+
+    GST_VALUE_HOLDS_MINI_OBJECT() was removed, use G_VALUE_HOLDS_BOXED() or
+    type-specific GST_VALUE_HOLDS_{BUFFER,CAPS,etc.}() instead.
+
+    The GST_MINI_OBJECT_READONLY flag was removed as it used to mark the
+    memory in buffers as READONLY. Marking memory READONLY can now be done
+    with the GstMemory API. Writability of miniobjects is now only done by using
+    the refcount.
+
+* GstBuffer
+    A GstBuffer is now a simple boxed type this means that subclassing is not
+    possible anymore. 
+
+    To add data to the buffer you would now use gst_buffer_take_memory() with
+    a GstMemory object containing the data. Multiple memory blocks can added to
+    a GstBuffer that can then be retrieved with gst_buffer_peek_memory().
+
+    GST_BUFFER_DATA(), GST_BUFFER_MALLOCDATA(), GST_BUFFER_FREE_FUNC() and
+    GST_BUFFER_SIZE() are gone, along with the fields in GstBuffer. Use the
+    memory API to get access to the buffer data. GST_BUFFER_SIZE() can be
+    replaced with gst_buffer_get_size() but if also access to the data is
+    required, gst_buffer_map() can return both the size and data in one go.
+
+    The most common way to access all the data in a buffer is by using
+    gst_buffer_map() and gst_buffer_unmap(). These calls require you to specify
+    the access mode required to the data and will automatically merge and return
+    a writable copy of the data.
+
+    The buffer must be writable (gst_buffer_is_writable()) in order to modify
+    the fields, metadata or buffer memory. gst_buffer_make_writable() will not
+    automatically make a writable copy of the memory but will instead increase
+    the refcount of the memory. The _map() and _peek_memory() methods will
+    automatically create writable copies when needed.
+    
+    gst_buffer_make_metadata_writable() is gone, you can replace this safely
+    with gst_buffer_make_writable().
+    
+    gst_buffer_copy_metadata() is gone, use gst_buffer_copy_into() instead and
+    mind use GST_BUFFER_COPY_METADATA instead of the former GST_BUFFER_COPY_ALL.
+
+    gst_buffer_create_sub() is gone and can be safely replaced with
+    gst_buffer_copy_region(). 
+
+    Changing the size of the buffer data can be done with gst_buffer_resize(),
+    which will also update the metadata fields correctly. gst_buffer_set_size()
+    is #defined to a special case of gst_buffer_resize() with a 0 offset.
+
+    gst_buffer_try_new_and_alloc() is replaced with gst_buffer_new_and_alloc(),
+    which now returns NULL when memory allocation fails.
+
+    GST_BUFFER_CAPS() is gone, caps are not set on buffers anymore but are set
+    on the pads where the buffer is pushed on. Likewise GST_BUFFER_COPY_CAPS is
+    not needed anymore. gst_buffer_get/set_caps() are gone too.
+
+    GST_BUFFER_TIMESTAMP is gone, use GST_BUFFER_PTS or GST_BUFFER_DTS instead.
+    Likewise GST_BUFFER_TIMESTAMP_IS_VALID() was changed to
+    GST_BUFFER_PTS_IS_VALID and GST_BUFFER_DTS_IS_VALID
+
+* GstBufferList
+    The GstBufferList object is much simplified because most of the
+    functionality in the groups is now part of the GstMemory in buffers.
+    
+    The object is reduced to encapsulating an array of buffers that you can send
+    with the regular gst_pad_push_list. The iterator is not needed anymore
+    because you can simply use gst_buffer_list_length() and gst_buffer_list_get()
+    to iterate the array.
+
+    For dealing with the groups, it's now needed to add the memory blocks to
+    GstBuffer and use the normal buffer API to get and merge the groups.
+
+    gst_buffer_list_sized_new() -> gst_buffer_list_new_sized()
+    gst_buffer_list_len() -> gst_buffer_list_length()
+
+* GstStructure
+
+    The GArray of the structure fields are moved to private part and are not
+    accessible from the application anymore. Use the methods to retrieve and
+    modify fields from the array.
+
+    gst_structure_empty_new() -> gst_structure_new_empty()
+    gst_structure_id_empty_new() -> gst_structure_new_id_empty()
+    gst_structure_id_new() -> gst_structure_new_id()
+
+* GstEvent
+    Boxed types derived from GstMiniObject.
+
+    GST_EVENT_SRC is removed. Don't use this anymore.
+
+    gst_event_new_qos_full() -> gst_event_new_qos()
+    gst_event_parse_qos_full() -> gst_event_parse_qos()
+
+    The GstStructure is removed from the public API, use the getters to get
+    a handle to a GstStructure.
+
+    GST_EVENT_NEWSEGMENT -> GST_EVENT_SEGMENT
+
+    gst_event_new_new_segment () -> gst_event_new_segment() and it takes a
+    GstSegment structure as an argument.
+    gst_event_parse_new_segment() -> gst_event_parse_segment() to retrieve the
+    GstSegment structure from the event.
+    gst_event_copy_segment() to fill a GstSegment structure.
+
+* GstQuery
+    Boxed types derived from GstMiniObject.
+
+    The GstStructure is removed from the public API, use the getters to get
+    a handle to a GstStructure.
+
+    gst_query_new_application() -> gst_query_new_custom()
+
+    gst_query_parse_formats_length() -> gst_query_parse_n_formats()
+    gst_query_parse_formats_nth() -> gst_query_parse_nth_format()
+
+    Some query utility functions no longer use an inout parameter for the
+    destination/query format:
+
+      - gst_pad_query_position()
+      - gst_pad_query_duration()
+      - gst_pad_query_convert()
+      - gst_pad_query_peer_position()
+      - gst_pad_query_peer_duration()
+      - gst_pad_query_peer_convert()
+      - gst_element_query_position()
+      - gst_element_query_duration()
+      - gst_element_query_convert()
+
+    gst_element_get_query_types() and gst_pad_get_query_types() with associated
+    functions were removed.
+
+* GstBufferList
+    Is now a boxed type derived from GstMiniObject.
+
+* GstMessage
+    Is now a boxed type derived from GstMiniObject
+
+    The GstStructure is removed from the public API, use the getters to get
+    a handle to a GstStructure.
+
+* GstCaps
+    Is now a boxed type derived from GstMiniObject.
+
+    GST_VIDEO_CAPS_xxx -> GST_VIDEO_CAPS_MAKE(xxx)
+
+* GstSegment
+    abs_rate was removed from the public fields, it can be trivially calculated
+    from the rate field.
+
+    accum was renamed to base. last_stop was renamed to position.
+
+    The segment info now contains all the information needed to convert buffer
+    timestamps to running_time and stream_time. There is no more segment
+    accumulation, the GstSegment is completely self contained.
+
+    gst_segment_set_duration() and gst_segment_set_last_stop() are removed,
+    simply modify the structure members duration and position respectively.
+
+    gst_segment_set_newsegment() is removed, it was used to accumulate segments
+    and is not needed anymore, use gst_segment_copy_into() or modify the segment
+    values directly.
+
+    gst_segment_set_seek() -> gst_segment_do_seek(). Updates the segment values
+    with seek parameters.
+
+* GstPluginFeature
+    GST_PLUGIN_FEATURE_NAME() was removed, use GST_OBJECT_NAME() instead.
+
+* GstTypeFind
+    gst_type_find_peek() returns a const guint8 * now.
+
+* GstTask
+    gst_task_create() -> gst_task_new()
+
+* GstAdapter
+    gst_adapter_peek() is removed, use gst_adapter_map() and gst_adapter_unmap()
+    to get access to raw data from the adapter.
+
+    Arguments changed from guint to gsize.
+
+    gst_adapter_prev_timestamp() is removed and should be replaced with
+    gst_adapter_prev_pts() and gst_adapter_prev_dts().
+
+* GstBitReader, GstByteReader, GstByteWriter
+    gst_*_reader_new_from_buffer(), gst_*_reader_init_from_buffer() removed, get
+    access to the buffer data with _map() and then use the _new() functions.
+
+    gst_byte_reader_new_from_buffer() and gst_byte_reader_init_from_buffer()
+    removed, get access to the buffer data and then use the _new() functions.
+
+* GstCollectPads
+    gst_collect_pads_read() removed, use _read_buffer() or _take_buffer() and
+    then use the memory API to get to the memory.
+
+* GstBaseSrc, GstBaseTransform, GstBaseSink
+    GstBaseSrc::get_caps(), GstBaseTransform::transform_caps() and
+    GstBaseSink::get_caps() now take a filter GstCaps* parameter to
+    filter the caps and allow better negotiation decisions.
+* GstBaseTransform
+    GstBaseTransform::transform_caps() now gets the complete caps passed
+    instead of getting it passed structure by structure.
+
+    GstBaseTransform::event() was renamed to sink_event(). The old function
+    uses the return value to determine if the event should be forwarded or not.
+    The new function has a default implementation that always forwards the event
+    and the return value is simply returned as a result from the event handler.
+    The semantics of the sink_event are thus the same as those for the src_event
+    function.
+
+* GstImplementsInterface
+    has been removed. Interfaces need to be updated to either have
+    is_ready/usable/available() methods, or have GError arguments
+    to their methods so we can return an appropriate error if a
+    particular interface isn't supported for a particular device.
+
+* GstIterator
+    uses a GValue based API now that is similar to the 0.10 API but
+    allows bindings to properly use GstIterator and prevents complex
+    return value ownership issues.
+
+* GstURIHandler
+    gst_uri_handler_get_uri() and the get_uri vfunc now return a copy of
+    the URI string
+
+    gst_uri_handler_set_uri() and the set_uri vfunc now take an additional
+    GError argument so the handler can notify the caller why it didn't
+    accept a particular URI.
+
+    gst_uri_handler_set_uri() now checks if the protocol of the URI passed
+    is one of the protocols advertised by the uri handler, so set_uri vfunc
+    implementations no longer need to check that as well.
+
+* GstTagList
+    is now an opaque object instead of being typedefed to a GstStructure. Cast
+    to GstStructure or use gst_structure_* API on it at your own peril (it may
+    still work for now, but might be changed in future).
+
+    gst_tag_list_new() has been renamed to gst_tag_list_new_empty().
+    gst_tag_list_new_full*() have been renamed to gst_tag_list_new*().
+
+* GstController:
+    has now been merged into GstObject. It does not exists as a individual
+    object anymore. In addition core contains a GstControlSource base class and
+    the GstControlBinding. The actual control sources are in the controller
+    library as before. The 2nd big change is that control sources generate
+    a sequence of gdouble values and those are mapped to the property type and
+    value range by GstControlBindings.
+    
+    For plugins the effect is that gst_controller_init() is gone and
+    gst_object_sync_values() is taking a GstObject * instead of GObject *.
+    
+    For applications the effect is larger. The whole gst_controller_* API is
+    gone and now available in simplified form under gst_object_*. ControlSources
+    are now attached via GstControlBinding to properties. There are no GValue
+    arguments used anymore when programming control sources.
+
+    gst_controller_new* -> gst_object_set_control_source
+    gst_controller_add_properties -> gst_object_set_control_source
+    gst_controller_set_control_source -> gst_object_set_control_source
+    gst_controller_get_control_source -> gst_object_get_control_source
+
+    gst_controller_set_property_disabled -> gst_object_set_controlled_property_disabled
+
+    gst_object_get_value_arrays has been removed. Loop over the controlled
+    properties fetch the value array. Also GstValueArray is gone. The fields of
+    GstValueArray are now passed directly to gst_object_get_value_array as
+    arguments.
+    
+    GstInterpolationControlSource has been split. There is a new 
+    GstTimedValueControlSource baseclass and 2 sub classes: 
+    GstInterpolationControlSource and GstTriggerControlSource. The API for setting
+    and getting the timestamps is in GstTimedValueControlSource.
+    
+    gst_interpolation_control_source_set_interpolation_mode() has been removed.
+    Set the "mode" gobject property on the control-source instead. The possible
+    enum values have been renamed from GST_INTERPOLATE_XXX to
+    GST_INTERPOLATION_MODE_XXX.
+
+* GstRegistry
+
+    gst_registry_get_default() -> gst_registry_get()
+    gst_default_registry_*(...) -> gst_registry_*(gst_registry_get(), ...)
+
+* GstValue
+
+    GST_TYPE_DATE -> G_TYPE_DATE
+    GST_VALUE_HOLDS_DATE(value) -> G_VALUE_HOLDS(value,G_TYPE_DATE)
+    gst_value_set_date() -> g_value_set_boxed()
+    gst_value_get_date() -> g_value_get_boxed()
+
+* GError/GstGError
+
+    GstGError -> GError
+    GST_TYPE_G_ERROR / gst_g_error_get_type() -> G_TYPE_ERROR
index f45bf97..7943be4 100644 (file)
@@ -132,7 +132,10 @@ RELEASE PROCEDURE:
        ftpadmin install gstreamer-0.10.42.tar.gz
 
   - Send release announcements to:
-    gstreamer-devel@lists.sourceforge.net gstreamer-announce@lists.sourceforge.net kde-multimedia@kde.org gnome-multimedia@gnome.org
+    gstreamer-devel@lists.freedesktop.org
+    gstreamer-announce@lists.freedesktop.org
+    kde-multimedia@kde.org
+    gnome-multimedia@gnome.org
   - Update freshmeat with new releases (get Uraeus to do it)
 
   - push release commit(s) to git repo
diff --git a/docs/random/status-0.11-14-jun-2011.txt b/docs/random/status-0.11-14-jun-2011.txt
new file mode 100644 (file)
index 0000000..b4309ac
--- /dev/null
@@ -0,0 +1,192 @@
+0.11 status 1 jun 2011
+----------------------
+
+Hello again GStreamer hackers,
+
+
+Here's another status update from the 0.11 branch. This one is packed
+with new stuff because it really took too long between the last 
+update, but well..
+
+
+Misc Core Changes
+-----------------
+
+The first set of big core change was done by über hacker Sebastian Dröge.
+He removed our special GST_BOILERPLATE macro. Because of some API strangeness
+we needed to do actions in the base_init method, which the GST_BOILERPLATE
+macro set up for us. The base_init concept is unfortunately not supported
+by almost all language bindings so we wanted to clean this up and use the
+regular G_DEFINE_TYPE macros. By inheriting metadata and pad templates
+from the parent, the GST_BOILERPLATE macro could be removed.
+
+
+Removal of gst_pad_alloc_buffer
+-------------------------------
+
+The next big change was the removal of gst_pad_alloc_buffer along with
+all the pad_alloc functions. The pad_alloc function were used to both
+implement allocation of buffers and notify upstream elements of new media
+formats. The functionality is replace by 3 new things: GstBufferPool (as
+noted in the previous status update), a new ALLOCATION query and a new
+RECONFIGURE event.
+
+The ALLOCATION query is used to query the downstream elements about the
+buffer properties they would like. These properties include the size,
+prefix and alignment of the memory. The downstream element can also propose
+a GstBufferPool. It is then the upstream element that decides how it
+will allocate buffers. This allows us, for example, to make the video
+decoders specify their required memory alignment to the videosink. 
+
+Since new format suggestions are no longer piggybacked upstream with the
+allocation, something new was needed to notify upstream elements of a
+format change. It started with bringing in the new RENEGOTIATE event
+that Thiago Santos had been experimenting with in the 0.10 branch. The
+new event basically lets upstream elements know that new formats are
+possible somewhere downstream and it would make them renegotiate a new
+format before pushing a new buffer.
+
+New format changes can also happen when new elements are linked, so
+gst_pad_link() will also send this RENEGOTIATE event upstream. As it turns
+out, adding new elements could also signal the availability of a new
+bufferpool or different ALLOCATION properties. The RENEGOTIATE event was
+thus renamed to the more generic RECONFIGURE event.
+
+The most impressive result of these changes is that most of the
+complicated code in GstBaseTransform could simply be removed.
+
+
+Sticky Events
+-------------
+
+The idea for the sticky events comes from the observation that a lot of the
+serialized downstream events (SEGMENT, EOS, TAGS, ..) are really context
+for the buffers that follow. The design called for making these events
+sticky on the pads, meaning that they become a property of the pads
+they travel over.
+
+The result is that the current timing information (SEGMENT event) or the
+current stream medatadata (TAG event) that is handled by the pad are 
+directly accessible by looking at the last event that traveled on the pad.
+
+By making the events stick on the pads, we can propagate them downstream
+automatically when new pads are linked. This should solve one of the
+biggest 0.10 problems when dealing with dynamic pipelines, the loss of
+events (mostly NEWSEGMENT events).
+
+It was then only natural to also make the CAPS event a sticky downstream 
+serialized event. CAPS are indeed also context for the buffers that follow.
+The caps property was also removed from GstBuffer, making caps negotiation
+separate from the buffer dataflow again.
+
+
+GstSegment changes
+------------------
+
+For the sticky events to work with SEGMENT events, we needed to change
+the SEGMENT event so that it became selfcontained. The complicated segment
+accumulation logic of 0.10 was simply removed and replaced with pad offsets.
+
+It is now possible to tweak the timing of the data comming from a pad by
+using the pad offset property.
+
+
+GstCaps optimizations
+---------------------
+
+It doesn't look like we'll be able to implement GstCaps iterators to 0.11 so
+Sebastian was looking for other ways to improve caps performance. One of the
+low hanging fruits was to pass the complete GstCaps structure to the
+GstBaseTransform transform_caps method. This allows for better and smarter
+implementations of the function at the cost of marginally more complex code.
+
+Sebastian also added a filter caps parameter to the gst_pad_get_caps()
+function. This allows the caller to pass preferences and possible caps to
+the function. The result is that the pad can make much better negotiation
+decisions.
+
+Sebastian also optimized gst_caps_is_subset()in the 0.10 branch and ported
+the results to 0.11 as well.
+
+with the still planned caps simplifications later, these changes should
+substantially improve caps negotiation speed.
+
+
+Pad probes
+----------
+
+Quite a few iterations were needed to reimplement the pad blocking and pad
+probes. The new infrastructure allows you to add callbacks for the various
+stages in the data transfer on a pad.
+
+It's now possible to be notified when no data is going over a pad with the
+IDLE probe. This should also fix one of the big problems with implementing
+dynamic pipelines and the old pad blocking.
+
+Not all features that we want to add to the new probes are implemented yet
+but they can be added later without much trouble.
+
+
+Other gems
+----------
+
+A new SCHEDULING query was added to get more information about the upstream
+elements scheduling properties. 
+
+Tim-Philipp Müller finally removed our dependency on libxml2. Back in the
+day, we used XML for serialization of objects and the registry. Object
+serialization had long been deprecated and the XML registry was replaced
+with a much faster binary registry.
+
+Tim also removed the unversioned gst-launch, gst-inspect and gst-typefind
+scripts. They were always confusing and annoying for packagers and users,
+it is just easier
+
+Edward Hervey spent some time keeping the unit tests working and making
+sure the API docs are up to data.
+
+GstIterator was made more binding friendly By Johan Dahlin and Sebastian.
+
+
+And what about the plugins..
+----------------------------
+
+As usual, all -base plugins are kept in sync with the core API updates and
+the new features. They are always a good place to see how the new API can
+be used and how to port things.
+
+
+What's next
+-----------
+
+Almost all of the features laid out in the GStreamer conference last year
+are now implemented. We also have quite a few new cool features that
+slipped in. Things are shaping up indeed.
+
+The last big missing piece is the redesign of the caps fields for raw audio
+and video. We plan to finish that in the next weeks.
+
+There are also a few smaller things we would like to do: use GstQuery
+for the various caps functions, do GstFlowReturn for the query/event
+functions, ...
+
+Meanwhile we start the stabilization phase and we will do a first prerelease
+of 0.11 this week to bring things to a wider audience. Now is the time to
+catch up and start porting your plugins to 0.11.
+
+There is still a lot of work to be done to port plugins to 0.11 before we
+can release 1.0. I ask everyone again (and especially maintainers) to help
+us porting plugins, it's really a lot of work!
+
+
+Have a nice hacking week,
+
+Wim
+
+
+
+
+
+
+
+
diff --git a/docs/random/use-cases-0.11.txt b/docs/random/use-cases-0.11.txt
new file mode 100644 (file)
index 0000000..6ba1d4d
--- /dev/null
@@ -0,0 +1,21 @@
+Use cases for 0.11
+------------------
+
+- improve performance 
+
+  * incremental caps
+  * cleanup caps fields
+  * Make miniobject a simple boxed type
+  * reverse negotiation with an event
+
+- buffer metadata
+
+  * Handle strides for video
+  * express crop, scaling, region of interest, ...
+  * Better support for foreign objects such as Cairo, OpenGL, OMX, ...
+
+- make dynamic pipelines easier
+
+  * sticky event propagation
+  * newsegment simplifications
+  * per-pad time offsets
diff --git a/docs/random/wtay/porting-list-0.11.txt b/docs/random/wtay/porting-list-0.11.txt
new file mode 100644 (file)
index 0000000..516292b
--- /dev/null
@@ -0,0 +1,586 @@
+ .Ported?
+ |  .Module
+ |  |    .Name
+ |  |    |               .Description
+ --------------------------------
+ * -core coreelements
+ * -core staticelements:  bin: Generic bin
+ * -core staticelements:  pipeline: Pipeline object
+
+ * -base adder:         adder: Adder
+ * -base alsa:          alsamixer: Alsa mixer
+ * -base alsa:          alsasink: Audio sink (ALSA)
+ * -base alsa:          alsasrc: Audio source (ALSA)
+ * -base app:           appsink: AppSink
+ * -base app:           appsrc: AppSrc
+ * -base audioconvert:  audioconvert: Audio converter
+ * -base audiorate:     audiorate: Audio rate adjuster
+ * -base audioresample: audioresample: Audio resampler
+ * -base audiotestsrc:  audiotestsrc: Audio test source
+ * -base cdparanoia:    cdparanoiasrc: CD Audio (cdda) Source, Paranoia IV
+ * -base encoding:      encodebin: Encoder Bin
+ * -base gdp:           gdpdepay: GDP Depayloader
+ * -base gdp:           gdppay: GDP Payloader
+ * -base gio:           giosink: GIO sink
+ * -base gio:           giosrc: GIO source
+ * -base gio:           giostreamsink: GIO stream sink
+ * -base gio:           giostreamsrc: GIO stream source
+ * -base libvisual:     libvisual_bumpscope: libvisual Bumpscope plugin plugin v.0.0.1
+ * -base libvisual:     libvisual_corona: libvisual libvisual corona plugin plugin v.0.1
+ * -base libvisual:     libvisual_infinite: libvisual infinite plugin plugin v.0.1
+ * -base libvisual:     libvisual_jakdaw: libvisual Jakdaw plugin plugin v.0.0.1
+ * -base libvisual:     libvisual_jess: libvisual jess plugin plugin v.0.1
+ * -base libvisual:     libvisual_lv_analyzer: libvisual libvisual analyzer plugin v.1.0
+ * -base libvisual:     libvisual_lv_scope: libvisual libvisual scope plugin v.0.1
+ * -base libvisual:     libvisual_oinksie: libvisual oinksie plugin plugin v.0.1
+ * -base ogg:           oggaviparse: Ogg AVI parser
+ * -base ogg:           oggdemux: Ogg demuxer
+ * -base ogg:           oggmux: Ogg muxer
+ * -base ogg:           oggparse: Ogg parser
+ * -base ogg:           ogmaudioparse: OGM audio stream parser
+ * -base ogg:           ogmtextparse: OGM text stream parser
+ * -base ogg:           ogmvideoparse: OGM video stream parser
+ * -base pango:         clockoverlay: Clock overlay
+ * -base pango:         textoverlay: Text overlay
+ * -base pango:         textrender: Text renderer
+ * -base pango:         timeoverlay: Time overlay
+ * -base playback:      playbin2: Player Bin 2
+ * -base playback:      playbin: Player Bin
+ * -base playback:      playsink: Player Sink
+ * -base playback:      subtitleoverlay: Subtitle Overlay
+ * -base subparse:      ssaparse: SSA Subtitle Parser
+ * -base subparse:      subparse: Subtitle parser
+ * -base subparse:      subparse_typefind: srt, sub, mpsub, mdvd, smi, txt, dks
+ * -base tcp:           multifdsink: Multi filedescriptor sink
+ * -base tcp:           tcpclientsink: TCP client sink
+ * -base tcp:           tcpclientsrc: TCP client source
+ * -base tcp:           tcpserversink: TCP server sink
+ * -base tcp:           tcpserversrc: TCP server source
+ * -base theora:        theoradec: Theora video decoder
+ * -base theora:        theoraenc: Theora video encoder
+ * -base theora:        theoraparse: Theora video parser
+ * -base typefindfunctions: application/msword: doc
+ * -base uridecodebin:  decodebin2: Decoder Bin
+ * -base uridecodebin:  uridecodebin: URI Decoder
+ * -base videoconvert:  videoconvert:  Colorspace converter
+ * -base videorate:     videorate: Video rate adjuster
+ * -base videoscale:    videoscale: Video scaler
+ * -base videotestsrc:  videotestsrc: Video test source
+ * -base volume:        volume: Volume
+ * -base vorbis:        vorbisdec: Vorbis audio decoder
+ * -base vorbis:        vorbisenc: Vorbis audio encoder
+ * -base vorbis:        vorbisparse: VorbisParse
+ * -base vorbis:        vorbistag: VorbisTag
+ * -base ximagesink:    ximagesink: Video sink
+ * -base xvimagesink:   xvimagesink: Video sink
+
+ * -good aasink:        aasink: ASCII art video sink
+ * -good alaw:          alawdec: A Law audio decoder
+ * -good alaw:          alawenc: A Law audio encoder
+ * -good alpha:         alpha: Alpha filter
+ * -good alphacolor:    alphacolor: Alpha color filter
+ * -good annodex:       cmmldec: CMML stream decoder
+ * -good annodex:       cmmlenc: CMML streams encoder
+ * -good audiofx:       audioamplify: Audio amplifier
+ * -good audiofx:       audiochebband: Band pass & band reject filter
+ * -good audiofx:       audiocheblimit: Low pass & high pass filter
+ * -good audiofx:       audiodynamic: Dynamic range controller
+ * -good audiofx:       audioecho: Audio echo
+ * -good audiofx:       audiofirfilter: Audio FIR filter
+ * -good audiofx:       audioiirfilter: Audio IIR filter
+ * -good audiofx:       audioinvert: Audio inversion
+ * -good audiofx:       audiokaraoke: AudioKaraoke
+ * -good audiofx:       audiopanorama: Stereo positioning
+ * -good audiofx:       audiowsincband: Band pass & band reject filter
+ * -good audiofx:       audiowsinclimit: Low pass & high pass filter
+ * -good audioparsers:  aacparse: AAC audio stream parser
+ * -good audioparsers:  ac3parse: AC3 audio stream parser
+ * -good audioparsers:  amrparse: AMR audio stream parser
+ * -good audioparsers:  dcaparse: DTS Coherent Acoustics audio stream parser
+ * -good audioparsers:  flacparse: FLAC audio parser
+ * -good audioparsers:  mpegaudioparse: MPEG1 Audio Parser
+ * -good auparse:       auparse: AU audio demuxer
+ * -good autodetect:    autoaudiosink: Auto audio sink
+ * -good autodetect:    autoaudiosrc: Auto audio source
+ * -good autodetect:    autovideosink: Auto video sink
+ * -good autodetect:    autovideosrc: Auto video source
+ * -good avi:           avidemux: Avi demuxer
+ * -good avi:           avimux: Avi muxer
+ * -good avi:           avisubtitle: Avi subtitle parser
+ * -good cacasink:      cacasink: A colored ASCII art video sink
+ * -good cutter:        cutter: Audio cutter
+ * -good debug:         breakmydata: Break my data
+ * -good debug:         capsdebug: Caps debug
+ * -good debug:         capssetter: CapsSetter
+ * -good debug:         cpureport: CPU report
+ * -good debug:         navseek: Seek based on left-right arrows
+ * -good debug:         progressreport: Progress report
+ * -good debug:         pushfilesrc: Push File Source
+ * -good debug:         rndbuffersize: Random buffer size
+ * -good debug:         taginject: TagInject
+ * -good debug:         testsink: Test plugin
+ * -good effectv:       dicetv: DiceTV effect
+ * -good effectv:       edgetv: EdgeTV effect
+ * -good effectv:       optv: OpTV effect
+ * -good effectv:       quarktv: QuarkTV effect
+ * -good effectv:       radioactv: RadioacTV effect
+ * -good effectv:       revtv: RevTV effect
+ * -good effectv:       rippletv: RippleTV effect
+ * -good effectv:       shagadelictv: ShagadelicTV
+ * -good effectv:       streaktv: StreakTV effect
+ * -good effectv:       vertigotv: VertigoTV effect
+ * -good effectv:       warptv: WarpTV effect
+ * -good equalizer:     equalizer-10bands: 10 Band Equalizer
+ * -good equalizer:     equalizer-3bands: 3 Band Equalizer
+ * -good equalizer:     equalizer-nbands: N Band Equalizer
+ * -good flac:          flacdec: FLAC audio decoder
+ * -good flac:          flacenc: FLAC audio encoder
+ * -good flac:          flactag: FLAC tagger
+ * -good flv:           flvdemux: FLV Demuxer
+ * -good flv:           flvmux: FLV muxer
+ * -good goom:          goom: GOOM: what a GOOM!
+ * -good gstrtpmanager: gstrtpbin: RTP Bin
+ * -good gstrtpmanager: gstrtpjitterbuffer: RTP packet jitter-buffer
+ * -good gstrtpmanager: gstrtpptdemux: RTP Demux
+ * -good gstrtpmanager: gstrtpsession: RTP Session
+ * -good gstrtpmanager: gstrtpssrcdemux: RTP SSRC Demux
+ * -good icydemux:      icydemux: ICY tag demuxer
+ * -good id3demux:      id3demux: ID3 tag demuxer
+ * -good isomp4:        3gppmux: 3GPP Muxer
+ * -good isomp4:        gppmux: 3GPP Muxer
+ * -good isomp4:        ismlmux: ISML Muxer
+ * -good isomp4:        mj2mux: MJ2 Muxer
+ * -good isomp4:        mp4mux: MP4 Muxer
+ * -good isomp4:        qtdemux: QuickTime demuxer
+ * -good isomp4:        qtmoovrecover: QT Moov Recover
+ * -good isomp4:        qtmux: QuickTime Muxer
+ * -good isomp4:        rtpxqtdepay: RTP packet depayloader
+ * -good jack:          jackaudiosink: Audio Sink (Jack)
+ * -good jack:          jackaudiosrc: Audio Source (Jack)
+ * -good jpeg:          jpegdec: JPEG image decoder
+ * -good jpeg:          jpegenc: JPEG image encoder
+ * -good effectv:       agingtv: AgingTV effect
+ * -good level:         level: Level
+ * -good mulaw:         mulawdec: Mu Law audio decoder
+ * -good mulaw:         mulawenc: Mu Law audio encoder
+ * -good multifile:     multifilesink: Multi-File Sink
+ * -good multifile:     multifilesrc: Multi-File Source
+ * -good multipart:     multipartdemux: Multipart demuxer
+ * -good multipart:     multipartmux: Multipart muxer
+ * -good navigationtest:  navigationtest: Video navigation test
+ * -good pulseaudio:    pulsemixer: PulseAudio Mixer
+ * -good pulseaudio:    pulsesink: PulseAudio Audio Sink
+ * -good pulseaudio:    pulsesrc: PulseAudio Audio Source
+ * -good replaygain:    rganalysis: ReplayGain analysis
+ * -good replaygain:    rglimiter: ReplayGain limiter
+ * -good replaygain:    rgvolume: ReplayGain volume
+ * -good rtp
+ * -good rtsp:          rtpdec: RTP Decoder
+ * -good rtsp:          rtspsrc: RTSP packet receiver
+ * -good shapewipe:     shapewipe: Shape Wipe transition filter
+ * -good soup:          souphttpclientsink: HTTP client sink
+ * -good soup:          souphttpsrc: HTTP client source
+ * -good spectrum:      spectrum: Spectrum analyzer
+ * -good speex:         speexdec: Speex audio decoder
+ * -good speex:         speexenc: Speex audio encoder
+ * -good udp:           dynudpsink: UDP packet sender
+ * -good udp:           multiudpsink: UDP packet sender
+ * -good udp:           udpsink: UDP packet sender
+ * -good udp:           udpsrc: UDP packet receiver
+ * -good video4linux2:  v4l2radio: Radio (video4linux2) Tuner
+ * -good video4linux2:  v4l2sink: Video (video4linux2) Sink
+ * -good video4linux2:  v4l2src: Video (video4linux2) Source
+ * -good videocrop:     aspectratiocrop: aspectratiocrop
+ * -good videocrop:     videocrop: Crop
+ * -good videofilter:   gamma: Video gamma correction
+ * -good videofilter:   videobalance: Video balance
+ * -good videofilter:   videoflip: Video flipper
+ * -good wavenc:        wavenc: WAV audio muxer
+ * -good wavparse:      wavparse: WAV audio demuxer
+ * -good ximagesrc:     ximagesrc: Ximage video source
+ * -good y4menc:        y4menc: YUV4MPEG video encoder
+
+ * -ugly a52dec:        a52dec: ATSC A/52 audio decoder
+ * -ugly amrwbdec:      amrwbdec: AMR-WB audio decoder
+ * -ugly amrnb:         amrnbdec: AMR-NB audio decoder
+ * -ugly amrnb:         amrnbenc: AMR-NB audio encoder
+ * -ugly asf:           asfdemux: ASF Demuxer
+ * -ugly asf:           rtpasfdepay: RTP ASF packet depayloader
+ * -ugly asf:           rtspwms: WMS RTSP Extension
+ * -ugly dvdlpcmdec:    dvdlpcmdec: DVD LPCM Audio decoder
+ * -ugly dvdread:       dvdreadsrc: DVD Source
+ * -ugly dvdsub:        dvdsubdec: DVD subtitle decoder
+ * -ugly dvdsub:        dvdsubparse: DVD subtitle parser
+ * -ugly lame:          lame: L.A.M.E. mp3 encoder
+ * -ugly lame:          lamemp3enc: L.A.M.E. mp3 encoder
+ * -ugly mad:           mad: mad mp3 decoder
+ * -ugly mpeg2dec:      mpeg2dec: mpeg1 and mpeg2 video decoder
+ * -ugly realmedia:     pnmsrc: PNM packet receiver
+ * -ugly realmedia:     rademux: RealAudio Demuxer
+ * -ugly realmedia:     rdtdepay: RDT packet parser
+ * -ugly realmedia:     rdtmanager: RTP Decoder
+ * -ugly realmedia:     rmdemux: RealMedia Demuxer
+ * -ugly realmedia:     rtspreal: RealMedia RTSP Extension
+ * -ugly siddec:        siddec: Sid decoder
+ * -ugly x264:          x264enc: x264enc
+
+ * -bad  assrender:     assrender: ASS/SSA Render
+ * -bad  bayer:         bayer2rgb: Bayer to RGB decoder for cameras
+ * -bad  bayer:         rgb2bayer: RGB to Bayer converter
+ * -bad  dataurisrc:    dataurisrc: data: URI source element
+ * -bad  dvb:           dvbbasebin: DVB bin
+ * -bad  dvb:           dvbsrc: DVB Source
+ * -bad  dvbsuboverlay: dvbsuboverlay: DVB Subtitles Overlay
+ * -bad  dvdspu:        dvdspu: Sub-picture Overlay
+ * -bad  faac:          faac: AAC audio encoder
+ * -bad  faad:          faad: AAC audio decoder
+ * -bad  flite:         flitetestsrc: Flite speech test source
+ * -bad  gmedec:        gmedec: Gaming console music file decoder
+ * -bad  jpegformat:    jifmux: JPEG stream muxer
+ * -bad  jpegformat:    jpegparse: JPEG stream parser
+ * -bad  kate:          katedec: Kate stream text decoder
+ * -bad  kate:          kateenc: Kate stream encoder
+ * -bad  kate:          kateparse: Kate stream parser
+ * -bad  kate:          katetag: Kate stream tagger
+ * -bad  mms:           mmssrc: MMS streaming source
+ * -bad  mpeg4videoparse:  mpeg4videoparse: MPEG 4 video elementary stream parser
+ * -bad  mpegtsdemux:   tsdemux: MPEG transport stream demuxer
+ * -bad  mpegtsdemux:   tsparse: MPEG transport stream parser
+ * -bad  rtmpsrc:       rtmpsrc: RTMP Source
+ * -bad  rtmpsink:      rtmpsink:
+ * -bad  sdp:           sdpdemux: SDP session setup
+ * -bad  y4mdec:        y4mdec: YUV4MPEG demuxer/decoder
+ * -bad  zbar:          zbar: Barcode detector
+
+ * -ff   ffmpeg:
+ * -ff   ffvideoscale:  ffvideoscale: FFMPEG Scale element
+ * -ff   postproc:
+
+ * gnl   gnonlin:       gnlcomposition: GNonLin Composition
+ * gnl   gnonlin:       gnloperation: GNonLin Operation
+ * gnl   gnonlin:       gnlsource: GNonLin Source
+ * gnl   gnonlin:       gnlurisource: GNonLin URI Source
+
+ -- essential --
+
+   -good apetag:        apedemux: APE tag demuxer
+   -bad  celt:          celtdec: Celt audio decoder
+   -bad  celt:          celtenc: Celt audio encoder
+   -bad  dtsdec:        dtsdec: DTS audio decoder
+   -good dv:            dvdec: DV video decoder
+   -good dv:            dvdemux: DV system stream demuxer
+   -bad  gsm:           gsmdec: GSM audio decoder
+   -bad  gsm:           gsmenc: GSM audio encoder
+   -bad  jp2k:          jp2kdec: Jasper JPEG2000 image decoder
+   -bad  jp2k:          jp2kenc: Jasper JPEG2000 image encoder
+   -good matroska:      matroskademux: Matroska demuxer
+   -good matroska:      matroskamux: Matroska muxer
+   -good matroska:      matroskaparse: Matroska parser
+   -good matroska:      webmmux: WebM muxer
+   -bad  musepack:      musepackdec: Musepack decoder
+   -bad  opus:          opusdec:
+   -bad  opus:          opusenc:
+   -bad  resindvd:      rsndvdbin: rsndvdbin
+   -bad  schro:         schrodec: Dirac Decoder
+   -bad  schro:         schroenc: Dirac Encoder
+   -bad  vp8:           vp8dec: On2 VP8 Decoder
+   -bad  vp8:           vp8enc: On2 VP8 Encoder
+   -good wavpack:       wavpackdec: Wavpack audio decoder
+   -good wavpack:       wavpackenc: Wavpack audio encoder
+   -good wavpack:       wavpackparse: Wavpack parser
+
+ -- non essential --
+
+   -good 1394:          dv1394src: Firewire (1394) DV video source
+   -good 1394:          hdv1394src: Firewire (1394) HDV video source
+
+   -bad  acmenc:        
+   -bad  acmmp3dec:     acmmp3dec      
+   -bad  adpcmdec:      adpcmdec: ADPCM decoder
+   -bad  adpcmenc:      adpcmenc: ADPCM encoder
+   -bad  aiff:          aiffmux: AIFF audio muxer
+   -bad  aiff:          aiffparse: AIFF audio demuxer
+   -bad  apexsink:      apexsink: Apple AirPort Express Audio Sink
+   -bad  applemedia:
+   -bad  asfmux:        asfmux: ASF muxer
+   -bad  asfmux:        asfparse: ASF parser
+   -bad  asfmux:        rtpasfpay: RTP ASF payloader
+   -bad  autoconvert:   autoconvert: Select convertor based on caps
+   -bad  autoconvert:   autovideoconvert: Select color space convertor based on caps
+   -bad  avcsrc:        avcsrc:
+
+         bluetooth:     a2dpsink: Bluetooth A2DP sink
+         bluetooth:     avdtpsink: Bluetooth AVDTP sink
+         bluetooth:     rtpsbcpay: RTP packet payloader
+         bluetooth:     sbcdec: Bluetooth SBC decoder
+         bluetooth:     sbcenc: Bluetooth SBC encoder
+         bluetooth:     sbcparse: Bluetooth SBC parser
+         bluetooth:     sbc: sbc
+   -bad  bz2:           bz2dec: BZ2 decoder
+   -bad  bz2:           bz2enc: BZ2 encoder
+
+   -good cairo:         cairooverlay: Cairo overlay
+   -good cairo:         cairorender: Cairo encoder
+   -good cairo:         cairotextoverlay: Text overlay
+   -good cairo:         cairotimeoverlay: Time overlay
+   -bad  camerabin2:    camerabin2: CameraBin2
+   -bad  camerabin2:    imagecapturebin: Image Capture Bin
+   -bad  camerabin2:    viewfinderbin: Viewfinder Bin
+   -bad  camerabin2:    wrappercamerabinsrc: V4l2 camera src element for camerabin
+   -bad  camerabin:     camerabin: Camera Bin
+   -bad  cdaudio:       cdaudio: CD player
+   -ugly cdio:          cdiocddasrc: CD audio source (CDDA)
+   -bad  cdxaparse:     cdxaparse: (S)VCD parser
+   -bad  cdxaparse:     vcdparse: (S)VCD stream parser
+   -bad  cog:           cogcolorconvert: Convert colorspace
+   -bad  cog:           cogcolorspace: YCbCr/RGB format conversion
+   -bad  cog:           cogdownsample: Scale down video by factor of 2
+   -bad  cog:           coglogoinsert: Overlay image onto video
+   -bad  cog:           cogmse: Calculate MSE
+   -bad  cog:           cogscale: Video scaler
+   -bad  coloreffects:  chromahold: Chroma hold filter
+   -bad  coloreffects:  coloreffects: Color Look-up Table filter
+   -bad  curl:          curlsink: Curl sink
+         cutter-test:   cutter-console-output: Cutter console output
+         cutter-test:   cutter-server: Cutter test server
+         cutter-test:   cutter-test-runner: Cutter test runner
+
+   -bad  d3dsinkwrapper: d3dvideosink:
+   -bad  dc1394:        dc1394src: 1394 IIDC Video Source
+   -bad  dccp:          dccpclientsink: DCCP client sink
+   -bad  dccp:          dccpclientsrc: DCCP client source
+   -bad  dccp:          dccpserversink: DCCP server sink
+   -bad  dccp:          dccpserversrc: DCCP server source
+   -bad  debugutilsbad: checksumsink: Checksum sink
+   -bad  debugutilsbad: chopmydata: FIXME
+   -bad  debugutilsbad: fpsdisplaysink: Measure and show framerate on videosink
+   -bad  decklink:      decklinksink: Decklink Sink
+   -bad  decklink:      decklinksrc: Decklink source
+   -good deinterlace:   deinterlace: Deinterlacer
+   -bad  directdraw :   directdrawsink: 
+   -good directsound:   directsoundsink: Direct Sound Audio Sink
+   -bad  directsoundsrc: directsoundsrc: Direct Sound Audio Source
+   -bad  divxdec:       divxdec:
+   -bad  divxenc:       divxenc:
+   -bad  dfbvideosink:  dfbvideosink: DirectFB video sink
+   -bad  dirac:         diracenc: Dirac Encoder
+   -bad  dshowdecwrapper:
+   -bad  dshowsrcwrapper: dshowaudiosrc
+   -bad  dshowsrcwrapper: dshowvideosrc
+   -bad  dshowsinkwrapper: dshowvideosink
+   -bad  dtmf:          dtmfdetect: DTMF detector element
+   -bad  dtmf:          dtmfsrc: DTMF tone generator
+   -bad  dtmf:          rtpdtmfdepay: RTP DTMF packet depayloader
+   -bad  dtmf:          rtpdtmfsrc: RTP DTMF packet generator
+   -bad  dxr3:          dxr3videosink
+   -bad  dxr3:          dxr3audiosink
+   -bad  dxr3:          dxr3spusink
+
+   -good efence:        efence: Electric Fence
+   -good esdsink:       esdsink: Esound audio sink
+
+   -bad  fbdevsink:     fbdevsink: fbdev video sink
+   -bad  festival:      festival: Festival Text-to-Speech synthesizer
+   -bad  fieldanalysis: fieldanalysis: Video field analysis
+   -good flxdec:        flxdec: FLX video decoder
+   -bad  fragmented:    hlsdemux: HLS Demuxer
+   -bad  freeze:        freeze: Stream freezer
+   -bad  frei0r:
+         fsfunnel:        fsfunnel: Farsight Funnel pipe fitting
+         fsmsnconference: fsmsncamrecvconference: Farsight MSN Reception Conference
+         fsmsnconference: fsmsncamsendconference: Farsight MSN Sending Conference
+         fsrawconference: fsrawconference: Generic bin
+         fsrtcpfilter:    fsrtcpfilter: RTCP Filter element
+         fsrtpconference: fsrtpconference: Farsight RTP Conference
+         fsvideoanyrate:  fsvideoanyrate: Videoanyrate element
+
+   -bad  gaudieffects:  burn: Burn
+   -bad  gaudieffects:  chromium: Chromium
+   -bad  gaudieffects:  dilate: Dilate
+   -bad  gaudieffects:  dodge: Dodge
+   -bad  gaudieffects:  exclusion: Exclusion
+   -bad  gaudieffects:  gaussianblur: GaussBlur
+   -bad  gaudieffects:  solarize: Solarize
+   -good gconfelements: gconfaudiosink: GConf audio sink
+   -good gconfelements: gconfaudiosrc: GConf audio source
+   -good gconfelements: gconfvideosink: GConf video sink
+   -good gconfelements: gconfvideosrc: GConf video source
+   -good gdkpixbuf:     gdkpixbufdec: GdkPixbuf image decoder
+   -good gdkpixbuf:     gdkpixbufscale: GdkPixbuf image scaler
+   -good gdkpixbuf:     gdkpixbufsink: GdkPixbuf sink
+   -bad  geometrictransform:  bulge: bulge
+   -bad  geometrictransform:  circle: circle
+   -bad  geometrictransform:  diffuse: diffuse
+   -bad  geometrictransform:  fisheye: fisheye
+   -bad  geometrictransform:  kaleidoscope: kaleidoscope
+   -bad  geometrictransform:  marble: marble
+   -bad  geometrictransform:  mirror: mirror
+   -bad  geometrictransform:  pinch: pinch
+   -bad  geometrictransform:  rotate: rotate
+   -bad  geometrictransform:  sphere: sphere
+   -bad  geometrictransform:  square: square
+   -bad  geometrictransform:  stretch: stretch
+   -bad  geometrictransform:  tunnel: tunnel
+   -bad  geometrictransform:  twirl: twirl
+   -bad  geometrictransform:  waterripple: waterripple
+   -good goom2k1:       goom2k1: GOOM: what a GOOM! 2k1 edition
+   -bad  gsettings:     gsettingsaudiosink: GSettings audio sink
+   -bad  gsettings:     gsettingsaudiosrc: GSettings audio src
+   -bad  gsettings:     gsettingsvideosink: GSettings video sink
+   -bad  gsettings:     gsettingsvideosrc: GSettings video src
+   -bad  gstsiren:      sirendec: Siren Decoder element
+   -bad  gstsiren:      sirenenc: Siren Encoder element
+
+   -bad  h264parse:     legacyh264parse: H264Parse
+   -bad  hdvparse:      hdvparse: HDVParser
+
+   -bad  id3tag:        id3mux: ID3 v1 and v2 Muxer
+   -ugly iec958:        ac3iec958: AC3 to IEC958 filter
+   -good imagefreeze:   imagefreeze: Still frame stream generator
+   -bad  interlace:     interlace: Interlace filter
+   -good interleave:    deinterleave: Audio deinterleaver
+   -good interleave:    interleave: Audio interleaver
+   -bad  invtelecine:   invtelecine: Inverse Telecine filter
+   -bad  ivfparse:      ivfparse: IVF parser
+
+   -bad  jp2kdecimator: jp2kdecimator: JPEG2000 decimator
+   -good jpeg:          smokedec: Smoke video decoder
+   -good jpeg:          smokeenc: Smoke video encoder
+
+
+   -bad  ladspa:       
+   -bad  legacyresample: legacyresample: Audio scaler
+   -bad  linsys:        linsyssdisink: SDI video sink
+   -bad  linsys:        linsyssdisrc: SDI video source
+   -bad  liveadder:     liveadder: Live Adder element
+   -bad  lv2:
+
+   -bad  mimic:         mimdec: Mimic Decoder
+   -bad  mimic:         mimenc: Mimic Encoder
+   -bad  modplug:       modplug: ModPlug
+   -good monoscope:     monoscope: Monoscope
+   -bad  mpeg2enc:      mpeg2enc: mpeg2enc video encoder
+   -bad  mpegdemux2:    mpegpsdemux: The Fluendo MPEG Program Stream Demuxer
+   -bad  mpegdemux2:    mpegtsdemux: The Fluendo MPEG Transport stream demuxer
+   -bad  mpegdemux2:    mpegtsparse: MPEG transport stream parser
+   -bad  mpegpsmux:     mpegpsmux: MPEG Program Stream Muxer
+   -ugly mpegstream:    dvddemux: DVD Demuxer
+   -ugly mpegstream:    mpegdemux: MPEG Demuxer
+   -ugly mpegstream:    mpegparse: MPEG System Parser
+   -bad  mpegtsmux:     mpegtsmux: MPEG Transport Stream Muxer
+   -bad  mpegvideoparse:  mpegvideoparse: MPEG video elementary stream parser
+   -bad  mplex:         mplex: mplex video multiplexer
+   -bad  musicbrainz:   trm: MusicBrainz TRM generator
+   -bad  mve:           mvedemux: MVE Demuxer
+   -bad  mve:           mvemux: MVE Multiplexer
+   -bad  mythtv:        mythtvsrc:
+   -bad  mxf:           mxfdemux: MXF Demuxer
+   -bad  mxf:           mxfmux: MXF muxer
+
+   -bad  nas:           nassink:
+         nice:          nicesink: ICE sink
+         nice:          nicesrc: ICE source
+   -bad  nsf:           nsfdec: Nsf decoder
+   -bad  nuvdemux:      nuvdemux: Nuv demuxer
+
+   -bad  ofa:           ofa: OFA
+   -bad  openal:        openalsink:
+   -bad  openal:        openalsrc:
+   -bad  opencv:
+   -good oss4:          oss4mixer: OSS v4 Audio Mixer
+   -good oss4:          oss4sink: OSS v4 Audio Sink
+   -good oss4:          oss4src: OSS v4 Audio Source
+   -good ossaudio:      ossmixer: OSS Mixer
+   -good ossaudio:      osssink: Audio Sink (OSS)
+   -good ossaudio:      osssrc: Audio Source (OSS)
+   -good osxaudio:      osxaudiosink: Audio Sink (OSX)
+   -good osxaudio:      osxaudiosrc: Audio Source (OSX)
+   -good osxvideo:      osxvideosink: Video Sink (OSX)
+   -bad  osxvideosrc:   osxvideosrc: Video Source (OSX)
+
+   -bad  patchdetect:   patchdetect: Color Patch Detector
+   -bad  pcapparse:     pcapparse: PCapParse
+   -good png:           pngdec: PNG image decoder
+   -good png:           pngenc: PNG image encoder
+   -bad  pnm:           pnmdec: PNM image decoder
+   -bad  pnm:           pnmenc: PNM image encoder
+
+   -bad  qtwrapper:
+
+   -bad  rawparse:      audioparse: Audio Parse
+   -bad  rawparse:      videoparse: Video Parse
+   -bad  rfbsrc:        rfbsrc: Rfb source
+   -bad  rsvg:          rsvgdec: SVG image decoder
+   -bad  rsvg:          rsvgoverlay: RSVG overlay
+   -bad  rtpmux:        rtpdtmfmux: RTP muxer
+   -bad  rtpmux:        rtpmux: RTP muxer
+   -bad  rtpvp8:        rtpvp8depay: RTP VP8 depayloader
+   -bad  rtpvp8:        rtpvp8pay: RTP VP8 payloader
+
+   -bad  scaletempo:    scaletempo: Scaletempo
+   -bad  sdi:           sdidemux: SDI Demuxer
+   -bad  sdi:           sdimux: SDI Muxer
+   -bad  sdl:           sdlaudiosink: SDL audio sink
+   -bad  sdl:           sdlvideosink: SDL video sink
+   -bad  segmentclip:   audiosegmentclip: Audio buffer segment clipper
+   -bad  segmentclip:   videosegmentclip: Video buffer segment clipper
+   -bad  shm:           shmsink: Shared Memory Sink
+   -bad  shm:           shmsrc: Shared Memory Source
+   -good shout2send:    shout2send: Icecast network sink
+   -good smpte:         smptealpha: SMPTE transitions
+   -good smpte:         smpte: SMPTE transitions
+   -bad  sndfile:       sfsink: Sndfile sink
+   -bad  sndfile:       sfsrc: Sndfile source
+   -bad  soundtouch:    bpmdetect: BPM Detector
+   -bad  soundtouch:    pitch: Pitch controller
+   -bad  spandsp:       spanplc:
+   -bad  spcdec:        spcdec:
+   -bad  speed:         speed: Speed
+   -bad  stereo:        stereo: Stereo effect
+   -bad  subenc:        srtenc: Srt encoder
+   -good sunaudio:      sunaudiomixer:
+   -good sunaudio:      sunaudiosink:
+   -good sunaudio:      sunaudiosrc:
+
+   -good taglib:        apev2mux: TagLib-based APEv2 Muxer
+   -good taglib:        id3v2mux: TagLib-based ID3v2 Muxer
+   -bad  teletext:      teletextdec:
+   -bad  timidity:      timidity:
+   -bad  tta:           ttadec: TTA audio decoder
+   -bad  tta:           ttaparse: TTA file parser
+   -ugly twolame:       twolame: TwoLAME mp2 encoder
+
+   -bad  vcdsrc:        vcdsrc: VCD Source
+   -bad  vdpau:
+   -good videobox:      videobox: Video box filter
+   -bad  videofiltersbad: scenechange: Scene change detector
+   -bad  videofiltersbad: zebrastripe: Zebra stripe overlay
+   -bad  videomaxrate:  videomaxrate: Video maximum rate adjuster
+   -bad  videomeasure:  measurecollector: Video measure collector
+   -bad  videomeasure:  ssim: SSim
+   -good videomixer:    videomixer2: Video mixer 2
+   -good videomixer:    videomixer: Video mixer
+   -bad  videoparsersbad: diracparse: Dirac parser
+   -bad  videoparsersbad: h263parse: H.263 parser
+   -bad  videoparsersbad: h264parse: H.264 parser
+   -bad  videosignal:   videoanalyse: Video analyser
+   -bad  videosignal:   videodetect: Video detecter
+   -bad  videosignal:   videomark: Video marker
+
+   -bad  vmnc:          vmncdec: VMnc video decoder
+   -bad  voaacenc:      voaacenc:
+   -bad  voamrwbenc:    voamrwbenc:
+
+   -bad  wasapi:        wasapisrc
+   -bad  wasapi:        wasapisink
+   -good waveform:      waveformsink:
+   -bad  wildmidi:      wildmidi: WildMidi
+   -bad  wininet:       wininetsrc:
+   -bad  winks:         ksvideosrc:
+   -bad  winscreencap:  gdiscreencapsrc
+   -bad  winscreencap:  dx9screencapsrc
+
+   -ugly xingmux:       xingmux: MP3 Xing muxer
+   -bad  xvid:          xviddec: XviD video decoder
+   -bad  xvid:          xvidenc: XviD video encoder
+
index 60d4b11..c0e032b 100644 (file)
@@ -1,11 +1,5 @@
 lib_LTLIBRARIES = libgstreamer-@GST_MAJORMINOR@.la
 
-if GST_DISABLE_LOADSAVE
-GST_LOADSAVE_SRC =
-else
-GST_LOADSAVE_SRC = gstxml.c
-endif
-
 if GST_DISABLE_REGISTRY
 GST_REGISTRY_SRC =
 else
@@ -44,7 +38,7 @@ built_header_make = gstenumtypes.h gstmarshal.h
 built_source_make = gstenumtypes.c gstmarshal.c
 
 EXTRA_libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
-       gstmarshal.list gsttrace.c gstxml.c \
+       gstmarshal.list gsttrace.c \
        gstregistrybinary.c
 
 
@@ -57,26 +51,27 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
        gstbin.c                \
        gstbuffer.c             \
        gstbufferlist.c         \
+       gstbufferpool.c         \
        gstbus.c                \
        gstcaps.c               \
        gstchildproxy.c         \
        gstclock.c              \
+       gstcontrolbinding.c \
+       gstcontrolsource.c \
        gstdatetime.c           \
        gstdebugutils.c         \
        gstelement.c            \
        gstelementfactory.c     \
        gsterror.c              \
        gstevent.c              \
-       gstfilter.c             \
        gstformat.c             \
        gstghostpad.c           \
-       gstindex.c              \
-       gstindexfactory.c       \
        gstinfo.c               \
-       gstinterface.c          \
        gstiterator.c           \
        gstatomicqueue.c        \
        gstmessage.c            \
+       gstmeta.c               \
+       gstmemory.c             \
        gstminiobject.c         \
        gstpad.c                \
        gstpadtemplate.c        \
@@ -91,6 +86,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
        gstquery.c              \
        gstregistry.c           \
        gstregistrychunks.c     \
+       gstsample.c             \
        gstsegment.c            \
        gststructure.c          \
        gstsystemclock.c        \
@@ -105,8 +101,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
        gstutils.c              \
        gstvalue.c              \
        gstparse.c              \
-       $(GST_REGISTRY_SRC)     \
-       $(GST_LOADSAVE_SRC)
+       $(GST_REGISTRY_SRC)
 
 # do not put files in the distribution that are generated
 nodist_libgstreamer_@GST_MAJORMINOR@_la_SOURCES = $(built_source_make)
@@ -134,7 +129,6 @@ libgstreamer_@GST_MAJORMINOR@_la_LIBADD =           \
        $(GST_PARSE_LA)                                 \
        $(GST_ALL_LIBS)                                 \
        $(WIN32_LIBS)                                   \
-       $(XML_LIBS)                                     \
        $(LIBM)
 
 libgstreamer_@GST_MAJORMINOR@_la_LDFLAGS =             \
@@ -149,28 +143,30 @@ gst_headers =                     \
        gstbin.h                \
        gstbuffer.h             \
        gstbufferlist.h         \
+       gstbufferpool.h         \
        gstbus.h                \
        gstcaps.h               \
        gstchildproxy.h         \
        gstclock.h              \
        gstcompat.h             \
+       gstcontrolbinding.h \
+       gstcontrolsource.h \
        gstdatetime.h           \
        gstdebugutils.h         \
        gstelement.h            \
+       gstelementmetadata.h    \
        gstelementfactory.h     \
        gsterror.h              \
        gstevent.h              \
-       gstfilter.h             \
        gstformat.h             \
        gstghostpad.h           \
-       gstindex.h              \
-       gstindexfactory.h       \
        gstinfo.h               \
-       gstinterface.h          \
        gstiterator.h           \
        gstatomicqueue.h        \
        gstmacros.h             \
        gstmessage.h            \
+       gstmeta.h               \
+       gstmemory.h             \
        gstminiobject.h         \
        gstpad.h                \
        gstpadtemplate.h        \
@@ -181,6 +177,7 @@ gst_headers =                       \
        gstpoll.h               \
        gstpreset.h             \
        gstquery.h              \
+       gstsample.h             \
        gstsegment.h            \
        gststructure.h          \
        gstsystemclock.h        \
@@ -195,8 +192,7 @@ gst_headers =                       \
        gstutils.h              \
        gstvalue.h              \
        gstregistry.h           \
-       gstparse.h              \
-       gstxml.h
+       gstparse.h
 
 libgstreamer_@GST_MAJORMINOR@include_HEADERS = $(gst_headers) math-compat.h
 
@@ -208,7 +204,7 @@ noinst_HEADERS =            \
        glib-compat-private.h   \
        gst-i18n-lib.h          \
        gst-i18n-app.h          \
-       gstelementdetails.h     \
+       gstelementmetadata.h    \
        gstpluginloader.h       \
        gstquark.h              \
        gstregistrybinary.h     \
@@ -275,22 +271,22 @@ Gst-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstreamer-@GST_MAJORMINOR@
        $(AM_V_GEN)GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
                $(INTROSPECTION_SCANNER) -v --namespace Gst \
                --nsversion=@GST_MAJORMINOR@ \
+               --warn-all \
                -I$(top_srcdir) \
                -I$(top_builddir) \
                -DIN_GOBJECT_INTROSPECTION=1 \
+               -DGST_USE_UNSTABLE_API \
                --c-include='gst/gst.h' \
-               --library=libgstreamer-0.10.la \
+               --library=libgstreamer-0.11.la \
                --include=GLib-2.0 \
                --include=GObject-2.0 \
                --include=GModule-2.0 \
-               --include=libxml2-2.0 \
                --libtool="$(top_builddir)/libtool" \
                --pkg glib-2.0 \
                --pkg gobject-2.0 \
                --pkg gmodule-no-export-2.0 \
                --pkg gthread-2.0 \
-               --pkg libxml-2.0 \
-               --pkg-export gstreamer-0.10 \
+               --pkg-export gstreamer-@GST_MAJORMINOR@ \
                --add-init-section="gst_init(NULL, NULL);" \
                --output $@ \
                $(gir_headers) \
index b9248e6..9a92993 100644 (file)
 
 G_BEGIN_DECLS
 
-#if !GLIB_CHECK_VERSION(2,25,0)
-
-#if defined (_MSC_VER) && !defined(_WIN64)
-typedef struct _stat32 GStatBuf;
-#else
-typedef struct stat GStatBuf;
-#endif
-
-#endif
-
-#if GLIB_CHECK_VERSION(2,26,0)
-#define GLIB_HAS_GDATETIME
-#endif
-
-/* See bug #651514 */
-#if GLIB_CHECK_VERSION(2,29,5)
-#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
-    g_atomic_pointer_compare_and_exchange ((a),(b),(c))
-#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
-    g_atomic_int_compare_and_exchange ((a),(b),(c))
-#else
-#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
-    g_atomic_pointer_compare_and_exchange ((volatile gpointer *)(a),(b),(c))
-#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
-    g_atomic_int_compare_and_exchange ((volatile int *)(a),(b),(c))
-#endif
-
-/* See bug #651514 */
-#if GLIB_CHECK_VERSION(2,29,5)
-#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_add ((a),(b))
-#else
-#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_exchange_and_add ((a),(b))
-#endif
-
 /* copies */
 
-#if GLIB_CHECK_VERSION (2, 31, 0)
-#define g_mutex_new gst_g_mutex_new
-static inline GMutex *
-gst_g_mutex_new (void)
-{
-  GMutex *mutex = g_slice_new (GMutex);
-  g_mutex_init (mutex);
-  return mutex;
-}
-#define g_mutex_free gst_g_mutex_free
-static inline void
-gst_g_mutex_free (GMutex *mutex)
-{
-  g_mutex_clear (mutex);
-  g_slice_free (GMutex, mutex);
-}
-#define g_static_rec_mutex_init gst_g_static_rec_mutex_init
-static inline void
-gst_g_static_rec_mutex_init (GStaticRecMutex *mutex)
-{
-  static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
-
-  *mutex = init_mutex;
-}
-#define g_cond_new gst_g_cond_new
-static inline GCond *
-gst_g_cond_new (void)
-{
-  GCond *cond = g_slice_new (GCond);
-  g_cond_init (cond);
-  return cond;
-}
-#define g_cond_free gst_g_cond_free
-static inline void
-gst_g_cond_free (GCond *cond)
-{
-  g_cond_clear (cond);
-  g_slice_free (GCond, cond);
-}
-#define g_cond_timed_wait gst_g_cond_timed_wait
-static inline gboolean
-gst_g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *abs_time)
-{
-  gint64 end_time;
-
-  if (abs_time == NULL) {
-    g_cond_wait (cond, mutex);
-    return TRUE;
-  }
-
-  end_time = abs_time->tv_sec;
-  end_time *= 1000000;
-  end_time += abs_time->tv_usec;
-
-  /* would be nice if we had clock_rtoffset, but that didn't seem to
-   * make it into the kernel yet...
-   */
-  /* if CLOCK_MONOTONIC is not defined then g_get_montonic_time() and
-   * g_get_real_time() are returning the same clock and we'd add ~0
-   */
-  end_time += g_get_monotonic_time () - g_get_real_time ();
-  return g_cond_wait_until (cond, mutex, end_time);
-}
-#endif /* GLIB_CHECK_VERSION (2, 31, 0) */
-
 /* adaptations */
 
 G_END_DECLS
index ff7f250..84b9552 100644 (file)
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -283,7 +283,7 @@ DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 #endif
 
 /**
- * gst_init_get_option_group:
+ * gst_init_get_option_group: (skip)
  *
  * Returns a #GOptionGroup with GStreamer's argument specifications. The
  * group is set up to use standard GOption callbacks, so when using this
@@ -360,32 +360,6 @@ gst_init_get_option_group (void)
     {NULL}
   };
 
-/* Since GLib 2.31.0 threading is always enabled and g_thread_init()
- * is not needed any longer and deprecated */
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  /* Since GLib 2.23.2 calling g_thread_init() 'late' is allowed and is
-   * automatically done as part of g_type_init() */
-  if (glib_check_version (2, 23, 3)) {
-    /* The GLib threading system must be initialised before calling any other
-     * GLib function according to the documentation; if the application hasn't
-     * called gst_init() yet or initialised the threading system otherwise, we
-     * better issue a warning here (since chances are high that the application
-     * has already called other GLib functions such as g_option_context_new() */
-    if (!g_thread_get_initialized ()) {
-      g_warning ("The GStreamer function gst_init_get_option_group() was\n"
-          "\tcalled, but the GLib threading system has not been initialised\n"
-          "\tyet, something that must happen before any other GLib function\n"
-          "\tis called. The application needs to be fixed so that it calls\n"
-          "\t   if (!g_thread_get_initialized ()) g_thread_init(NULL);\n"
-          "\tas very first thing in its main() function. Please file a bug\n"
-          "\tagainst this application.");
-      g_thread_init (NULL);
-    }
-  } else {
-    /* GLib >= 2.23.2 */
-  }
-#endif
-
   group = g_option_group_new ("gst", _("GStreamer Options"),
       _("Show GStreamer Options"), NULL, NULL);
   g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre,
@@ -428,11 +402,6 @@ gst_init_check (int *argc, char **argv[], GError ** err)
 #endif
   gboolean res;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  if (!g_thread_get_initialized ())
-    g_thread_init (NULL);
-#endif
-
   if (gst_initialized) {
     GST_DEBUG ("already initialized gst");
     return TRUE;
@@ -580,13 +549,10 @@ init_pre (GOptionContext * context, GOptionGroup * group, gpointer data,
 
   g_type_init ();
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  /* we need threading to be enabled right here */
-  g_assert (g_thread_get_initialized ());
+#ifndef GST_DISABLE_GST_DEBUG
+  _priv_gst_debug_init ();
 #endif
 
-  _gst_debug_init ();
-
 #ifdef ENABLE_NLS
   setlocale (LC_ALL, "");
   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
@@ -673,8 +639,15 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_log_set_handler (g_log_domain_gstreamer, llf, debug_log_handler, NULL);
 
   _priv_gst_quarks_initialize ();
-  _gst_format_initialize ();
-  _gst_query_initialize ();
+  _priv_gst_memory_initialize ();
+  _priv_gst_format_initialize ();
+  _priv_gst_query_initialize ();
+  _priv_gst_structure_initialize ();
+  _priv_gst_caps_initialize ();
+  _priv_gst_meta_initialize ();
+
+  g_mutex_init (&_gst_trace_mutex);
+
   g_type_class_ref (gst_object_get_type ());
   g_type_class_ref (gst_pad_get_type ());
   g_type_class_ref (gst_element_factory_get_type ());
@@ -685,14 +658,12 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_task_get_type ());
   g_type_class_ref (gst_clock_get_type ());
 
-  g_type_class_ref (gst_index_factory_get_type ());
   gst_uri_handler_get_type ();
 
   g_type_class_ref (gst_object_flags_get_type ());
   g_type_class_ref (gst_bin_flags_get_type ());
-  g_type_class_ref (gst_buffer_flag_get_type ());
+  g_type_class_ref (gst_buffer_flags_get_type ());
   g_type_class_ref (gst_buffer_copy_flags_get_type ());
-  g_type_class_ref (gst_buffer_list_item_get_type ());
   g_type_class_ref (gst_bus_flags_get_type ());
   g_type_class_ref (gst_bus_sync_reply_get_type ());
   g_type_class_ref (gst_caps_flags_get_type ());
@@ -715,12 +686,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_seek_flags_get_type ());
   g_type_class_ref (gst_qos_type_get_type ());
   g_type_class_ref (gst_format_get_type ());
-  g_type_class_ref (gst_index_certainty_get_type ());
-  g_type_class_ref (gst_index_entry_type_get_type ());
-  g_type_class_ref (gst_index_lookup_method_get_type ());
-  g_type_class_ref (gst_assoc_flags_get_type ());
-  g_type_class_ref (gst_index_resolver_method_get_type ());
-  g_type_class_ref (gst_index_flags_get_type ());
   g_type_class_ref (gst_debug_level_get_type ());
   g_type_class_ref (gst_debug_color_flags_get_type ());
   g_type_class_ref (gst_iterator_result_get_type ());
@@ -730,7 +695,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_pad_link_return_get_type ());
   g_type_class_ref (gst_pad_link_check_get_type ());
   g_type_class_ref (gst_flow_return_get_type ());
-  g_type_class_ref (gst_activate_mode_get_type ());
+  g_type_class_ref (gst_pad_mode_get_type ());
   g_type_class_ref (gst_pad_direction_get_type ());
   g_type_class_ref (gst_pad_flags_get_type ());
   g_type_class_ref (gst_pad_presence_get_type ());
@@ -750,28 +715,36 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_task_state_get_type ());
   g_type_class_ref (gst_alloc_trace_flags_get_type ());
   g_type_class_ref (gst_type_find_probability_get_type ());
+  g_type_class_ref (gst_uri_error_get_type ());
   g_type_class_ref (gst_uri_type_get_type ());
   g_type_class_ref (gst_parse_error_get_type ());
   g_type_class_ref (gst_parse_flags_get_type ());
   g_type_class_ref (gst_search_mode_get_type ());
   g_type_class_ref (gst_progress_type_get_type ());
+  g_type_class_ref (gst_buffer_pool_flags_get_type ());
+  g_type_class_ref (gst_memory_flags_get_type ());
+  g_type_class_ref (gst_map_flags_get_type ());
   g_type_class_ref (gst_caps_intersect_mode_get_type ());
-
-  gst_structure_get_type ();
-  _gst_value_initialize ();
+  g_type_class_ref (gst_pad_probe_type_get_type ());
+  g_type_class_ref (gst_pad_probe_return_get_type ());
+  g_type_class_ref (gst_segment_flags_get_type ());
+  g_type_class_ref (gst_scheduling_flags_get_type ());
+  g_type_class_ref (gst_meta_flags_get_type ());
+
+  g_type_class_ref (gst_control_binding_get_type ());
+  g_type_class_ref (gst_control_source_get_type ());
+
+  _priv_gst_event_initialize ();
+  _priv_gst_buffer_initialize ();
+  _priv_gst_message_initialize ();
+  _priv_gst_buffer_list_initialize ();
+  _priv_gst_sample_initialize ();
+  _priv_gst_value_initialize ();
   g_type_class_ref (gst_param_spec_fraction_get_type ());
-  gst_caps_get_type ();
-  _gst_event_initialize ();
-  _gst_buffer_initialize ();
-  _gst_buffer_list_initialize ();
-  gst_buffer_list_iterator_get_type ();
-  _gst_message_initialize ();
-  _gst_tag_initialize ();
+  _priv_gst_tag_initialize ();
   gst_parse_context_get_type ();
 
-  _gst_plugin_initialize ();
-
-  gst_g_error_get_type ();
+  _priv_gst_plugin_initialize ();
 
   /* register core plugins */
   gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
@@ -833,7 +806,7 @@ gst_debug_help (void)
   if (!init_post (NULL, NULL, NULL, NULL))
     exit (1);
 
-  list2 = gst_registry_plugin_filter (gst_registry_get_default (),
+  list2 = gst_registry_plugin_filter (gst_registry_get (),
       select_all, FALSE, NULL);
 
   /* FIXME this is gross.  why don't debug have categories PluginFeatures? */
@@ -1043,6 +1016,8 @@ gst_deinit (void)
 
   _priv_gst_registry_cleanup ();
 
+  g_mutex_clear (&_gst_trace_mutex);
+
   g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ()));
@@ -1051,12 +1026,10 @@ gst_deinit (void)
   g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_task_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_index_factory_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_buffer_flag_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffer_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_buffer_list_item_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
@@ -1086,23 +1059,17 @@ gst_deinit (void)
   g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_qos_type_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_format_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_index_certainty_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_index_entry_type_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_index_lookup_method_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_assoc_flags_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_index_resolver_method_get_type
-          ()));
-  g_type_class_unref (g_type_class_peek (gst_index_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_message_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_meta_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_link_check_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ()));
-  g_type_class_unref (g_type_class_peek (gst_activate_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_mode_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ()));
@@ -1120,10 +1087,21 @@ gst_deinit (void)
   g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type
           ()));
   g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_uri_error_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_progress_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_buffer_pool_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_memory_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_map_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_probe_type_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_pad_probe_return_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_segment_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_scheduling_flags_get_type ()));
+
+  g_type_class_unref (g_type_class_peek (gst_control_binding_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_control_source_get_type ()));
 
   gst_deinitialized = TRUE;
   GST_INFO ("deinitialized GStreamer");
index 35ef290..93a51df 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
 #ifndef __GST_H__
 #define __GST_H__
 
+#ifndef GST_USE_UNSTABLE_API
+#warning "The GStreamer 0.11 API is still unstable and will change in future."
+#warning "Define GST_USE_UNSTABLE_API to avoid this warning."
+#endif
+
 #include <glib.h>
 
 #include <gst/glib-compat.h>
 #include <gst/gstbin.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstbufferlist.h>
+#include <gst/gstbufferpool.h>
 #include <gst/gstcaps.h>
 #include <gst/gstchildproxy.h>
 #include <gst/gstclock.h>
+#include <gst/gstcontrolsource.h>
 #include <gst/gstdatetime.h>
 #include <gst/gstdebugutils.h>
 #include <gst/gstelement.h>
+#include <gst/gstelementmetadata.h>
 #include <gst/gsterror.h>
 #include <gst/gstevent.h>
 #include <gst/gstghostpad.h>
-#include <gst/gstindex.h>
-#include <gst/gstindexfactory.h>
 #include <gst/gstinfo.h>
-#include <gst/gstinterface.h>
 #include <gst/gstiterator.h>
 #include <gst/gstmarshal.h>
 #include <gst/gstmessage.h>
+#include <gst/gstmemory.h>
 #include <gst/gstminiobject.h>
 #include <gst/gstobject.h>
 #include <gst/gstpad.h>
@@ -61,6 +67,7 @@
 #include <gst/gstpreset.h>
 #include <gst/gstquery.h>
 #include <gst/gstregistry.h>
+#include <gst/gstsample.h>
 #include <gst/gstsegment.h>
 #include <gst/gststructure.h>
 #include <gst/gstsystemclock.h>
@@ -74,7 +81,6 @@
 #include <gst/gsturi.h>
 #include <gst/gstutils.h>
 #include <gst/gstvalue.h>
-#include <gst/gstxml.h>
 
 #include <gst/gstparse.h>
 
@@ -100,7 +106,7 @@ void            gst_segtrap_set_enabled         (gboolean enabled);
 gboolean        gst_registry_fork_is_enabled    (void);
 void            gst_registry_fork_set_enabled   (gboolean enabled);
 
-gboolean        gst_update_registry (void);
+gboolean        gst_update_registry             (void);
 
 G_END_DECLS
 
index c36a72d..dd93110 100644 (file)
@@ -79,6 +79,7 @@ struct _GstPluginPrivate {
   GstStructure *cache_data;
 };
 
+/* FIXME: could rename all priv_gst_* functions to __gst_* now */
 gboolean priv_gst_plugin_loading_have_whitelist (void);
 
 guint32  priv_gst_plugin_loading_get_whitelist_hash (void);
@@ -91,45 +92,47 @@ gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin);
 
 gboolean _priv_gst_in_valgrind (void);
 
-/* Initialize GStreamer private quark storage */
-void _priv_gst_quarks_initialize (void);
-
-/* Other init functions called from gst_init().
- * FIXME 0.11: rename to _priv_gst_foo_init() so they don't get exported
- * (can't do this now because these functions used to be in our public
- * headers, so at least the symbols need to continue to be available unless
- * we want enterprise edition packagers dancing on our heads) */
-void  _gst_buffer_initialize (void);
-void  _gst_buffer_list_initialize (void);
-void  _gst_event_initialize (void);
-void  _gst_format_initialize (void);
-void  _gst_message_initialize (void);
-void  _gst_plugin_initialize (void);
-void  _gst_query_initialize (void);
-void  _gst_tag_initialize (void);
-void  _gst_value_initialize (void);
+/* init functions called from gst_init(). */
+void  _priv_gst_quarks_initialize (void);
+void  _priv_gst_buffer_initialize (void);
+void  _priv_gst_buffer_list_initialize (void);
+void  _priv_gst_structure_initialize (void);
+void  _priv_gst_caps_initialize (void);
+void  _priv_gst_event_initialize (void);
+void  _priv_gst_format_initialize (void);
+void  _priv_gst_message_initialize (void);
+void  _priv_gst_memory_initialize (void);
+void  _priv_gst_meta_initialize (void);
+void  _priv_gst_plugin_initialize (void);
+void  _priv_gst_query_initialize (void);
+void  _priv_gst_sample_initialize (void);
+void  _priv_gst_tag_initialize (void);
+void  _priv_gst_value_initialize (void);
+void  _priv_gst_debug_init (void);
 
 /* Private registry functions */
 gboolean _priv_gst_registry_remove_cache_plugins (GstRegistry *registry);
 void _priv_gst_registry_cleanup (void);
 gboolean _gst_plugin_loader_client_run (void);
 
-void _priv_gst_pad_invalidate_cache (GstPad *pad);
-
 /* Used in GstBin for manual state handling */
 void _priv_gst_element_state_changed (GstElement *element, GstState oldstate,
     GstState newstate, GstState pending);
 
 /* used in both gststructure.c and gstcaps.c; numbers are completely made up */
-#define STRUCTURE_ESTIMATED_STRING_LEN(s) (16 + (s)->fields->len * 22)
+#define STRUCTURE_ESTIMATED_STRING_LEN(s) (16 + gst_structure_n_fields(s) * 22)
 
 gboolean  priv_gst_structure_append_to_gstring (const GstStructure * structure,
                                                 GString            * s);
 /* registry cache backends */
-/* FIXME 0.11: use priv_ prefix */
-gboolean               gst_registry_binary_read_cache  (GstRegistry * registry, const char *location);
-gboolean               gst_registry_binary_write_cache (GstRegistry * registry, const char *location);
+gboolean               priv_gst_registry_binary_read_cache     (GstRegistry * registry, const char *location);
+gboolean               priv_gst_registry_binary_write_cache    (GstRegistry * registry, GList * plugins, const char *location);
+
+void      __gst_element_factory_add_static_pad_template (GstElementFactory    * elementfactory,
+                                                         GstStaticPadTemplate * templ);
 
+void      __gst_element_factory_add_interface           (GstElementFactory    * elementfactory,
+                                                         const gchar          * interfacename);
 
 /* used in gstvalue.c and gststructure.c */
 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
@@ -184,7 +187,6 @@ GST_EXPORT GstDebugCategory *GST_CAT_PIPELINE;
 GST_EXPORT GstDebugCategory *GST_CAT_PLUGIN_LOADING;
 GST_EXPORT GstDebugCategory *GST_CAT_PLUGIN_INFO;
 GST_EXPORT GstDebugCategory *GST_CAT_PROPERTIES;
-GST_EXPORT GstDebugCategory *GST_CAT_XML;
 GST_EXPORT GstDebugCategory *GST_CAT_NEGOTIATION;
 GST_EXPORT GstDebugCategory *GST_CAT_REFCOUNTING;
 GST_EXPORT GstDebugCategory *GST_CAT_ERROR_SYSTEM;
@@ -224,7 +226,6 @@ extern GstDebugCategory *_priv_GST_CAT_POLL;
 #define GST_CAT_PLUGIN_LOADING   NULL
 #define GST_CAT_PLUGIN_INFO      NULL
 #define GST_CAT_PROPERTIES       NULL
-#define GST_CAT_XML              NULL
 #define GST_CAT_NEGOTIATION      NULL
 #define GST_CAT_REFCOUNTING      NULL
 #define GST_CAT_ERROR_SYSTEM     NULL
@@ -241,10 +242,6 @@ extern GstDebugCategory *_priv_GST_CAT_POLL;
 
 #endif
 
-#ifdef GST_DISABLE_DEPRECATED
-typedef GList*                 (*GstPadIntLinkFunction)        (GstPad *pad);
-#endif
-
 
 G_END_DECLS
 #endif /* __GST_PRIVATE_H__ */
index 5b21be6..dc75c89 100644 (file)
@@ -113,7 +113,7 @@ add_to_free_list (GstAtomicQueue * queue, GstAQueueMem * mem)
 {
   do {
     mem->free = g_atomic_pointer_get (&queue->free_list);
-  } while (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&queue->free_list,
+  } while (!g_atomic_pointer_compare_and_exchange (&queue->free_list,
           mem->free, mem));
 }
 
@@ -127,7 +127,7 @@ clear_free_list (GstAtomicQueue * queue)
     free_list = g_atomic_pointer_get (&queue->free_list);
     if (free_list == NULL)
       return;
-  } while (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&queue->free_list, free_list,
+  } while (!g_atomic_pointer_compare_and_exchange (&queue->free_list, free_list,
           NULL));
 
   while (free_list) {
@@ -248,7 +248,7 @@ gst_atomic_queue_peek (GstAtomicQueue * queue)
 
     /* now we try to move the next array as the head memory. If we fail to do that,
      * some other reader managed to do it first and we retry */
-    if (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&queue->head_mem, head_mem,
+    if (!g_atomic_pointer_compare_and_exchange (&queue->head_mem, head_mem,
             next))
       continue;
 
@@ -305,7 +305,7 @@ gst_atomic_queue_pop (GstAtomicQueue * queue)
 
       /* now we try to move the next array as the head memory. If we fail to do that,
        * some other reader managed to do it first and we retry */
-      if (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&queue->head_mem, head_mem,
+      if (!g_atomic_pointer_compare_and_exchange (&queue->head_mem, head_mem,
               next))
         continue;
 
@@ -363,7 +363,7 @@ gst_atomic_queue_push (GstAtomicQueue * queue, gpointer data)
       mem = new_queue_mem ((size << 1) + 1, tail);
 
       /* try to make our new array visible to other writers */
-      if (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&queue->tail_mem, tail_mem,
+      if (!g_atomic_pointer_compare_and_exchange (&queue->tail_mem, tail_mem,
               mem)) {
         /* we tried to swap the new writer array but something changed. This is
          * because some other writer beat us to it, we free our memory and try
index f3d1b56..2f466e8 100644 (file)
  * Last reviewed on 2006-04-28 (0.10.6)
  */
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "gst_private.h"
 
 #include "gstevent.h"
 #include "gstbin.h"
 #include "gstmarshal.h"
-#include "gstxml.h"
 #include "gstinfo.h"
 #include "gsterror.h"
 
-#include "gstindex.h"
-#include "gstindexfactory.h"
 #include "gstutils.h"
 #include "gstchildproxy.h"
 
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#undef GstXmlNodePtr
-#define GstXmlNodePtr xmlNodePtr
-#include <libxml/parser.h>
-GstXmlNodePtr gst_object_save_thyself (GstObject * object,
-    GstXmlNodePtr parent);
-void gst_object_restore_thyself (GstObject * object, GstXmlNodePtr parent);
-GstElement *gst_xml_make_element (xmlNodePtr cur, GstObject * parent);
-#endif
-#endif
-
-/* enable for DURATION caching.
- * FIXME currently too many elements don't update
- * their duration when it changes so we return inaccurate values. */
-#undef DURATION_CACHING
-
 /* latency is by default enabled now.
  * live-preroll and no-live-preroll in the environment var GST_COMPAT
  * to enables or disable it respectively.
@@ -219,8 +196,11 @@ struct _GstBinPrivate
 
   guint32 structure_cookie;
 
+#if 0
   /* cached index */
   GstIndex *index;
+#endif
+
   /* forward messages from our children */
   gboolean message_forward;
 
@@ -248,16 +228,18 @@ static void gst_bin_state_changed (GstElement * element, GstState oldstate,
 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
     GstState * state, GstState * pending, GstClockTime timeout);
 static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
-    gboolean flag_pending);
-static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
+    gboolean flag_pending, gboolean reset_time);
+static void bin_handle_async_start (GstBin * bin);
 static void bin_push_state_continue (BinContinueData * data);
 static void bin_do_eos (GstBin * bin);
 
 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
 
+#if 0
 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
 static GstIndex *gst_bin_get_index_func (GstElement * element);
+#endif
 
 static GstClock *gst_bin_provide_clock_func (GstElement * element);
 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
@@ -270,11 +252,6 @@ static gboolean gst_bin_query (GstElement * element, GstQuery * query);
 
 static gboolean gst_bin_do_latency_func (GstBin * bin);
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
-static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
-#endif
-
 static void bin_remove_messages (GstBin * bin, GstObject * src,
     GstMessageType types);
 static void gst_bin_continue_func (BinContinueData * data);
@@ -307,7 +284,7 @@ static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
 
 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
 
-#define _do_init(type) \
+#define _do_init \
 { \
   const gchar *compat; \
   static const GInterfaceInfo iface_info = { \
@@ -315,7 +292,7 @@ static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
     NULL, \
     NULL}; \
   \
-  g_type_add_interface_static (type, GST_TYPE_CHILD_PROXY, &iface_info); \
+  g_type_add_interface_static (g_define_type_id, GST_TYPE_CHILD_PROXY, &iface_info); \
   \
   GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \
       "debugging info for the 'bin' container element"); \
@@ -330,19 +307,8 @@ static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
   } \
 }
 
-GST_BOILERPLATE_FULL (GstBin, gst_bin, GstElement, GST_TYPE_ELEMENT, _do_init);
-
-static void
-gst_bin_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class, "Generic bin",
-      "Generic/Bin",
-      "Simple container object",
-      "Erik Walthinsen <omega@cse.ogi.edu>,"
-      "Wim Taymans <wim.taymans@gmail.com>");
-}
+#define gst_bin_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstBin, gst_bin, GST_TYPE_ELEMENT, _do_init);
 
 static GstObject *
 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
@@ -404,13 +370,13 @@ _gst_boolean_accumulator (GSignalInvocationHint * ihint,
 static void
 gst_bin_class_init (GstBinClass * klass)
 {
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  GstObjectClass *gstobject_class = (GstObjectClass *) klass;
-#endif
-  GstElementClass *gstelement_class = (GstElementClass *) klass;
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GError *err;
 
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
   g_type_class_add_private (klass, sizeof (GstBinPrivate));
 
   gobject_class->set_property = gst_bin_set_property;
@@ -497,21 +463,20 @@ gst_bin_class_init (GstBinClass * klass)
 
   gobject_class->dispose = gst_bin_dispose;
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  gstobject_class->save_thyself =
-      ((gpointer (*)(GstObject * object,
-              gpointer self)) * GST_DEBUG_FUNCPTR (gst_bin_save_thyself));
-  gstobject_class->restore_thyself =
-      ((void (*)(GstObject * object,
-              gpointer self)) *GST_DEBUG_FUNCPTR (gst_bin_restore_thyself));
-#endif
+  gst_element_class_set_metadata (gstelement_class, "Generic bin",
+      "Generic/Bin",
+      "Simple container object",
+      "Erik Walthinsen <omega@cse.ogi.edu>,"
+      "Wim Taymans <wim.taymans@gmail.com>");
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
   gstelement_class->state_changed = GST_DEBUG_FUNCPTR (gst_bin_state_changed);
   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
+#if 0
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_bin_get_index_func);
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
+#endif
   gstelement_class->provide_clock =
       GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
@@ -535,7 +500,7 @@ gst_bin_class_init (GstBinClass * klass)
 }
 
 static void
-gst_bin_init (GstBin * bin, GstBinClass * klass)
+gst_bin_init (GstBin * bin)
 {
   GstBus *bus;
 
@@ -547,7 +512,7 @@ gst_bin_init (GstBin * bin, GstBinClass * klass)
   bin->clock_dirty = FALSE;
 
   /* Set up a bus for listening to child elements */
-  bus = gst_bus_new ();
+  bus = g_object_new (GST_TYPE_BUS, "enable-async", FALSE, NULL);
   bin->child_bus = bus;
   GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
       bus);
@@ -566,7 +531,6 @@ gst_bin_dispose (GObject * object)
   GstBus **child_bus_p = &bin->child_bus;
   GstClock **provided_clock_p = &bin->provided_clock;
   GstElement **clock_provider_p = &bin->clock_provider;
-  GstIndex **index_p = &bin->priv->index;
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
 
@@ -574,7 +538,6 @@ gst_bin_dispose (GObject * object)
   gst_object_replace ((GstObject **) child_bus_p, NULL);
   gst_object_replace ((GstObject **) provided_clock_p, NULL);
   gst_object_replace ((GstObject **) clock_provider_p, NULL);
-  gst_object_replace ((GstObject **) index_p, NULL);
   bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
   GST_OBJECT_UNLOCK (object);
 
@@ -653,6 +616,7 @@ gst_bin_get_property (GObject * object, guint prop_id,
   }
 }
 
+#if 0
 /* return the cached index */
 static GstIndex *
 gst_bin_get_index_func (GstElement * element)
@@ -681,6 +645,7 @@ gst_bin_set_index_func (GstElement * element, GstIndex * index)
   gboolean done;
   GstIterator *it;
   GstIndex *old;
+  GValue data = { 0, };
 
   bin = GST_BIN_CAST (element);
 
@@ -701,18 +666,16 @@ gst_bin_set_index_func (GstElement * element, GstIndex * index)
   /* set the index on all elements in the bin */
   done = FALSE;
   while (!done) {
-    gpointer data;
-
     switch (gst_iterator_next (it, &data)) {
       case GST_ITERATOR_OK:
       {
-        GstElement *child = GST_ELEMENT_CAST (data);
+        GstElement *child = g_value_get_object (&data);
 
         GST_DEBUG_OBJECT (bin, "setting index on '%s'",
             GST_ELEMENT_NAME (child));
         gst_element_set_index (child, index);
 
-        gst_object_unref (child);
+        g_value_reset (&data);
         break;
       }
       case GST_ITERATOR_RESYNC:
@@ -726,6 +689,7 @@ gst_bin_set_index_func (GstElement * element, GstIndex * index)
         break;
     }
   }
+  g_value_unset (&data);
   gst_iterator_free (it);
   return;
 
@@ -736,6 +700,7 @@ was_set:
     return;
   }
 }
+#endif
 
 /* set the clock on all elements in this bin
  *
@@ -748,6 +713,7 @@ gst_bin_set_clock_func (GstElement * element, GstClock * clock)
   gboolean done;
   GstIterator *it;
   gboolean res = TRUE;
+  GValue data = { 0, };
 
   bin = GST_BIN_CAST (element);
 
@@ -755,16 +721,14 @@ gst_bin_set_clock_func (GstElement * element, GstClock * clock)
 
   done = FALSE;
   while (!done) {
-    gpointer data;
-
     switch (gst_iterator_next (it, &data)) {
       case GST_ITERATOR_OK:
       {
-        GstElement *child = GST_ELEMENT_CAST (data);
+        GstElement *child = g_value_get_object (&data);
 
         res &= gst_element_set_clock (child, clock);
 
-        gst_object_unref (child);
+        g_value_reset (&data);
         break;
       }
       case GST_ITERATOR_RESYNC:
@@ -779,8 +743,12 @@ gst_bin_set_clock_func (GstElement * element, GstClock * clock)
         break;
     }
   }
+  g_value_unset (&data);
   gst_iterator_free (it);
 
+  if (res)
+    res = GST_ELEMENT_CLASS (parent_class)->set_clock (element, clock);
+
   return res;
 }
 
@@ -800,7 +768,8 @@ gst_bin_provide_clock_func (GstElement * element)
   GstElement *provider = NULL;
   GstBin *bin;
   GstIterator *it;
-  gpointer val;
+  gboolean done;
+  GValue val = { 0, };
   GstClock **provided_clock_p;
   GstElement **clock_provider_p;
 
@@ -813,25 +782,53 @@ gst_bin_provide_clock_func (GstElement * element)
   GST_DEBUG_OBJECT (bin, "finding new clock");
 
   it = gst_bin_sort_iterator_new (bin);
+  GST_OBJECT_UNLOCK (bin);
+
+  done = FALSE;
+  while (!done) {
+    switch (gst_iterator_next (it, &val)) {
+      case GST_ITERATOR_OK:
+      {
+        GstElement *child = g_value_get_object (&val);
+        GstClock *clock;
+
+        clock = gst_element_provide_clock (child);
+        if (clock) {
+          GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s",
+              clock, GST_ELEMENT_NAME (child));
+          if (result) {
+            gst_object_unref (result);
+            gst_object_unref (provider);
+          }
+          result = clock;
+          provider = gst_object_ref (child);
+        }
 
-  while (it->next (it, &val) == GST_ITERATOR_OK) {
-    GstElement *child = GST_ELEMENT_CAST (val);
-    GstClock *clock;
-
-    clock = gst_element_provide_clock (child);
-    if (clock) {
-      GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s",
-          clock, GST_ELEMENT_NAME (child));
-      if (result) {
-        gst_object_unref (result);
-        gst_object_unref (provider);
+        g_value_reset (&val);
+        break;
       }
-      result = clock;
-      provider = child;
-    } else {
-      gst_object_unref (child);
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (it);
+        break;
+      default:
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
     }
   }
+  g_value_unset (&val);
+  gst_iterator_free (it);
+
+  GST_OBJECT_LOCK (bin);
+  if (!bin->clock_dirty) {
+    if (provider)
+      gst_object_unref (provider);
+    if (result)
+      gst_object_unref (result);
+    result = NULL;
+
+    goto not_dirty;
+  }
 
   provided_clock_p = &bin->provided_clock;
   clock_provider_p = &bin->clock_provider;
@@ -846,8 +843,6 @@ gst_bin_provide_clock_func (GstElement * element)
     gst_object_unref (provider);
   GST_OBJECT_UNLOCK (bin);
 
-  gst_iterator_free (it);
-
   return result;
 
 not_dirty:
@@ -1030,10 +1025,13 @@ is_eos (GstBin * bin, guint32 * seqnum)
 }
 
 static void
-unlink_pads (GstPad * pad)
+unlink_pads (const GValue * item, gpointer user_data)
 {
+  GstPad *pad;
   GstPad *peer;
 
+  pad = g_value_get_object (item);
+
   if ((peer = gst_pad_get_peer (pad))) {
     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
       gst_pad_unlink (pad, peer);
@@ -1041,7 +1039,6 @@ unlink_pads (GstPad * pad)
       gst_pad_unlink (peer, pad);
     gst_object_unref (peer);
   }
-  gst_object_unref (pad);
 }
 
 /* vmethod that adds an element to a bin
@@ -1053,7 +1050,7 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
 {
   gchar *elem_name;
   GstIterator *it;
-  gboolean is_sink, is_source;
+  gboolean is_sink, is_source, provides_clock, requires_clock;
   GstMessage *clock_message = NULL, *async_message = NULL;
   GstStateChangeReturn ret;
 
@@ -1066,8 +1063,12 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
   /* get the element name to make sure it is unique in this bin. */
   GST_OBJECT_LOCK (element);
   elem_name = g_strdup (GST_ELEMENT_NAME (element));
-  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
-  is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SOURCE);
+  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
+  is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE);
+  provides_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+  requires_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
   GST_OBJECT_UNLOCK (element);
 
   GST_OBJECT_LOCK (bin);
@@ -1088,17 +1089,22 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
   if (is_sink) {
     GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink",
         elem_name);
-    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
+    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SINK);
   }
   if (is_source) {
     GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was source",
         elem_name);
-    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE);
+    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SOURCE);
   }
-  if (gst_element_provides_clock (element)) {
+  if (provides_clock) {
     GST_DEBUG_OBJECT (bin, "element \"%s\" can provide a clock", elem_name);
     clock_message =
         gst_message_new_clock_provide (GST_OBJECT_CAST (element), NULL, TRUE);
+    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+  }
+  if (requires_clock) {
+    GST_DEBUG_OBJECT (bin, "element \"%s\" requires a clock", elem_name);
+    GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
   }
 
   bin->children = g_list_prepend (bin->children, element);
@@ -1116,9 +1122,12 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
    * that is not important right now. When the pipeline goes to PLAYING,
    * a new clock will be selected */
   gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
+
+#if 0
   /* set the cached index on the children */
   if (bin->priv->index)
     gst_element_set_index (element, bin->priv->index);
+#endif
 
   ret = GST_STATE_RETURN (bin);
   /* no need to update the state if we are in error */
@@ -1136,13 +1145,12 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
     {
       /* create message to track this aync element when it posts an async-done
        * message */
-      async_message =
-          gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE);
+      async_message = gst_message_new_async_start (GST_OBJECT_CAST (element));
       break;
     }
     case GST_STATE_CHANGE_NO_PREROLL:
       /* ignore all async elements we might have and commit our state */
-      bin_handle_async_done (bin, ret, FALSE);
+      bin_handle_async_done (bin, ret, FALSE, FALSE);
       break;
     case GST_STATE_CHANGE_FAILURE:
       break;
@@ -1163,7 +1171,7 @@ no_state_recalc:
 
   /* unlink all linked pads */
   it = gst_element_iterate_pads (element);
-  gst_iterator_foreach (it, (GFunc) unlink_pads, element);
+  gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, NULL);
   gst_iterator_free (it);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
@@ -1264,7 +1272,8 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
 {
   gchar *elem_name;
   GstIterator *it;
-  gboolean is_sink, is_source, othersink, othersource, found;
+  gboolean is_sink, is_source, provides_clock, requires_clock;
+  gboolean othersink, othersource, otherprovider, otherrequirer, found;
   GstMessage *clock_message = NULL;
   GstClock **provided_clock_p;
   GstElement **clock_provider_p;
@@ -1277,25 +1286,32 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
   GST_OBJECT_LOCK (element);
   /* Check if the element is already being removed and immediately
    * return */
-  if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_UNPARENTING)))
+  if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (element,
+              GST_ELEMENT_FLAG_UNPARENTING)))
     goto already_removing;
 
-  GST_OBJECT_FLAG_SET (element, GST_ELEMENT_UNPARENTING);
+  GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_UNPARENTING);
   /* grab element name so we can print it */
   elem_name = g_strdup (GST_ELEMENT_NAME (element));
-  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
-  is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SOURCE);
+  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
+  is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE);
+  provides_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+  requires_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
   GST_OBJECT_UNLOCK (element);
 
   /* unlink all linked pads */
   it = gst_element_iterate_pads (element);
-  gst_iterator_foreach (it, (GFunc) unlink_pads, element);
+  gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, NULL);
   gst_iterator_free (it);
 
   GST_OBJECT_LOCK (bin);
   found = FALSE;
   othersink = FALSE;
   othersource = FALSE;
+  otherprovider = FALSE;
+  otherrequirer = FALSE;
   have_no_preroll = FALSE;
   /* iterate the elements, we collect which ones are async and no_preroll. We
    * also remove the element when we find it. */
@@ -1309,16 +1325,24 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
       /* remove the element */
       bin->children = g_list_delete_link (bin->children, walk);
     } else {
-      gboolean child_sink, child_source;
+      gboolean child_sink, child_source, child_provider, child_requirer;
 
       GST_OBJECT_LOCK (child);
-      child_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
-      child_source = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SOURCE);
+      child_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK);
+      child_source = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE);
+      child_provider =
+          GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+      child_requirer =
+          GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
       /* when we remove a sink, check if there are other sinks. */
       if (is_sink && !othersink && child_sink)
         othersink = TRUE;
       if (is_source && !othersource && child_source)
         othersource = TRUE;
+      if (provides_clock && !otherprovider && child_provider)
+        otherprovider = TRUE;
+      if (requires_clock && !otherrequirer && child_requirer)
+        otherrequirer = TRUE;
       /* check if we have NO_PREROLL children */
       if (GST_STATE_RETURN (child) == GST_STATE_CHANGE_NO_PREROLL)
         have_no_preroll = TRUE;
@@ -1339,14 +1363,23 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
   if (is_sink && !othersink) {
     /* we're not a sink anymore */
     GST_DEBUG_OBJECT (bin, "we removed the last sink");
-    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
+    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SINK);
   }
   if (is_source && !othersource) {
     /* we're not a source anymore */
     GST_DEBUG_OBJECT (bin, "we removed the last source");
-    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SOURCE);
+    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SOURCE);
+  }
+  if (provides_clock && !otherprovider) {
+    /* we're not a clock provider anymore */
+    GST_DEBUG_OBJECT (bin, "we removed the last clock provider");
+    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+  }
+  if (requires_clock && !otherrequirer) {
+    /* we're not a clock requirer anymore */
+    GST_DEBUG_OBJECT (bin, "we removed the last clock requirer");
+    GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
   }
-
 
   /* if the clock provider for this element is removed, we lost
    * the clock as well, we need to inform the parent of this
@@ -1436,7 +1469,7 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
     else
       ret = GST_STATE_CHANGE_SUCCESS;
 
-    bin_handle_async_done (bin, ret, FALSE);
+    bin_handle_async_done (bin, ret, FALSE, FALSE);
   } else {
     GST_DEBUG_OBJECT (bin,
         "recalc state preroll: %d, other async: %d, this async %d",
@@ -1476,7 +1509,7 @@ no_state_recalc:
   gst_object_unparent (GST_OBJECT_CAST (element));
 
   GST_OBJECT_LOCK (element);
-  GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_UNPARENTING);
+  GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_UNPARENTING);
   GST_OBJECT_UNLOCK (element);
 
   g_signal_emit (bin, gst_bin_signals[ELEMENT_REMOVED], 0, element);
@@ -1554,13 +1587,6 @@ no_function:
   }
 }
 
-static GstIteratorItem
-iterate_child (GstIterator * it, GstElement * child)
-{
-  gst_object_ref (child);
-  return GST_ITERATOR_ITEM_PASS;
-}
-
 /**
  * gst_bin_iterate_elements:
  * @bin: a #GstBin
@@ -1582,26 +1608,19 @@ gst_bin_iterate_elements (GstBin * bin)
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
   GST_OBJECT_LOCK (bin);
-  /* add ref because the iterator refs the bin. When the iterator
-   * is freed it will unref the bin again using the provided dispose
-   * function. */
-  gst_object_ref (bin);
   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
       GST_OBJECT_GET_LOCK (bin),
-      &bin->children_cookie,
-      &bin->children,
-      bin,
-      (GstIteratorItemFunction) iterate_child,
-      (GstIteratorDisposeFunction) gst_object_unref);
+      &bin->children_cookie, &bin->children, (GObject *) bin, NULL);
   GST_OBJECT_UNLOCK (bin);
 
   return result;
 }
 
 static GstIteratorItem
-iterate_child_recurse (GstIterator * it, GstElement * child)
+iterate_child_recurse (GstIterator * it, const GValue * item)
 {
-  gst_object_ref (child);
+  GstElement *child = g_value_get_object (item);
+
   if (GST_IS_BIN (child)) {
     GstIterator *other = gst_bin_iterate_recurse (GST_BIN_CAST (child));
 
@@ -1632,17 +1651,11 @@ gst_bin_iterate_recurse (GstBin * bin)
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
   GST_OBJECT_LOCK (bin);
-  /* add ref because the iterator refs the bin. When the iterator
-   * is freed it will unref the bin again using the provided dispose
-   * function. */
-  gst_object_ref (bin);
   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
       GST_OBJECT_GET_LOCK (bin),
       &bin->children_cookie,
       &bin->children,
-      bin,
-      (GstIteratorItemFunction) iterate_child_recurse,
-      (GstIteratorDisposeFunction) gst_object_unref);
+      (GObject *) bin, (GstIteratorItemFunction) iterate_child_recurse);
   GST_OBJECT_UNLOCK (bin);
 
   return result;
@@ -1658,7 +1671,7 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
   /* we lock the child here for the remainder of the function to
    * get its name and flag safely. */
   GST_OBJECT_LOCK (child);
-  is_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
+  is_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
       "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
@@ -1668,17 +1681,12 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
 }
 
 static gint
-sink_iterator_filter (GstElement * child, GstBin * bin)
+sink_iterator_filter (const GValue * vchild, GValue * vbin)
 {
-  if (bin_element_is_sink (child, bin) == 0) {
-    /* returns 0 because this is a GCompareFunc */
-    return 0;
-  } else {
-    /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
-       through */
-    gst_object_unref (child);
-    return 1;
-  }
+  GstBin *bin = g_value_get_object (vbin);
+  GstElement *child = g_value_get_object (vchild);
+
+  return (bin_element_is_sink (child, bin));
 }
 
 /**
@@ -1686,7 +1694,7 @@ sink_iterator_filter (GstElement * child, GstBin * bin)
  * @bin: a #GstBin
  *
  * Gets an iterator for all elements in the bin that have the
- * #GST_ELEMENT_IS_SINK flag set.
+ * #GST_ELEMENT_FLAG_SINK flag set.
  *
  * Each element yielded by the iterator will have its refcount increased, so
  * unref after use.
@@ -1700,12 +1708,18 @@ gst_bin_iterate_sinks (GstBin * bin)
 {
   GstIterator *children;
   GstIterator *result;
+  GValue vbin = { 0, };
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
+  g_value_init (&vbin, GST_TYPE_BIN);
+  g_value_set_object (&vbin, bin);
+
   children = gst_bin_iterate_elements (bin);
   result = gst_iterator_filter (children,
-      (GCompareFunc) sink_iterator_filter, bin);
+      (GCompareFunc) sink_iterator_filter, &vbin);
+
+  g_value_unset (&vbin);
 
   return result;
 }
@@ -1720,7 +1734,7 @@ bin_element_is_src (GstElement * child, GstBin * bin)
   /* we lock the child here for the remainder of the function to
    * get its name and other info safely. */
   GST_OBJECT_LOCK (child);
-  is_src = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SOURCE);
+  is_src = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
       "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not");
@@ -1730,17 +1744,12 @@ bin_element_is_src (GstElement * child, GstBin * bin)
 }
 
 static gint
-src_iterator_filter (GstElement * child, GstBin * bin)
+src_iterator_filter (const GValue * vchild, GValue * vbin)
 {
-  if (bin_element_is_src (child, bin) == 0) {
-    /* returns 0 because this is a GCompareFunc */
-    return 0;
-  } else {
-    /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
-       through */
-    gst_object_unref (child);
-    return 1;
-  }
+  GstBin *bin = g_value_get_object (vbin);
+  GstElement *child = g_value_get_object (vchild);
+
+  return (bin_element_is_src (child, bin));
 }
 
 /**
@@ -1748,7 +1757,7 @@ src_iterator_filter (GstElement * child, GstBin * bin)
  * @bin: a #GstBin
  *
  * Gets an iterator for all elements in the bin that have the
- * #GST_ELEMENT_IS_SOURCE flag set.
+ * #GST_ELEMENT_FLAG_SOURCE flag set.
  *
  * Each element yielded by the iterator will have its refcount increased, so
  * unref after use.
@@ -1762,12 +1771,18 @@ gst_bin_iterate_sources (GstBin * bin)
 {
   GstIterator *children;
   GstIterator *result;
+  GValue vbin = { 0, };
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
+  g_value_init (&vbin, GST_TYPE_BIN);
+  g_value_set_object (&vbin, bin);
+
   children = gst_bin_iterate_elements (bin);
   result = gst_iterator_filter (children,
-      (GCompareFunc) src_iterator_filter, bin);
+      (GCompareFunc) src_iterator_filter, &vbin);
+
+  g_value_unset (&vbin);
 
   return result;
 }
@@ -1783,7 +1798,9 @@ gst_bin_get_state_func (GstElement * element, GstState * state,
 
   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
 
-  ret = parent_class->get_state (element, state, pending, timeout);
+  ret =
+      GST_ELEMENT_CLASS (parent_class)->get_state (element, state, pending,
+      timeout);
 
   return ret;
 }
@@ -1812,6 +1829,26 @@ typedef struct _GstBinSortIterator
   gboolean dirty;               /* we detected structure change */
 } GstBinSortIterator;
 
+static void
+gst_bin_sort_iterator_copy (const GstBinSortIterator * it,
+    GstBinSortIterator * copy)
+{
+  GHashTableIter iter;
+  gpointer key, value;
+
+  copy->queue = it->queue;
+  g_queue_foreach (&copy->queue, (GFunc) gst_object_ref, NULL);
+
+  copy->bin = gst_object_ref (it->bin);
+  if (it->best)
+    copy->best = gst_object_ref (it->best);
+
+  copy->hash = g_hash_table_new (NULL, NULL);
+  g_hash_table_iter_init (&iter, it->hash);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    g_hash_table_insert (copy->hash, key, value);
+}
+
 /* we add and subtract 1 to make sure we don't confuse NULL and 0 */
 #define HASH_SET_DEGREE(bit, elem, deg) \
     g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1))
@@ -1871,7 +1908,7 @@ reset_degree (GstElement * element, GstBinSortIterator * bit)
 
   /* sinks are added right away */
   GST_OBJECT_LOCK (element);
-  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
+  is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
   GST_OBJECT_UNLOCK (element);
 
   if (is_sink) {
@@ -1991,14 +2028,13 @@ find_element (GstElement * element, GstBinSortIterator * bit)
 /* get next element in iterator. the returned element has the
  * refcount increased */
 static GstIteratorResult
-gst_bin_sort_iterator_next (GstBinSortIterator * bit, gpointer * result)
+gst_bin_sort_iterator_next (GstBinSortIterator * bit, GValue * result)
 {
+  GstElement *best;
   GstBin *bin = bit->bin;
 
   /* empty queue, we have to find a next best element */
   if (g_queue_is_empty (&bit->queue)) {
-    GstElement *best;
-
     bit->best = NULL;
     bit->best_deg = G_MAXINT;
     g_list_foreach (bin->children, (GFunc) find_element, bit);
@@ -2014,9 +2050,8 @@ gst_bin_sort_iterator_next (GstBinSortIterator * bit, gpointer * result)
       /* best unhandled element, schedule as next element */
       GST_DEBUG_OBJECT (bin, "queue empty, next best: %s",
           GST_ELEMENT_NAME (best));
-      gst_object_ref (best);
       HASH_SET_DEGREE (bit, best, -1);
-      *result = best;
+      g_value_set_object (result, best);
     } else {
       GST_DEBUG_OBJECT (bin, "queue empty, elements exhausted");
       /* no more unhandled elements, we are done */
@@ -2024,12 +2059,14 @@ gst_bin_sort_iterator_next (GstBinSortIterator * bit, gpointer * result)
     }
   } else {
     /* everything added to the queue got reffed */
-    *result = g_queue_pop_head (&bit->queue);
+    best = g_queue_pop_head (&bit->queue);
+    g_value_set_object (result, best);
+    gst_object_unref (best);
   }
 
-  GST_DEBUG_OBJECT (bin, "queue head gives %s", GST_ELEMENT_NAME (*result));
+  GST_DEBUG_OBJECT (bin, "queue head gives %s", GST_ELEMENT_NAME (best));
   /* update degrees of linked elements */
-  update_degree (GST_ELEMENT_CAST (*result), bit);
+  update_degree (best, bit);
 
   return GST_ITERATOR_OK;
 }
@@ -2062,7 +2099,6 @@ gst_bin_sort_iterator_free (GstBinSortIterator * bit)
   clear_queue (&bit->queue);
   g_hash_table_destroy (bit->hash);
   gst_object_unref (bin);
-  g_free (bit);
 }
 
 /* should be called with the bin LOCK held */
@@ -2078,6 +2114,7 @@ gst_bin_sort_iterator_new (GstBin * bin)
       GST_TYPE_ELEMENT,
       GST_OBJECT_GET_LOCK (bin),
       &bin->priv->structure_cookie,
+      (GstIteratorCopyFunction) gst_bin_sort_iterator_copy,
       (GstIteratorNextFunction) gst_bin_sort_iterator_next,
       (GstIteratorItemFunction) NULL,
       (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
@@ -2140,7 +2177,7 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element,
   GST_ELEMENT_START_TIME (element) = start_time;
   element->base_time = base_time;
   /* peel off the locked flag */
-  locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+  locked = GST_ELEMENT_IS_LOCKED_STATE (element);
   /* Get the previous set_state result to preserve NO_PREROLL and ASYNC */
   ret = GST_STATE_RETURN (element);
   child_current = GST_STATE (element);
@@ -2244,17 +2281,14 @@ unneeded:
 /* gst_iterator_fold functions for pads_activate
  * Stop the iterator if activating one pad failed. */
 static gboolean
-activate_pads (GstPad * pad, GValue * ret, gboolean * active)
+activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
 {
+  GstPad *pad = g_value_get_object (vpad);
   gboolean cont = TRUE;
 
   if (!(cont = gst_pad_set_active (pad, *active)))
     g_value_set_boolean (ret, FALSE);
-  else if (!*active)
-    gst_pad_set_caps (pad, NULL);
 
-  /* unref the object that was reffed for us by _fold */
-  gst_object_unref (pad);
   return cont;
 }
 
@@ -2427,6 +2461,7 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition)
   GstClockTime base_time, start_time;
   GstIterator *it;
   gboolean done;
+  GValue data = { 0, };
 
   /* we don't need to take the STATE_LOCK, it is already taken */
   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
@@ -2505,14 +2540,12 @@ restart:
 
   done = FALSE;
   while (!done) {
-    gpointer data;
-
     switch (gst_iterator_next (it, &data)) {
       case GST_ITERATOR_OK:
       {
         GstElement *child;
 
-        child = GST_ELEMENT_CAST (data);
+        child = g_value_get_object (&data);
 
         /* set state and base_time now */
         ret = gst_bin_element_set_state (bin, child, base_time, start_time,
@@ -2548,7 +2581,6 @@ restart:
             parent = gst_object_get_parent (GST_OBJECT_CAST (child));
             if (parent == GST_OBJECT_CAST (element)) {
               /* element is still in bin, really error now */
-              gst_object_unref (child);
               gst_object_unref (parent);
               goto done;
             }
@@ -2574,7 +2606,7 @@ restart:
             g_assert_not_reached ();
             break;
         }
-        gst_object_unref (child);
+        g_value_reset (&data);
         break;
       }
       case GST_ITERATOR_RESYNC:
@@ -2589,7 +2621,7 @@ restart:
     }
   }
 
-  ret = parent_class->change_state (element, transition);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
     goto done;
 
@@ -2606,6 +2638,7 @@ restart:
   }
 
 done:
+  g_value_unset (&data);
   gst_iterator_free (it);
 
   GST_OBJECT_LOCK (bin);
@@ -2638,7 +2671,7 @@ done:
     bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
 
     GST_DEBUG_OBJECT (bin, "async elements commited");
-    bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE);
+    bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE, FALSE);
   }
 
 state_end:
@@ -2679,6 +2712,7 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
   GstIterator *iter;
   gboolean res = TRUE;
   gboolean done = FALSE;
+  GValue data = { 0, };
 
   if (GST_EVENT_IS_DOWNSTREAM (event)) {
     iter = gst_bin_iterate_sources (bin);
@@ -2691,19 +2725,15 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
   }
 
   while (!done) {
-    gpointer data;
-
     switch (gst_iterator_next (iter, &data)) {
       case GST_ITERATOR_OK:
       {
-        GstElement *child;
+        GstElement *child = g_value_get_object (&data);;
 
         gst_event_ref (event);
-        child = GST_ELEMENT_CAST (data);
         res &= gst_element_send_event (child, event);
         GST_LOG_OBJECT (child, "After handling %s event: %d",
             GST_EVENT_TYPE_NAME (event), res);
-        gst_object_unref (child);
         break;
       }
       case GST_ITERATOR_RESYNC:
@@ -2718,6 +2748,7 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
         break;
     }
   }
+  g_value_unset (&data);
   gst_iterator_free (iter);
   gst_event_unref (event);
 
@@ -2816,7 +2847,7 @@ bin_push_state_continue (BinContinueData * data)
  * This function is called with the OBJECT lock.
  */
 static void
-bin_handle_async_start (GstBin * bin, gboolean new_base_time)
+bin_handle_async_start (GstBin * bin)
 {
   GstState old_state, new_state;
   gboolean toplevel;
@@ -2832,8 +2863,7 @@ bin_handle_async_start (GstBin * bin, gboolean new_base_time)
    * are busy with a state change or when we are NO_PREROLL. */
   if (!toplevel)
     /* non toplevel bin, prepare async-start for the parent */
-    amessage =
-        gst_message_new_async_start (GST_OBJECT_CAST (bin), new_base_time);
+    amessage = gst_message_new_async_start (GST_OBJECT_CAST (bin));
 
   if (bin->polling || GST_STATE_PENDING (bin) != GST_STATE_VOID_PENDING)
     goto was_busy;
@@ -2900,7 +2930,7 @@ was_no_preroll:
  */
 static void
 bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
-    gboolean flag_pending)
+    gboolean flag_pending, gboolean reset_time)
 {
   GstState current, pending, target;
   GstStateChangeReturn old_ret;
@@ -2928,7 +2958,7 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
   target = GST_STATE_TARGET (bin);
   pending = GST_STATE_PENDING (bin) = target;
 
-  amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin));
+  amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin), reset_time);
 
   old_state = GST_STATE (bin);
   /* this is the state we should go to next */
@@ -3318,14 +3348,11 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
     }
     case GST_MESSAGE_ASYNC_START:
     {
-      gboolean new_base_time;
       GstState target;
 
       GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
           src ? GST_OBJECT_NAME (src) : "(NULL)");
 
-      gst_message_parse_async_start (message, &new_base_time);
-
       GST_OBJECT_LOCK (bin);
       bin_do_message_forward (bin, message);
 
@@ -3336,7 +3363,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
       /* takes ownership of the message */
       bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START);
 
-      bin_handle_async_start (bin, new_base_time);
+      bin_handle_async_start (bin);
       GST_OBJECT_UNLOCK (bin);
       break;
 
@@ -3351,11 +3378,14 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
     }
     case GST_MESSAGE_ASYNC_DONE:
     {
+      gboolean reset_time;
       GstState target;
 
       GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
           src ? GST_OBJECT_NAME (src) : "(NULL)");
 
+      gst_message_parse_async_done (message, &reset_time);
+
       GST_OBJECT_LOCK (bin);
       bin_do_message_forward (bin, message);
 
@@ -3376,7 +3406,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
          * need to set the pending_done flag so that at the end of the state
          * change we can see if we need to verify pending async elements, hence
          * the TRUE argument here. */
-        bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE);
+        bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE, reset_time);
       } else {
         GST_DEBUG_OBJECT (bin, "there are more async elements pending");
       }
@@ -3457,8 +3487,10 @@ bin_query_min_max_init (GstBin * bin, QueryFold * fold)
 }
 
 static gboolean
-bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
+bin_query_duration_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
 {
+  GstElement *item = g_value_get_object (vitem);
+
   if (gst_element_query (item, fold->query)) {
     gint64 duration;
 
@@ -3472,7 +3504,6 @@ bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
       fold->max = duration;
   }
 
-  gst_object_unref (item);
   return TRUE;
 }
 
@@ -3487,18 +3518,18 @@ bin_query_duration_done (GstBin * bin, QueryFold * fold)
 
   GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
 
-#ifdef DURATION_CACHING
   /* and cache now */
   GST_OBJECT_LOCK (bin);
   bin->messages = g_list_prepend (bin->messages,
       gst_message_new_duration (GST_OBJECT_CAST (bin), format, fold->max));
   GST_OBJECT_UNLOCK (bin);
-#endif
 }
 
 static gboolean
-bin_query_position_fold (GstElement * item, GValue * ret, QueryFold * fold)
+bin_query_position_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
 {
+  GstElement *item = g_value_get_object (vitem);
+
   if (gst_element_query (item, fold->query)) {
     gint64 position;
 
@@ -3512,7 +3543,6 @@ bin_query_position_fold (GstElement * item, GValue * ret, QueryFold * fold)
       fold->max = position;
   }
 
-  gst_object_unref (item);
   return TRUE;
 }
 
@@ -3529,8 +3559,10 @@ bin_query_position_done (GstBin * bin, QueryFold * fold)
 }
 
 static gboolean
-bin_query_latency_fold (GstElement * item, GValue * ret, QueryFold * fold)
+bin_query_latency_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
 {
+  GstElement *item = g_value_get_object (vitem);
+
   if (gst_element_query (item, fold->query)) {
     GstClockTime min, max;
     gboolean live;
@@ -3558,7 +3590,6 @@ bin_query_latency_fold (GstElement * item, GValue * ret, QueryFold * fold)
     GST_DEBUG_OBJECT (item, "failed query");
   }
 
-  gst_object_unref (item);
   return TRUE;
 }
 
@@ -3576,8 +3607,9 @@ bin_query_latency_done (GstBin * bin, QueryFold * fold)
 
 /* generic fold, return first valid result */
 static gboolean
-bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
+bin_query_generic_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
 {
+  GstElement *item = g_value_get_object (vitem);
   gboolean res;
 
   if ((res = gst_element_query (item, fold->query))) {
@@ -3585,8 +3617,6 @@ bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
     GST_DEBUG_OBJECT (item, "answered query %p", fold->query);
   }
 
-  gst_object_unref (item);
-
   /* and stop as soon as we have a valid result */
   return !res;
 }
@@ -3606,7 +3636,6 @@ gst_bin_query (GstElement * element, GstQuery * query)
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_DURATION:
     {
-#ifdef DURATION_CACHING
       GList *cached;
       GstFormat qformat;
 
@@ -3637,7 +3666,6 @@ gst_bin_query (GstElement * element, GstQuery * query)
         }
       }
       GST_OBJECT_UNLOCK (bin);
-#endif
       /* no cached value found, iterate and collect durations */
       fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
       fold_init = bin_query_min_max_init;
@@ -3703,26 +3731,22 @@ gst_bin_query (GstElement * element, GstQuery * query)
 done:
   gst_iterator_free (iter);
 
-#ifdef DURATION_CACHING
 exit:
-#endif
   GST_DEBUG_OBJECT (bin, "query %p result %d", query, res);
 
   return res;
 }
 
 static gint
-compare_name (GstElement * element, const gchar * name)
+compare_name (const GValue * velement, const gchar * name)
 {
   gint eq;
+  GstElement *element = g_value_get_object (velement);
 
   GST_OBJECT_LOCK (element);
   eq = strcmp (GST_ELEMENT_NAME (element), name);
   GST_OBJECT_UNLOCK (element);
 
-  if (eq != 0) {
-    gst_object_unref (element);
-  }
   return eq;
 }
 
@@ -3744,7 +3768,9 @@ GstElement *
 gst_bin_get_by_name (GstBin * bin, const gchar * name)
 {
   GstIterator *children;
-  gpointer result;
+  GValue result = { 0, };
+  GstElement *element;
+  gboolean found;
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
 
@@ -3752,11 +3778,18 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name)
       GST_ELEMENT_NAME (bin), name);
 
   children = gst_bin_iterate_recurse (bin);
-  result = gst_iterator_find_custom (children,
-      (GCompareFunc) compare_name, (gpointer) name);
+  found = gst_iterator_find_custom (children,
+      (GCompareFunc) compare_name, &result, (gpointer) name);
   gst_iterator_free (children);
 
-  return GST_ELEMENT_CAST (result);
+  if (found) {
+    element = g_value_dup_object (&result);
+    g_value_unset (&result);
+  } else {
+    element = NULL;
+  }
+
+  return element;
 }
 
 /**
@@ -3800,17 +3833,15 @@ gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
 }
 
 static gint
-compare_interface (GstElement * element, gpointer interface)
+compare_interface (const GValue * velement, GValue * interface)
 {
-  GType interface_type = (GType) interface;
+  GstElement *element = g_value_get_object (velement);
+  GType interface_type = (GType) g_value_get_pointer (interface);
   gint ret;
 
   if (G_TYPE_CHECK_INSTANCE_TYPE (element, interface_type)) {
     ret = 0;
   } else {
-    /* we did not find the element, need to release the ref
-     * added by the iterator */
-    gst_object_unref (element);
     ret = 1;
   }
   return ret;
@@ -3835,17 +3866,31 @@ GstElement *
 gst_bin_get_by_interface (GstBin * bin, GType iface)
 {
   GstIterator *children;
-  gpointer result;
+  GValue result = { 0, };
+  GstElement *element;
+  gboolean found;
+  GValue viface = { 0, };
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
 
+  g_value_init (&viface, G_TYPE_POINTER);
+  g_value_set_pointer (&viface, (gpointer) iface);
+
   children = gst_bin_iterate_recurse (bin);
-  result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
-      (gpointer) iface);
+  found = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
+      &result, &viface);
   gst_iterator_free (children);
 
-  return GST_ELEMENT_CAST (result);
+  if (found) {
+    element = g_value_dup_object (&result);
+    g_value_unset (&result);
+  } else {
+    element = NULL;
+  }
+  g_value_unset (&viface);
+
+  return element;
 }
 
 /**
@@ -3871,68 +3916,19 @@ gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
 {
   GstIterator *children;
   GstIterator *result;
+  GValue viface = { 0, };
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
 
+  g_value_init (&viface, G_TYPE_POINTER);
+  g_value_set_pointer (&viface, (gpointer) iface);
+
   children = gst_bin_iterate_recurse (bin);
   result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
-      (gpointer) iface);
-
-  return result;
-}
+      &viface);
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static xmlNodePtr
-gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
-{
-  GstBin *bin = GST_BIN_CAST (object);
-  xmlNodePtr childlist, elementnode;
-  GList *children;
-  GstElement *child;
-
-  if (GST_OBJECT_CLASS (parent_class)->save_thyself)
-    GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
-
-  childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
-
-  GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
-      GST_ELEMENT_NAME (bin), bin->numchildren);
+  g_value_unset (&viface);
 
-  children = g_list_last (bin->children);
-  while (children) {
-    child = GST_ELEMENT_CAST (children->data);
-    elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
-    gst_object_save_thyself (GST_OBJECT (child), elementnode);
-    children = g_list_previous (children);
-  }
-  return childlist;
-}
-
-static void
-gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
-{
-  GstBin *bin = GST_BIN_CAST (object);
-  xmlNodePtr field = self->xmlChildrenNode;
-  xmlNodePtr childlist;
-
-  while (field) {
-    if (!strcmp ((char *) field->name, "children")) {
-      GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
-          GST_ELEMENT_NAME (object));
-      childlist = field->xmlChildrenNode;
-      while (childlist) {
-        if (!strcmp ((char *) childlist->name, "element")) {
-          /* gst_xml_make_element will gst_bin_add() the element to ourself */
-          gst_xml_make_element (childlist, GST_OBJECT (bin));
-        }
-        childlist = childlist->next;
-      }
-    }
-
-    field = field->next;
-  }
-  if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
-    (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
+  return result;
 }
-#endif /* GST_DISABLE_LOADSAVE */
index 2473ef6..19c7634 100644 (file)
@@ -117,7 +117,7 @@ struct _GstBin {
   /*< private >*/
   GstBinPrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 /**
@@ -156,7 +156,7 @@ struct _GstBinClass {
   gboolean     (*do_latency)           (GstBin *bin);
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING-1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 GType          gst_bin_get_type                (void);
index edc0a6e..e0b64cf 100644 (file)
 /**
  * SECTION:gstbuffer
  * @short_description: Data-passing buffer type, supporting sub-buffers.
- * @see_also: #GstPad, #GstMiniObject
+ * @see_also: #GstPad, #GstMiniObject, #GstBufferPool
  *
  * Buffers are the basic unit of data transfer in GStreamer.  The #GstBuffer
- * type provides all the state necessary to define a region of memory as part
- * of a stream.  Sub-buffers are also supported, allowing a smaller region of a
- * buffer to become its own buffer, with mechanisms in place to ensure that
- * neither memory space goes away prematurely.
+ * type provides all the state necessary to define the regions of memory as
+ * part of a stream. Region copies are also supported, allowing a smaller
+ * region of a buffer to become its own buffer, with mechanisms in place to
+ * ensure that neither memory space goes away prematurely.
  *
  * Buffers are usually created with gst_buffer_new(). After a buffer has been
- * created one will typically allocate memory for it and set the size of the
- * buffer data.  The following example creates a buffer that can hold a given
- * video frame with a given width, height and bits per plane.
+ * created one will typically allocate memory for it and add it to the buffer.
+ * The following example creates a buffer that can hold a given video frame
+ * with a given width, height and bits per plane.
  * <example>
  * <title>Creating a buffer for a video frame</title>
  *   <programlisting>
  *   GstBuffer *buffer;
+ *   GstMemory *memory;
  *   gint size, width, height, bpp;
  *   ...
  *   size = width * height * bpp;
  *   buffer = gst_buffer_new ();
- *   GST_BUFFER_SIZE (buffer) = size;
- *   GST_BUFFER_MALLOCDATA (buffer) = g_malloc (size);
- *   GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
+ *   memory = gst_allocator_alloc (NULL, size, 0);
+ *   gst_buffer_take_memory (buffer, -1, memory);
  *   ...
  *   </programlisting>
  * </example>
  *
- * Alternatively, use gst_buffer_new_and_alloc()
+ * Alternatively, use gst_buffer_new_allocate()
  * to create a buffer with preallocated data of a given size.
  *
- * The data pointed to by the buffer can be retrieved with the GST_BUFFER_DATA()
- * macro. The size of the data can be found with GST_BUFFER_SIZE(). For buffers
- * of size 0, the data pointer is undefined (usually NULL) and should never be used.
+ * Buffers can contain a list of #GstMemory objects. You can retrieve how many
+ * memory objects with gst_buffer_n_memory() and you can get a pointer
+ * to memory with gst_buffer_peek_memory()
  *
- * If an element knows what pad you will push the buffer out on, it should use
- * gst_pad_alloc_buffer() instead to create a buffer.  This allows downstream
- * elements to provide special buffers to write in, like hardware buffers.
- *
- * A buffer has a pointer to a #GstCaps describing the media type of the data
- * in the buffer. Attach caps to the buffer with gst_buffer_set_caps(); this
- * is typically done before pushing out a buffer using gst_pad_push() so that
- * the downstream element knows the type of the buffer.
- *
- * A buffer will usually have a timestamp, and a duration, but neither of these
+ * A buffer will usually have timestamps, and a duration, but neither of these
  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
- * meaningful value can be given for these, they should be set. The timestamp
+ * meaningful value can be given for these, they should be set. The timestamps
  * and duration are measured in nanoseconds (they are #GstClockTime values).
  *
  * A buffer can also have one or both of a start and an end offset. These are
  * next element.
  *
  * To efficiently create a smaller buffer out of an existing one, you can
- * use gst_buffer_create_sub().
+ * use gst_buffer_copy_region().
  *
- * If a plug-in wants to modify the buffer data in-place, it should first obtain
- * a buffer that is safe to modify by using gst_buffer_make_writable().  This
- * function is optimized so that a copy will only be made when it is necessary.
- *
- * A plugin that only wishes to modify the metadata of a buffer, such as the
- * offset, timestamp or caps, should use gst_buffer_make_metadata_writable(),
- * which will create a subbuffer of the original buffer to ensure the caller
- * has sole ownership, and not copy the buffer data.
+ * If a plug-in wants to modify the buffer data or metadata in-place, it should
+ * first obtain a buffer that is safe to modify by using
+ * gst_buffer_make_writable().  This function is optimized so that a copy will
+ * only be made when it is necessary.
  *
  * Several flags of the buffer can be set and unset with the
  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlag is set.
  *
  * Buffers can be efficiently merged into a larger buffer with
- * gst_buffer_merge() and gst_buffer_span() if the gst_buffer_is_span_fast()
+ * gst_buffer_span(), which avoids memory copies when the gst_buffer_is_span_fast()
  * function returns TRUE.
  *
  * An element should either unref the buffer or push it out on a src pad
  * using gst_pad_push() (see #GstPad).
  *
  * Buffers are usually freed by unreffing them with gst_buffer_unref(). When
- * the refcount drops to 0, any data pointed to by GST_BUFFER_MALLOCDATA() will
- * also be freed.
+ * the refcount drops to 0, any data pointed to by the buffer is unreffed as
+ * well.
  *
- * Last reviewed on August 11th, 2006 (0.10.10)
+ * Last reviewed on November 8, 2011 (0.11.2)
  */
 #include "gst_private.h"
 
 #endif
 
 #include "gstbuffer.h"
+#include "gstbufferpool.h"
 #include "gstinfo.h"
 #include "gstutils.h"
 #include "gstminiobject.h"
 #include "gstversion.h"
 
-struct _GstBufferPrivate
-{
-  GList *qdata;
-  /* think about locking buffer->priv etc. when adding more fields */
-};
+GType _gst_buffer_type = 0;
 
-static void gst_buffer_finalize (GstBuffer * buffer);
-static GstBuffer *_gst_buffer_copy (GstBuffer * buffer);
+static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[],
+    guint n, gsize offset, gsize size, gboolean writable);
 
-static GType _gst_buffer_type = 0;
+typedef struct _GstMetaItem GstMetaItem;
 
-/* buffer alignment in bytes
- * an alignment of 8 would be the same as malloc() guarantees
- */
-#ifdef HAVE_POSIX_MEMALIGN
-#if defined(BUFFER_ALIGNMENT_MALLOC)
-static size_t _gst_buffer_data_alignment = 8;
-#elif defined(BUFFER_ALIGNMENT_PAGESIZE)
-static size_t _gst_buffer_data_alignment = 0;
-#elif defined(BUFFER_ALIGNMENT)
-static size_t _gst_buffer_data_alignment = BUFFER_ALIGNMENT;
-#else
-#error "No buffer alignment configured"
-#endif
-
-static inline gboolean
-aligned_malloc (gpointer * memptr, guint size)
+struct _GstMetaItem
 {
-  gint res;
-
-  res = posix_memalign (memptr, _gst_buffer_data_alignment, size);
-  return (res == 0);
-}
-
-#endif /* HAVE_POSIX_MEMALIGN */
-
-void
-_gst_buffer_initialize (void)
-{
-  /* the GstMiniObject types need to be class_ref'd once before it can be
-   * done from multiple threads;
-   * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
-  g_type_class_ref (gst_buffer_get_type ());
-#ifdef HAVE_GETPAGESIZE
-#ifdef BUFFER_ALIGNMENT_PAGESIZE
-  _gst_buffer_data_alignment = getpagesize ();
-#endif
-#endif
-}
+  GstMetaItem *next;
+  GstMeta meta;
+};
+#define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem))
 
-#define _do_init \
-{ \
-  _gst_buffer_type = g_define_type_id; \
-}
+#define GST_BUFFER_MEM_MAX         16
 
-G_DEFINE_TYPE_WITH_CODE (GstBuffer, gst_buffer, GST_TYPE_MINI_OBJECT, _do_init);
+#define GST_BUFFER_MEM_LEN(b)      (((GstBufferImpl *)(b))->len)
+#define GST_BUFFER_MEM_ARRAY(b)    (((GstBufferImpl *)(b))->mem)
+#define GST_BUFFER_MEM_PTR(b,i)    (((GstBufferImpl *)(b))->mem[i])
+#define GST_BUFFER_BUFMEM(b)       (((GstBufferImpl *)(b))->bufmem)
+#define GST_BUFFER_META(b)         (((GstBufferImpl *)(b))->item)
 
-static void
-gst_buffer_class_init (GstBufferClass * klass)
+typedef struct
 {
-  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_buffer_copy;
-  klass->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_buffer_finalize;
+  GstBuffer buffer;
 
-  g_type_class_add_private (klass, sizeof (GstBufferPrivate));
-}
-
-static void
-gst_buffer_finalize (GstBuffer * buffer)
-{
-  g_return_if_fail (buffer != NULL);
-
-  GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
+  /* the memory blocks */
+  guint len;
+  GstMemory *mem[GST_BUFFER_MEM_MAX];
 
-  /* free our data */
-  if (G_LIKELY (buffer->malloc_data))
-    buffer->free_func (buffer->malloc_data);
+  /* memory of the buffer when allocated from 1 chunk */
+  GstMemory *bufmem;
 
-  gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
+  /* FIXME, make metadata allocation more efficient by using part of the
+   * GstBufferImpl */
+  GstMetaItem *item;
+} GstBufferImpl;
 
-  if (buffer->parent)
-    gst_buffer_unref (buffer->parent);
+static GstMemory *
+_span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
+{
+  GstMemory *span, **mem[1];
+  gsize len[1];
 
-  if (G_UNLIKELY (buffer->priv != NULL)) {
-    GstBufferPrivate *priv = buffer->priv;
+  /* not enough room, span buffers */
+  mem[0] = GST_BUFFER_MEM_ARRAY (buffer);
+  len[0] = GST_BUFFER_MEM_LEN (buffer);
 
-    while (priv->qdata != NULL) {
-      GstStructure *s = priv->qdata->data;
+  if (size == -1)
+    size = gst_buffer_get_size (buffer);
 
-      gst_structure_set_parent_refcount (s, NULL);
-      gst_structure_free (s);
-      priv->qdata = g_list_delete_link (priv->qdata, priv->qdata);
-    }
-    priv->qdata = NULL;
-  }
+  span = _gst_buffer_arr_span (mem, len, 1, offset, size, writable);
 
-/*   ((GstMiniObjectClass *) */
-/*       gst_buffer_parent_class)->finalize (GST_MINI_OBJECT_CAST (buffer)); */
+  return span;
 }
 
-static inline GstBufferPrivate *
-gst_buffer_ensure_priv (GstBuffer * buf)
+static void
+_replace_memory (GstBuffer * buffer, GstMemory * mem)
 {
-  GstBufferPrivate *priv = buf->priv;
+  gsize len, i;
 
-  if (priv != NULL)
-    return priv;
+  /* unref old buffers */
+  len = GST_BUFFER_MEM_LEN (buffer);
+  for (i = 0; i < len; i++)
+    gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
 
-  priv = buf->priv =
-      G_TYPE_INSTANCE_GET_PRIVATE (buf, GST_TYPE_BUFFER, GstBufferPrivate);
-
-  return priv;
+  /* replace with single spanned buffer */
+  GST_BUFFER_MEM_PTR (buffer, 0) = mem;
+  GST_BUFFER_MEM_LEN (buffer) = 1;
 }
 
-static void
-gst_buffer_copy_qdata (GstBuffer * dest, const GstBuffer * src)
+static inline void
+_memory_add (GstBuffer * buffer, guint idx, GstMemory * mem)
 {
-  GstBufferPrivate *priv;
-  GQueue qdata_copy = G_QUEUE_INIT;
-  GList *l;
-
-  if (G_LIKELY (src->priv == NULL))
-    return;
-
-  for (l = src->priv->qdata; l != NULL; l = l->next) {
-    GstStructure *s = gst_structure_copy (l->data);
+  guint i, len = GST_BUFFER_MEM_LEN (buffer);
+
+  if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
+    /* too many buffer, span them. */
+    /* FIXME, there is room for improvement here: We could only try to merge
+     * 2 buffers to make some room. If we can't efficiently merge 2 buffers we
+     * could try to only merge the two smallest buffers to avoid memcpy, etc. */
+    _replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
+    /* we now have 1 single spanned buffer */
+    len = 1;
+  }
 
-    gst_structure_set_parent_refcount (s, &dest->mini_object.refcount);
-    g_queue_push_tail (&qdata_copy, s);
+  if (idx == -1)
+    idx = len;
 
-    GST_CAT_TRACE (GST_CAT_BUFFER, "copying qdata '%s' from buffer %p to %p",
-        g_quark_to_string (s->name), src, dest);
+  for (i = len; i > idx; i--) {
+    /* move buffers to insert, FIXME, we need to insert first and then merge */
+    GST_BUFFER_MEM_PTR (buffer, i) = GST_BUFFER_MEM_PTR (buffer, i - 1);
   }
+  /* and insert the new buffer */
+  GST_BUFFER_MEM_PTR (buffer, idx) = mem;
+  GST_BUFFER_MEM_LEN (buffer) = len + 1;
+}
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer);
 
-  priv = gst_buffer_ensure_priv (dest);
-  priv->qdata = qdata_copy.head;
+void
+_priv_gst_buffer_initialize (void)
+{
+  _gst_buffer_type = gst_buffer_get_type ();
 }
 
 /**
- * gst_buffer_copy_metadata:
+ * gst_buffer_copy_into:
  * @dest: a destination #GstBuffer
  * @src: a source #GstBuffer
  * @flags: flags indicating what metadata fields should be copied.
+ * @offset: offset to copy from
+ * @size: total size to copy. If -1, all data is copied.
  *
- * Copies the metadata from @src into @dest. The data, size and mallocdata
- * fields are not copied.
- *
- * @flags indicate which fields will be copied. Use #GST_BUFFER_COPY_ALL to copy
- * all the metadata fields.
- *
- * This function is typically called from a custom buffer copy function after
- * creating @dest and setting the data, size, mallocdata.
+ * Copies the information from @src into @dest.
  *
- * Since: 0.10.13
+ * @flags indicate which fields will be copied.
  */
 void
-gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
-    GstBufferCopyFlags flags)
+gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
+    GstBufferCopyFlags flags, gsize offset, gsize size)
 {
+  GstMetaItem *walk;
+  gsize bufsize;
+
   g_return_if_fail (dest != NULL);
   g_return_if_fail (src != NULL);
 
@@ -294,196 +248,190 @@ gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
   if (G_UNLIKELY (dest == src))
     return;
 
-#if GST_VERSION_NANO == 1
-  /* we enable this extra debugging in git versions only for now */
-  g_warn_if_fail (gst_buffer_is_metadata_writable (dest));
-#endif
+  g_return_if_fail (gst_buffer_is_writable (dest));
 
-  GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p", src, dest);
+  bufsize = gst_buffer_get_size (src);
+  g_return_if_fail (bufsize >= offset);
+  if (size == -1)
+    size = bufsize - offset;
+  g_return_if_fail (bufsize >= offset + size);
 
-  if (flags & GST_BUFFER_COPY_FLAGS) {
-    guint mask;
+  GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
+      "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
+      bufsize);
 
-    /* copy relevant flags */
-    mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
-        GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
-        GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
-        GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
-    GST_MINI_OBJECT_FLAGS (dest) |= GST_MINI_OBJECT_FLAGS (src) & mask;
+  if (flags & GST_BUFFER_COPY_FLAGS) {
+    /* copy flags */
+    GST_MINI_OBJECT_FLAGS (dest) = GST_MINI_OBJECT_FLAGS (src);
   }
 
   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
-    GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src);
-    GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
-    GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
-    GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
-  }
-
-  if (flags & GST_BUFFER_COPY_CAPS) {
-    gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
-  }
-
-  if ((flags & GST_BUFFER_COPY_QDATA)) {
-    GST_CAT_TRACE (GST_CAT_BUFFER, "copying qdata from %p to %p", src, dest);
-    gst_buffer_copy_qdata (dest, src);
+    if (offset == 0) {
+      GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
+      GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
+      GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
+      if (size == bufsize) {
+        GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
+        GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
+      }
+    } else {
+      GST_BUFFER_PTS (dest) = GST_CLOCK_TIME_NONE;
+      GST_BUFFER_DTS (dest) = GST_CLOCK_TIME_NONE;
+      GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE;
+      GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE;
+      GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE;
+    }
   }
-}
 
-/**
- * gst_buffer_set_qdata:
- * @buffer: a #GstBuffer
- * @quark: name quark of data structure to set or replace
- * @data: (transfer full) (allow-none): a #GstStructure to store with the
- *    buffer, name must match @quark. Can be NULL to remove an existing
- *    structure. This function takes ownership of the structure passed.
- *
- * Set metadata structure for name quark @quark to @data, or remove the
- * existing metadata structure by that name in case @data is NULL.
- *
- * Takes ownership of @data.
- *
- * Since: 0.10.36
- */
-void
-gst_buffer_set_qdata (GstBuffer * buffer, GQuark quark, GstStructure * data)
-{
-  GstBufferPrivate *priv;
-  GList *l;
+  if (flags & GST_BUFFER_COPY_MEMORY) {
+    GstMemory *mem;
+    gsize skip, left, len, i, bsize;
 
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-  g_return_if_fail (gst_buffer_is_metadata_writable (buffer));
-  g_return_if_fail (data == NULL || quark == gst_structure_get_name_id (data));
+    len = GST_BUFFER_MEM_LEN (src);
+    left = size;
+    skip = offset;
 
-  /* locking should not really be required, since the metadata_writable
-   * check ensures that the caller is the only one holding a ref, so as
-   * as a second ref is added everything turns read-only */
-  priv = gst_buffer_ensure_priv (buffer);
+    /* copy and make regions of the memory */
+    for (i = 0; i < len && left > 0; i++) {
+      mem = GST_BUFFER_MEM_PTR (src, i);
+      bsize = gst_memory_get_sizes (mem, NULL, NULL);
 
-  if (data) {
-    gst_structure_set_parent_refcount (data, &buffer->mini_object.refcount);
+      if (bsize <= skip) {
+        /* don't copy buffer */
+        skip -= bsize;
+      } else {
+        gsize tocopy;
+
+        tocopy = MIN (bsize - skip, left);
+        if (mem->flags & GST_MEMORY_FLAG_NO_SHARE) {
+          /* no share, always copy then */
+          mem = gst_memory_copy (mem, skip, tocopy);
+          skip = 0;
+        } else if (tocopy < bsize) {
+          /* we need to clip something */
+          mem = gst_memory_share (mem, skip, tocopy);
+          skip = 0;
+        } else {
+          mem = gst_memory_ref (mem);
+        }
+        _memory_add (dest, -1, mem);
+        left -= tocopy;
+      }
+    }
+    if (flags & GST_BUFFER_COPY_MERGE) {
+      _replace_memory (dest, _span_memory (dest, 0, size, FALSE));
+    }
   }
 
-  for (l = priv->qdata; l != NULL; l = l->next) {
-    GstStructure *s = l->data;
+  if (flags & GST_BUFFER_COPY_META) {
+    for (walk = GST_BUFFER_META (src); walk; walk = walk->next) {
+      GstMeta *meta = &walk->meta;
+      const GstMetaInfo *info = meta->info;
 
-    if (s->name == quark) {
-      GST_CAT_LOG (GST_CAT_BUFFER, "Replacing qdata '%s' on buffer %p: "
-          "%" GST_PTR_FORMAT " => %" GST_PTR_FORMAT, g_quark_to_string (quark),
-          buffer, s, data);
-      gst_structure_set_parent_refcount (s, NULL);
-      gst_structure_free (s);
-
-      if (data == NULL)
-        priv->qdata = g_list_delete_link (priv->qdata, l);
-      else
-        l->data = data;
-
-      goto done;
+      if (info->copy_func)
+        info->copy_func (dest, meta, src, offset, size);
     }
   }
-
-  GST_CAT_LOG (GST_CAT_BUFFER, "Set qdata '%s' on buffer %p: %" GST_PTR_FORMAT,
-      g_quark_to_string (quark), buffer, data);
-
-  priv->qdata = g_list_prepend (priv->qdata, data);
-
-done:
-
-  return;
 }
 
-/**
- * gst_buffer_get_qdata:
- * @buffer: a #GstBuffer
- * @quark: name quark of data structure to find
- *
- * Get metadata structure for name quark @quark.
- *
- * Returns: (transfer none): a #GstStructure, or NULL if not found
- *
- * Since: 0.10.36
- */
-const GstStructure *
-gst_buffer_get_qdata (GstBuffer * buffer, GQuark quark)
+static GstBuffer *
+_gst_buffer_copy (GstBuffer * buffer)
 {
-  GstStructure *ret = NULL;
+  GstBuffer *copy;
 
-  /* no need for locking: if the caller has the only ref, we're safe, and
-   * if the buffer has multiple refs, it's not metadata-writable any longer
-   * and the data can't change */
+  g_return_val_if_fail (buffer != NULL, NULL);
 
-  GST_CAT_LOG (GST_CAT_BUFFER, "Looking for qdata '%s' on buffer %p",
-      g_quark_to_string (quark), buffer);
+  /* create a fresh new buffer */
+  copy = gst_buffer_new ();
 
-  if (buffer->priv != NULL) {
-    GList *l;
+  /* we simply copy everything from our parent */
+  gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1);
 
-    for (l = buffer->priv->qdata; l != NULL; l = l->next) {
-      GstStructure *s = l->data;
+  return copy;
+}
 
-      GST_CAT_LOG (GST_CAT_BUFFER, "checking qdata '%s' on buffer %p",
-          g_quark_to_string (s->name), buffer);
+/* the default dispose function revives the buffer and returns it to the
+ * pool when there is a pool */
+static gboolean
+_gst_buffer_dispose (GstBuffer * buffer)
+{
+  GstBufferPool *pool;
 
-      if (s->name == quark) {
-        ret = s;
-        break;
-      }
-    }
-  }
+  /* no pool, do free */
+  if ((pool = buffer->pool) == NULL)
+    return TRUE;
+
+  /* keep the buffer alive */
+  gst_buffer_ref (buffer);
+  /* return the buffer to the pool */
+  GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool);
+  gst_buffer_pool_release_buffer (pool, buffer);
 
-  return ret;
+  return FALSE;
 }
 
-static GstBuffer *
-_gst_buffer_copy (GstBuffer * buffer)
+static void
+_gst_buffer_free (GstBuffer * buffer)
 {
-  GstBuffer *copy;
+  GstMetaItem *walk, *next;
+  guint i, len;
+  gsize msize;
 
-  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_if_fail (buffer != NULL);
 
-  /* create a fresh new buffer */
-  copy = gst_buffer_new ();
+  GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
 
-  /* we simply copy everything from our parent */
-#ifdef HAVE_POSIX_MEMALIGN
-  {
-    gpointer memptr = NULL;
+  /* free metadata */
+  for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
+    GstMeta *meta = &walk->meta;
+    const GstMetaInfo *info = meta->info;
 
-    if (G_LIKELY (buffer->size)) {
-      if (G_UNLIKELY (!aligned_malloc (&memptr, buffer->size))) {
-        /* terminate on error like g_memdup() would */
-        g_error ("%s: failed to allocate %u bytes", G_STRLOC, buffer->size);
-      } else {
-        memcpy (memptr, buffer->data, buffer->size);
-      }
-    }
-    copy->data = (guint8 *) memptr;
-    GST_BUFFER_FREE_FUNC (copy) = free;
+    /* call free_func if any */
+    if (info->free_func)
+      info->free_func (meta, buffer);
+
+    next = walk->next;
+    /* and free the slice */
+    g_slice_free1 (ITEM_SIZE (info), walk);
   }
-#else
-  copy->data = g_memdup (buffer->data, buffer->size);
-#endif
 
-  /* make sure it gets freed (even if the parent is subclassed, we return a
-     normal buffer) */
-  copy->malloc_data = copy->data;
-  copy->size = buffer->size;
+  /* get the size, when unreffing the memory, we could also unref the buffer
+   * itself */
+  msize = GST_MINI_OBJECT_SIZE (buffer);
 
-  gst_buffer_copy_metadata (copy, buffer, GST_BUFFER_COPY_ALL);
+  /* free our memory */
+  len = GST_BUFFER_MEM_LEN (buffer);
+  for (i = 0; i < len; i++)
+    gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
 
-  return copy;
+  /* we set msize to 0 when the buffer is part of the memory block */
+  if (msize)
+    g_slice_free1 (msize, buffer);
+  else
+    gst_memory_unref (GST_BUFFER_BUFMEM (buffer));
 }
 
 static void
-gst_buffer_init (GstBuffer * buffer)
+gst_buffer_init (GstBufferImpl * buffer, gsize size)
 {
-  GST_CAT_LOG (GST_CAT_BUFFER, "init %p", buffer);
-
-  GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), _gst_buffer_type, size);
+
+  buffer->buffer.mini_object.copy =
+      (GstMiniObjectCopyFunction) _gst_buffer_copy;
+  buffer->buffer.mini_object.dispose =
+      (GstMiniObjectDisposeFunction) _gst_buffer_dispose;
+  buffer->buffer.mini_object.free =
+      (GstMiniObjectFreeFunction) _gst_buffer_free;
+
+  GST_BUFFER (buffer)->pool = NULL;
+  GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
+  GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
-  GST_BUFFER_FREE_FUNC (buffer) = g_free;
+
+  GST_BUFFER_MEM_LEN (buffer) = 0;
+  GST_BUFFER_META (buffer) = NULL;
 }
 
 /**
@@ -498,228 +446,780 @@ gst_buffer_init (GstBuffer * buffer)
 GstBuffer *
 gst_buffer_new (void)
 {
-  GstBuffer *newbuf;
-
-  newbuf = (GstBuffer *) gst_mini_object_new (_gst_buffer_type);
+  GstBufferImpl *newbuf;
 
+  newbuf = g_slice_new (GstBufferImpl);
   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
 
-  return newbuf;
+  gst_buffer_init (newbuf, sizeof (GstBufferImpl));
+
+  return GST_BUFFER_CAST (newbuf);
 }
 
 /**
- * gst_buffer_new_and_alloc:
+ * gst_buffer_new_allocate:
+ * @allocator: (allow-none): the #GstAllocator to use, or NULL to use the
+ *     default allocator
  * @size: the size in bytes of the new buffer's data.
+ * @align: the alignment of the buffer memory
+ *
+ * Tries to create a newly allocated buffer with data of the given size and
+ * alignment from @allocator. If the requested amount of memory can't be
+ * allocated, NULL will be returned. The allocated buffer memory is not cleared.
  *
- * Creates a newly allocated buffer with data of the given size.
- * The buffer memory is not cleared. If the requested amount of
- * memory can't be allocated, the program will abort. Use
- * gst_buffer_try_new_and_alloc() if you want to handle this case
- * gracefully or have gotten the size to allocate from an untrusted
- * source such as a media stream.
- * 
+ * When @allocator is NULL, the default memory allocator will be used.
  *
- * Note that when @size == 0, the buffer data pointer will be NULL.
+ * Allocator buffer memory will be aligned to multiples of (@align + 1) bytes.
+ *
+ * Note that when @size == 0, the buffer will not have memory associated with it.
  *
  * MT safe.
  *
- * Returns: (transfer full): the new #GstBuffer.
+ * Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't
+ *     be allocated.
  */
 GstBuffer *
-gst_buffer_new_and_alloc (guint size)
+gst_buffer_new_allocate (const GstAllocator * allocator, gsize size,
+    gsize align)
 {
   GstBuffer *newbuf;
+  GstMemory *mem;
+#if 0
+  guint8 *data;
+  gsize asize;
+#endif
+
+#if 1
+  if (size > 0) {
+    mem = gst_allocator_alloc (allocator, size, align);
+    if (G_UNLIKELY (mem == NULL))
+      goto no_memory;
+  } else {
+    mem = NULL;
+  }
 
   newbuf = gst_buffer_new ();
 
-#ifdef HAVE_POSIX_MEMALIGN
-  {
-    gpointer memptr = NULL;
+  if (mem != NULL)
+    _memory_add (newbuf, -1, mem);
 
-    if (G_LIKELY (size)) {
-      if (G_UNLIKELY (!aligned_malloc (&memptr, size))) {
-        /* terminate on error like g_memdup() would */
-        g_error ("%s: failed to allocate %u bytes", G_STRLOC, size);
-      }
-    }
-    newbuf->malloc_data = (guint8 *) memptr;
-    GST_BUFFER_FREE_FUNC (newbuf) = free;
+  GST_CAT_LOG (GST_CAT_BUFFER,
+      "new buffer %p of size %" G_GSIZE_FORMAT " from allocator %p", newbuf,
+      size, allocator);
+#endif
+
+#if 0
+  asize = sizeof (GstBufferImpl) + size;
+  data = g_slice_alloc (asize);
+  if (G_UNLIKELY (data == NULL))
+    goto no_memory;
+
+  newbuf = GST_BUFFER_CAST (data);
+
+  gst_buffer_init ((GstBufferImpl *) data, asize);
+  if (size > 0) {
+    mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL,
+        size, 0, size);
+    _memory_add (newbuf, -1, mem);
   }
-#else
-  newbuf->malloc_data = g_malloc (size);
 #endif
-  GST_BUFFER_DATA (newbuf) = newbuf->malloc_data;
-  GST_BUFFER_SIZE (newbuf) = size;
 
-  GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
+#if 0
+  /* allocate memory and buffer, it might be interesting to do this but there
+   * are many complications. We need to keep the memory mapped to access the
+   * buffer fields and the memory for the buffer might be just very slow. We
+   * also need to do some more magic to get the alignment right. */
+  asize = sizeof (GstBufferImpl) + size;
+  mem = gst_allocator_alloc (allocator, asize, align);
+  if (G_UNLIKELY (mem == NULL))
+    goto no_memory;
+
+  /* map the data part and init the buffer in it, set the buffer size to 0 so
+   * that a finalize won't free the buffer */
+  data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
+  gst_buffer_init ((GstBufferImpl *) data, 0);
+  gst_memory_unmap (mem);
+
+  /* strip off the buffer */
+  gst_memory_resize (mem, sizeof (GstBufferImpl), size);
+
+  newbuf = GST_BUFFER_CAST (data);
+  GST_BUFFER_BUFMEM (newbuf) = mem;
+
+  if (size > 0)
+    _memory_add (newbuf, -1, gst_memory_ref (mem));
+#endif
 
   return newbuf;
+
+  /* ERRORS */
+no_memory:
+  {
+    GST_CAT_WARNING (GST_CAT_BUFFER,
+        "failed to allocate %" G_GSIZE_FORMAT " bytes", size);
+    return NULL;
+  }
 }
 
 /**
- * gst_buffer_try_new_and_alloc:
- * @size: the size in bytes of the new buffer's data.
+ * gst_buffer_new_wrapped_full:
+ * @data: data to wrap
+ * @free_func: function to free @data
+ * @offset: offset in @data of valid data
+ * @size: size of valid data in @data starting at @offset
  *
- * Tries to create a newly allocated buffer with data of the given size. If
- * the requested amount of memory can't be allocated, NULL will be returned.
- * The buffer memory is not cleared.
- *
- * Note that when @size == 0, the buffer data pointer will be NULL.
+ * Creates a new buffer that wraps the given @data.  Valid data is set
+ * to start at @offset and up to @size.  If no @free_func is provided,
+ * buffer memory is marked READONLY.
  *
  * MT safe.
  *
- * Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't
- *     be allocated.
- *
- * Since: 0.10.13
+ * Returns: (transfer full): a new #GstBuffer
  */
 GstBuffer *
-gst_buffer_try_new_and_alloc (guint size)
+gst_buffer_new_wrapped_full (gpointer data, GFreeFunc free_func, gsize offset,
+    gsize size)
 {
   GstBuffer *newbuf;
-  guint8 *malloc_data;
-#ifdef HAVE_POSIX_MEMALIGN
-  gpointer memptr = NULL;
-
-  if (G_LIKELY (size)) {
-    if (G_UNLIKELY (!aligned_malloc (&memptr, size))) {
-      GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
-      return NULL;
-    }
-  }
-  malloc_data = (guint8 *) memptr;
-#else
-  malloc_data = g_try_malloc (size);
-
-  if (G_UNLIKELY (malloc_data == NULL && size != 0)) {
-    GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
-    return NULL;
-  }
-#endif
 
-  /* FIXME: there's no g_type_try_create_instance() in GObject yet, so this
-   * will still abort if a new GstBuffer structure can't be allocated */
   newbuf = gst_buffer_new ();
+  gst_buffer_take_memory (newbuf, -1,
+      gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
+          data, free_func, offset + size, offset, size));
 
-  GST_BUFFER_MALLOCDATA (newbuf) = malloc_data;
-  GST_BUFFER_DATA (newbuf) = malloc_data;
-  GST_BUFFER_SIZE (newbuf) = size;
-#ifdef HAVE_POSIX_MEMALIGN
-  GST_BUFFER_FREE_FUNC (newbuf) = free;
-#endif
+  return newbuf;
+}
 
-  GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
+/**
+ * gst_buffer_new_wrapped:
+ * @data: data to wrap
+ * @size: allocated size of @data
+ *
+ * Creates a new buffer that wraps the given @data. The memory will be freed
+ * with g_free and will be marked writable.
+ *
+ * MT safe.
+ *
+ * Returns: (transfer full): a new #GstBuffer
+ */
+GstBuffer *
+gst_buffer_new_wrapped (gpointer data, gsize size)
+{
+  return gst_buffer_new_wrapped_full (data, g_free, 0, size);
+}
 
-  return newbuf;
+/**
+ * gst_buffer_n_memory:
+ * @buffer: a #GstBuffer.
+ *
+ * Get the amount of memory blocks that this buffer has.
+ *
+ * Returns: (transfer full): the amount of memory block in this buffer.
+ */
+guint
+gst_buffer_n_memory (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+
+  return GST_BUFFER_MEM_LEN (buffer);
+}
+
+/**
+ * gst_buffer_take_memory:
+ * @buffer: a #GstBuffer.
+ * @idx: the index to add the memory at, or -1 to append it to the end
+ * @mem: (transfer full): a #GstMemory.
+ *
+ * Add the memory block @mem to @buffer at @idx. This function takes ownership
+ * of @mem and thus doesn't increase its refcount.
+ */
+void
+gst_buffer_take_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (gst_buffer_is_writable (buffer));
+  g_return_if_fail (mem != NULL);
+  g_return_if_fail (idx == -1 ||
+      (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)));
+
+  _memory_add (buffer, idx, mem);
+}
+
+static GstMemory *
+_get_memory (GstBuffer * buffer, guint idx, gboolean write)
+{
+  GstMemory *mem;
+
+  mem = GST_BUFFER_MEM_PTR (buffer, idx);
+
+  if (G_UNLIKELY (write && !gst_memory_is_writable (mem))) {
+    GstMemory *copy;
+    GST_CAT_LOG (GST_CAT_BUFFER,
+        "making writable copy of memory %p in buffer %p", mem, buffer);
+    /* replace with a writable copy */
+    copy = gst_memory_copy (mem, 0, -1);
+    GST_BUFFER_MEM_PTR (buffer, idx) = copy;
+    gst_memory_unref (mem);
+    mem = copy;
+  }
+  return mem;
 }
 
 /**
- * gst_buffer_get_caps:
+ * gst_buffer_peek_memory:
  * @buffer: a #GstBuffer.
+ * @idx: an index
+ * @flags: #GstMapFlags
  *
- * Gets the media type of the buffer. This can be NULL if there
- * is no media type attached to this buffer.
+ * Get the memory block in @buffer at @idx for memory access in @flags.
+ * This function does not return a refcount to the memory block. The memory
+ * block stays valid for as long as the caller has a valid reference to @buffer
+ * and as long as no operations that modify the memory blocks are called, such
+ * as gst_buffer_remove_memory_range(), gst_buffer_take_memory() and gst_buffer_resize().
  *
- * Returns: (transfer full): a reference to the #GstCaps. unref after usage.
- * Returns NULL if there were no caps on this buffer.
+ * @buffer should be writable when @flags contains #GST_MAP_WRITE. If the memory
+ * at @idx is not writable, a new writable copy will be installed in @buffer and
+ * returned.
+ *
+ * Returns: a #GstMemory at @idx.
  */
-/* this is not made atomic because if the buffer were reffed from multiple
- * threads, it would have a refcount > 2 and thus be immutable.
+GstMemory *
+gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags)
+{
+  GstMemory *mem;
+  gboolean write;
+
+  write = (flags & GST_MAP_WRITE) != 0;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+  g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
+
+  /* check if we can write when asked for write access */
+  if (G_UNLIKELY (write && !gst_buffer_is_writable (buffer)))
+    goto not_writable;
+
+  mem = _get_memory (buffer, idx, write);
+
+  return mem;
+
+  /* ERRORS */
+not_writable:
+  {
+    g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
+    return NULL;
+  }
+}
+
+/**
+ * gst_buffer_remove_memory_range:
+ * @buffer: a #GstBuffer.
+ * @idx: an index
+ * @length: a length
+ *
+ * Remove @len memory blocks in @buffer starting from @idx.
+ *
+ * @length can be -1, in which case all memory starting from @idx is removed.
  */
-GstCaps *
-gst_buffer_get_caps (GstBuffer * buffer)
+void
+gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
 {
-  GstCaps *ret;
+  guint len, i, end;
 
-  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (gst_buffer_is_writable (buffer));
 
-  ret = GST_BUFFER_CAPS (buffer);
+  len = GST_BUFFER_MEM_LEN (buffer);
+  if (length == -1) {
+    g_return_if_fail (idx < len);
+    length = len - idx;
+  }
 
-  if (ret)
-    gst_caps_ref (ret);
+  end = idx + length;
+  for (i = idx; i < end; i++)
+    gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
 
-  return ret;
+  if (end != len) {
+    g_memmove (&GST_BUFFER_MEM_PTR (buffer, idx),
+        &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
+  }
+  GST_BUFFER_MEM_LEN (buffer) = len - length;
 }
 
 /**
- * gst_buffer_set_caps:
+ * gst_buffer_get_sizes:
  * @buffer: a #GstBuffer.
- * @caps: (transfer none): a #GstCaps.
+ * @offset: a pointer to the offset
+ * @maxsize: a pointer to the maxsize
+ *
+ * Get the total size of all memory blocks in @buffer.
  *
- * Sets the media type on the buffer. The refcount of the caps will
- * be increased and any previous caps on the buffer will be
- * unreffed.
+ * When not %NULL, @offset will contain the offset of the data in the first
+ * memory block in @buffer and @maxsize will contain the sum of the size
+ * and @offset and the amount of extra padding on the last memory block.
+ * @offset and @maxsize can be used to resize the buffer with
+ * gst_buffer_resize().
+ *
+ * Returns: the total size of the memory in @buffer.
  */
-/* this is not made atomic because if the buffer were reffed from multiple
- * threads, it would have a refcount > 2 and thus be immutable.
+gsize
+gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
+{
+  guint len;
+  gsize size;
+  GstMemory *mem;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+
+  if (G_LIKELY (len == 1)) {
+    /* common case */
+    mem = GST_BUFFER_MEM_PTR (buffer, 0);
+    size = gst_memory_get_sizes (mem, offset, maxsize);
+  } else {
+    guint i;
+    gsize extra, offs;
+
+    size = offs = extra = 0;
+    for (i = 0; i < len; i++) {
+      gsize s, o, ms;
+
+      mem = GST_BUFFER_MEM_PTR (buffer, i);
+      s = gst_memory_get_sizes (mem, &o, &ms);
+
+      if (s) {
+        if (size == 0)
+          /* first size, take accumulated data before as the offset */
+          offs = extra + o;
+        /* add sizes */
+        size += s;
+        /* save the amount of data after this block */
+        extra = ms - (o + s);
+      } else {
+        /* empty block, add as extra */
+        extra += ms;
+      }
+    }
+    if (offset)
+      *offset = offs;
+    if (maxsize)
+      *maxsize = offs + size + extra;
+  }
+  return size;
+}
+
+/**
+ * gst_buffer_resize:
+ * @buffer: a #GstBuffer.
+ * @offset: the offset adjustement
+ * @size: the new size or -1 to just adjust the offset
+ *
+ * Set the total size of the buffer
  */
 void
-gst_buffer_set_caps (GstBuffer * buffer, GstCaps * caps)
+gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
 {
-  g_return_if_fail (buffer != NULL);
-  g_return_if_fail (caps == NULL || GST_CAPS_IS_SIMPLE (caps));
+  guint len;
+  guint i;
+  gsize bsize, bufsize, bufoffs, bufmax;
+  GstMemory *mem;
+
+  g_return_if_fail (gst_buffer_is_writable (buffer));
+  g_return_if_fail (size >= -1);
+
+  bufsize = gst_buffer_get_sizes (buffer, &bufoffs, &bufmax);
+
+  GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT
+      " size:%" G_GSIZE_FORMAT " offs:%" G_GSIZE_FORMAT " max:%"
+      G_GSIZE_FORMAT, buffer, offset, size, bufsize, bufoffs, bufmax);
+
+  /* we can't go back further than the current offset or past the end of the
+   * buffer */
+  g_return_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0
+          && bufoffs + offset <= bufmax));
+  if (size == -1) {
+    g_return_if_fail (bufsize >= offset);
+    size = bufsize - offset;
+  }
+  g_return_if_fail (bufmax >= bufoffs + offset + size);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+
+  /* copy and trim */
+  for (i = 0; i < len; i++) {
+    gsize left, noffs;
+
+    mem = GST_BUFFER_MEM_PTR (buffer, i);
+    bsize = gst_memory_get_sizes (mem, NULL, NULL);
+
+    noffs = 0;
+    /* last buffer always gets resized to the remaining size */
+    if (i + 1 == len)
+      left = size;
+    /* shrink buffers before the offset */
+    else if ((gssize) bsize <= offset) {
+      left = 0;
+      noffs = offset - bsize;
+      offset = 0;
+    }
+    /* clip other buffers */
+    else
+      left = MIN (bsize - offset, size);
+
+    if (offset != 0 || left != bsize) {
+      /* we need to clip something */
+      if (gst_memory_is_writable (mem)) {
+        gst_memory_resize (mem, offset, left);
+      } else {
+        GstMemory *tmp;
 
-#if GST_VERSION_NANO == 1
-  /* we enable this extra debugging in git versions only for now */
-  g_warn_if_fail (gst_buffer_is_metadata_writable (buffer));
-  /* FIXME: would be nice to also check if caps are fixed here, but expensive */
-#endif
+        if (mem->flags & GST_MEMORY_FLAG_NO_SHARE)
+          tmp = gst_memory_copy (mem, offset, left);
+        else
+          tmp = gst_memory_share (mem, offset, left);
+
+        gst_memory_unref (mem);
+        mem = tmp;
+      }
+    }
+    offset = noffs;
+    size -= left;
 
-  gst_caps_replace (&GST_BUFFER_CAPS (buffer), caps);
+    GST_BUFFER_MEM_PTR (buffer, i) = mem;
+  }
 }
 
 /**
- * gst_buffer_is_metadata_writable:
- * @buf: a #GstBuffer
+ * gst_buffer_map:
+ * @buffer: a #GstBuffer.
+ * @size: (out) (allow-none): a location for the size
+ * @maxsize: (out) (allow-none): a location for the max size
+ * @flags: flags for the mapping
+ *
+ * This function return a pointer to the memory in @buffer. @flags describe the
+ * desired access of the memory. When @flags is #GST_MAP_WRITE, @buffer should
+ * be writable (as returned from gst_buffer_is_writable()).
+ *
+ * @size and @maxsize will contain the current valid number of bytes in the
+ * returned memory area and the total maximum mount of bytes available in the
+ * returned memory area respectively. Both parameters can be %NULL.
+ *
+ * When @buffer is writable but the memory isn't, a writable copy will
+ * automatically be created and returned. The readonly copy of the buffer memory
+ * will then also be replaced with this writable copy.
  *
- * Similar to gst_buffer_is_writable, but this only ensures that the
- * refcount of the buffer is 1, indicating that the caller is the sole
- * owner and can change the buffer metadata, such as caps and timestamps.
+ * When the buffer contains multiple memory blocks, the returned pointer will be
+ * a concatenation of the memory blocks.
  *
- * Returns: TRUE if the metadata is writable.
+ * Returns: (transfer none): a pointer to the memory for the buffer.
  */
-gboolean
-gst_buffer_is_metadata_writable (GstBuffer * buf)
+gpointer
+gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
+    GstMapFlags flags)
 {
-  return (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1);
+  guint len;
+  gpointer data;
+  GstMemory *mem;
+  gboolean write, writable;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  write = (flags & GST_MAP_WRITE) != 0;
+  writable = gst_buffer_is_writable (buffer);
+
+  /* check if we can write when asked for write access */
+  if (G_UNLIKELY (write && !writable))
+    goto not_writable;
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+
+  if (G_UNLIKELY (len == 0)) {
+    /* no memory, return immediately */
+    if (size)
+      *size = 0;
+    if (maxsize)
+      *maxsize = 0;
+    return NULL;
+  }
+
+  if (G_LIKELY (len == 1)) {
+    /* we can take the first one */
+    mem = GST_BUFFER_MEM_PTR (buffer, 0);
+  } else {
+    /* we need to span memory */
+    if (writable) {
+      /* if we can write, we can change the memory with the spanned
+       * memory */
+      mem = _span_memory (buffer, 0, -1, write);
+      _replace_memory (buffer, mem);
+    } else {
+      gsize bsize;
+
+      /* extract all data in new memory, FIXME slow!! */
+      bsize = gst_buffer_get_size (buffer);
+
+      data = g_malloc (bsize);
+      gst_buffer_extract (buffer, 0, data, bsize);
+      if (size)
+        *size = bsize;
+      if (maxsize)
+        *maxsize = bsize;
+      return data;
+    }
+  }
+
+  if (G_UNLIKELY (write && !gst_memory_is_writable (mem))) {
+    GstMemory *copy;
+    /* replace with a writable copy */
+    copy = gst_memory_copy (mem, 0, -1);
+    GST_BUFFER_MEM_PTR (buffer, 0) = copy;
+    gst_memory_unref (mem);
+    mem = copy;
+  }
+
+  data = gst_memory_map (mem, size, maxsize, flags);
+
+  return data;
+
+  /* ERROR */
+not_writable:
+  {
+    g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
+    return NULL;
+  }
 }
 
 /**
- * gst_buffer_make_metadata_writable:
- * @buf: (transfer full): a #GstBuffer
- *
- * Similar to gst_buffer_make_writable, but does not ensure that the buffer
- * data array is writable. Instead, this just ensures that the returned buffer
- * is solely owned by the caller, by creating a subbuffer of the original
- * buffer if necessary.
- * 
- * After calling this function, @buf should not be referenced anymore. The
- * result of this function has guaranteed writable metadata.
- *
- * Returns: (transfer full): a new #GstBuffer with writable metadata, which
- *     may or may not be the same as @buf.
+ * gst_buffer_unmap:
+ * @buffer: a #GstBuffer.
+ * @data: the previously mapped data
+ * @size: the size of @data, or -1
+ *
+ * Release the memory previously mapped with gst_buffer_map(). Pass -1 to size
+ * if no update is needed.
+ *
+ * Returns: #TRUE on success. #FALSE can be returned when the new size is larger
+ * than the maxsize of the memory.
  */
-GstBuffer *
-gst_buffer_make_metadata_writable (GstBuffer * buf)
+gboolean
+gst_buffer_unmap (GstBuffer * buffer, gpointer data, gssize size)
 {
-  GstBuffer *ret;
+  guint len;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+  g_return_val_if_fail (size >= -1, FALSE);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+
+  if (G_LIKELY (len == 1)) {
+    GstMemory *mem = GST_BUFFER_MEM_PTR (buffer, 0);
 
-  if (gst_buffer_is_metadata_writable (buf)) {
-    ret = buf;
+    gst_memory_unmap (mem);
   } else {
-    ret = gst_buffer_create_sub (buf, 0, GST_BUFFER_SIZE (buf));
+    /* this must have been from read-only access. After _map, the buffer either
+     * only contains 1 memory block or it allocated memory to join memory
+     * blocks. It's not allowed to add buffers between _map and _unmap. */
+    g_free (data);
+  }
+  return TRUE;
+}
 
-    gst_buffer_unref (buf);
+/**
+ * gst_buffer_fill:
+ * @buffer: a #GstBuffer.
+ * @offset: the offset to fill
+ * @src: the source address
+ * @size: the size to fill
+ *
+ * Copy @size bytes from @src to @buffer at @offset.
+ *
+ * Returns: The amount of bytes copied. This value can be lower than @size
+ *    when @buffer did not contain enough data.
+ */
+gsize
+gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
+    gsize size)
+{
+  gsize i, len, left;
+  const guint8 *ptr = src;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
+  g_return_val_if_fail (src != NULL, 0);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+  left = size;
+
+  for (i = 0; i < len && left > 0; i++) {
+    guint8 *data;
+    gsize ssize, tocopy;
+    GstMemory *mem;
+
+    mem = _get_memory (buffer, i, TRUE);
+
+    data = gst_memory_map (mem, &ssize, NULL, GST_MAP_WRITE);
+    if (ssize > offset) {
+      /* we have enough */
+      tocopy = MIN (ssize - offset, left);
+      memcpy (data + offset, ptr, tocopy);
+      left -= tocopy;
+      ptr += tocopy;
+      offset = 0;
+    } else {
+      /* offset past buffer, skip */
+      offset -= ssize;
+    }
+    gst_memory_unmap (mem);
   }
+  return size - left;
+}
 
-  return ret;
+/**
+ * gst_buffer_extract:
+ * @buffer: a #GstBuffer.
+ * @offset: the offset to extract
+ * @dest: the destination address
+ * @size: the size to extract
+ *
+ * Copy @size bytes starting from @offset in @buffer to @dest.
+ *
+ * Returns: The amount of bytes extracted. This value can be lower than @size
+ *    when @buffer did not contain enough data.
+ */
+gsize
+gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
+{
+  gsize i, len, left;
+  guint8 *ptr = dest;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (dest != NULL, 0);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+  left = size;
+
+  for (i = 0; i < len && left > 0; i++) {
+    guint8 *data;
+    gsize ssize, tocopy;
+    GstMemory *mem;
+
+    mem = GST_BUFFER_MEM_PTR (buffer, i);
+
+    data = gst_memory_map (mem, &ssize, NULL, GST_MAP_READ);
+    if (ssize > offset) {
+      /* we have enough */
+      tocopy = MIN (ssize - offset, left);
+      memcpy (ptr, data + offset, tocopy);
+      left -= tocopy;
+      ptr += tocopy;
+      offset = 0;
+    } else {
+      /* offset past buffer, skip */
+      offset -= ssize;
+    }
+    gst_memory_unmap (mem);
+  }
+  return size - left;
 }
 
-#define GST_IS_SUBBUFFER(obj)   (GST_BUFFER_CAST(obj)->parent != NULL)
+/**
+ * gst_buffer_memcmp:
+ * @buffer: a #GstBuffer.
+ * @offset: the offset in @buffer
+ * @mem: the memory to compare
+ * @size: the size to compare
+ *
+ * Compare @size bytes starting from @offset in @buffer with the memory in @mem.
+ *
+ * Returns: 0 if the memory is equal.
+ */
+gint
+gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
+    gsize size)
+{
+  gsize i, len;
+  const guint8 *ptr = mem;
+  gint res = 0;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (mem != NULL, 0);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+
+  for (i = 0; i < len && size > 0 && res == 0; i++) {
+    guint8 *data;
+    gsize ssize, tocmp;
+    GstMemory *mem;
+
+    mem = GST_BUFFER_MEM_PTR (buffer, i);
+
+    data = gst_memory_map (mem, &ssize, NULL, GST_MAP_READ);
+    if (ssize > offset) {
+      /* we have enough */
+      tocmp = MIN (ssize - offset, size);
+      res = memcmp (ptr, data + offset, tocmp);
+      size -= tocmp;
+      ptr += tocmp;
+      offset = 0;
+    } else {
+      /* offset past buffer, skip */
+      offset -= ssize;
+    }
+    gst_memory_unmap (mem);
+  }
+  return res;
+}
 
 /**
- * gst_buffer_create_sub:
+ * gst_buffer_memset:
+ * @buffer: a #GstBuffer.
+ * @offset: the offset in @buffer
+ * @val: the value to set
+ * @size: the size to set
+ *
+ * Fill @buf with @size bytes with @val starting from @offset.
+ *
+ * Returns: The amount of bytes filled. This value can be lower than @size
+ *    when @buffer did not contain enough data.
+ */
+gsize
+gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
+{
+  gsize i, len, left;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
+
+  len = GST_BUFFER_MEM_LEN (buffer);
+  left = size;
+
+  for (i = 0; i < len && left > 0; i++) {
+    guint8 *data;
+    gsize ssize, toset;
+    GstMemory *mem;
+
+    mem = _get_memory (buffer, i, TRUE);
+
+    data = gst_memory_map (mem, &ssize, NULL, GST_MAP_WRITE);
+    if (ssize > offset) {
+      /* we have enough */
+      toset = MIN (ssize - offset, left);
+      memset (data + offset, val, toset);
+      left -= toset;
+      offset = 0;
+    } else {
+      /* offset past buffer, skip */
+      offset -= ssize;
+    }
+    gst_memory_unmap (mem);
+  }
+  return size - left;
+}
+
+/**
+ * gst_buffer_copy_region:
  * @parent: a #GstBuffer.
+ * @flags: the #GstBufferCopyFlags
  * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
  *          begins.
  * @size: the size of the new #GstBuffer sub-buffer, in bytes.
@@ -739,77 +1239,112 @@ gst_buffer_make_metadata_writable (GstBuffer * buf)
  *     invalid.
  */
 GstBuffer *
-gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
+gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
+    gsize offset, gsize size)
 {
-  GstBuffer *subbuffer;
-  GstBuffer *parent;
-  gboolean complete;
+  GstBuffer *copy;
 
   g_return_val_if_fail (buffer != NULL, NULL);
-  g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
-  g_return_val_if_fail (buffer->size >= offset + size, NULL);
-
-  /* find real parent */
-  if (GST_IS_SUBBUFFER (buffer)) {
-    parent = buffer->parent;
-  } else {
-    parent = buffer;
-  }
-  gst_buffer_ref (parent);
 
   /* create the new buffer */
-  subbuffer = gst_buffer_new ();
-  subbuffer->parent = parent;
-  GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAG_READONLY);
+  copy = gst_buffer_new ();
 
-  GST_CAT_LOG (GST_CAT_BUFFER, "new subbuffer %p (parent %p)", subbuffer,
-      parent);
+  GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT
+      "-%" G_GSIZE_FORMAT, copy, buffer, offset, size);
 
-  /* set the right values in the child */
-  GST_BUFFER_DATA (subbuffer) = buffer->data + offset;
-  GST_BUFFER_SIZE (subbuffer) = size;
+  gst_buffer_copy_into (copy, buffer, flags, offset, size);
 
-  if ((offset == 0) && (size == GST_BUFFER_SIZE (buffer))) {
-    /* copy all the flags except IN_CAPS */
-    GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAGS (buffer));
-    GST_BUFFER_FLAG_UNSET (subbuffer, GST_BUFFER_FLAG_IN_CAPS);
-  } else {
-    /* copy only PREROLL & GAP flags */
-    GST_BUFFER_FLAG_SET (subbuffer, (GST_BUFFER_FLAGS (buffer) &
-            (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_GAP)));
-  }
+  return copy;
+}
 
-  /* we can copy the timestamp and offset if the new buffer starts at
-   * offset 0 */
-  if (offset == 0) {
-    GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer);
-    GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET (buffer);
-    complete = (buffer->size == size);
-  } else {
-    GST_BUFFER_TIMESTAMP (subbuffer) = GST_CLOCK_TIME_NONE;
-    GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET_NONE;
-    complete = FALSE;
+static gboolean
+_gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n,
+    gsize * offset, GstMemory ** parent)
+{
+  GstMemory *mcur, *mprv;
+  gboolean have_offset = FALSE;
+  guint count, i;
+
+  mcur = mprv = NULL;
+  for (count = 0; count < n; count++) {
+    gsize offs, clen;
+    GstMemory **cmem;
+
+    cmem = mem[count];
+    clen = len[count];
+
+    for (i = 0; i < clen; i++) {
+      if (mcur)
+        mprv = mcur;
+      mcur = cmem[i];
+
+      if (mprv && mcur) {
+        /* check is memory is contiguous */
+        if (!gst_memory_is_span (mprv, mcur, &offs))
+          return FALSE;
+
+        if (!have_offset) {
+          if (offset)
+            *offset = offs;
+          if (parent)
+            *parent = mprv->parent;
+
+          have_offset = TRUE;
+        }
+      }
+    }
   }
+  return have_offset;
+}
 
-  if (complete) {
-    GstCaps *caps;
-
-    /* if we copied the complete buffer we can copy the duration,
-     * offset_end and caps as well */
-    GST_BUFFER_DURATION (subbuffer) = GST_BUFFER_DURATION (buffer);
-    GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_END (buffer);
-    if ((caps = GST_BUFFER_CAPS (buffer)))
-      gst_caps_ref (caps);
-    GST_BUFFER_CAPS (subbuffer) = caps;
-
-    /* and also the attached qdata */
-    gst_buffer_copy_qdata (subbuffer, buffer);
+static GstMemory *
+_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
+    gsize size, gboolean writable)
+{
+  GstMemory *span, *parent = NULL;
+  gsize poffset = 0;
+
+  if (!writable
+      && _gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
+    if (parent->flags & GST_MEMORY_FLAG_NO_SHARE)
+      span = gst_memory_copy (parent, offset + poffset, size);
+    else
+      span = gst_memory_share (parent, offset + poffset, size);
   } else {
-    GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE;
-    GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE;
-    GST_BUFFER_CAPS (subbuffer) = NULL;
+    gsize count, left;
+    guint8 *dest, *ptr;
+
+    span = gst_allocator_alloc (NULL, size, 0);
+    dest = gst_memory_map (span, NULL, NULL, GST_MAP_WRITE);
+
+    ptr = dest;
+    left = size;
+
+    for (count = 0; count < n; count++) {
+      gsize i, tocopy, clen, ssize;
+      guint8 *src;
+      GstMemory **cmem;
+
+      cmem = mem[count];
+      clen = len[count];
+
+      for (i = 0; i < clen && left > 0; i++) {
+        src = gst_memory_map (cmem[i], &ssize, NULL, GST_MAP_READ);
+        tocopy = MIN (ssize, left);
+        if (tocopy > offset) {
+          memcpy (ptr, src + offset, tocopy - offset);
+          left -= tocopy;
+          ptr += tocopy;
+          offset = 0;
+        } else {
+          offset -= tocopy;
+        }
+        gst_memory_unmap (cmem[i]);
+      }
+    }
+    gst_memory_unmap (span);
   }
-  return subbuffer;
+  return span;
 }
 
 /**
@@ -818,7 +1353,7 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
  * @buf2: the second #GstBuffer.
  *
  * Determines whether a gst_buffer_span() can be done without copying
- * the contents, that is, whether the data areas are contiguous sub-buffers of 
+ * the contents, that is, whether the data areas are contiguous sub-buffers of
  * the same buffer.
  *
  * MT safe.
@@ -828,14 +1363,20 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
 gboolean
 gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
 {
-  g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE);
+  GstMemory **mem[2];
+  gsize len[2];
+
+  g_return_val_if_fail (GST_IS_BUFFER (buf1), FALSE);
+  g_return_val_if_fail (GST_IS_BUFFER (buf2), FALSE);
   g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE);
   g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE);
 
-  /* it's only fast if we have subbuffers of the same parent */
-  return (GST_IS_SUBBUFFER (buf1) &&
-      GST_IS_SUBBUFFER (buf2) && (buf1->parent == buf2->parent)
-      && ((buf1->data + buf1->size) == buf2->data));
+  mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
+  len[0] = GST_BUFFER_MEM_LEN (buf1);
+  mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
+  len[1] = GST_BUFFER_MEM_LEN (buf2);
+
+  return _gst_buffer_arr_is_span_fast (mem, len, 2, NULL, NULL);
 }
 
 /**
@@ -844,7 +1385,7 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
  * @offset: the offset in the first buffer from where the new
  * buffer should start.
  * @buf2: the second source #GstBuffer to merge.
- * @len: the total length of the new buffer.
+ * @size: the total size of the new buffer.
  *
  * Creates a new buffer that consists of part of buf1 and buf2.
  * Logically, buf1 and buf2 are concatenated into a single larger
@@ -862,40 +1403,41 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
  *     buffers, or NULL if the arguments are invalid.
  */
 GstBuffer *
-gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
-    guint32 len)
+gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size)
 {
   GstBuffer *newbuf;
+  GstMemory *span;
+  GstMemory **mem[2];
+  gsize len[2], len1, len2;
 
-  g_return_val_if_fail (buf1 != NULL && buf2 != NULL, NULL);
+  g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
+  g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
   g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL);
   g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL);
-  g_return_val_if_fail (len > 0, NULL);
-  g_return_val_if_fail (len <= buf1->size + buf2->size - offset, NULL);
+  len1 = gst_buffer_get_size (buf1);
+  len2 = gst_buffer_get_size (buf2);
+  g_return_val_if_fail (len1 + len2 > offset, NULL);
+  if (size == -1)
+    size = len1 + len2 - offset;
+  else
+    g_return_val_if_fail (size <= len1 + len2 - offset, NULL);
 
-  /* if the two buffers have the same parent and are adjacent */
-  if (gst_buffer_is_span_fast (buf1, buf2)) {
-    GstBuffer *parent = buf1->parent;
+  mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
+  len[0] = GST_BUFFER_MEM_LEN (buf1);
+  mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
+  len[1] = GST_BUFFER_MEM_LEN (buf2);
 
-    /* we simply create a subbuffer of the common parent */
-    newbuf = gst_buffer_create_sub (parent,
-        buf1->data - parent->data + offset, len);
-  } else {
-    GST_CAT_DEBUG (GST_CAT_BUFFER,
-        "slow path taken while spanning buffers %p and %p", buf1, buf2);
-    /* otherwise we simply have to brute-force copy the buffers */
-    newbuf = gst_buffer_new_and_alloc (len);
+  span = _gst_buffer_arr_span (mem, len, 2, offset, size, FALSE);
 
-    /* copy the first buffer's data across */
-    memcpy (newbuf->data, buf1->data + offset, buf1->size - offset);
-    /* copy the second buffer's data across */
-    memcpy (newbuf->data + (buf1->size - offset), buf2->data,
-        len - (buf1->size - offset));
-  }
+  newbuf = gst_buffer_new ();
+  _memory_add (newbuf, -1, span);
+
+#if 0
   /* if the offset is 0, the new buffer has the same timestamp as buf1 */
   if (offset == 0) {
     GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1);
-    GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buf1);
+    GST_BUFFER_PTS (newbuf) = GST_BUFFER_PTS (buf1);
+    GST_BUFFER_DTS (newbuf) = GST_BUFFER_DTS (buf1);
 
     /* if we completely merged the two buffers (appended), we can
      * calculate the duration too. Also make sure we's not messing with
@@ -913,6 +1455,222 @@ gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
       }
     }
   }
+#endif
 
   return newbuf;
 }
+
+/**
+ * gst_buffer_get_meta:
+ * @buffer: a #GstBuffer
+ * @info: a #GstMetaInfo
+ *
+ * Get the metadata for the api in @info on buffer. When there is no such
+ * metadata, NULL is returned.
+ *
+ * Note that the result metadata might not be of the implementation @info.
+ *
+ * Returns: the metadata for the api in @info on @buffer.
+ */
+GstMeta *
+gst_buffer_get_meta (GstBuffer * buffer, const GstMetaInfo * info)
+{
+  GstMetaItem *item;
+  GstMeta *result = NULL;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_val_if_fail (info != NULL, NULL);
+
+  /* find GstMeta of the requested API */
+  for (item = GST_BUFFER_META (buffer); item; item = item->next) {
+    GstMeta *meta = &item->meta;
+    if (meta->info->api == info->api) {
+      result = meta;
+      break;
+    }
+  }
+  return result;
+}
+
+/**
+ * gst_buffer_add_meta:
+ * @buffer: a #GstBuffer
+ * @info: a #GstMetaInfo
+ * @params: params for @info
+ *
+ * Add metadata for @info to @buffer using the parameters in @params.
+ *
+ * Returns: (transfer none): the metadata for the api in @info on @buffer.
+ */
+GstMeta *
+gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info,
+    gpointer params)
+{
+  GstMetaItem *item;
+  GstMeta *result = NULL;
+  gsize size;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_val_if_fail (info != NULL, NULL);
+
+  /* create a new slice */
+  size = ITEM_SIZE (info);
+  item = g_slice_alloc (size);
+  result = &item->meta;
+  result->info = info;
+  result->flags = GST_META_FLAG_NONE;
+
+  GST_CAT_DEBUG (GST_CAT_BUFFER,
+      "alloc metadata %p (%s) of size %" G_GSIZE_FORMAT, result,
+      g_type_name (info->type), info->size);
+
+  /* call the init_func when needed */
+  if (info->init_func)
+    if (!info->init_func (result, params, buffer))
+      goto init_failed;
+
+  /* and add to the list of metadata */
+  item->next = GST_BUFFER_META (buffer);
+  GST_BUFFER_META (buffer) = item;
+
+  return result;
+
+init_failed:
+  {
+    g_slice_free1 (size, item);
+    return NULL;
+  }
+}
+
+/**
+ * gst_buffer_remove_meta:
+ * @buffer: a #GstBuffer
+ * @meta: a #GstMeta
+ *
+ * Remove the metadata for @meta on @buffer.
+ *
+ * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
+ * metadata was on @buffer.
+ */
+gboolean
+gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
+{
+  GstMetaItem *walk, *prev;
+
+  g_return_val_if_fail (buffer != NULL, FALSE);
+  g_return_val_if_fail (meta != NULL, FALSE);
+
+  /* find the metadata and delete */
+  prev = GST_BUFFER_META (buffer);
+  for (walk = prev; walk; walk = walk->next) {
+    GstMeta *m = &walk->meta;
+    if (m == meta) {
+      const GstMetaInfo *info = meta->info;
+
+      /* remove from list */
+      if (GST_BUFFER_META (buffer) == walk)
+        GST_BUFFER_META (buffer) = walk->next;
+      else
+        prev->next = walk->next;
+      /* call free_func if any */
+      if (info->free_func)
+        info->free_func (m, buffer);
+
+      /* and free the slice */
+      g_slice_free1 (ITEM_SIZE (info), walk);
+      break;
+    }
+    prev = walk;
+  }
+  return walk != NULL;
+}
+
+/**
+ * gst_buffer_iterate_meta:
+ * @buffer: a #GstBuffer
+ * @state: an opaque state pointer
+ *
+ * Retrieve the next #GstMeta after @current. If @state points
+ * to %NULL, the first metadata is returned.
+ *
+ * @state will be updated with an opage state pointer 
+ *
+ * Returns: The next #GstMeta or %NULL when there are no more items.
+ */
+GstMeta *
+gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
+{
+  GstMetaItem **meta;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_val_if_fail (state != NULL, NULL);
+
+  meta = (GstMetaItem **) state;
+  if (*meta == NULL)
+    /* state NULL, move to first item */
+    *meta = GST_BUFFER_META (buffer);
+  else
+    /* state !NULL, move to next item in list */
+    *meta = (*meta)->next;
+
+  if (*meta)
+    return &(*meta)->meta;
+  else
+    return NULL;
+}
+
+/**
+ * gst_buffer_foreach_meta:
+ * @buffer: a #GstBuffer
+ * @func: (scope call): a #GstBufferForeachMetaFunc to call
+ * @user_data: (closure): user data passed to @func
+ *
+ * Call @func with @user_data for each meta in @buffer.
+ *
+ * @func can modify the passed meta pointer or its contents. The return value
+ * of @func define if this function returns or if the remaining metadata items
+ * in the buffer should be skipped.
+ */
+void
+gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func,
+    gpointer user_data)
+{
+  GstMetaItem *walk, *prev, *next;
+
+  g_return_if_fail (buffer != NULL);
+  g_return_if_fail (func != NULL);
+
+  /* find the metadata and delete */
+  prev = GST_BUFFER_META (buffer);
+  for (walk = prev; walk; walk = next) {
+    GstMeta *m, *new;
+    gboolean res;
+
+    m = new = &walk->meta;
+    next = walk->next;
+
+    res = func (buffer, &new, user_data);
+
+    if (new == NULL) {
+      const GstMetaInfo *info = m->info;
+
+      GST_CAT_DEBUG (GST_CAT_BUFFER, "remove metadata %p (%s)", m,
+          g_type_name (info->type));
+
+      /* remove from list */
+      if (GST_BUFFER_META (buffer) == walk)
+        GST_BUFFER_META (buffer) = next;
+      else
+        prev->next = next;
+
+      /* call free_func if any */
+      if (info->free_func)
+        info->free_func (m, buffer);
+
+      /* and free the slice */
+      g_slice_free1 (ITEM_SIZE (info), walk);
+    }
+    if (!res)
+      break;
+  }
+}
index 2d6999d..d527532 100644 (file)
 
 #include <gst/gstminiobject.h>
 #include <gst/gstclock.h>
-#include <gst/gstcaps.h>
+#include <gst/gstmemory.h>
 
 G_BEGIN_DECLS
 
+GST_EXPORT GType _gst_buffer_type;
+
 typedef struct _GstBuffer GstBuffer;
-typedef struct _GstBufferClass GstBufferClass;
-typedef struct _GstBufferPrivate GstBufferPrivate;
+typedef struct _GstBufferPool GstBufferPool;
 
 /**
  * GST_BUFFER_TRACE_NAME:
@@ -41,13 +42,10 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
  */
 #define GST_BUFFER_TRACE_NAME           "GstBuffer"
 
-#define GST_TYPE_BUFFER                         (gst_buffer_get_type())
-#define GST_IS_BUFFER(obj)                      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER))
-#define GST_IS_BUFFER_CLASS(klass)              (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER))
-#define GST_BUFFER_GET_CLASS(obj)               (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER, GstBufferClass))
-#define GST_BUFFER(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER, GstBuffer))
-#define GST_BUFFER_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER, GstBufferClass))
+#define GST_TYPE_BUFFER                         (_gst_buffer_type)
+#define GST_IS_BUFFER(obj)                      (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_BUFFER))
 #define GST_BUFFER_CAST(obj)                    ((GstBuffer *)(obj))
+#define GST_BUFFER(obj)                         (GST_BUFFER_CAST(obj))
 
 /**
  * GST_BUFFER_FLAGS:
@@ -81,29 +79,27 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
  */
 #define GST_BUFFER_FLAG_UNSET(buf,flag)         GST_MINI_OBJECT_FLAG_UNSET (buf, flag)
 
+
 /**
- * GST_BUFFER_DATA:
- * @buf: a #GstBuffer.
- *
- * A pointer to the data element of this buffer.
- */
-#define GST_BUFFER_DATA(buf)                    (GST_BUFFER_CAST(buf)->data)
-/**
- * GST_BUFFER_SIZE:
- * @buf: a #GstBuffer.
+ * GST_BUFFER_PTS:
+ * @buf: a #GstBuffer.:
  *
- * The size in bytes of the data in this buffer.
+ * The presentation timestamp (pts) in nanoseconds (as a #GstClockTime)
+ * of the data in the buffer. This is the timestamp when the media should be
+ * presented to the user.
+ * Value will be %GST_CLOCK_TIME_NONE if the pts is unknown.
  */
-#define GST_BUFFER_SIZE(buf)                    (GST_BUFFER_CAST(buf)->size)
+#define GST_BUFFER_PTS(buf)                     (GST_BUFFER_CAST(buf)->pts)
 /**
- * GST_BUFFER_TIMESTAMP:
+ * GST_BUFFER_DTS:
  * @buf: a #GstBuffer.:
  *
- * The timestamp in nanoseconds (as a #GstClockTime) of the data in the buffer.
- * Value will be %GST_CLOCK_TIME_NONE if the timestamp is unknown.
- *
+ * The decoding timestamp (dts) in nanoseconds (as a #GstClockTime)
+ * of the data in the buffer. This is the timestamp when the media should be
+ * decoded or processed otherwise.
+ * Value will be %GST_CLOCK_TIME_NONE if the dts is unknown.
  */
-#define GST_BUFFER_TIMESTAMP(buf)               (GST_BUFFER_CAST(buf)->timestamp)
+#define GST_BUFFER_DTS(buf)                     (GST_BUFFER_CAST(buf)->dts)
 /**
  * GST_BUFFER_DURATION:
  * @buf: a #GstBuffer.
@@ -113,13 +109,6 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
  */
 #define GST_BUFFER_DURATION(buf)                (GST_BUFFER_CAST(buf)->duration)
 /**
- * GST_BUFFER_CAPS:
- * @buf: a #GstBuffer.
- *
- * The caps for this buffer.
- */
-#define GST_BUFFER_CAPS(buf)                    (GST_BUFFER_CAST(buf)->caps)
-/**
  * GST_BUFFER_OFFSET:
  * @buf: a #GstBuffer.
  *
@@ -133,28 +122,6 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
  * The offset in the source file of the end of this buffer.
  */
 #define GST_BUFFER_OFFSET_END(buf)              (GST_BUFFER_CAST(buf)->offset_end)
-/**
- * GST_BUFFER_MALLOCDATA:
- * @buf: a #GstBuffer.
- *
- * A pointer to any data allocated for this buffer using g_malloc(). If this is
- * non-NULL, this memory will be freed at the end of the buffer's lifecycle
- * (i.e. when its refcount becomes zero).
- */
-#define GST_BUFFER_MALLOCDATA(buf)              (GST_BUFFER_CAST(buf)->malloc_data)
-/**
- * GST_BUFFER_FREE_FUNC:
- * @buf: a #GstBuffer.
- *
- * A pointer to a function that will be called on the buffer's malloc_data when
- * this buffer is finalized. Defaults to g_free().
- *
- * Note that the free function only affects the buffer's malloc_data; if the
- * buffer's malloc_data is %NULL, the function will not be called.
- *
- * Since: 0.10.22
- */
-#define GST_BUFFER_FREE_FUNC(buf)               (GST_BUFFER_CAST(buf)->free_func)
 
 /**
  * GST_BUFFER_OFFSET_NONE:
@@ -171,12 +138,19 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
  */
 #define GST_BUFFER_DURATION_IS_VALID(buffer)    (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
 /**
- * GST_BUFFER_TIMESTAMP_IS_VALID:
+ * GST_BUFFER_PTS_IS_VALID:
+ * @buffer: a #GstBuffer
+ *
+ * Tests if the pts is known.
+ */
+#define GST_BUFFER_PTS_IS_VALID(buffer)   (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer)))
+/**
+ * GST_BUFFER_DTS_IS_VALID:
  * @buffer: a #GstBuffer
  *
- * Tests if the timestamp is known.
+ * Tests if the dts is known.
  */
-#define GST_BUFFER_TIMESTAMP_IS_VALID(buffer)   (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
+#define GST_BUFFER_DTS_IS_VALID(buffer)   (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buffer)))
 /**
  * GST_BUFFER_OFFSET_IS_VALID:
  * @buffer: a #GstBuffer
@@ -202,51 +176,65 @@ typedef struct _GstBufferPrivate GstBufferPrivate;
 #define GST_BUFFER_IS_DISCONT(buffer)   (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
 
 /**
- * GstBufferFlag:
- * @GST_BUFFER_FLAG_READONLY: the buffer is read-only. This means the data of
- * the buffer should not be modified. The metadata might still be modified.
- * @GST_BUFFER_FLAG_PREROLL: the buffer is part of a preroll and should not be
- * displayed.
- * @GST_BUFFER_FLAG_DISCONT: the buffer marks a discontinuity in the stream.
- * This typically occurs after a seek or a dropped buffer from a live or
- * network source.
- * @GST_BUFFER_FLAG_IN_CAPS: the buffer has been added as a field in a #GstCaps.
- * @GST_BUFFER_FLAG_GAP: the buffer has been created to fill a gap in the
- * stream and contains media neutral data (elements can switch to optimized code
- * path that ignores the buffer content).
- * @GST_BUFFER_FLAG_DELTA_UNIT: this unit cannot be decoded independently.
- * @GST_BUFFER_FLAG_MEDIA1: a flag whose use is specific to the caps of the buffer. Since: 0.10.23.
- * @GST_BUFFER_FLAG_MEDIA2: a flag whose use is specific to the caps of the buffer. Since: 0.10.23.
- * @GST_BUFFER_FLAG_MEDIA3: a flag whose use is specific to the caps of the buffer. Since: 0.10.23.
- * @GST_BUFFER_FLAG_MEDIA4: a flag whose use is specific to the caps of the buffer. Since: 0.10.33.
- * @GST_BUFFER_FLAG_LAST: additional flags can be added starting from this flag.
+ * GstBufferFlags:
+ * @GST_BUFFER_FLAG_LIVE:        the buffer is live data and should be discarded in
+ *                               the PAUSED state.
+ * @GST_BUFFER_FLAG_DECODE_ONLY: the buffer contains data that should be dropped
+ *                               because it will be clipped against the segment
+ *                               boundaries or because it does not contain data
+ *                               that should be shown to the user.
+ * @GST_BUFFER_FLAG_DISCONT:     the buffer marks a data discontinuity in the stream.
+ *                               This typically occurs after a seek or a dropped buffer
+ *                               from a live or network source.
+ * @GST_BUFFER_FLAG_RESYNC:      the buffer timestamps might have a discontinuity
+ *                               and this buffer is a good point to resynchronize.
+ * @GST_BUFFER_FLAG_CORRUPTED:   the buffer data is corrupted.
+ * @GST_BUFFER_FLAG_MARKER:      the buffer contains a media specific marker. for
+ *                               video this is typically the end of a frame boundary, for audio
+ *                               this is usually the end of a talkspurt.
+ * @GST_BUFFER_FLAG_HEADER:      the buffer contains header information that is
+ *                               needed to decode the following data
+ * @GST_BUFFER_FLAG_GAP:         the buffer has been created to fill a gap in the
+ *                               stream and contains media neutral data (elements can
+ *                               switch to optimized code path that ignores the buffer
+ *                               content).
+ * @GST_BUFFER_FLAG_DROPPABLE:   the buffer can be dropped without breaking the
+ *                               stream, for example to reduce bandwidth.
+ * @GST_BUFFER_FLAG_DELTA_UNIT:  this unit cannot be decoded independently.
+ * @GST_BUFFER_FLAG_IN_CAPS:     the buffer has been added as a field in a #GstCaps.
+ * @GST_BUFFER_FLAG_LAST:        additional media specific flags can be added starting from
+ *                               this flag.
  *
  * A set of buffer flags used to describe properties of a #GstBuffer.
  */
 typedef enum {
-  GST_BUFFER_FLAG_READONLY   = GST_MINI_OBJECT_FLAG_READONLY,
-  GST_BUFFER_FLAG_MEDIA4     = GST_MINI_OBJECT_FLAG_RESERVED1,
-  GST_BUFFER_FLAG_PREROLL    = (GST_MINI_OBJECT_FLAG_LAST << 0),
-  GST_BUFFER_FLAG_DISCONT    = (GST_MINI_OBJECT_FLAG_LAST << 1),
-  GST_BUFFER_FLAG_IN_CAPS    = (GST_MINI_OBJECT_FLAG_LAST << 2),
-  GST_BUFFER_FLAG_GAP        = (GST_MINI_OBJECT_FLAG_LAST << 3),
-  GST_BUFFER_FLAG_DELTA_UNIT = (GST_MINI_OBJECT_FLAG_LAST << 4),
-  GST_BUFFER_FLAG_MEDIA1     = (GST_MINI_OBJECT_FLAG_LAST << 5),
-  GST_BUFFER_FLAG_MEDIA2     = (GST_MINI_OBJECT_FLAG_LAST << 6),
-  GST_BUFFER_FLAG_MEDIA3     = (GST_MINI_OBJECT_FLAG_LAST << 7),
-  GST_BUFFER_FLAG_LAST       = (GST_MINI_OBJECT_FLAG_LAST << 8)
-} GstBufferFlag;
+  GST_BUFFER_FLAG_LIVE        = (GST_MINI_OBJECT_FLAG_LAST << 0),
+  GST_BUFFER_FLAG_DECODE_ONLY = (GST_MINI_OBJECT_FLAG_LAST << 1),
+  GST_BUFFER_FLAG_DISCONT     = (GST_MINI_OBJECT_FLAG_LAST << 2),
+  GST_BUFFER_FLAG_RESYNC      = (GST_MINI_OBJECT_FLAG_LAST << 3),
+  GST_BUFFER_FLAG_CORRUPTED   = (GST_MINI_OBJECT_FLAG_LAST << 4),
+  GST_BUFFER_FLAG_MARKER      = (GST_MINI_OBJECT_FLAG_LAST << 5),
+  GST_BUFFER_FLAG_HEADER      = (GST_MINI_OBJECT_FLAG_LAST << 6),
+  GST_BUFFER_FLAG_GAP         = (GST_MINI_OBJECT_FLAG_LAST << 7),
+  GST_BUFFER_FLAG_DROPPABLE   = (GST_MINI_OBJECT_FLAG_LAST << 8),
+  GST_BUFFER_FLAG_DELTA_UNIT  = (GST_MINI_OBJECT_FLAG_LAST << 9),
+  GST_BUFFER_FLAG_IN_CAPS     = (GST_MINI_OBJECT_FLAG_LAST << 10),
+
+  GST_BUFFER_FLAG_LAST        = (GST_MINI_OBJECT_FLAG_LAST << 16)
+} GstBufferFlags;
 
 /**
  * GstBuffer:
  * @mini_object: the parent structure
- * @data: pointer to the buffer data
- * @size: size of buffer data
- * @timestamp: timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
- *     timestamp is not known or relevant.
+ * @pool: pointer to the pool owner of the buffer
+ * @pts: presentation timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
+ *     pts is not known or relevant. The pts contains the timestamp when the
+ *     media should be presented to the user.
+ * @dts: decoding timestamp of the buffer, can be #GST_CLOCK_TIME_NONE when the
+ *     dts is not known or relevant. The dts contains the timestamp when the
+ *     media should be processed.
  * @duration: duration in time of the buffer data, can be #GST_CLOCK_TIME_NONE
  *     when the duration is not known or relevant.
- * @caps: the #GstCaps describing the data format in this buffer
  * @offset: a media specific offset for the buffer data.
  *     For video frames, this is the frame number of this buffer.
  *     For audio samples, this is the offset of the first sample in this buffer.
@@ -254,11 +242,6 @@ typedef enum {
  *       byte in this buffer.
  * @offset_end: the last offset contained in this buffer. It has the same
  *     format as @offset.
- * @malloc_data: a pointer to the allocated memory associated with this buffer.
- *     When the buffer is freed, this data will freed with @free_func.
- * @free_func: a custom function that will be called with @malloc_data, defaults
- *     to g_free(). Since 0.10.22.
- * @parent: the parent buffer if this is a subbuffer. Since 0.10.26.
  *
  * The structure of a #GstBuffer. Use the associated macros to access the public
  * variables.
@@ -267,61 +250,74 @@ struct _GstBuffer {
   GstMiniObject          mini_object;
 
   /*< public >*/ /* with COW */
-  /* pointer to data and its size */
-  guint8                *data;
-  guint                  size;
+  GstBufferPool         *pool;
 
   /* timestamp */
-  GstClockTime           timestamp;
+  GstClockTime           pts;
+  GstClockTime           dts;
   GstClockTime           duration;
 
-  /* the media type of this buffer */
-  GstCaps               *caps;
-
   /* media specific offset */
   guint64                offset;
   guint64                offset_end;
+};
 
-  guint8                *malloc_data;
+GType       gst_buffer_get_type            (void);
 
-  /* ABI Added */
-  GFreeFunc              free_func;
-  GstBuffer             *parent;
+/* allocation */
+GstBuffer * gst_buffer_new                 (void);
+GstBuffer * gst_buffer_new_allocate        (const GstAllocator * allocator, gsize size, gsize align);
+GstBuffer * gst_buffer_new_wrapped_full    (gpointer data, GFreeFunc free_func, gsize offset, gsize size);
+GstBuffer * gst_buffer_new_wrapped         (gpointer data, gsize size);
 
-  /*< private >*/
-  GstBufferPrivate      *priv;
-  gpointer _gst_reserved[GST_PADDING - 3];
-};
+/* memory blocks */
+guint       gst_buffer_n_memory            (GstBuffer *buffer);
+void        gst_buffer_take_memory         (GstBuffer *buffer, gint idx, GstMemory *mem);
+GstMemory * gst_buffer_peek_memory         (GstBuffer *buffer, guint idx, GstMapFlags flags);
+void        gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint length);
 
-struct _GstBufferClass {
-  GstMiniObjectClass    mini_object_class;
-};
+/**
+ * gst_buffer_remove_memory:
+ * @b: a #GstBuffer.
+ * @i: an index
+ *
+ * Remove the memory block in @b at @i.
+ */
+#define     gst_buffer_remove_memory(b,i)  gst_buffer_remove_memory_range ((b), (i), 1)
 
-GType       gst_buffer_get_type (void);
+gsize       gst_buffer_fill                (GstBuffer *buffer, gsize offset,
+                                            gconstpointer src, gsize size);
+gsize       gst_buffer_extract             (GstBuffer *buffer, gsize offset,
+                                            gpointer dest, gsize size);
+gint        gst_buffer_memcmp              (GstBuffer *buffer, gsize offset,
+                                            gconstpointer mem, gsize size);
+gsize       gst_buffer_memset              (GstBuffer *buffer, gsize offset,
+                                            guint8 val, gsize size);
 
-/* allocation */
-GstBuffer * gst_buffer_new               (void) G_GNUC_MALLOC;
-GstBuffer * gst_buffer_new_and_alloc     (guint size) G_GNUC_MALLOC;
-GstBuffer * gst_buffer_try_new_and_alloc (guint size) G_GNUC_MALLOC;
+gsize       gst_buffer_get_sizes           (GstBuffer *buffer, gsize *offset, gsize *maxsize);
+void        gst_buffer_resize              (GstBuffer *buffer, gssize offset, gssize size);
 
 /**
- * gst_buffer_set_data:
- * @buf: a #GstBuffer
- * @data: The data (a #guint8 *) to set on the buffer.
- * @size: The size (in bytes, as a #guint) of the data being set.
+ * gst_buffer_get_size:
+ * @b: a #GstBuffer.
  *
- * A convenience function to set the data and size on a buffer.
- * This will replace any existing data pointer set on this buffer, but will
- * not change GST_BUFFER_MALLOCDATA(), if any. Callers should ensure that
- * GST_BUFFER_MALLOCDATA() is non-NULL, or should free that and set it to NULL.
+ * Get the size of @b.
+ */
+#define     gst_buffer_get_size(b)         gst_buffer_get_sizes ((b), NULL, NULL)
+/**
+ * gst_buffer_set_size:
+ * @b: a #GstBuffer.
+ * @s: a new size
  *
- * No checks are done on the data or size arguments passed.
+ * Set the size of @b to @s. This will remove or trim the memory blocks
+ * in the buffer.
  */
-#define         gst_buffer_set_data(buf, data, size)    \
-G_STMT_START {                                          \
-  GST_BUFFER_DATA (buf) = data;                         \
-  GST_BUFFER_SIZE (buf) = size;                         \
-} G_STMT_END
+#define     gst_buffer_set_size(b,s)       gst_buffer_resize ((b), 0, (s))
+
+/* getting memory */
+gpointer    gst_buffer_map                 (GstBuffer *buffer, gsize *size, gsize *maxsize,
+                                            GstMapFlags flags);
+gboolean    gst_buffer_unmap               (GstBuffer *buffer, gpointer data, gssize size);
 
 /* refcounting */
 /**
@@ -354,8 +350,7 @@ gst_buffer_ref (GstBuffer * buf)
  * @buf: (transfer full): a #GstBuffer.
  *
  * Decreases the refcount of the buffer. If the refcount reaches 0, the buffer
- * will be freed. If GST_BUFFER_MALLOCDATA() is non-NULL, this pointer will
- * also be freed at this time.
+ * with the associated metadata and memory will be freed.
  */
 #ifdef _FOOL_GTK_DOC_
 G_INLINE_FUNC void gst_buffer_unref (GstBuffer * buf);
@@ -390,38 +385,50 @@ gst_buffer_copy (const GstBuffer * buf)
 
 /**
  * GstBufferCopyFlags:
+ * @GST_BUFFER_COPY_NONE: copy nothing
  * @GST_BUFFER_COPY_FLAGS: flag indicating that buffer flags should be copied
- * @GST_BUFFER_COPY_TIMESTAMPS: flag indicating that buffer timestamp, duration,
- * offset and offset_end should be copied
- * @GST_BUFFER_COPY_CAPS: flag indicating that buffer caps should be copied
- * @GST_BUFFER_COPY_QDATA: flag indicating that buffer qdata should be copied
- *    (Since 0.10.36)
- *
- * A set of flags that can be provided to the gst_buffer_copy_metadata()
- * function to specify which metadata fields should be copied.
- *
- * Since: 0.10.13
+ * @GST_BUFFER_COPY_TIMESTAMPS: flag indicating that buffer pts, dts,
+ * duration, offset and offset_end should be copied
+ * @GST_BUFFER_COPY_MEMORY: flag indicating that buffer memory should be copied
+ * and appended to already existing memory
+ * @GST_BUFFER_COPY_MERGE: flag indicating that buffer memory should be
+ * merged
+ * @GST_BUFFER_COPY_META: flag indicating that buffer meta should be
+ * copied
+ *
+ * A set of flags that can be provided to the gst_buffer_copy_into()
+ * function to specify which items should be copied.
  */
 typedef enum {
-  GST_BUFFER_COPY_FLAGS      = (1 << 0),
-  GST_BUFFER_COPY_TIMESTAMPS = (1 << 1),
-  GST_BUFFER_COPY_CAPS       = (1 << 2),
-  GST_BUFFER_COPY_QDATA      = (1 << 3)
+  GST_BUFFER_COPY_NONE           = 0,
+  GST_BUFFER_COPY_FLAGS          = (1 << 0),
+  GST_BUFFER_COPY_TIMESTAMPS     = (1 << 1),
+  GST_BUFFER_COPY_META           = (1 << 2),
+  GST_BUFFER_COPY_MEMORY         = (1 << 3),
+  GST_BUFFER_COPY_MERGE          = (1 << 4)
 } GstBufferCopyFlags;
 
 /**
+ * GST_BUFFER_COPY_METADATA:
+ *
+ * Combination of all possible metadata fields that can be copied with
+ * gst_buffer_copy_into().
+ */
+#define GST_BUFFER_COPY_METADATA       (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |\
+                                        GST_BUFFER_COPY_META)
+
+/**
  * GST_BUFFER_COPY_ALL:
  *
  * Combination of all possible fields that can be copied with
- * gst_buffer_copy_metadata().
- *
- * Since: 0.10.13
+ * gst_buffer_copy_into().
  */
-#define GST_BUFFER_COPY_ALL ((GstBufferCopyFlags) (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_CAPS | GST_BUFFER_COPY_QDATA))
+#define GST_BUFFER_COPY_ALL  ((GstBufferCopyFlags)(GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY))
 
-/* copies metadata into newly allocated buffer */
-void            gst_buffer_copy_metadata        (GstBuffer *dest, const GstBuffer *src,
-                                                 GstBufferCopyFlags flags);
+/* copies memory or metadata into newly allocated buffer */
+void            gst_buffer_copy_into            (GstBuffer *dest, GstBuffer *src,
+                                                 GstBufferCopyFlags flags,
+                                                 gsize offset, gsize size);
 
 /**
  * gst_buffer_is_writable:
@@ -446,22 +453,6 @@ void            gst_buffer_copy_metadata        (GstBuffer *dest, const GstBuffe
  */
 #define         gst_buffer_make_writable(buf)   GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (buf)))
 
-/* Ensure that the metadata of the buffer is writable, even if the buffer data
- * isn't */
-gboolean        gst_buffer_is_metadata_writable (GstBuffer *buf);
-GstBuffer*      gst_buffer_make_metadata_writable (GstBuffer *buf);
-
-/* per-buffer user data */
-
-void                  gst_buffer_set_qdata (GstBuffer     * buffer,
-                                            GQuark          quark,
-                                            GstStructure  * data);
-
-const GstStructure *  gst_buffer_get_qdata (GstBuffer     * buffer,
-                                            GQuark          quark);
-
-
-
 /**
  * gst_buffer_replace:
  * @obuf: (inout) (transfer full): pointer to a pointer to a #GstBuffer to be
@@ -475,26 +466,61 @@ const GstStructure *  gst_buffer_get_qdata (GstBuffer     * buffer,
  * buffer is unreffed, the new is reffed).
  *
  * Either @nbuf or the #GstBuffer pointed to by @obuf may be NULL.
+ *
+ * Returns: TRUE when @obuf was different from @nbuf.
  */
 #ifdef _FOOL_GTK_DOC_
-G_INLINE_FUNC void gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf);
+G_INLINE_FUNC gboolean gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf);
 #endif
 
-static inline void
+static inline gboolean
 gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf)
 {
-  gst_mini_object_replace ((GstMiniObject **) obuf, (GstMiniObject *) nbuf);
+  return gst_mini_object_replace ((GstMiniObject **) obuf, (GstMiniObject *) nbuf);
 }
 
-GstCaps*        gst_buffer_get_caps             (GstBuffer *buffer);
-void            gst_buffer_set_caps             (GstBuffer *buffer, GstCaps *caps);
-
-/* creating a subbuffer */
-GstBuffer*      gst_buffer_create_sub           (GstBuffer *parent, guint offset, guint size) G_GNUC_MALLOC;
+/* creating a region */
+GstBuffer*      gst_buffer_copy_region          (GstBuffer *parent, GstBufferCopyFlags flags,
+                                                 gsize offset, gsize size);
 
 /* span, two buffers, intelligently */
 gboolean        gst_buffer_is_span_fast         (GstBuffer *buf1, GstBuffer *buf2);
-GstBuffer*      gst_buffer_span                 (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len) G_GNUC_MALLOC;
+GstBuffer*      gst_buffer_span                 (GstBuffer *buf1, gsize offset, GstBuffer *buf2, gsize size) G_GNUC_MALLOC;
+
+/* metadata */
+#include <gst/gstmeta.h>
+
+/**
+ * GstBufferMetaFunc:
+ * @buffer: a #GstBuffer
+ * @meta: a pointer to a #GstMeta
+ * @user_data: user data passed to gst_buffer_foreach_meta()
+ *
+ * A function that will be called from gst_buffer_foreach_meta(). The @meta
+ * field will point to a the reference of the meta.
+ *
+ * @buffer should not be modified from this callback.
+ *
+ * When this function returns %TRUE, the next meta will be
+ * returned. When %FALSE is returned, gst_buffer_foreach_meta() will return.
+ *
+ * When @meta is set to NULL, the item will be removed from the buffer.
+ *
+ * Returns: %FALSE when gst_buffer_foreach_meta() should stop
+ */
+typedef gboolean (*GstBufferForeachMetaFunc)    (GstBuffer *buffer, GstMeta **meta,
+                                                 gpointer user_data);
+
+GstMeta *       gst_buffer_get_meta             (GstBuffer *buffer, const GstMetaInfo *info);
+GstMeta *       gst_buffer_add_meta             (GstBuffer *buffer, const GstMetaInfo *info,
+                                                 gpointer params);
+gboolean        gst_buffer_remove_meta          (GstBuffer *buffer, GstMeta *meta);
+
+GstMeta *       gst_buffer_iterate_meta         (GstBuffer *buffer, gpointer *state);
+
+void            gst_buffer_foreach_meta         (GstBuffer *buffer,
+                                                 GstBufferForeachMetaFunc func,
+                                                 gpointer user_data);
 
 /**
  * gst_value_set_buffer:
@@ -503,7 +529,7 @@ GstBuffer*      gst_buffer_span                 (GstBuffer *buf1, guint32 offset
  *
  * Sets @b as the value of @v.  Caller retains reference to buffer.
  */
-#define         gst_value_set_buffer(v,b)       gst_value_set_mini_object(v, GST_MINI_OBJECT_CAST(b))
+#define         gst_value_set_buffer(v,b)       g_value_set_boxed((v),(b))
 /**
  * gst_value_take_buffer:
  * @v: a #GValue to receive the data
@@ -511,7 +537,7 @@ GstBuffer*      gst_buffer_span                 (GstBuffer *buf1, guint32 offset
  *
  * Sets @b as the value of @v.  Caller gives away reference to buffer.
  */
-#define         gst_value_take_buffer(v,b)      gst_value_take_mini_object(v, GST_MINI_OBJECT_CAST(b))
+#define         gst_value_take_buffer(v,b)      g_value_take_boxed(v,(b))
 /**
  * gst_value_get_buffer:
  * @v: a #GValue to query
@@ -522,7 +548,7 @@ GstBuffer*      gst_buffer_span                 (GstBuffer *buf1, guint32 offset
  *
  * Returns: (transfer none): buffer
  */
-#define         gst_value_get_buffer(v)         GST_BUFFER_CAST (gst_value_get_mini_object(v))
+#define         gst_value_get_buffer(v)         GST_BUFFER_CAST (g_value_get_boxed(v))
 
 G_END_DECLS
 
index 721c4c3..d0accb9 100644 (file)
 
 /**
  * SECTION:gstbufferlist
- * @short_description: Grouped scatter data buffer type for data-passing
+ * @short_description: Lists of buffers for data-passing
  * @see_also: #GstPad, #GstMiniObject
  *
- * Buffer lists are units of grouped scatter/gather data transfer in
- * GStreamer.
+ * Buffer lists are an object containing a list of buffers.
  *
  * Buffer lists are created with gst_buffer_list_new() and filled with data
- * using a #GstBufferListIterator. The iterator has no current buffer; its
- * cursor position lies between buffers, immediately before the buffer that
- * would be returned by gst_buffer_list_iterator_next(). After iterating to the
- * end of a group the iterator must be advanced to the next group by a call to
- * gst_buffer_list_iterator_next_group() before any further calls to
- * gst_buffer_list_iterator_next() can return buffers again. The cursor position
- * of a newly created iterator lies before the first group; a call to
- * gst_buffer_list_iterator_next_group() is necessary before calls to
- * gst_buffer_list_iterator_next() can return buffers.
+ * using a gst_buffer_list_insert().
  *
- * <informalfigure>
- *   <programlisting>
- *      +--- group0 ----------------------+--- group1 ------------+
- *      |   buffer0   buffer1   buffer2   |   buffer3   buffer4   |
- *    ^   ^         ^         ^         ^   ^         ^         ^
- *    Iterator positions between buffers
- *   </programlisting>
- * </informalfigure>
- *
- * The gst_buffer_list_iterator_remove(), gst_buffer_list_iterator_steal(),
- * gst_buffer_list_iterator_take() and gst_buffer_list_iterator_do() functions
- * are not defined in terms of the cursor position; they operate on the last
- * element returned from gst_buffer_list_iterator_next().
- *
- * The basic use pattern of creating a buffer list with an iterator is as
- * follows:
- *
- * <example>
- * <title>Creating a buffer list</title>
- *   <programlisting>
- *    GstBufferList *list;
- *    GstBufferListIterator *it;
- *
- *    list = gst_buffer_list_new ();
- *    it = gst_buffer_list_iterate (list);
- *    gst_buffer_list_iterator_add_group (it);
- *    gst_buffer_list_iterator_add (it, header1);
- *    gst_buffer_list_iterator_add (it, data1);
- *    gst_buffer_list_iterator_add_group (it);
- *    gst_buffer_list_iterator_add (it, header2);
- *    gst_buffer_list_iterator_add (it, data2);
- *    gst_buffer_list_iterator_add_group (it);
- *    gst_buffer_list_iterator_add (it, header3);
- *    gst_buffer_list_iterator_add (it, data3);
- *    ...
- *    gst_buffer_list_iterator_free (it);
- *   </programlisting>
- * </example>
- *
- * The basic use pattern of iterating over a buffer list is as follows:
- *
- * <example>
- * <title>Iterating a buffer list</title>
- *   <programlisting>
- *    GstBufferListIterator *it;
- *
- *    it = gst_buffer_list_iterate (list);
- *    while (gst_buffer_list_iterator_next_group (it)) {
- *      while ((buffer = gst_buffer_list_iterator_next (it)) != NULL) {
- *        do_something_with_buffer (buffer);
- *      }
- *    }
- *    gst_buffer_list_iterator_free (it);
- *   </programlisting>
- * </example>
- *
- * The basic use pattern of modifying a buffer in a list is as follows:
- *
- * <example>
- * <title>Modifying the data of the first buffer in a list</title>
- *   <programlisting>
- *    GstBufferListIterator *it;
- *
- *    list = gst_buffer_list_make_writable (list);
- *    it = gst_buffer_list_iterate (list);
- *    if (gst_buffer_list_iterator_next_group (it)) {
- *      GstBuffer *buf
- *
- *      buf = gst_buffer_list_iterator_next (it);
- *      if (buf != NULL) {
- *        buf = gst_buffer_list_iterator_do (it,
- *            (GstBufferListDoFunction) gst_mini_object_make_writable, NULL);
- *        modify_data (GST_BUFFER_DATA (buf));
- *      }
- *    }
- *    gst_buffer_list_iterator_free (it);
- *   </programlisting>
- * </example>
- *
- * Since: 0.10.24
  */
 #include "gst_private.h"
 
 
 #define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST
 
-#define GROUP_START NULL
-static gconstpointer STOLEN = "";
-
 /**
  * GstBufferList:
  *
@@ -141,107 +49,93 @@ struct _GstBufferList
 {
   GstMiniObject mini_object;
 
-  GQueue *buffers;
-};
-
-struct _GstBufferListClass
-{
-  GstMiniObjectClass mini_object_class;
-};
-
-/**
- * GstBufferListIterator:
- *
- * Opaque iterator for a #GstBufferList.
- *
- * Since: 0.10.24
- */
-struct _GstBufferListIterator
-{
-  GstBufferList *list;
-  GList *next;
-  GList *last_returned;
+  GArray *array;
 };
 
-static GType _gst_buffer_list_type = 0;
+GType _gst_buffer_list_type = 0;
 
-G_DEFINE_TYPE (GstBufferList, gst_buffer_list, GST_TYPE_MINI_OBJECT);
+GST_DEFINE_MINI_OBJECT_TYPE (GstBufferList, gst_buffer_list);
 
 void
-_gst_buffer_list_initialize (void)
+_priv_gst_buffer_list_initialize (void)
 {
-  GType type = gst_buffer_list_get_type ();
+  _gst_buffer_list_type = gst_buffer_list_get_type ();
+}
+
+static GstBufferList *
+_gst_buffer_list_copy (GstBufferList * list)
+{
+  GstBufferList *copy;
+  guint i, len;
+
+  len = list->array->len;
+  copy = gst_buffer_list_new_sized (len);
 
-  g_type_class_ref (type);
-  _gst_buffer_list_type = type;
+  /* add and ref all buffers in the array */
+  for (i = 0; i < len; i++) {
+    GstBuffer *buf = g_array_index (list->array, GstBuffer *, i);
+    buf = gst_buffer_ref (buf);
+    g_array_append_val (copy->array, buf);
+  }
+  return copy;
 }
 
 static void
-gst_buffer_list_init (GstBufferList * list)
+_gst_buffer_list_free (GstBufferList * list)
 {
-  list->buffers = g_queue_new ();
+  guint i, len;
+  GST_LOG ("free %p", list);
 
-  GST_LOG ("init %p", list);
+  /* unrefs all buffers too */
+  len = list->array->len;
+  for (i = 0; i < len; i++)
+    gst_buffer_unref (g_array_index (list->array, GstBuffer *, i));
+  g_array_free (list->array, TRUE);
+
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (list), list);
 }
 
 static void
-gst_buffer_list_finalize (GstBufferList * list)
+gst_buffer_list_init (GstBufferList * list, gsize size, guint asize)
 {
-  GList *tmp;
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (list), _gst_buffer_list_type,
+      size);
 
-  g_return_if_fail (list != NULL);
+  list->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
+  list->mini_object.free = (GstMiniObjectFreeFunction) _gst_buffer_list_free;
 
-  GST_LOG ("finalize %p", list);
+  list->array = g_array_sized_new (FALSE, FALSE, sizeof (GstBuffer *), asize);
 
-  tmp = list->buffers->head;
-  while (tmp) {
-    if (tmp->data != GROUP_START && tmp->data != STOLEN) {
-      gst_buffer_unref (GST_BUFFER_CAST (tmp->data));
-    }
-    tmp = tmp->next;
-  }
-  g_queue_free (list->buffers);
-
-/* Not chaining up because GstMiniObject::finalize() does nothing
-  GST_MINI_OBJECT_CLASS (gst_buffer_list_parent_class)->finalize
-      (GST_MINI_OBJECT_CAST (list));*/
+  GST_LOG ("init %p", list);
 }
 
-static GstBufferList *
-_gst_buffer_list_copy (GstBufferList * list)
+/**
+ * gst_buffer_list_new_sized:
+ * @size: an initial reserved size
+ *
+ * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
+ * the returned #GstBufferList. The list will have @size space preallocated so
+ * that memory reallocations can be avoided.
+ *
+ * Free-function: gst_buffer_list_unref
+ *
+ * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
+ *     after usage.
+ *
+ * Since: 0.10.24
+ */
+GstBufferList *
+gst_buffer_list_new_sized (guint size)
 {
-  GstBufferList *list_copy;
-  GQueue *buffers_copy;
-  GList *tmp;
-
-  g_return_val_if_fail (list != NULL, NULL);
+  GstBufferList *list;
 
-  /* shallow copy of list and pointers */
-  buffers_copy = g_queue_copy (list->buffers);
+  list = g_slice_new0 (GstBufferList);
 
-  /* ref all buffers in the list */
-  tmp = list->buffers->head;
-  while (tmp) {
-    if (tmp->data != GROUP_START && tmp->data != STOLEN) {
-      tmp->data = gst_buffer_ref (GST_BUFFER_CAST (tmp->data));
-    }
-    tmp = g_list_next (tmp);
-  }
-
-  list_copy = gst_buffer_list_new ();
-  g_queue_free (list_copy->buffers);
-  list_copy->buffers = buffers_copy;
+  GST_LOG ("new %p", list);
 
-  return list_copy;
-}
+  gst_buffer_list_init (list, sizeof (GstBufferList), size);
 
-static void
-gst_buffer_list_class_init (GstBufferListClass * list_class)
-{
-  list_class->mini_object_class.copy =
-      (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
-  list_class->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_buffer_list_finalize;
+  return list;
 }
 
 /**
@@ -260,43 +154,25 @@ gst_buffer_list_class_init (GstBufferListClass * list_class)
 GstBufferList *
 gst_buffer_list_new (void)
 {
-  GstBufferList *list;
-
-  list = (GstBufferList *) gst_mini_object_new (_gst_buffer_list_type);
-
-  GST_LOG ("new %p", list);
-
-  return list;
+  return gst_buffer_list_new_sized (8);
 }
 
 /**
- * gst_buffer_list_n_groups:
+ * gst_buffer_list_length:
  * @list: a #GstBufferList
  *
- * Returns the number of groups in @list.
+ * Returns the number of buffers in @list.
  *
- * Returns: the number of groups in the buffer list
+ * Returns: the number of buffers in the buffer list
  *
  * Since: 0.10.24
  */
 guint
-gst_buffer_list_n_groups (GstBufferList * list)
+gst_buffer_list_length (GstBufferList * list)
 {
-  GList *tmp;
-  guint n;
-
-  g_return_val_if_fail (list != NULL, 0);
-
-  tmp = list->buffers->head;
-  n = 0;
-  while (tmp) {
-    if (tmp->data == GROUP_START) {
-      n++;
-    }
-    tmp = g_list_next (tmp);
-  }
+  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0);
 
-  return n;
+  return list->array->len;
 }
 
 /**
@@ -308,8 +184,8 @@ gst_buffer_list_n_groups (GstBufferList * list)
  * Call @func with @data for each buffer in @list.
  *
  * @func can modify the passed buffer pointer or its contents. The return value
- * of @func define if this function returns or if the remaining buffers in a
- * group should be skipped.
+ * of @func define if this function returns or if the remaining buffers in
+ * the list should be skipped.
  *
  * Since: 0.10.24
  */
@@ -317,70 +193,44 @@ void
 gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
     gpointer user_data)
 {
-  GList *tmp, *next;
-  guint group, idx;
-  GstBufferListItem res;
+  guint i, len;
 
-  g_return_if_fail (list != NULL);
+  g_return_if_fail (GST_IS_BUFFER_LIST (list));
   g_return_if_fail (func != NULL);
 
-  next = list->buffers->head;
-  group = idx = 0;
-  while (next) {
-    GstBuffer *buffer;
-
-    tmp = next;
-    next = g_list_next (tmp);
-
-    buffer = tmp->data;
-
-    if (buffer == GROUP_START) {
-      group++;
-      idx = 0;
-      continue;
-    } else if (buffer == STOLEN)
-      continue;
-    else
-      idx++;
-
-    /* need to decrement the indices */
-    res = func (&buffer, group - 1, idx - 1, user_data);
-
-    if (G_UNLIKELY (buffer != tmp->data)) {
-      /* the function changed the buffer */
-      if (buffer == NULL) {
-        /* we were asked to remove the item */
-        g_queue_delete_link (list->buffers, tmp);
-        idx--;
+  len = list->array->len;
+  for (i = 0; i < len;) {
+    GstBuffer *buf, *buf_ret;
+    gboolean ret;
+
+    buf = buf_ret = g_array_index (list->array, GstBuffer *, i);
+    ret = func (&buf_ret, i, user_data);
+
+    /* Check if the function changed the buffer */
+    if (buf != buf_ret) {
+      if (buf_ret == NULL) {
+        g_array_remove_index (list->array, i);
+        len--;
       } else {
-        /* change the buffer */
-        tmp->data = buffer;
+        g_array_index (list->array, GstBuffer *, i) = buf_ret;
       }
     }
 
-    switch (res) {
-      case GST_BUFFER_LIST_CONTINUE:
-        break;
-      case GST_BUFFER_LIST_SKIP_GROUP:
-        while (next && next->data != GROUP_START)
-          next = g_list_next (next);
-        break;
-      case GST_BUFFER_LIST_END:
-        return;
-    }
+    if (!ret)
+      break;
+
+    /* If the buffer was not removed by func go to the next buffer */
+    if (buf_ret != NULL)
+      i++;
   }
 }
 
 /**
  * gst_buffer_list_get:
  * @list: a #GstBufferList
- * @group: the group
- * @idx: the index in @group
+ * @idx: the index
  *
- * Get the buffer at @idx in @group.
- *
- * Note that this function is not efficient for iterating over the entire list.
- * Use an iterator or gst_buffer_list_foreach() instead.
+ * Get the buffer at @idx.
  *
  * Returns: (transfer none): the buffer at @idx in @group or NULL when there
  *     is no buffer. The buffer remains valid as long as @list is valid.
@@ -388,528 +238,48 @@ gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
  * Since: 0.10.24
  */
 GstBuffer *
-gst_buffer_list_get (GstBufferList * list, guint group, guint idx)
-{
-  GList *tmp;
-  guint cgroup, cidx;
-
-  g_return_val_if_fail (list != NULL, NULL);
-
-  tmp = list->buffers->head;
-  cgroup = 0;
-  while (tmp) {
-    if (tmp->data == GROUP_START) {
-      if (cgroup == group) {
-        /* we found the group */
-        tmp = g_list_next (tmp);
-        cidx = 0;
-        while (tmp && tmp->data != GROUP_START) {
-          if (tmp->data != STOLEN) {
-            if (cidx == idx)
-              return GST_BUFFER_CAST (tmp->data);
-            else
-              cidx++;
-          }
-          tmp = g_list_next (tmp);
-        }
-        break;
-      } else {
-        cgroup++;
-        if (cgroup > group)
-          break;
-      }
-    }
-    tmp = g_list_next (tmp);
-  }
-  return NULL;
-}
-
-static GstBufferListIterator *
-gst_buffer_list_iterator_copy (const GstBufferListIterator * it)
+gst_buffer_list_get (GstBufferList * list, guint idx)
 {
-  GstBufferListIterator *ret;
+  GstBuffer *buf;
 
-  ret = g_slice_new (GstBufferListIterator);
-  ret->list = it->list;
-  ret->next = it->next;
-  ret->last_returned = it->last_returned;
+  g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL);
+  g_return_val_if_fail (idx < list->array->len, NULL);
 
-  return ret;
-}
+  buf = g_array_index (list->array, GstBuffer *, idx);
 
-GType
-gst_buffer_list_iterator_get_type (void)
-{
-  static GType type = 0;
-
-  if (G_UNLIKELY (type == 0)) {
-    type = g_boxed_type_register_static ("GstBufferListIterator",
-        (GBoxedCopyFunc) gst_buffer_list_iterator_copy,
-        (GBoxedFreeFunc) gst_buffer_list_iterator_free);
-  }
-
-  return type;
+  return buf;
 }
 
 /**
- * gst_buffer_list_iterate:
+ * gst_buffer_list_insert:
  * @list: a #GstBufferList
+ * @idx: the index
+ * @buffer: a #GstBuffer
  *
- * Iterate the buffers in @list. The owner of the iterator must also be the
- * owner of a reference to @list while the returned iterator is in use.
- *
- * Free-function: gst_buffer_list_iterator_free
- *
- * Returns: (transfer full): a new #GstBufferListIterator of the buffers in
- *     @list. gst_buffer_list_iterator_free() after usage
+ * Insert @buffer at @idx in @list. Other buffers are moved to make room for
+ * this new buffer.
  *
- * Since: 0.10.24
- */
-GstBufferListIterator *
-gst_buffer_list_iterate (GstBufferList * list)
-{
-  GstBufferListIterator *it;
-
-  g_return_val_if_fail (list != NULL, NULL);
-
-  it = g_slice_new (GstBufferListIterator);
-  it->list = list;
-  it->next = list->buffers->head;
-  it->last_returned = NULL;
-
-  return it;
-}
-
-/**
- * gst_buffer_list_iterator_free:
- * @it: (transfer full): the #GstBufferListIterator to free
- *
- * Free the iterator.
- *
- * Since: 0.10.24
+ * A -1 value for @idx will append the buffer at the end.
  */
 void
-gst_buffer_list_iterator_free (GstBufferListIterator * it)
+gst_buffer_list_insert (GstBufferList * list, guint idx, GstBuffer * buffer)
 {
-  g_return_if_fail (it != NULL);
-
-  g_slice_free (GstBufferListIterator, it);
-}
-
-/**
- * gst_buffer_list_iterator_n_buffers:
- * @it: a #GstBufferListIterator
- *
- * Returns the number of buffers left to iterate in the current group. I.e. the
- * number of calls that can be made to gst_buffer_list_iterator_next() before
- * it returns NULL.
- *
- * This function will not move the implicit cursor or in any other way affect
- * the state of the iterator @it.
- *
- * Returns: the number of buffers left to iterate in the current group
- *
- * Since: 0.10.24
- */
-guint
-gst_buffer_list_iterator_n_buffers (const GstBufferListIterator * it)
-{
-  GList *tmp;
-  guint n;
-
-  g_return_val_if_fail (it != NULL, 0);
-
-  tmp = it->next;
-  n = 0;
-  while (tmp && tmp->data != GROUP_START) {
-    if (tmp->data != STOLEN) {
-      n++;
-    }
-    tmp = g_list_next (tmp);
-  }
-
-  return n;
-}
-
-/**
- * gst_buffer_list_iterator_add:
- * @it: a #GstBufferListIterator
- * @buffer: (transfer full): a #GstBuffer
- *
- * Inserts @buffer into the #GstBufferList iterated with @it. The buffer is
- * inserted into the current group, immediately before the buffer that would be
- * returned by gst_buffer_list_iterator_next(). The buffer is inserted before
- * the implicit cursor, a subsequent call to gst_buffer_list_iterator_next()
- * will return the buffer after the inserted buffer, if any.
- *
- * This function takes ownership of @buffer.
- *
- * Since: 0.10.24
- */
-void
-gst_buffer_list_iterator_add (GstBufferListIterator * it, GstBuffer * buffer)
-{
-  g_return_if_fail (it != NULL);
+  g_return_if_fail (GST_IS_BUFFER_LIST (list));
   g_return_if_fail (buffer != NULL);
 
-  /* adding before the first group start is not allowed */
-  g_return_if_fail (it->next != it->list->buffers->head);
-
-  /* cheap insert into the GQueue */
-  if (it->next != NULL) {
-    g_queue_insert_before (it->list->buffers, it->next, buffer);
-  } else {
-    g_queue_push_tail (it->list->buffers, buffer);
+  if (idx == -1)
+    g_array_append_val (list->array, buffer);
+  else {
+    g_return_if_fail (idx < list->array->len);
+    g_array_insert_val (list->array, idx, buffer);
   }
 }
 
-/**
- * gst_buffer_list_iterator_add_list:
- * @it: a #GstBufferListIterator
- * @list: (transfer full) (element-type Gst.Buffer): a #GList of buffers
- *
- * Inserts @list of buffers into the #GstBufferList iterated with @it. The list is
- * inserted into the current group, immediately before the buffer that would be
- * returned by gst_buffer_list_iterator_next(). The list is inserted before
- * the implicit cursor, a subsequent call to gst_buffer_list_iterator_next()
- * will return the buffer after the last buffer of the inserted list, if any.
- *
- * This function takes ownership of @list and all its buffers.
- *
- * Since: 0.10.31
- */
-void
-gst_buffer_list_iterator_add_list (GstBufferListIterator * it, GList * list)
-{
-  GList *last;
-  guint len;
-
-  g_return_if_fail (it != NULL);
-  g_return_if_fail (it->next != it->list->buffers->head);
-
-  if (list == NULL)
-    return;
-
-  last = list;
-  len = 1;
-  while (last->next) {
-    last = last->next;
-    len++;
-  }
-
-  if (it->next) {
-    last->next = it->next;
-    list->prev = it->next->prev;
-    it->next->prev = last;
-    if (list->prev)
-      list->prev->next = list;
-  } else {
-    it->list->buffers->tail->next = list;
-    list->prev = it->list->buffers->tail;
-    it->list->buffers->tail = last;
-  }
-  it->list->buffers->length += len;
-}
-
-/**
- * gst_buffer_list_iterator_add_group:
- * @it: a #GstBufferListIterator
- *
- * Inserts a new, empty group into the #GstBufferList iterated with @it. The
- * group is inserted immediately before the group that would be returned by
- * gst_buffer_list_iterator_next_group(). A subsequent call to
- * gst_buffer_list_iterator_next_group() will advance the iterator to the group
- * after the inserted group, if any.
- *
- * Since: 0.10.24
- */
-void
-gst_buffer_list_iterator_add_group (GstBufferListIterator * it)
-{
-  g_return_if_fail (it != NULL);
-
-  /* advance iterator to next group start */
-  while (it->next != NULL && it->next->data != GROUP_START) {
-    it->next = g_list_next (it->next);
-  }
-
-  /* cheap insert of a group start into the GQueue */
-  if (it->next != NULL) {
-    g_queue_insert_before (it->list->buffers, it->next, GROUP_START);
-  } else {
-    g_queue_push_tail (it->list->buffers, GROUP_START);
-  }
-}
-
-/**
- * gst_buffer_list_iterator_next:
- * @it: a #GstBufferListIterator
- *
- * Returns the next buffer in the list iterated with @it. If the iterator is at
- * the end of a group, NULL will be returned. This function may be called
- * repeatedly to iterate through the current group.
- *
- * The caller will not get a new ref to the returned #GstBuffer and must not
- * unref it.
- *
- * Returns: (transfer none): the next buffer in the current group of the
- *     buffer list, or NULL
- *
- * Since: 0.10.24
- */
-GstBuffer *
-gst_buffer_list_iterator_next (GstBufferListIterator * it)
-{
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (it != NULL, NULL);
-
-  while (it->next != NULL && it->next->data != GROUP_START &&
-      it->next->data == STOLEN) {
-    it->next = g_list_next (it->next);
-  }
-
-  if (it->next == NULL || it->next->data == GROUP_START) {
-    goto no_buffer;
-  }
-
-  buffer = GST_BUFFER_CAST (it->next->data);
-
-  it->last_returned = it->next;
-  it->next = g_list_next (it->next);
-
-  return buffer;
-
-no_buffer:
-  {
-    it->last_returned = NULL;
-    return NULL;
-  }
-}
-
-/**
- * gst_buffer_list_iterator_next_group:
- * @it: a #GstBufferListIterator
- *
- * Advance the iterator @it to the first buffer in the next group. If the
- * iterator is at the last group, FALSE will be returned. This function may be
- * called repeatedly to iterate through the groups in a buffer list.
- *
- * Returns: TRUE if the iterator could be advanced to the next group, FALSE if
- * the iterator was already at the last group
- *
- * Since: 0.10.24
- */
-gboolean
-gst_buffer_list_iterator_next_group (GstBufferListIterator * it)
-{
-  g_return_val_if_fail (it != NULL, FALSE);
-
-  /* advance iterator to next group start */
-  while (it->next != NULL && it->next->data != GROUP_START) {
-    it->next = g_list_next (it->next);
-  }
-
-  if (it->next) {
-    /* move one step beyond the group start */
-    it->next = g_list_next (it->next);
-  }
-
-  it->last_returned = NULL;
-
-  return (it->next != NULL);
-}
-
-/**
- * gst_buffer_list_iterator_remove:
- * @it: a #GstBufferListIterator
- *
- * Removes the last buffer returned by gst_buffer_list_iterator_next() from
- * the #GstBufferList iterated with @it. gst_buffer_list_iterator_next() must
- * have been called on @it before this function is called. This function can
- * only be called once per call to gst_buffer_list_iterator_next().
- *
- * The removed buffer is unreffed.
- *
- * Since: 0.10.24
- */
 void
-gst_buffer_list_iterator_remove (GstBufferListIterator * it)
-{
-  g_return_if_fail (it != NULL);
-  g_return_if_fail (it->last_returned != NULL);
-  g_assert (it->last_returned->data != GROUP_START);
-
-  if (it->last_returned->data != STOLEN) {
-    gst_buffer_unref (it->last_returned->data);
-  }
-  g_queue_delete_link (it->list->buffers, it->last_returned);
-  it->last_returned = NULL;
-}
-
-/**
- * gst_buffer_list_iterator_take:
- * @it: a #GstBufferListIterator
- * @buffer: (transfer full): a #GstBuffer
- *
- * Replaces the last buffer returned by gst_buffer_list_iterator_next() with
- * @buffer in the #GstBufferList iterated with @it and takes ownership of
- * @buffer. gst_buffer_list_iterator_next() must have been called on @it before
- * this function is called. gst_buffer_list_iterator_remove() must not have been
- * called since the last call to gst_buffer_list_iterator_next().
- *
- * This function unrefs the replaced buffer if it has not been stolen with
- * gst_buffer_list_iterator_steal() and takes ownership of @buffer (i.e. the
- * refcount of @buffer is not increased).
- *
- * FIXME 0.11: this conditional taking-ownership is not good for bindings
- *
- * Since: 0.10.24
- */
-void
-gst_buffer_list_iterator_take (GstBufferListIterator * it, GstBuffer * buffer)
-{
-  g_return_if_fail (it != NULL);
-  g_return_if_fail (it->last_returned != NULL);
-  g_return_if_fail (buffer != NULL);
-  g_assert (it->last_returned->data != GROUP_START);
-
-  if (it->last_returned->data != STOLEN) {
-    gst_buffer_unref (it->last_returned->data);
-  }
-  it->last_returned->data = buffer;
-}
-
-/**
- * gst_buffer_list_iterator_steal:
- * @it: a #GstBufferListIterator
- *
- * Returns the last buffer returned by gst_buffer_list_iterator_next() without
- * modifying the refcount of the buffer.
- *
- * Returns: (transfer none): the last buffer returned by
- *     gst_buffer_list_iterator_next()
- *
- * Since: 0.10.24
- */
-GstBuffer *
-gst_buffer_list_iterator_steal (GstBufferListIterator * it)
+gst_buffer_list_remove (GstBufferList * list, guint idx, guint length)
 {
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (it != NULL, NULL);
-  g_return_val_if_fail (it->last_returned != NULL, NULL);
-  g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
-  g_assert (it->last_returned->data != GROUP_START);
-
-  buffer = it->last_returned->data;
-  it->last_returned->data = (gpointer) STOLEN;
+  g_return_if_fail (GST_IS_BUFFER_LIST (list));
+  g_return_if_fail (idx < list->array->len);
 
-  return buffer;
-}
-
-/**
- * gst_buffer_list_iterator_do:
- * @it: a #GstBufferListIterator
- * @do_func: (scope call): the function to be called
- * @user_data: (closure): the gpointer to optional user data.
- *
- * Calls the given function for the last buffer returned by
- * gst_buffer_list_iterator_next(). gst_buffer_list_iterator_next() must have
- * been called on @it before this function is called.
- * gst_buffer_list_iterator_remove() and gst_buffer_list_iterator_steal() must
- * not have been called since the last call to gst_buffer_list_iterator_next().
- *
- * See #GstBufferListDoFunction for more details.
- *
- * Returns: (transfer none): the return value from @do_func
- *
- * Since: 0.10.24
- */
-GstBuffer *
-gst_buffer_list_iterator_do (GstBufferListIterator * it,
-    GstBufferListDoFunction do_func, gpointer user_data)
-{
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (it != NULL, NULL);
-  g_return_val_if_fail (it->last_returned != NULL, NULL);
-  g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
-  g_return_val_if_fail (do_func != NULL, NULL);
-  g_return_val_if_fail (gst_buffer_list_is_writable (it->list), NULL);
-  g_assert (it->last_returned->data != GROUP_START);
-
-  buffer = gst_buffer_list_iterator_steal (it);
-  buffer = do_func (buffer, user_data);
-  if (buffer == NULL) {
-    gst_buffer_list_iterator_remove (it);
-  } else {
-    gst_buffer_list_iterator_take (it, buffer);
-  }
-
-  return buffer;
-}
-
-/**
- * gst_buffer_list_iterator_merge_group:
- * @it: a #GstBufferListIterator
- *
- * Merge a buffer list group into a normal #GstBuffer by copying its metadata
- * and memcpying its data into consecutive memory. All buffers in the current
- * group after the implicit cursor will be merged into one new buffer. The
- * metadata of the new buffer will be a copy of the metadata of the buffer that
- * would be returned by gst_buffer_list_iterator_next(). If there is no buffer
- * in the current group after the implicit cursor, NULL will be returned.
- *
- * This function will not move the implicit cursor or in any other way affect
- * the state of the iterator @it or the list.
- *
- * Returns: (transfer full): a new #GstBuffer, gst_buffer_unref() after usage,
- *     or NULL
- *
- * Since: 0.10.24
- */
-GstBuffer *
-gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it)
-{
-  GList *tmp;
-  guint size;
-  GstBuffer *buf;
-  guint8 *ptr;
-
-  g_return_val_if_fail (it != NULL, NULL);
-
-  /* calculate size of merged buffer */
-  size = 0;
-  tmp = it->next;
-  while (tmp && tmp->data != GROUP_START) {
-    if (tmp->data != STOLEN) {
-      size += GST_BUFFER_SIZE (tmp->data);
-    }
-    tmp = g_list_next (tmp);
-  }
-
-  if (size == 0) {
-    return NULL;
-  }
-
-  /* allocate a new buffer */
-  buf = gst_buffer_new_and_alloc (size);
-
-  /* copy metadata from the next buffer after the implicit cursor */
-  gst_buffer_copy_metadata (buf, GST_BUFFER_CAST (it->next->data),
-      GST_BUFFER_COPY_ALL);
-
-  /* copy data of all buffers before the next group start into the new buffer */
-  ptr = GST_BUFFER_DATA (buf);
-  tmp = it->next;
-  do {
-    if (tmp->data != STOLEN) {
-      memcpy (ptr, GST_BUFFER_DATA (tmp->data), GST_BUFFER_SIZE (tmp->data));
-      ptr += GST_BUFFER_SIZE (tmp->data);
-    }
-    tmp = g_list_next (tmp);
-  } while (tmp && tmp->data != GROUP_START);
-
-  return buf;
+  g_array_remove_range (list->array, idx, length);
 }
index 10c4a1f..4b0dfeb 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_BUFFER_LIST (gst_buffer_list_get_type ())
-#define GST_IS_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_LIST))
-#define GST_IS_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_LIST))
-#define GST_BUFFER_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_LIST, GstBufferListClass))
-#define GST_BUFFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_LIST, GstBufferList))
-#define GST_BUFFER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_LIST, GstBufferListClass))
-#define GST_BUFFER_LIST_CAST(obj) ((GstBufferList *)obj)
+GST_EXPORT GType _gst_buffer_list_type;
 
-#define GST_TYPE_BUFFER_LIST_ITERATOR (gst_buffer_list_iterator_get_type ())
+#define GST_TYPE_BUFFER_LIST      (_gst_buffer_list_type)
+#define GST_IS_BUFFER_LIST(obj)   (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_BUFFER_LIST))
+#define GST_BUFFER_LIST_CAST(obj) ((GstBufferList *)obj)
+#define GST_BUFFER_LIST(obj)      (GST_BUFFER_LIST_CAST(obj))
 
 typedef struct _GstBufferList GstBufferList;
-typedef struct _GstBufferListClass GstBufferListClass;
-typedef struct _GstBufferListIterator GstBufferListIterator;
-
-/**
- * GstBufferListDoFunction:
- * @buffer: (transfer full): the #GstBuffer
- * @user_data: user data
- *
- * A function for accessing the last buffer returned by
- * gst_buffer_list_iterator_next(). The function can leave @buffer in the list,
- * replace @buffer in the list or remove @buffer from the list, depending on
- * the return value. If the function returns NULL, @buffer will be removed from
- * the list, otherwise @buffer will be replaced with the returned buffer.
- *
- * The last buffer returned by gst_buffer_list_iterator_next() will be replaced
- * with the buffer returned from the function. The function takes ownership of
- * @buffer and if a different value than @buffer is returned, @buffer must be
- * unreffed. If NULL is returned, the buffer will be removed from the list. The
- * list must be writable.
- *
- * Returns: (transfer full): the buffer to replace @buffer in the list, or NULL
- *     to remove @buffer from the list
- *
- * Since: 0.10.24
- */
-typedef GstBuffer* (*GstBufferListDoFunction) (GstBuffer * buffer, gpointer user_data);
-
-/**
- * GstBufferListItem:
- * @GST_BUFFER_LIST_CONTINUE:   Retrieve next buffer
- * @GST_BUFFER_LIST_SKIP_GROUP: Skip to next group
- * @GST_BUFFER_LIST_END:        End iteration
- *
- * The result of the #GstBufferListFunc.
- *
- * Since: 0.10.24
- */
-typedef enum {
-  GST_BUFFER_LIST_CONTINUE,
-  GST_BUFFER_LIST_SKIP_GROUP,
-  GST_BUFFER_LIST_END
-} GstBufferListItem;
 
 /**
  * GstBufferListFunc:
  * @buffer: pointer the buffer
- * @group: the group index of @buffer
- * @idx: the index in @group of @buffer
+ * @idx: the index of @buffer
  * @user_data: user data passed to gst_buffer_list_foreach()
  *
  * A function that will be called from gst_buffer_list_foreach(). The @buffer
- * field will point to a the reference of the buffer at @idx in @group.
+ * field will point to a the reference of the buffer at @idx.
  *
- * When this function returns #GST_BUFFER_LIST_CONTINUE, the next buffer will be
- * returned. When #GST_BUFFER_LIST_SKIP_GROUP is returned, all remaining buffers
- * in the current group will be skipped and the first buffer of the next group
- * is returned (if any). When GST_BUFFER_LIST_END is returned,
- * gst_buffer_list_foreach() will return.
+ * When this function returns %TRUE, the next buffer will be
+ * returned. When %FALSE is returned, gst_buffer_list_foreach() will return.
  *
  * When @buffer is set to NULL, the item will be removed from the bufferlist.
  * When @buffer has been made writable, the new buffer reference can be assigned
  * to @buffer. This function is responsible for unreffing the old buffer when
  * removing or modifying.
  *
- * Returns: a #GstBufferListItem
- *
- * Since: 0.10.24
+ * Returns: %FALSE when gst_buffer_list_foreach() should stop
  */
-typedef GstBufferListItem (*GstBufferListFunc)   (GstBuffer **buffer, guint group, guint idx,
-                                                  gpointer user_data);
-
+typedef gboolean   (*GstBufferListFunc)   (GstBuffer **buffer, guint idx,
+                                           gpointer user_data);
 
-GType gst_buffer_list_get_type (void);
-
-/* allocation */
-GstBufferList *gst_buffer_list_new (void);
 
 /* refcounting */
 /**
@@ -209,34 +153,23 @@ gst_buffer_list_copy (const GstBufferList * list)
  */
 #define gst_buffer_list_make_writable(list) GST_BUFFER_LIST_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (list)))
 
-guint                    gst_buffer_list_n_groups              (GstBufferList *list);
-
-void                     gst_buffer_list_foreach               (GstBufferList *list,
-                                                                GstBufferListFunc func,
-                                                               gpointer user_data);
-GstBuffer *              gst_buffer_list_get                   (GstBufferList *list, guint group, guint idx);
+GType                    gst_buffer_list_get_type              (void);
 
-/* iterator */
-GType                    gst_buffer_list_iterator_get_type     (void);
-GstBufferListIterator *  gst_buffer_list_iterate               (GstBufferList *list) G_GNUC_MALLOC;
-void                     gst_buffer_list_iterator_free         (GstBufferListIterator *it);
+/* allocation */
+GstBufferList *          gst_buffer_list_new                   (void) G_GNUC_MALLOC;
+GstBufferList *          gst_buffer_list_new_sized             (guint size) G_GNUC_MALLOC;
 
-guint                    gst_buffer_list_iterator_n_buffers    (const GstBufferListIterator *it);
-GstBuffer *              gst_buffer_list_iterator_next         (GstBufferListIterator *it);
-gboolean                 gst_buffer_list_iterator_next_group   (GstBufferListIterator *it);
+guint                    gst_buffer_list_length                (GstBufferList *list);
 
-void                     gst_buffer_list_iterator_add          (GstBufferListIterator *it, GstBuffer *buffer);
-void                     gst_buffer_list_iterator_add_list     (GstBufferListIterator *it, GList *list);
-void                     gst_buffer_list_iterator_add_group    (GstBufferListIterator *it);
-void                     gst_buffer_list_iterator_remove       (GstBufferListIterator *it);
-GstBuffer *              gst_buffer_list_iterator_steal        (GstBufferListIterator *it);
-void                     gst_buffer_list_iterator_take         (GstBufferListIterator *it, GstBuffer *buffer);
+GstBuffer *              gst_buffer_list_get                   (GstBufferList *list, guint idx);
+void                     gst_buffer_list_insert                (GstBufferList *list, guint idx, GstBuffer *buffer);
+void                     gst_buffer_list_remove                (GstBufferList *list, guint idx, guint length);
 
-GstBuffer *              gst_buffer_list_iterator_do           (GstBufferListIterator *it, GstBufferListDoFunction do_func,
-                                                                gpointer user_data);
+void                     gst_buffer_list_foreach               (GstBufferList *list,
+                                                                GstBufferListFunc func,
+                                                               gpointer user_data);
 
-/* conversion */
-GstBuffer *              gst_buffer_list_iterator_merge_group  (const GstBufferListIterator *it);
+#define gst_buffer_list_add(l,b) gst_buffer_list_insert((l),-1,(b));
 
 G_END_DECLS
 
diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c
new file mode 100644 (file)
index 0000000..0978848
--- /dev/null
@@ -0,0 +1,979 @@
+/* GStreamer
+ * Copyright (C) 2010 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gstbufferpool.c: GstBufferPool baseclass
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstbufferpool
+ * @short_description: Pool for buffers
+ * @see_also: #GstBuffer
+ *
+ */
+
+#include "gst_private.h"
+#include "glib-compat-private.h"
+
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+#include <sys/types.h>
+
+#include "gstinfo.h"
+#include "gstquark.h"
+
+#include "gstbufferpool.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_buffer_pool_debug);
+#define GST_CAT_DEFAULT gst_buffer_pool_debug
+
+#define GST_BUFFER_POOL_GET_PRIVATE(obj)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BUFFER_POOL, GstBufferPoolPrivate))
+
+#define GST_BUFFER_POOL_LOCK(pool)   (g_rec_mutex_lock(&pool->priv->rec_lock))
+#define GST_BUFFER_POOL_UNLOCK(pool) (g_rec_mutex_unlock(&pool->priv->rec_lock))
+
+struct _GstBufferPoolPrivate
+{
+  GRecMutex rec_lock;
+  guint size;
+  guint min_buffers;
+  guint max_buffers;
+  guint prefix;
+  guint align;
+};
+
+enum
+{
+  /* add more above */
+  LAST_SIGNAL
+};
+
+static void gst_buffer_pool_finalize (GObject * object);
+
+G_DEFINE_TYPE (GstBufferPool, gst_buffer_pool, GST_TYPE_OBJECT);
+
+static gboolean default_start (GstBufferPool * pool);
+static gboolean default_stop (GstBufferPool * pool);
+static gboolean default_set_config (GstBufferPool * pool,
+    GstStructure * config);
+static GstFlowReturn default_alloc_buffer (GstBufferPool * pool,
+    GstBuffer ** buffer, GstBufferPoolParams * params);
+static GstFlowReturn default_acquire_buffer (GstBufferPool * pool,
+    GstBuffer ** buffer, GstBufferPoolParams * params);
+static void default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer,
+    GstBufferPoolParams * params);
+static void default_free_buffer (GstBufferPool * pool, GstBuffer * buffer);
+static void default_release_buffer (GstBufferPool * pool, GstBuffer * buffer);
+
+static void
+gst_buffer_pool_class_init (GstBufferPoolClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+
+  g_type_class_add_private (klass, sizeof (GstBufferPoolPrivate));
+
+  gobject_class->finalize = gst_buffer_pool_finalize;
+
+  klass->start = default_start;
+  klass->stop = default_stop;
+  klass->set_config = default_set_config;
+  klass->acquire_buffer = default_acquire_buffer;
+  klass->reset_buffer = default_reset_buffer;
+  klass->alloc_buffer = default_alloc_buffer;
+  klass->release_buffer = default_release_buffer;
+  klass->free_buffer = default_free_buffer;
+
+  GST_DEBUG_CATEGORY_INIT (gst_buffer_pool_debug, "bufferpool", 0,
+      "bufferpool debug");
+}
+
+static void
+gst_buffer_pool_init (GstBufferPool * pool)
+{
+  pool->priv = GST_BUFFER_POOL_GET_PRIVATE (pool);
+
+  g_rec_mutex_init (&pool->priv->rec_lock);
+
+  pool->poll = gst_poll_new_timer ();
+  pool->queue = gst_atomic_queue_new (10);
+  pool->flushing = TRUE;
+  pool->active = FALSE;
+  pool->configured = FALSE;
+  pool->started = FALSE;
+  pool->config = gst_structure_new_id_empty (GST_QUARK (BUFFER_POOL_CONFIG));
+  gst_buffer_pool_config_set (pool->config, NULL, 0, 0, 0, 0, 0);
+  gst_poll_write_control (pool->poll);
+
+  GST_DEBUG_OBJECT (pool, "created");
+}
+
+static void
+gst_buffer_pool_finalize (GObject * object)
+{
+  GstBufferPool *pool;
+
+  pool = GST_BUFFER_POOL_CAST (object);
+
+  GST_DEBUG_OBJECT (pool, "finalize");
+
+  gst_buffer_pool_set_active (pool, FALSE);
+  gst_atomic_queue_unref (pool->queue);
+  gst_poll_free (pool->poll);
+  gst_structure_free (pool->config);
+  g_rec_mutex_clear (&pool->priv->rec_lock);
+
+  G_OBJECT_CLASS (gst_buffer_pool_parent_class)->finalize (object);
+}
+
+/**
+ * gst_buffer_pool_new:
+ *
+ * Creates a new #GstBufferPool instance.
+ *
+ * Returns: (transfer full): a new #GstBufferPool instance
+ */
+GstBufferPool *
+gst_buffer_pool_new (void)
+{
+  GstBufferPool *result;
+
+  result = g_object_newv (GST_TYPE_BUFFER_POOL, 0, NULL);
+  GST_DEBUG_OBJECT (result, "created new buffer pool");
+
+  return result;
+}
+
+static GstFlowReturn
+default_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+    GstBufferPoolParams * params)
+{
+  GstBufferPoolPrivate *priv = pool->priv;
+  GstMemory *mem;
+
+  *buffer = gst_buffer_new ();
+
+  mem = gst_allocator_alloc (NULL, priv->size + priv->prefix, priv->align);
+  gst_memory_resize (mem, priv->prefix, priv->size);
+  gst_buffer_take_memory (*buffer, -1, mem);
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+mark_meta_pooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data)
+{
+  GST_META_FLAG_SET (*meta, GST_META_FLAG_POOLED);
+
+  return TRUE;
+}
+
+/* the default implementation for preallocating the buffers
+ * in the pool */
+static gboolean
+default_start (GstBufferPool * pool)
+{
+  guint i;
+  GstBufferPoolPrivate *priv = pool->priv;
+  GstBufferPoolClass *pclass;
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  /* no alloc function, error */
+  if (G_UNLIKELY (pclass->alloc_buffer == NULL))
+    goto no_alloc;
+
+  /* we need to prealloc buffers */
+  for (i = 0; i < priv->min_buffers; i++) {
+    GstBuffer *buffer;
+
+    if (pclass->alloc_buffer (pool, &buffer, NULL) != GST_FLOW_OK)
+      goto alloc_failed;
+
+    gst_buffer_foreach_meta (buffer, mark_meta_pooled, pool);
+    GST_LOG_OBJECT (pool, "prealloced buffer %d: %p", i, buffer);
+    /* release to the queue, we call the vmethod directly, we don't need to do
+     * the other refcount handling right now. */
+    if (G_LIKELY (pclass->release_buffer))
+      pclass->release_buffer (pool, buffer);
+  }
+  return TRUE;
+
+  /* ERRORS */
+no_alloc:
+  {
+    GST_WARNING_OBJECT (pool, "no alloc function");
+    return FALSE;
+  }
+alloc_failed:
+  {
+    GST_WARNING_OBJECT (pool, "alloc function failed");
+    return FALSE;
+  }
+}
+
+/* must be called with the lock */
+static gboolean
+do_start (GstBufferPool * pool)
+{
+  if (!pool->started) {
+    GstBufferPoolClass *pclass;
+
+    pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+    GST_LOG_OBJECT (pool, "starting");
+    /* start the pool, subclasses should allocate buffers and put them
+     * in the queue */
+    if (G_LIKELY (pclass->start)) {
+      if (!pclass->start (pool))
+        return FALSE;
+    }
+    pool->started = TRUE;
+  }
+  return TRUE;
+}
+
+
+static void
+default_free_buffer (GstBufferPool * pool, GstBuffer * buffer)
+{
+  gst_buffer_unref (buffer);
+}
+
+/* must be called with the lock */
+static gboolean
+default_stop (GstBufferPool * pool)
+{
+  GstBuffer *buffer;
+  GstBufferPoolClass *pclass;
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  /* clear the pool */
+  while ((buffer = gst_atomic_queue_pop (pool->queue))) {
+    GST_LOG_OBJECT (pool, "freeing %p", buffer);
+    gst_poll_read_control (pool->poll);
+
+    if (G_LIKELY (pclass->free_buffer))
+      pclass->free_buffer (pool, buffer);
+  }
+  return TRUE;
+}
+
+/* must be called with the lock */
+static gboolean
+do_stop (GstBufferPool * pool)
+{
+  if (pool->started) {
+    GstBufferPoolClass *pclass;
+
+    pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+    GST_LOG_OBJECT (pool, "stopping");
+    if (G_LIKELY (pclass->stop)) {
+      if (!pclass->stop (pool))
+        return FALSE;
+    }
+    pool->started = FALSE;
+  }
+  return TRUE;
+}
+
+/**
+ * gst_buffer_pool_set_active:
+ * @pool: a #GstBufferPool
+ * @active: the new active state
+ *
+ * Control the active state of @pool. When the pool is active, new calls to
+ * gst_buffer_pool_acquire_buffer() will return with GST_FLOW_WRONG_STATE.
+ *
+ * Activating the bufferpool will preallocate all resources in the pool based on
+ * the configuration of the pool.
+ *
+ * Deactivating will free the resources again when there are no outstanding
+ * buffers. When there are outstanding buffers, they will be freed as soon as
+ * they are all returned to the pool.
+ *
+ * Returns: %FALSE when the pool was not configured or when preallocation of the
+ * buffers failed.
+ */
+gboolean
+gst_buffer_pool_set_active (GstBufferPool * pool, gboolean active)
+{
+  gboolean res = TRUE;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE);
+
+  GST_LOG_OBJECT (pool, "active %d", active);
+
+  GST_BUFFER_POOL_LOCK (pool);
+  /* just return if we are already in the right state */
+  if (pool->active == active)
+    goto was_ok;
+
+  /* we need to be configured */
+  if (!pool->configured)
+    goto not_configured;
+
+  if (active) {
+    if (!do_start (pool))
+      goto start_failed;
+
+    /* unset the flushing state now */
+    gst_poll_read_control (pool->poll);
+    g_atomic_int_set (&pool->flushing, FALSE);
+  } else {
+    gint outstanding;
+
+    /* set to flushing first */
+    g_atomic_int_set (&pool->flushing, TRUE);
+    gst_poll_write_control (pool->poll);
+
+    /* when all buffers are in the pool, free them. Else they will be
+     * freed when they are released */
+    outstanding = g_atomic_int_get (&pool->outstanding);
+    GST_LOG_OBJECT (pool, "outstanding buffers %d", outstanding);
+    if (outstanding == 0) {
+      if (!do_stop (pool))
+        goto stop_failed;
+    }
+  }
+  pool->active = active;
+  GST_BUFFER_POOL_UNLOCK (pool);
+
+  return res;
+
+was_ok:
+  {
+    GST_DEBUG_OBJECT (pool, "pool was in the right state");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return TRUE;
+  }
+not_configured:
+  {
+    GST_ERROR_OBJECT (pool, "pool was not configured");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return FALSE;
+  }
+start_failed:
+  {
+    GST_ERROR_OBJECT (pool, "start failed");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return FALSE;
+  }
+stop_failed:
+  {
+    GST_WARNING_OBJECT (pool, "stop failed");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_buffer_pool_is_active:
+ * @pool: a #GstBufferPool
+ *
+ * Check if @pool is active. A pool can be activated with the
+ * gst_buffer_pool_set_active() call.
+ *
+ * Returns: %TRUE when the pool is active.
+ */
+gboolean
+gst_buffer_pool_is_active (GstBufferPool * pool)
+{
+  gboolean res;
+
+  GST_BUFFER_POOL_LOCK (pool);
+  res = pool->active;
+  GST_BUFFER_POOL_UNLOCK (pool);
+
+  return res;
+}
+
+static gboolean
+default_set_config (GstBufferPool * pool, GstStructure * config)
+{
+  GstBufferPoolPrivate *priv = pool->priv;
+  const GstCaps *caps;
+  guint size, min_buffers, max_buffers;
+  guint prefix, align;
+
+  /* parse the config and keep around */
+  if (!gst_buffer_pool_config_get (config, &caps, &size, &min_buffers,
+          &max_buffers, &prefix, &align))
+    goto wrong_config;
+
+  GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
+
+  priv->size = size;
+  priv->min_buffers = min_buffers;
+  priv->max_buffers = max_buffers;
+  priv->prefix = prefix;
+  priv->align = align;
+
+  return TRUE;
+
+wrong_config:
+  {
+    GST_WARNING_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_buffer_pool_set_config:
+ * @pool: a #GstBufferPool
+ * @config: (transfer full): a #GstStructure
+ *
+ * Set the configuration of the pool. The pool must be inactive and all buffers
+ * allocated form this pool must be returned or else this function will do
+ * nothing and return FALSE.
+ *
+ * @config is a #GstStructure that contains the configuration parameters for
+ * the pool. A default and mandatory set of parameters can be configured with
+ * gst_buffer_pool_config_set(). This function takes ownership of @config.
+ *
+ * Returns: TRUE when the configuration could be set.
+ */
+gboolean
+gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
+{
+  gboolean result;
+  GstBufferPoolClass *pclass;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE);
+  g_return_val_if_fail (config != NULL, FALSE);
+
+  GST_BUFFER_POOL_LOCK (pool);
+  /* can't change the settings when active */
+  if (pool->active)
+    goto was_active;
+
+  /* we can't change when outstanding buffers */
+  if (g_atomic_int_get (&pool->outstanding) != 0)
+    goto have_outstanding;
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  /* set the new config */
+  if (G_LIKELY (pclass->set_config))
+    result = pclass->set_config (pool, config);
+  else
+    result = FALSE;
+
+  if (result) {
+    if (pool->config)
+      gst_structure_free (pool->config);
+    pool->config = config;
+
+    /* now we are configured */
+    pool->configured = TRUE;
+  }
+  GST_BUFFER_POOL_UNLOCK (pool);
+
+  return result;
+
+  /* ERRORS */
+was_active:
+  {
+    GST_WARNING_OBJECT (pool, "can't change config, we are active");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return FALSE;
+  }
+have_outstanding:
+  {
+    GST_WARNING_OBJECT (pool, "can't change config, have outstanding buffers");
+    GST_BUFFER_POOL_UNLOCK (pool);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_buffer_pool_get_config:
+ * @pool: a #GstBufferPool
+ *
+ * Get a copy of the current configuration of the pool. This configuration
+ * can either be modified and used for the gst_buffer_pool_set_config() call
+ * or it must be freed after usage.
+ *
+ * Returns: (transfer full): a copy of the current configuration of @pool. use
+ * gst_structure_free() after usage or gst_buffer_pool_set_config().
+ */
+GstStructure *
+gst_buffer_pool_get_config (GstBufferPool * pool)
+{
+  GstStructure *result;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), NULL);
+
+  GST_BUFFER_POOL_UNLOCK (pool);
+  result = gst_structure_copy (pool->config);
+  GST_BUFFER_POOL_UNLOCK (pool);
+
+  return result;
+}
+
+static const gchar *empty_option[] = { NULL };
+
+/**
+ * gst_buffer_pool_get_options:
+ * @pool: a #GstBufferPool
+ *
+ * Get a NULL terminated array of string with supported bufferpool options for
+ * @pool. An option would typically be enabled with
+ * gst_buffer_pool_config_add_option().
+ *
+ * Returns: (array zero-terminated=1) (transfer none): a NULL terminated array of strings.
+ */
+const gchar **
+gst_buffer_pool_get_options (GstBufferPool * pool)
+{
+  GstBufferPoolClass *pclass;
+  const gchar **result;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), NULL);
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  if (G_LIKELY (pclass->get_options)) {
+    if ((result = pclass->get_options (pool)) == NULL)
+      goto invalid_result;
+  } else
+    result = empty_option;
+
+  return result;
+
+  /* ERROR */
+invalid_result:
+  {
+    g_warning ("bufferpool subclass returned NULL options");
+    return empty_option;
+  }
+}
+
+/**
+ * gst_buffer_pool_has_option:
+ * @pool: a #GstBufferPool
+ * @option: an option
+ *
+ * Check if the bufferpool supports @option.
+ *
+ * Returns: a NULL terminated array of strings.
+ */
+gboolean
+gst_buffer_pool_has_option (GstBufferPool * pool, const gchar * option)
+{
+  guint i;
+  const gchar **options;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE);
+  g_return_val_if_fail (option != NULL, FALSE);
+
+  options = gst_buffer_pool_get_options (pool);
+
+  for (i = 0; options[i]; i++) {
+    if (g_str_equal (options[i], option))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * gst_buffer_pool_config_set:
+ * @config: a #GstBufferPool configuration
+ * @caps: caps for the buffers
+ * @size: the size of each buffer, not including prefix
+ * @min_buffers: the minimum amount of buffers to allocate.
+ * @max_buffers: the maximum amount of buffers to allocate or 0 for unlimited.
+ * @prefix: prefix each buffer with this many bytes
+ * @align: alignment of the buffer data.
+ *
+ * Configure @config with the given parameters.
+ */
+void
+gst_buffer_pool_config_set (GstStructure * config, const GstCaps * caps,
+    guint size, guint min_buffers, guint max_buffers, guint prefix, guint align)
+{
+  g_return_if_fail (config != NULL);
+
+  gst_structure_id_set (config,
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (SIZE), G_TYPE_UINT, size,
+      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
+      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
+      GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
+      GST_QUARK (ALIGN), G_TYPE_UINT, align, NULL);
+}
+
+/**
+ * gst_buffer_pool_config_add_option:
+ * @config: a #GstBufferPool configuration
+ * @option: an option to add
+ *
+ * Enabled the option in @config. This will instruct the @bufferpool to enable
+ * the specified option on the buffers that it allocates.
+ *
+ * The supported options by @pool can be retrieved with gst_buffer_pool_get_options().
+ */
+void
+gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option)
+{
+  GValueArray *array;
+  const GValue *value;
+  GValue option_value = { 0 };
+  gint i;
+
+  g_return_if_fail (config != NULL);
+
+  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  if (value) {
+    array = (GValueArray *) g_value_get_boxed (value);
+  } else {
+    GValue new_array_val = { 0, };
+
+    array = g_value_array_new (0);
+
+    g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
+    g_value_take_boxed (&new_array_val, array);
+
+    gst_structure_id_take_value (config, GST_QUARK (OPTIONS), &new_array_val);
+  }
+  for (i = 0; i < array->n_values; i++) {
+    value = g_value_array_get_nth (array, i);
+    if (g_str_equal (option, g_value_get_string (value)))
+      return;
+  }
+  g_value_init (&option_value, G_TYPE_STRING);
+  g_value_set_string (&option_value, option);
+  g_value_array_append (array, &option_value);
+  g_value_unset (&option_value);
+}
+
+/**
+ * gst_buffer_pool_config_n_options:
+ * @config: a #GstBufferPool configuration
+ *
+ * Retrieve the number of values currently stored in the
+ * options array of the @config structure.
+ *
+ * Returns: the options array size as a #guint.
+ */
+guint
+gst_buffer_pool_config_n_options (GstStructure * config)
+{
+  GValueArray *array;
+  const GValue *value;
+  guint size = 0;
+
+  g_return_val_if_fail (config != NULL, 0);
+
+  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  if (value) {
+    array = (GValueArray *) g_value_get_boxed (value);
+    size = array->n_values;
+  }
+  return size;
+}
+
+/**
+ * gst_buffer_pool_config_get_option:
+ * @config: a #GstBufferPool configuration
+ * @index: position in the option array to read
+ *
+ * Parse an available @config and get the option
+ * at @index of the options API array.
+ *
+ * Returns: a #gchar of the option at @index.
+ */
+const gchar *
+gst_buffer_pool_config_get_option (GstStructure * config, guint index)
+{
+  const GValue *value;
+  const gchar *ret = NULL;
+
+  g_return_val_if_fail (config != NULL, 0);
+
+  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  if (value) {
+    GValueArray *array;
+    GValue *option_value;
+
+    array = (GValueArray *) g_value_get_boxed (value);
+    option_value = g_value_array_get_nth (array, index);
+
+    if (option_value)
+      ret = g_value_get_string (option_value);
+  }
+  return ret;
+}
+
+/**
+ * gst_buffer_pool_config_has_option:
+ * @config: a #GstBufferPool configuration
+ * @option: an option
+ *
+ * Check if @config contains @option
+ *
+ * Returns: TRUE if the options array contains @option.
+ */
+gboolean
+gst_buffer_pool_config_has_option (GstStructure * config, const gchar * option)
+{
+  const GValue *value;
+
+  g_return_val_if_fail (config != NULL, 0);
+
+  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  if (value) {
+    GValueArray *array;
+    GValue *option_value;
+    gint i;
+
+    array = (GValueArray *) g_value_get_boxed (value);
+    for (i = 0; i < array->n_values; i++) {
+      option_value = g_value_array_get_nth (array, i);
+      if (g_str_equal (option, g_value_get_string (option_value)))
+        return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * gst_buffer_pool_config_get:
+ * @config: (transfer none): a #GstBufferPool configuration
+ * @caps: (out): the caps of buffers
+ * @size: (out): the size of each buffer, not including prefix
+ * @min_buffers: (out): the minimum amount of buffers to allocate.
+ * @max_buffers: (out): the maximum amount of buffers to allocate or 0 for unlimited.
+ * @prefix: (out): prefix each buffer with this many bytes
+ * @align: (out): alignment of the buffer data.
+ *
+ * Get the configuration values from @config.
+ */
+gboolean
+gst_buffer_pool_config_get (GstStructure * config, const GstCaps ** caps,
+    guint * size, guint * min_buffers, guint * max_buffers, guint * prefix,
+    guint * align)
+{
+  g_return_val_if_fail (config != NULL, FALSE);
+
+  return gst_structure_id_get (config,
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (SIZE), G_TYPE_UINT, size,
+      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
+      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
+      GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
+      GST_QUARK (ALIGN), G_TYPE_UINT, align, NULL);
+}
+
+static GstFlowReturn
+default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+    GstBufferPoolParams * params)
+{
+  GstFlowReturn result;
+  GstBufferPoolClass *pclass;
+  GstBufferPoolPrivate *priv = pool->priv;
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  while (TRUE) {
+    if (G_UNLIKELY (g_atomic_int_get (&pool->flushing)))
+      goto flushing;
+
+    /* try to get a buffer from the queue */
+    *buffer = gst_atomic_queue_pop (pool->queue);
+    if (G_LIKELY (*buffer)) {
+      gst_poll_read_control (pool->poll);
+      result = GST_FLOW_OK;
+      GST_LOG_OBJECT (pool, "acquired buffer %p", *buffer);
+      break;
+    }
+
+    /* no buffer */
+    if (priv->max_buffers == 0) {
+      /* no max_buffers, we allocate some more */
+      if (G_LIKELY (pclass->alloc_buffer)) {
+        result = pclass->alloc_buffer (pool, buffer, params);
+        if (result == GST_FLOW_OK && *buffer)
+          gst_buffer_foreach_meta (*buffer, mark_meta_pooled, pool);
+        else
+          result = GST_FLOW_ERROR;
+      } else
+        result = GST_FLOW_NOT_SUPPORTED;
+      GST_LOG_OBJECT (pool, "alloc buffer %p", *buffer);
+      break;
+    }
+
+    /* check if we need to wait */
+    if (params && (params->flags & GST_BUFFER_POOL_FLAG_DONTWAIT)) {
+      GST_LOG_OBJECT (pool, "no more buffers");
+      result = GST_FLOW_EOS;
+      break;
+    }
+
+    /* now wait */
+    GST_LOG_OBJECT (pool, "waiting for free buffers");
+    gst_poll_wait (pool->poll, GST_CLOCK_TIME_NONE);
+  }
+
+  return result;
+
+  /* ERRORS */
+flushing:
+  {
+    GST_DEBUG_OBJECT (pool, "we are flushing");
+    return GST_FLOW_WRONG_STATE;
+  }
+}
+
+static inline void
+dec_outstanding (GstBufferPool * pool)
+{
+  if (g_atomic_int_dec_and_test (&pool->outstanding)) {
+    /* all buffers are returned to the pool, see if we need to free them */
+    if (g_atomic_int_get (&pool->flushing)) {
+      /* take the lock so that set_active is not run concurrently */
+      GST_BUFFER_POOL_LOCK (pool);
+      /* recheck the flushing state in the lock, the pool could have been
+       * set to active again */
+      if (g_atomic_int_get (&pool->flushing))
+        do_stop (pool);
+
+      GST_BUFFER_POOL_UNLOCK (pool);
+    }
+  }
+}
+
+static gboolean
+remove_meta_unpooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data)
+{
+  if (!GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED))
+    *meta = NULL;
+  return TRUE;
+}
+
+static void
+default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer,
+    GstBufferPoolParams * params)
+{
+  GST_BUFFER_FLAGS (buffer) = 0;
+
+  GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
+  GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
+  GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
+  GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
+  GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
+
+  /* remove all metadata without the POOLED flag */
+  gst_buffer_foreach_meta (buffer, remove_meta_unpooled, pool);
+}
+
+/**
+ * gst_buffer_pool_acquire_buffer:
+ * @pool: a #GstBufferPool
+ * @buffer: (out): a location for a #GstBuffer
+ * @params: (transfer none) (allow-none) parameters.
+ *
+ * Acquire a buffer from @pool. @buffer should point to a memory location that
+ * can hold a pointer to the new buffer.
+ *
+ * @params can be NULL or contain optional parameters to influence the allocation.
+ *
+ * Returns: a #GstFlowReturn such as GST_FLOW_WRONG_STATE when the pool is
+ * inactive.
+ */
+GstFlowReturn
+gst_buffer_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+    GstBufferPoolParams * params)
+{
+  GstBufferPoolClass *pclass;
+  GstFlowReturn result;
+
+  g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), GST_FLOW_ERROR);
+  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  /* assume we'll have one more outstanding buffer we need to do that so
+   * that concurrent set_active doesn't clear the buffers */
+  g_atomic_int_inc (&pool->outstanding);
+
+  if (G_LIKELY (pclass->acquire_buffer))
+    result = pclass->acquire_buffer (pool, buffer, params);
+  else
+    result = GST_FLOW_NOT_SUPPORTED;
+
+  if (G_LIKELY (result == GST_FLOW_OK)) {
+    /* all buffers from the pool point to the pool and have the refcount of the
+     * pool incremented */
+    (*buffer)->pool = gst_object_ref (pool);
+    /* now reset the buffer when needed */
+    if (G_LIKELY (pclass->reset_buffer))
+      pclass->reset_buffer (pool, *buffer, params);
+  } else {
+    dec_outstanding (pool);
+  }
+
+  return result;
+}
+
+static void
+default_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
+{
+  /* keep it around in our queue */
+  GST_LOG_OBJECT (pool, "released buffer %p", buffer);
+  gst_atomic_queue_push (pool->queue, buffer);
+  gst_poll_write_control (pool->poll);
+}
+
+/**
+ * gst_buffer_pool_release_buffer:
+ * @pool: a #GstBufferPool
+ * @buffer: (transfer none): a #GstBuffer
+ *
+ * Release @buffer to @pool. @buffer should have previously been allocated from
+ * @pool with gst_buffer_pool_acquire_buffer().
+ *
+ * This function is usually called automatically when the last ref on @buffer
+ * disappears.
+ */
+void
+gst_buffer_pool_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
+{
+  GstBufferPoolClass *pclass;
+
+  g_return_if_fail (GST_IS_BUFFER_POOL (pool));
+  g_return_if_fail (buffer != NULL);
+
+  /* check that the buffer is ours, all buffers returned to the pool have the
+   * pool member set to NULL and the pool refcount decreased */
+  if (!g_atomic_pointer_compare_and_exchange (&buffer->pool, pool, NULL))
+    return;
+
+  pclass = GST_BUFFER_POOL_GET_CLASS (pool);
+
+  if (G_LIKELY (pclass->release_buffer))
+    pclass->release_buffer (pool, buffer);
+
+  dec_outstanding (pool);
+
+  /* decrease the refcount that the buffer had to us */
+  gst_object_unref (pool);
+}
diff --git a/gst/gstbufferpool.h b/gst/gstbufferpool.h
new file mode 100644 (file)
index 0000000..33b1cbe
--- /dev/null
@@ -0,0 +1,218 @@
+/* GStreamer
+ * Copyright (C) 2010 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gstbufferpool.h: Header for GstBufferPool object
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_BUFFER_POOL_H__
+#define __GST_BUFFER_POOL_H__
+
+#include <gst/gstminiobject.h>
+#include <gst/gstatomicqueue.h>
+#include <gst/gstpoll.h>
+#include <gst/gstclock.h>
+#include <gst/gstpad.h>
+#include <gst/gstbuffer.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstBufferPoolPrivate GstBufferPoolPrivate;
+typedef struct _GstBufferPoolClass GstBufferPoolClass;
+
+/**
+ * GST_BUFFER_POOL_TRACE_NAME:
+ *
+ * The name used for tracing memory allocations.
+ */
+#define GST_BUFFER_POOL_TRACE_NAME           "GstBufferPool"
+
+#define GST_TYPE_BUFFER_POOL                 (gst_buffer_pool_get_type())
+#define GST_IS_BUFFER_POOL(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_POOL))
+#define GST_IS_BUFFER_POOL_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_POOL))
+#define GST_BUFFER_POOL_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_POOL, GstBufferPoolClass))
+#define GST_BUFFER_POOL(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_POOL, GstBufferPool))
+#define GST_BUFFER_POOL_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_POOL, GstBufferPoolClass))
+#define GST_BUFFER_POOL_CAST(obj)            ((GstBufferPool *)(obj))
+
+/**
+ * GstBufferPoolFlags:
+ * @GST_BUFFER_POOL_FLAG_NONE: no flags
+ * @GST_BUFFER_POOL_FLAG_KEY_UNIT: buffer is keyframe
+ * @GST_BUFFER_POOL_FLAG_DONTWAIT: don't wait for buffer. This makes the
+ * acquire_buffer method return GST_FLOW_UNEXPECTED.
+ * @GST_BUFFER_POOL_FLAG_DISCONT: buffer is discont
+ * @GST_BUFFER_POOL_FLAG_LAST: last flag, subclasses can use private flags
+ *    starting from this value.
+ *
+ * Additional flags to control the allocation of a buffer
+ */
+typedef enum {
+  GST_BUFFER_POOL_FLAG_NONE     = 0,
+  GST_BUFFER_POOL_FLAG_KEY_UNIT = (1 << 0),
+  GST_BUFFER_POOL_FLAG_DONTWAIT = (1 << 1),
+  GST_BUFFER_POOL_FLAG_DISCONT  = (1 << 2),
+  GST_BUFFER_POOL_FLAG_LAST     = (1 << 16),
+} GstBufferPoolFlags;
+
+/**
+ * GstBufferPoolParams:
+ * @format: the format of @start and @stop
+ * @start: the start position
+ * @stop: the stop position
+ * @flags: additional flags
+ *
+ * Parameters passed to the gst_buffer_pool_acquire_buffer() function to control the
+ * allocation of the buffer.
+ *
+ * The default implementation ignores the @start and @stop members but other
+ * implementations can use this extra information to decide what buffer to
+ * return.
+ */
+typedef struct _GstBufferPoolParams {
+  GstFormat          format;
+  gint64             start;
+  gint64             stop;
+  GstBufferPoolFlags flags;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+} GstBufferPoolParams;
+
+/**
+ * GST_BUFFER_POOL_IS_FLUSHING:
+ * @pool: a GstBufferPool
+ *
+ * Check if the bufferpool is flushing. Subclasses might want to check the
+ * state of the pool in the acquire function.
+ */
+#define GST_BUFFER_POOL_IS_FLUSHING(pool)  (g_atomic_int_get (&pool->flushing))
+
+/**
+ * GstBufferPool:
+ * @object: the parent structure
+ *
+ * The structure of a #GstBufferPool. Use the associated macros to access the public
+ * variables.
+ */
+struct _GstBufferPool {
+  GstObject            object;
+
+  /*< private >*/
+  gboolean             active;
+  gboolean             flushing;
+  gboolean             started;
+  gint                 outstanding;
+  GstAtomicQueue      *queue;
+  GstPoll             *poll;
+
+  gboolean             configured;
+  GstStructure        *config;
+
+  GstBufferPoolPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstBufferPoolClass:
+ * @object_class:  Object parent class
+ * @get_options: get a list of options supported by this pool
+ * @set_config: apply the bufferpool configuration. The default configuration
+ *              will parse the default config parameters
+ * @start: start the bufferpool. The default implementation will preallocate
+ *         min-buffers buffers and put them in the queue
+ * @stop: stop the bufferpool. the default implementation will free the
+ *        preallocated buffers. This function is called when all the buffers are
+ *        returned to the pool.
+ * @acquire_buffer: get a new buffer from the pool. The default implementation
+ *        will take a buffer from the queue and optionally wait for a buffer to
+ *        be released when there are no buffers available.
+ * @alloc_buffer: allocate a buffer. the default implementation allocates
+ *        buffers from the default memory allocator and with the configured
+ *        size, prefix and alignment.
+ * @reset_buffer: reset the buffer to its state when it was freshly allocated.
+ *        The default implementation will clear the flags, timestamps and
+ *        will remove the metadata added after alloc_buffer.
+ * @release_buffer: release a buffer back in the pool. The default
+ *        implementation will put the buffer back in the queue and notify any
+ *        blocking acquire_buffer calls.
+ * @free_buffer: free a buffer. The default implementation unrefs the buffer.
+ *
+ * The GstBufferPool class.
+ */
+struct _GstBufferPoolClass {
+  GstObjectClass    object_class;
+
+  /* vmethods */
+  const gchar ** (*get_options)    (GstBufferPool *pool);
+  gboolean       (*set_config)     (GstBufferPool *pool, GstStructure *config);
+
+  gboolean       (*start)          (GstBufferPool *pool);
+  gboolean       (*stop)           (GstBufferPool *pool);
+
+  GstFlowReturn  (*acquire_buffer) (GstBufferPool *pool, GstBuffer **buffer,
+                                    GstBufferPoolParams *params);
+  GstFlowReturn  (*alloc_buffer)   (GstBufferPool *pool, GstBuffer **buffer,
+                                    GstBufferPoolParams *params);
+  void           (*reset_buffer)   (GstBufferPool *pool, GstBuffer *buffer,
+                                    GstBufferPoolParams *params);
+  void           (*release_buffer) (GstBufferPool *pool, GstBuffer *buffer);
+  void           (*free_buffer)    (GstBufferPool *pool, GstBuffer *buffer);
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GType       gst_buffer_pool_get_type (void);
+
+/* allocation */
+GstBufferPool *  gst_buffer_pool_new  (void);
+
+/* state management */
+gboolean         gst_buffer_pool_set_active      (GstBufferPool *pool, gboolean active);
+gboolean         gst_buffer_pool_is_active       (GstBufferPool *pool);
+
+gboolean         gst_buffer_pool_set_config      (GstBufferPool *pool, GstStructure *config);
+GstStructure *   gst_buffer_pool_get_config      (GstBufferPool *pool);
+
+const gchar **   gst_buffer_pool_get_options     (GstBufferPool *pool);
+gboolean         gst_buffer_pool_has_option      (GstBufferPool *pool, const gchar *option);
+
+/* helpers for configuring the config structure */
+void             gst_buffer_pool_config_set      (GstStructure *config, const GstCaps *caps,
+                                                  guint size, guint min_buffers, guint max_buffers,
+                                                  guint prefix, guint align);
+gboolean         gst_buffer_pool_config_get      (GstStructure *config, const GstCaps **caps,
+                                                  guint *size, guint *min_buffers, guint *max_buffers,
+                                                  guint *prefix, guint *align);
+
+/* options */
+guint            gst_buffer_pool_config_n_options   (GstStructure *config);
+void             gst_buffer_pool_config_add_option  (GstStructure *config, const gchar *option);
+const gchar *    gst_buffer_pool_config_get_option  (GstStructure *config, guint index);
+gboolean         gst_buffer_pool_config_has_option  (GstStructure *config, const gchar *option);
+
+/* buffer management */
+GstFlowReturn    gst_buffer_pool_acquire_buffer  (GstBufferPool *pool, GstBuffer **buffer,
+                                                  GstBufferPoolParams *params);
+void             gst_buffer_pool_release_buffer  (GstBufferPool *pool, GstBuffer *buffer);
+
+G_END_DECLS
+
+#endif /* __GST_BUFFER_POOL_H__ */
index b80420b..efb5269 100644 (file)
@@ -75,6 +75,7 @@
 #include <sys/types.h>
 
 #include "gstinfo.h"
+#include "gstpoll.h"
 
 #include "gstbus.h"
 #include "glib-compat-private.h"
@@ -89,49 +90,56 @@ enum
   LAST_SIGNAL
 };
 
-static void gst_bus_dispose (GObject * object);
+#define DEFAULT_ENABLE_ASYNC (TRUE)
+
+enum
+{
+  PROP_0,
+  PROP_ENABLE_ASYNC
+};
 
-static void gst_bus_set_main_context (GstBus * bus, GMainContext * ctx);
+static void gst_bus_dispose (GObject * object);
 
-static GstObjectClass *parent_class = NULL;
 static guint gst_bus_signals[LAST_SIGNAL] = { 0 };
 
 struct _GstBusPrivate
 {
   guint num_sync_message_emitters;
-  GCond *queue_cond;
   GSource *watch_id;
-  GMainContext *main_context;
+
+  gboolean enable_async;
+  GstPoll *poll;
+  GPollFD pollfd;
 };
 
+#define gst_bus_parent_class parent_class
 G_DEFINE_TYPE (GstBus, gst_bus, GST_TYPE_OBJECT);
 
-/* fixme: do something about this */
 static void
-marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
-    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
-    gpointer marshal_data)
+gst_bus_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1,
-      gpointer data2);
-  register marshalfunc_VOID__MINIOBJECT callback;
-  register GCClosure *cc = (GCClosure *) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 2);
+  GstBus *bus = GST_BUS_CAST (object);
 
-  if (G_CCLOSURE_SWAP_DATA (closure)) {
-    data1 = closure->data;
-    data2 = g_value_peek_pointer (param_values + 0);
-  } else {
-    data1 = g_value_peek_pointer (param_values + 0);
-    data2 = closure->data;
+  switch (prop_id) {
+    case PROP_ENABLE_ASYNC:
+      bus->priv->enable_async = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
-  callback =
-      (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
-      cc->callback);
+}
+
+static void
+gst_bus_constructed (GObject * object)
+{
+  GstBus *bus = GST_BUS_CAST (object);
 
-  callback (data1, gst_value_get_mini_object (param_values + 1), data2);
+  if (bus->priv->enable_async) {
+    bus->priv->poll = gst_poll_new_timer ();
+    gst_poll_get_read_gpollfd (bus->priv->poll, &bus->priv->pollfd);
+  }
 }
 
 static void
@@ -139,9 +147,26 @@ gst_bus_class_init (GstBusClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
-
   gobject_class->dispose = gst_bus_dispose;
+  gobject_class->set_property = gst_bus_set_property;
+  gobject_class->constructed = gst_bus_constructed;
+
+  /* GstBus:enable-async:
+   *
+   * Enable async message delivery support for bus watches,
+   * gst_bus_pop() and similar API. Without this only the
+   * synchronous message handlers are called.
+   *
+   * This property is used to create the child element buses
+   * in #GstBin.
+   *
+   * Since: 0.10.33
+   */
+  g_object_class_install_property (gobject_class, PROP_ENABLE_ASYNC,
+      g_param_spec_boolean ("enable-async", "Enable Async",
+          "Enable async message delivery for bus watches and gst_bus_pop()",
+          DEFAULT_ENABLE_ASYNC,
+          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstBus::sync-message:
@@ -162,7 +187,7 @@ gst_bus_class_init (GstBusClass * klass)
       g_signal_new ("sync-message", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       G_STRUCT_OFFSET (GstBusClass, sync_message), NULL, NULL,
-      marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
+      g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 
   /**
    * GstBus::message:
@@ -177,7 +202,7 @@ gst_bus_class_init (GstBusClass * klass)
       g_signal_new ("message", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       G_STRUCT_OFFSET (GstBusClass, message), NULL, NULL,
-      marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
+      g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_MESSAGE);
 
   g_type_class_add_private (klass, sizeof (GstBusPrivate));
 }
@@ -185,11 +210,11 @@ gst_bus_class_init (GstBusClass * klass)
 static void
 gst_bus_init (GstBus * bus)
 {
-  bus->queue = g_queue_new ();
-  bus->queue_lock = g_mutex_new ();
+  bus->queue = gst_atomic_queue_new (32);
+  g_mutex_init (&bus->queue_lock);
 
   bus->priv = G_TYPE_INSTANCE_GET_PRIVATE (bus, GST_TYPE_BUS, GstBusPrivate);
-  bus->priv->queue_cond = g_cond_new ();
+  bus->priv->enable_async = DEFAULT_ENABLE_ASYNC;
 
   GST_DEBUG_OBJECT (bus, "created");
 }
@@ -202,65 +227,25 @@ gst_bus_dispose (GObject * object)
   if (bus->queue) {
     GstMessage *message;
 
-    g_mutex_lock (bus->queue_lock);
+    g_mutex_lock (&bus->queue_lock);
     do {
-      message = g_queue_pop_head (bus->queue);
+      message = gst_atomic_queue_pop (bus->queue);
       if (message)
         gst_message_unref (message);
     } while (message != NULL);
-    g_queue_free (bus->queue);
+    gst_atomic_queue_unref (bus->queue);
     bus->queue = NULL;
-    g_mutex_unlock (bus->queue_lock);
-    g_mutex_free (bus->queue_lock);
-    bus->queue_lock = NULL;
-    g_cond_free (bus->priv->queue_cond);
-    bus->priv->queue_cond = NULL;
-  }
+    g_mutex_unlock (&bus->queue_lock);
+    g_mutex_clear (&bus->queue_lock);
 
-  if (bus->priv->main_context) {
-    g_main_context_unref (bus->priv->main_context);
-    bus->priv->main_context = NULL;
+    if (bus->priv->poll)
+      gst_poll_free (bus->priv->poll);
+    bus->priv->poll = NULL;
   }
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
-static void
-gst_bus_wakeup_main_context (GstBus * bus)
-{
-  GMainContext *ctx;
-
-  GST_OBJECT_LOCK (bus);
-  if ((ctx = bus->priv->main_context))
-    g_main_context_ref (ctx);
-  GST_OBJECT_UNLOCK (bus);
-
-  g_main_context_wakeup (ctx);
-
-  if (ctx)
-    g_main_context_unref (ctx);
-}
-
-static void
-gst_bus_set_main_context (GstBus * bus, GMainContext * ctx)
-{
-  GST_OBJECT_LOCK (bus);
-
-  if (bus->priv->main_context != NULL) {
-    g_main_context_unref (bus->priv->main_context);
-    bus->priv->main_context = NULL;
-  }
-
-  if (ctx != NULL) {
-    bus->priv->main_context = g_main_context_ref (ctx);
-  }
-
-  GST_DEBUG_OBJECT (bus, "setting main context to %p, GLib default context: %p",
-      ctx, g_main_context_default ());
-
-  GST_OBJECT_UNLOCK (bus);
-}
-
 /**
  * gst_bus_new:
  *
@@ -302,10 +287,8 @@ gst_bus_post (GstBus * bus, GstMessage * message)
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
   g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
 
-  GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus, type %s, %" GST_PTR_FORMAT
-      " from source %" GST_PTR_FORMAT,
-      message, GST_MESSAGE_TYPE_NAME (message), message->structure,
-      message->src);
+  GST_DEBUG_OBJECT (bus, "[msg %p] posting on bus %" GST_PTR_FORMAT, message,
+      message);
 
   GST_OBJECT_LOCK (bus);
   /* check if the bus is flushing */
@@ -327,6 +310,11 @@ gst_bus_post (GstBus * bus, GstMessage * message)
       && handler != gst_bus_sync_signal_handler)
     gst_bus_sync_signal_handler (bus, message, NULL);
 
+  /* If this is a bus without async message delivery
+   * always drop the message */
+  if (!bus->priv->poll)
+    reply = GST_BUS_DROP;
+
   /* now see what we should do with the message */
   switch (reply) {
     case GST_BUS_DROP:
@@ -336,24 +324,20 @@ gst_bus_post (GstBus * bus, GstMessage * message)
     case GST_BUS_PASS:
       /* pass the message to the async queue, refcount passed in the queue */
       GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message);
-      g_mutex_lock (bus->queue_lock);
-      g_queue_push_tail (bus->queue, message);
-      g_cond_broadcast (bus->priv->queue_cond);
-      g_mutex_unlock (bus->queue_lock);
+      gst_atomic_queue_push (bus->queue, message);
+      gst_poll_write_control (bus->priv->poll);
       GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);
 
-      gst_bus_wakeup_main_context (bus);
-
       break;
     case GST_BUS_ASYNC:
     {
       /* async delivery, we need a mutex and a cond to block
        * on */
-      GMutex *lock = g_mutex_new ();
-      GCond *cond = g_cond_new ();
+      GCond *cond = GST_MESSAGE_GET_COND (message);
+      GMutex *lock = GST_MESSAGE_GET_LOCK (message);
 
-      GST_MESSAGE_COND (message) = cond;
-      GST_MESSAGE_GET_LOCK (message) = lock;
+      g_cond_init (cond);
+      g_mutex_init (lock);
 
       GST_DEBUG_OBJECT (bus, "[msg %p] waiting for async delivery", message);
 
@@ -361,12 +345,9 @@ gst_bus_post (GstBus * bus, GstMessage * message)
        * queue. When the message is handled by the app and destroyed,
        * the cond will be signalled and we can continue */
       g_mutex_lock (lock);
-      g_mutex_lock (bus->queue_lock);
-      g_queue_push_tail (bus->queue, message);
-      g_cond_broadcast (bus->priv->queue_cond);
-      g_mutex_unlock (bus->queue_lock);
 
-      gst_bus_wakeup_main_context (bus);
+      gst_atomic_queue_push (bus->queue, message);
+      gst_poll_write_control (bus->priv->poll);
 
       /* now block till the message is freed */
       g_cond_wait (cond, lock);
@@ -374,8 +355,8 @@ gst_bus_post (GstBus * bus, GstMessage * message)
 
       GST_DEBUG_OBJECT (bus, "[msg %p] delivered asynchronously", message);
 
-      g_mutex_free (lock);
-      g_cond_free (cond);
+      g_mutex_clear (lock);
+      g_cond_clear (cond);
       break;
     }
     default:
@@ -414,10 +395,8 @@ gst_bus_have_pending (GstBus * bus)
 
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
 
-  g_mutex_lock (bus->queue_lock);
   /* see if there is a message on the bus */
-  result = !g_queue_is_empty (bus->queue);
-  g_mutex_unlock (bus->queue_lock);
+  result = gst_atomic_queue_length (bus->queue) != 0;
 
   return result;
 }
@@ -483,18 +462,26 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
     GstMessageType types)
 {
   GstMessage *message;
-  GTimeVal *timeval, abstimeout;
+  GTimeVal now, then;
   gboolean first_round = TRUE;
+  GstClockTime elapsed = 0;
 
   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
   g_return_val_if_fail (types != 0, NULL);
+  g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL);
 
-  g_mutex_lock (bus->queue_lock);
+  g_mutex_lock (&bus->queue_lock);
 
   while (TRUE) {
-    GST_LOG_OBJECT (bus, "have %d messages", g_queue_get_length (bus->queue));
+    gint ret;
+
+    GST_LOG_OBJECT (bus, "have %d messages",
+        gst_atomic_queue_length (bus->queue));
+
+    while ((message = gst_atomic_queue_pop (bus->queue))) {
+      if (bus->priv->poll)
+        gst_poll_read_control (bus->priv->poll);
 
-    while ((message = g_queue_pop_head (bus->queue))) {
       GST_DEBUG_OBJECT (bus, "got message %p, %s from %s, type mask is %u",
           message, GST_MESSAGE_TYPE_NAME (message),
           GST_MESSAGE_SRC_NAME (message), (guint) types);
@@ -512,28 +499,27 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
     if (timeout == 0)
       break;
 
-    if (timeout == GST_CLOCK_TIME_NONE) {
-      /* wait forever */
-      timeval = NULL;
-    } else if (first_round) {
-      glong add = timeout / 1000;
-
-      if (add == 0)
-        /* no need to wait */
-        break;
-
-      /* make timeout absolute */
-      g_get_current_time (&abstimeout);
-      g_time_val_add (&abstimeout, add);
-      timeval = &abstimeout;
-      first_round = FALSE;
-      GST_DEBUG_OBJECT (bus, "blocking for message, timeout %ld", add);
-    } else {
-      /* calculated the absolute end time already, no need to do it again */
-      GST_DEBUG_OBJECT (bus, "blocking for message, again");
-      timeval = &abstimeout;    /* fool compiler */
+    else if (timeout != GST_CLOCK_TIME_NONE) {
+      if (first_round) {
+        g_get_current_time (&then);
+        first_round = FALSE;
+      } else {
+        g_get_current_time (&now);
+
+        elapsed = GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (then);
+
+        if (elapsed > timeout)
+          break;
+      }
     }
-    if (!g_cond_timed_wait (bus->priv->queue_cond, bus->queue_lock, timeval)) {
+
+    /* only here in timeout case */
+    g_assert (bus->priv->poll);
+    g_mutex_unlock (&bus->queue_lock);
+    ret = gst_poll_wait (bus->priv->poll, timeout - elapsed);
+    g_mutex_lock (&bus->queue_lock);
+
+    if (ret == 0) {
       GST_INFO_OBJECT (bus, "timed out, breaking loop");
       break;
     } else {
@@ -543,7 +529,7 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
 
 beach:
 
-  g_mutex_unlock (bus->queue_lock);
+  g_mutex_unlock (&bus->queue_lock);
 
   return message;
 }
@@ -645,11 +631,11 @@ gst_bus_peek (GstBus * bus)
 
   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
 
-  g_mutex_lock (bus->queue_lock);
-  message = g_queue_peek_head (bus->queue);
+  g_mutex_lock (&bus->queue_lock);
+  message = gst_atomic_queue_peek (bus->queue);
   if (message)
     gst_message_ref (message);
-  g_mutex_unlock (bus->queue_lock);
+  g_mutex_unlock (&bus->queue_lock);
 
   GST_DEBUG_OBJECT (bus, "peek on bus, got message %p", message);
 
@@ -704,24 +690,13 @@ typedef struct
 {
   GSource source;
   GstBus *bus;
-  gboolean inited;
 } GstBusSource;
 
 static gboolean
 gst_bus_source_prepare (GSource * source, gint * timeout)
 {
-  GstBusSource *bsrc = (GstBusSource *) source;
-
-  /* we do this here now that we know that we're attached to a main context
-   * (we don't support detaching a source from a main context and then
-   * re-attaching it to a different main context) */
-  if (G_UNLIKELY (!bsrc->inited)) {
-    gst_bus_set_main_context (bsrc->bus, g_source_get_context (source));
-    bsrc->inited = TRUE;
-  }
-
   *timeout = -1;
-  return gst_bus_have_pending (bsrc->bus);
+  return FALSE;
 }
 
 static gboolean
@@ -729,7 +704,7 @@ gst_bus_source_check (GSource * source)
 {
   GstBusSource *bsrc = (GstBusSource *) source;
 
-  return gst_bus_have_pending (bsrc->bus);
+  return bsrc->bus->priv->pollfd.revents & (G_IO_IN | G_IO_HUP | G_IO_ERR);
 }
 
 static gboolean
@@ -792,7 +767,6 @@ gst_bus_source_finalize (GSource * source)
     bus->priv->watch_id = NULL;
   GST_OBJECT_UNLOCK (bus);
 
-  gst_bus_set_main_context (bsource->bus, NULL);
   gst_object_unref (bsource->bus);
   bsource->bus = NULL;
 }
@@ -820,16 +794,15 @@ gst_bus_create_watch (GstBus * bus)
   GstBusSource *source;
 
   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
+  g_return_val_if_fail (bus->priv->poll != NULL, NULL);
 
   source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
       sizeof (GstBusSource));
 
-#if GLIB_CHECK_VERSION(2,26,0)
   g_source_set_name ((GSource *) source, "GStreamer message bus watch");
-#endif
 
   source->bus = gst_object_ref (bus);
-  source->inited = FALSE;
+  g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
 
   return (GSource *) source;
 }
@@ -893,7 +866,7 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
  * from @func.
  *
  * Returns: The event source id.
- *
+ * Rename to: gst_bus_add_watch
  * MT safe.
  */
 guint
@@ -912,7 +885,7 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
 }
 
 /**
- * gst_bus_add_watch:
+ * gst_bus_add_watch: (skip)
  * @bus: a #GstBus to create the watch for
  * @func: A function to call when a message is received.
  * @user_data: user data passed to @func.
index 30afe60..46ae371 100644 (file)
@@ -28,6 +28,7 @@ typedef struct _GstBusClass GstBusClass;
 
 #include <gst/gstmessage.h>
 #include <gst/gstclock.h>
+#include <gst/gstatomicqueue.h>
 
 G_BEGIN_DECLS
 
@@ -115,8 +116,8 @@ struct _GstBus
   GstObject         object;
 
   /*< private >*/
-  GQueue           *queue;
-  GMutex           *queue_lock;
+  GstAtomicQueue   *queue;
+  GMutex            queue_lock;
 
   GstBusSyncHandler sync_handler;
   gpointer          sync_handler_data;
@@ -126,7 +127,8 @@ struct _GstBus
 
   /*< private >*/
   GstBusPrivate    *priv;
-  gpointer _gst_reserved[GST_PADDING - 1];
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstBusClass
index ef3f8ff..3bfe62b 100644 (file)
@@ -43,8 +43,8 @@
  *  <title>Creating caps</title>
  *  <programlisting>
  *  GstCaps *caps;
- *  caps = gst_caps_new_simple ("video/x-raw-yuv",
- *       "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+ *  caps = gst_caps_new_simple ("video/x-raw",
+ *       "format", G_TYPE_STRING, "I420"),
  *       "framerate", GST_TYPE_FRACTION, 25, 1,
  *       "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
  *       "width", G_TYPE_INT, 320,
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
 
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#include <libxml/parser.h>
-xmlNodePtr gst_caps_save_thyself (const GstCaps * caps, xmlNodePtr parent);
-GstCaps *gst_caps_load_thyself (xmlNodePtr parent);
-#endif
-#endif
-
 #define DEBUG_REFCOUNT
 
-#define CAPS_POISON(caps) G_STMT_START{ \
-  if (caps) { \
-    GstCaps *_newcaps = gst_caps_copy (caps); \
-    gst_caps_unref(caps); \
-    caps = _newcaps; \
-  } \
-} G_STMT_END
-#define STRUCTURE_POISON(structure) G_STMT_START{ \
-  if (structure) { \
-    GstStructure *_newstruct = gst_structure_copy (structure); \
-    gst_structure_free(structure); \
-    structure = _newstruct; \
-  } \
-} G_STMT_END
+
+#define GST_CAPS_ARRAY(c) ((GPtrArray *)((c)->priv))
+
+#define GST_CAPS_LEN(c)   (GST_CAPS_ARRAY(c)->len)
+
 #define IS_WRITABLE(caps) \
-  (g_atomic_int_get (&(caps)->refcount) == 1)
+  (GST_CAPS_REFCOUNT_VALUE (caps) == 1)
 
 /* same as gst_caps_is_any () */
 #define CAPS_IS_ANY(caps)                              \
-  ((caps)->flags & GST_CAPS_FLAGS_ANY)
+  (GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY)
 
 /* same as gst_caps_is_empty () */
 #define CAPS_IS_EMPTY(caps)                            \
   (!CAPS_IS_ANY(caps) && CAPS_IS_EMPTY_SIMPLE(caps))
 
 #define CAPS_IS_EMPTY_SIMPLE(caps)                                     \
-  (((caps)->structs == NULL) || ((caps)->structs->len == 0))
+  ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0))
 
 /* quick way to get a caps structure at an index without doing a type or array
  * length check */
 #define gst_caps_get_structure_unchecked(caps, index) \
-     ((GstStructure *)g_ptr_array_index ((caps)->structs, (index)))
+     ((GstStructure *)g_ptr_array_index (GST_CAPS_ARRAY (caps), (index)))
 /* quick way to append a structure without checking the args */
 #define gst_caps_append_structure_unchecked(caps, structure) G_STMT_START{\
   GstStructure *__s=structure;                                      \
-  gst_structure_set_parent_refcount (__s, &caps->refcount);         \
-  g_ptr_array_add (caps->structs, __s);                             \
+  if (gst_structure_set_parent_refcount (__s, &GST_MINI_OBJECT_REFCOUNT(caps)))         \
+    g_ptr_array_add (GST_CAPS_ARRAY (caps), __s);                             \
 }G_STMT_END
 
 /* lock to protect multiple invocations of static caps to caps conversion */
@@ -129,26 +112,87 @@ static void gst_caps_transform_to_string (const GValue * src_value,
     GValue * dest_value);
 static gboolean gst_caps_from_string_inplace (GstCaps * caps,
     const gchar * string);
-static GstCaps *gst_caps_copy_conditional (GstCaps * src);
 
-GType
-gst_caps_get_type (void)
+GType _gst_caps_type = 0;
+GstCaps *_gst_caps_any;
+GstCaps *_gst_caps_none;
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps);
+
+void
+_priv_gst_caps_initialize (void)
 {
-  static GType gst_caps_type = 0;
+  _gst_caps_type = gst_caps_get_type ();
 
-  if (G_UNLIKELY (gst_caps_type == 0)) {
-    gst_caps_type = g_boxed_type_register_static ("GstCaps",
-        (GBoxedCopyFunc) gst_caps_copy_conditional,
-        (GBoxedFreeFunc) gst_caps_unref);
+  _gst_caps_any = gst_caps_new_any ();
+  _gst_caps_none = gst_caps_new_empty ();
+
+  g_value_register_transform_func (_gst_caps_type,
+      G_TYPE_STRING, gst_caps_transform_to_string);
+}
 
-    g_value_register_transform_func (gst_caps_type,
-        G_TYPE_STRING, gst_caps_transform_to_string);
+static GstCaps *
+_gst_caps_copy (const GstCaps * caps)
+{
+  GstCaps *newcaps;
+  GstStructure *structure;
+  guint i, n;
+
+  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
+
+  newcaps = gst_caps_new_empty ();
+  GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
+  n = GST_CAPS_LEN (caps);
+
+  for (i = 0; i < n; i++) {
+    structure = gst_caps_get_structure_unchecked (caps, i);
+    gst_caps_append_structure (newcaps, gst_structure_copy (structure));
   }
 
-  return gst_caps_type;
+  return newcaps;
 }
 
 /* creation/deletion */
+static void
+_gst_caps_free (GstCaps * caps)
+{
+  GstStructure *structure;
+  guint i, len;
+
+  /* The refcount must be 0, but since we're only called by gst_caps_unref,
+   * don't bother testing. */
+  len = GST_CAPS_LEN (caps);
+  /* This can be used to get statistics about caps sizes */
+  /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
+  for (i = 0; i < len; i++) {
+    structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
+    gst_structure_set_parent_refcount (structure, NULL);
+    gst_structure_free (structure);
+  }
+  g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE);
+
+#ifdef DEBUG_REFCOUNT
+  GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
+#endif
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (caps), caps);
+}
+
+static void
+gst_caps_init (GstCaps * caps, gsize size)
+{
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), _gst_caps_type, size);
+
+  caps->mini_object.copy = (GstMiniObjectCopyFunction) _gst_caps_copy;
+  caps->mini_object.dispose = NULL;
+  caps->mini_object.free = (GstMiniObjectFreeFunction) _gst_caps_free;
+
+  /* the 32 has been determined by logging caps sizes in _gst_caps_free
+   * but g_ptr_array uses 16 anyway if it expands once, so this does not help
+   * in practise
+   * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32);
+   */
+  caps->priv = g_ptr_array_new ();
+}
 
 /**
  * gst_caps_new_empty:
@@ -162,17 +206,11 @@ gst_caps_get_type (void)
 GstCaps *
 gst_caps_new_empty (void)
 {
-  GstCaps *caps = g_slice_new (GstCaps);
+  GstCaps *caps;
 
-  caps->type = GST_TYPE_CAPS;
-  caps->refcount = 1;
-  caps->flags = GST_CAPS_FLAGS_NONE;
-  caps->structs = g_ptr_array_new ();
-  /* the 32 has been determined by logging caps sizes in _gst_caps_free
-   * but g_ptr_array uses 16 anyway if it expands once, so this does not help
-   * in practise
-   * caps->structs = g_ptr_array_sized_new (32);
-   */
+  caps = g_slice_new (GstCaps);
+
+  gst_caps_init (caps, sizeof (GstCaps));
 
 #ifdef DEBUG_REFCOUNT
   GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps);
@@ -194,7 +232,31 @@ gst_caps_new_any (void)
 {
   GstCaps *caps = gst_caps_new_empty ();
 
-  caps->flags = GST_CAPS_FLAGS_ANY;
+  GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY);
+
+  return caps;
+}
+
+/**
+ * gst_caps_new_empty_simple:
+ * @media_type: the media type of the structure
+ *
+ * Creates a new #GstCaps that contains one #GstStructure with name
+ * @media_type.
+ * Caller is responsible for unreffing the returned caps.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ */
+GstCaps *
+gst_caps_new_empty_simple (const char *media_type)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+
+  caps = gst_caps_new_empty ();
+  structure = gst_structure_new_empty (media_type);
+  if (structure)
+    gst_caps_append_structure_unchecked (caps, structure);
 
   return caps;
 }
@@ -283,162 +345,6 @@ gst_caps_new_full_valist (GstStructure * structure, va_list var_args)
   return caps;
 }
 
-/**
- * gst_caps_copy:
- * @caps: the #GstCaps to copy
- *
- * Creates a new #GstCaps as a copy of the old @caps. The new caps will have a
- * refcount of 1, owned by the caller. The structures are copied as well.
- *
- * Note that this function is the semantic equivalent of a gst_caps_ref()
- * followed by a gst_caps_make_writable(). If you only want to hold on to a
- * reference to the data, you should use gst_caps_ref().
- *
- * When you are finished with the caps, call gst_caps_unref() on it.
- *
- * Returns: (transfer full): the new #GstCaps
- */
-GstCaps *
-gst_caps_copy (const GstCaps * caps)
-{
-  GstCaps *newcaps;
-  GstStructure *structure;
-  guint i, n;
-
-  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
-
-  newcaps = gst_caps_new_empty ();
-  newcaps->flags = caps->flags;
-  n = caps->structs->len;
-
-  for (i = 0; i < n; i++) {
-    structure = gst_caps_get_structure_unchecked (caps, i);
-    gst_caps_append_structure_unchecked (newcaps,
-        gst_structure_copy (structure));
-  }
-
-  return newcaps;
-}
-
-static void
-_gst_caps_free (GstCaps * caps)
-{
-  GstStructure *structure;
-  guint i, len;
-
-  /* The refcount must be 0, but since we're only called by gst_caps_unref,
-   * don't bother testing. */
-  len = caps->structs->len;
-  /* This can be used to get statistics about caps sizes */
-  /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
-  for (i = 0; i < len; i++) {
-    structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
-    gst_structure_set_parent_refcount (structure, NULL);
-    gst_structure_free (structure);
-  }
-  g_ptr_array_free (caps->structs, TRUE);
-#ifdef USE_POISONING
-  memset (caps, 0xff, sizeof (GstCaps));
-#endif
-
-#ifdef DEBUG_REFCOUNT
-  GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps);
-#endif
-  g_slice_free (GstCaps, caps);
-}
-
-/**
- * gst_caps_make_writable:
- * @caps: (transfer full): the #GstCaps to make writable
- *
- * Returns a writable copy of @caps.
- *
- * If there is only one reference count on @caps, the caller must be the owner,
- * and so this function will return the caps object unchanged. If on the other
- * hand there is more than one reference on the object, a new caps object will
- * be returned. The caller's reference on @caps will be removed, and instead the
- * caller will own a reference to the returned object.
- *
- * In short, this function unrefs the caps in the argument and refs the caps
- * that it returns. Don't access the argument after calling this function. See
- * also: gst_caps_ref().
- *
- * Returns: (transfer full): the same #GstCaps object.
- */
-GstCaps *
-gst_caps_make_writable (GstCaps * caps)
-{
-  GstCaps *copy;
-
-  g_return_val_if_fail (caps != NULL, NULL);
-
-  /* we are the only instance reffing this caps */
-  if (IS_WRITABLE (caps))
-    return caps;
-
-  /* else copy */
-  GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy caps");
-  copy = gst_caps_copy (caps);
-  gst_caps_unref (caps);
-
-  return copy;
-}
-
-/**
- * gst_caps_ref:
- * @caps: the #GstCaps to reference
- *
- * Add a reference to a #GstCaps object.
- *
- * From this point on, until the caller calls gst_caps_unref() or
- * gst_caps_make_writable(), it is guaranteed that the caps object will not
- * change. This means its structures won't change, etc. To use a #GstCaps
- * object, you must always have a refcount on it -- either the one made
- * implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with
- * this function.
- *
- * Returns: (transfer full): the same #GstCaps object.
- */
-GstCaps *
-gst_caps_ref (GstCaps * caps)
-{
-  g_return_val_if_fail (caps != NULL, NULL);
-
-#ifdef DEBUG_REFCOUNT
-  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p %d->%d", caps,
-      GST_CAPS_REFCOUNT_VALUE (caps), GST_CAPS_REFCOUNT_VALUE (caps) + 1);
-#endif
-  g_return_val_if_fail (GST_CAPS_REFCOUNT_VALUE (caps) > 0, NULL);
-
-  g_atomic_int_inc (&caps->refcount);
-
-  return caps;
-}
-
-/**
- * gst_caps_unref:
- * @caps: (transfer full): the #GstCaps to unref
- *
- * Unref a #GstCaps and free all its structures and the
- * structures' values when the refcount reaches 0.
- */
-void
-gst_caps_unref (GstCaps * caps)
-{
-  g_return_if_fail (caps != NULL);
-
-#ifdef DEBUG_REFCOUNT
-  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p %d->%d", caps,
-      GST_CAPS_REFCOUNT_VALUE (caps), GST_CAPS_REFCOUNT_VALUE (caps) - 1);
-#endif
-
-  g_return_if_fail (GST_CAPS_REFCOUNT_VALUE (caps) > 0);
-
-  /* if we ended up with the refcount at zero, free the caps */
-  if (G_UNLIKELY (g_atomic_int_dec_and_test (&caps->refcount)))
-    _gst_caps_free (caps);
-}
-
 GType
 gst_static_caps_get_type (void)
 {
@@ -471,13 +377,13 @@ gst_static_caps_get (GstStaticCaps * static_caps)
   caps = (GstCaps *) static_caps;
 
   /* refcount is 0 when we need to convert */
-  if (G_UNLIKELY (g_atomic_int_get (&caps->refcount) == 0)) {
+  if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) == 0)) {
     const char *string;
     GstCaps temp;
 
     G_LOCK (static_caps_lock);
     /* check if other thread already updated */
-    if (G_UNLIKELY (g_atomic_int_get (&caps->refcount) > 0))
+    if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) > 0))
       goto done;
 
     string = static_caps->string;
@@ -491,24 +397,15 @@ gst_static_caps_get (GstStaticCaps * static_caps)
      * real caps, refcount last. We do this because we must leave the refcount
      * of the result caps to 0 so that other threads don't run away with the
      * caps while we are constructing it. */
-    temp.type = GST_TYPE_CAPS;
-    temp.flags = GST_CAPS_FLAGS_NONE;
-    temp.structs = g_ptr_array_new ();
-
-    /* initialize the caps to a refcount of 1 so the caps can be writable for
-     * the next statement */
-    temp.refcount = 1;
+    gst_caps_init (&temp, sizeof (GstCaps));
 
     /* convert to string */
     if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string)))
       g_critical ("Could not convert static caps \"%s\"", string);
 
-    /* now copy stuff over to the real caps. */
-    caps->type = temp.type;
-    caps->flags = temp.flags;
-    caps->structs = temp.structs;
-    /* and bump the refcount so other threads can now read */
-    g_atomic_int_set (&caps->refcount, 1);
+    GST_MINI_OBJECT_REFCOUNT (&temp) = 0;
+    memcpy (caps, &temp, sizeof (GstCaps));
+    gst_caps_ref (caps);
 
     GST_CAT_TRACE (GST_CAT_CAPS, "created %p", static_caps);
   done:
@@ -528,13 +425,41 @@ no_string:
   }
 }
 
+/**
+ * gst_static_caps_cleanup:
+ * @static_caps: the #GstStaticCaps to convert
+ *
+ * Clean up the caps contained in @static_caps when the refcount is 0.
+ */
+void
+gst_static_caps_cleanup (GstStaticCaps * static_caps)
+{
+  GstCaps *caps = (GstCaps *) static_caps;
+
+  /* FIXME: this is not threadsafe */
+  if (GST_CAPS_REFCOUNT_VALUE (caps) == 1) {
+    GstStructure *structure;
+    guint i, clen;
+
+    clen = GST_CAPS_LEN (caps);
+
+    for (i = 0; i < clen; i++) {
+      structure = (GstStructure *) gst_caps_get_structure (caps, i);
+      gst_structure_set_parent_refcount (structure, NULL);
+      gst_structure_free (structure);
+    }
+    g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE);
+    GST_CAPS_REFCOUNT (caps) = 0;
+  }
+}
+
 /* manipulation */
 
 static GstStructure *
 gst_caps_remove_and_get_structure (GstCaps * caps, guint idx)
 {
   /* don't use index_fast, gst_caps_do_simplify relies on the order */
-  GstStructure *s = g_ptr_array_remove_index (caps->structs, idx);
+  GstStructure *s = g_ptr_array_remove_index (GST_CAPS_ARRAY (caps), idx);
 
   gst_structure_set_parent_refcount (s, NULL);
   return s;
@@ -559,7 +484,7 @@ gst_caps_steal_structure (GstCaps * caps, guint index)
   g_return_val_if_fail (caps != NULL, NULL);
   g_return_val_if_fail (IS_WRITABLE (caps), NULL);
 
-  if (G_UNLIKELY (index >= caps->structs->len))
+  if (G_UNLIKELY (index >= GST_CAPS_LEN (caps)))
     return NULL;
 
   return gst_caps_remove_and_get_structure (caps, index);
@@ -586,18 +511,15 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
 
   caps2 = gst_caps_make_writable (caps2);
 
-#ifdef USE_POISONING
-  CAPS_POISON (caps2);
-#endif
   if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
     /* FIXME: this leaks */
-    caps1->flags |= GST_CAPS_FLAGS_ANY;
-    for (i = caps2->structs->len - 1; i >= 0; i--) {
+    GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
+    for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, i);
       gst_structure_free (structure);
     }
   } else {
-    for (i = caps2->structs->len; i; i--) {
+    for (i = GST_CAPS_LEN (caps2); i; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, 0);
       gst_caps_append_structure_unchecked (caps1, structure);
     }
@@ -629,22 +551,19 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
 
   caps2 = gst_caps_make_writable (caps2);
 
-#ifdef USE_POISONING
-  CAPS_POISON (caps2);
-#endif
   if (G_UNLIKELY (CAPS_IS_ANY (caps1))) {
-    for (i = caps2->structs->len - 1; i >= 0; i--) {
+    for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, i);
       gst_structure_free (structure);
     }
   } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) {
-    caps1->flags |= GST_CAPS_FLAGS_ANY;
-    for (i = caps1->structs->len - 1; i >= 0; i--) {
+    GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
+    for (i = GST_CAPS_LEN (caps1) - 1; i >= 0; i--) {
       structure = gst_caps_remove_and_get_structure (caps1, i);
       gst_structure_free (structure);
     }
   } else {
-    for (i = caps2->structs->len; i; i--) {
+    for (i = GST_CAPS_LEN (caps2); i; i--) {
       structure = gst_caps_remove_and_get_structure (caps2, 0);
       gst_caps_merge_structure (caps1, structure);
     }
@@ -676,12 +595,6 @@ gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
   g_return_if_fail (IS_WRITABLE (caps));
 
   if (G_LIKELY (structure)) {
-    g_return_if_fail (structure->parent_refcount == NULL);
-#if 0
-#ifdef USE_POISONING
-    STRUCTURE_POISON (structure);
-#endif
-#endif
     gst_caps_append_structure_unchecked (caps, structure);
   }
 }
@@ -726,14 +639,8 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
     int i;
     gboolean unique = TRUE;
 
-    g_return_if_fail (structure->parent_refcount == NULL);
-#if 0
-#ifdef USE_POISONING
-    STRUCTURE_POISON (structure);
-#endif
-#endif
     /* check each structure */
-    for (i = caps->structs->len - 1; i >= 0; i--) {
+    for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
       structure1 = gst_caps_get_structure_unchecked (caps, i);
       /* if structure is a subset of structure1, then skip it */
       if (gst_structure_is_subset (structure, structure1)) {
@@ -762,7 +669,7 @@ gst_caps_get_size (const GstCaps * caps)
 {
   g_return_val_if_fail (GST_IS_CAPS (caps), 0);
 
-  return caps->structs->len;
+  return GST_CAPS_LEN (caps);
 }
 
 /**
@@ -792,7 +699,7 @@ GstStructure *
 gst_caps_get_structure (const GstCaps * caps, guint index)
 {
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
-  g_return_val_if_fail (index < caps->structs->len, NULL);
+  g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
 
   return gst_caps_get_structure_unchecked (caps, index);
 }
@@ -816,9 +723,9 @@ gst_caps_copy_nth (const GstCaps * caps, guint nth)
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
   newcaps = gst_caps_new_empty ();
-  newcaps->flags = caps->flags;
+  GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
 
-  if (G_LIKELY (caps->structs->len > nth)) {
+  if (G_LIKELY (GST_CAPS_LEN (caps) > nth)) {
     structure = gst_caps_get_structure_unchecked (caps, nth);
     gst_caps_append_structure_unchecked (newcaps,
         gst_structure_copy (structure));
@@ -842,7 +749,7 @@ gst_caps_truncate (GstCaps * caps)
   g_return_if_fail (GST_IS_CAPS (caps));
   g_return_if_fail (IS_WRITABLE (caps));
 
-  i = caps->structs->len - 1;
+  i = GST_CAPS_LEN (caps) - 1;
 
   while (i > 0)
     gst_caps_remove_structure (caps, i--);
@@ -870,7 +777,7 @@ gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value)
   g_return_if_fail (field != NULL);
   g_return_if_fail (G_IS_VALUE (value));
 
-  len = caps->structs->len;
+  len = GST_CAPS_LEN (caps);
   for (i = 0; i < len; i++) {
     GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
     gst_structure_set_value (structure, field, value);
@@ -904,10 +811,6 @@ gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
 
     type = va_arg (varargs, GType);
 
-    if (G_UNLIKELY (type == G_TYPE_DATE)) {
-      g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
-      type = GST_TYPE_DATE;
-    }
     G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
     if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
@@ -1009,7 +912,7 @@ gst_caps_is_fixed (const GstCaps * caps)
 
   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
 
-  if (caps->structs->len != 1)
+  if (GST_CAPS_LEN (caps) != 1)
     return FALSE;
 
   structure = gst_caps_get_structure_unchecked (caps, 0);
@@ -1087,8 +990,8 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
   if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
     return FALSE;
 
-  for (i = subset->structs->len - 1; i >= 0; i--) {
-    for (j = superset->structs->len - 1; j >= 0; j--) {
+  for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) {
+    for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
       s1 = gst_caps_get_structure_unchecked (subset, i);
       s2 = gst_caps_get_structure_unchecked (superset, j);
       if (gst_structure_is_subset (s1, s2)) {
@@ -1135,7 +1038,7 @@ gst_caps_is_subset_structure (const GstCaps * caps,
   if (CAPS_IS_EMPTY (caps))
     return FALSE;
 
-  for (i = caps->structs->len - 1; i >= 0; i--) {
+  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
     s = gst_caps_get_structure_unchecked (caps, i);
     if (gst_structure_is_subset (structure, s)) {
       /* If we found a superset return TRUE */
@@ -1209,10 +1112,10 @@ gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
   if (G_UNLIKELY (caps1 == NULL || caps2 == NULL))
     return FALSE;
 
-  if (caps1->structs->len != caps2->structs->len)
+  if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
     return FALSE;
 
-  for (i = 0; i < caps1->structs->len; i++) {
+  for (i = 0; i < GST_CAPS_LEN (caps1); i++) {
     if (!gst_structure_is_equal (gst_caps_get_structure_unchecked (caps1, i),
             gst_caps_get_structure_unchecked (caps2, i)))
       return FALSE;
@@ -1275,8 +1178,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
    * structures. The result is that the intersections are ordered based on the
    * sum of the indexes in the list.
    */
-  len1 = caps1->structs->len;
-  len2 = caps2->structs->len;
+  len1 = GST_CAPS_LEN (caps1);
+  len2 = GST_CAPS_LEN (caps2);
   for (i = 0; i < len1 + len2 - 1; i++) {
     /* superset index goes from 0 to sgst_caps_structure_intersectuperset->structs->len-1 */
     j = MIN (i, len1 - 1);
@@ -1316,7 +1219,7 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
 
   /* caps are exactly the same pointers, just copy one caps */
   if (G_UNLIKELY (caps1 == caps2))
-    return gst_caps_copy (caps1);
+    return _gst_caps_copy (caps1);
 
   /* empty caps on either side, return empty */
   if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2)))
@@ -1324,9 +1227,9 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
 
   /* one of the caps is any, just copy the other caps */
   if (G_UNLIKELY (CAPS_IS_ANY (caps1)))
-    return gst_caps_copy (caps2);
+    return _gst_caps_copy (caps2);
   if (G_UNLIKELY (CAPS_IS_ANY (caps2)))
-    return gst_caps_copy (caps1);
+    return _gst_caps_copy (caps1);
 
   dest = gst_caps_new_empty ();
 
@@ -1346,13 +1249,13 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
    * the structures diagonally down, then we iterate over the caps2
    * structures.
    */
-  len1 = caps1->structs->len;
-  len2 = caps2->structs->len;
+  len1 = GST_CAPS_LEN (caps1);
+  len2 = GST_CAPS_LEN (caps2);
   for (i = 0; i < len1 + len2 - 1; i++) {
-    /* caps1 index goes from 0 to caps1->structs->len-1 */
+    /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */
     j = MIN (i, len1 - 1);
-    /* caps2 index stays 0 until i reaches caps1->structs->len, then it counts
-     * up from 1 to caps2->structs->len - 1 */
+    /* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts
+     * up from 1 to GST_CAPS_LEN (caps2) - 1 */
     k = (i > j) ? (i - j) : 0;  /* MAX (0, i - j) */
 
     /* now run the diagonal line, end condition is the left or bottom
@@ -1414,8 +1317,8 @@ gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2)
 
   dest = gst_caps_new_empty ();
 
-  len1 = caps1->structs->len;
-  len2 = caps2->structs->len;
+  len1 = GST_CAPS_LEN (caps1);
+  len2 = GST_CAPS_LEN (caps2);
   for (i = 0; i < len1; i++) {
     struct1 = gst_caps_get_structure_unchecked (caps1, i);
     for (j = 0; j < len2; j++) {
@@ -1564,7 +1467,7 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
     return gst_caps_new_empty ();
   }
   if (CAPS_IS_EMPTY_SIMPLE (subtrahend))
-    return gst_caps_copy (minuend);
+    return _gst_caps_copy (minuend);
 
   /* FIXME: Do we want this here or above?
      The reason we need this is that there is no definition about what
@@ -1572,10 +1475,10 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
      You can only remove everything or nothing and that is done above.
      Note: there's a test that checks this behaviour. */
   g_return_val_if_fail (!CAPS_IS_ANY (minuend), NULL);
-  sublen = subtrahend->structs->len;
+  sublen = GST_CAPS_LEN (subtrahend);
   g_assert (sublen > 0);
 
-  src = gst_caps_copy (minuend);
+  src = _gst_caps_copy (minuend);
   for (i = 0; i < sublen; i++) {
     guint srclen;
 
@@ -1585,7 +1488,7 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
       src = dest;
     }
     dest = gst_caps_new_empty ();
-    srclen = src->structs->len;
+    srclen = GST_CAPS_LEN (src);
     for (j = 0; j < srclen; j++) {
       min = gst_caps_get_structure_unchecked (src, j);
       if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) {
@@ -1635,7 +1538,7 @@ gst_caps_structure_union (const GstStructure * struct1,
   if (struct1->name != struct2->name)
     return NULL;
 
-  dest = gst_structure_id_empty_new (struct1->name);
+  dest = gst_structure_new_id_empty (struct1->name);
 
   for (i = 0; i < struct1->fields->len; i++) {
     GValue dest_value = { 0 };
@@ -1680,16 +1583,16 @@ gst_caps_union (const GstCaps * caps1, const GstCaps * caps2)
   g_return_val_if_fail (caps2 != NULL, NULL);
 
   if (CAPS_IS_EMPTY (caps1))
-    return gst_caps_copy (caps2);
+    return _gst_caps_copy (caps2);
 
   if (CAPS_IS_EMPTY (caps2))
-    return gst_caps_copy (caps1);
+    return _gst_caps_copy (caps1);
 
   if (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))
     return gst_caps_new_any ();
 
-  dest1 = gst_caps_copy (caps1);
-  dest2 = gst_caps_copy (caps2);
+  dest1 = _gst_caps_copy (caps1);
+  dest2 = _gst_caps_copy (caps2);
   gst_caps_append (dest1, dest2);
 
   gst_caps_do_simplify (dest1);
@@ -1750,7 +1653,7 @@ gst_caps_normalize (const GstCaps * caps)
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
-  newcaps = gst_caps_copy (caps);
+  newcaps = _gst_caps_copy (caps);
   nf.caps = newcaps;
 
   for (i = 0; i < gst_caps_get_size (newcaps); i++) {
@@ -1876,8 +1779,8 @@ gst_caps_switch_structures (GstCaps * caps, GstStructure * old,
 {
   gst_structure_set_parent_refcount (old, NULL);
   gst_structure_free (old);
-  gst_structure_set_parent_refcount (new, &caps->refcount);
-  g_ptr_array_index (caps->structs, i) = new;
+  gst_structure_set_parent_refcount (new, &GST_CAPS_REFCOUNT (caps));
+  g_ptr_array_index (GST_CAPS_ARRAY (caps), i) = new;
 }
 
 /**
@@ -1904,10 +1807,10 @@ gst_caps_do_simplify (GstCaps * caps)
   if (gst_caps_get_size (caps) < 2)
     return FALSE;
 
-  g_ptr_array_sort (caps->structs, gst_caps_compare_structures);
+  g_ptr_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures);
 
-  start = caps->structs->len - 1;
-  for (i = caps->structs->len - 1; i >= 0; i--) {
+  start = GST_CAPS_LEN (caps) - 1;
+  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
     simplify = gst_caps_get_structure_unchecked (caps, i);
     if (gst_structure_get_name_id (simplify) !=
         gst_structure_get_name_id (gst_caps_get_structure_unchecked (caps,
@@ -1942,84 +1845,31 @@ gst_caps_do_simplify (GstCaps * caps)
   return TRUE;
 }
 
-/* persistence */
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
 /**
- * gst_caps_save_thyself:
- * @caps: a #GstCaps structure
- * @parent: a XML parent node
- *
- * Serializes a #GstCaps to XML and adds it as a child node of @parent.
+ * gst_caps_fixate:
+ * @caps: a #GstCaps to fixate
  *
- * Returns: a XML node pointer
+ * Modifies the given @caps inplace into a representation with only fixed
+ * values. First the caps will be truncated and then the first structure will be
+ * fixated with gst_structure_fixate(). @caps should be writable.
  */
-xmlNodePtr
-gst_caps_save_thyself (const GstCaps * caps, xmlNodePtr parent)
+void
+gst_caps_fixate (GstCaps * caps)
 {
-  char *s = gst_caps_to_string (caps);
-
-  xmlNewChild (parent, NULL, (xmlChar *) "caps", (xmlChar *) s);
-  g_free (s);
-  return parent;
-}
+  GstStructure *s;
 
-/**
- * gst_caps_load_thyself:
- * @parent: a XML node
- *
- * Creates a #GstCaps from its XML serialization.
- *
- * Returns: a new #GstCaps structure
- */
-GstCaps *
-gst_caps_load_thyself (xmlNodePtr parent)
-{
-  if (strcmp ("caps", (char *) parent->name) == 0) {
-    return gst_caps_from_string ((gchar *) xmlNodeGetContent (parent));
-  }
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
 
-  return NULL;
+  /* default fixation */
+  gst_caps_truncate (caps);
+  s = gst_caps_get_structure (caps, 0);
+  gst_structure_fixate (s);
 }
-#endif
 
 /* utility */
 
 /**
- * gst_caps_replace:
- * @caps: (inout) (transfer full): a pointer to #GstCaps
- * @newcaps: a #GstCaps to replace *caps
- *
- * Replaces *caps with @newcaps.  Unrefs the #GstCaps in the location
- * pointed to by @caps, if applicable, then modifies @caps to point to
- * @newcaps. An additional ref on @newcaps is taken.
- *
- * This function does not take any locks so you might want to lock
- * the object owning @caps pointer.
- */
-void
-gst_caps_replace (GstCaps ** caps, GstCaps * newcaps)
-{
-  GstCaps *oldcaps;
-
-  g_return_if_fail (caps != NULL);
-
-  oldcaps = *caps;
-
-  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p, %p -> %p", caps, oldcaps, newcaps);
-
-  if (newcaps != oldcaps) {
-    if (newcaps)
-      gst_caps_ref (newcaps);
-
-    *caps = newcaps;
-
-    if (oldcaps)
-      gst_caps_unref (oldcaps);
-  }
-}
-
-/**
  * gst_caps_to_string:
  * @caps: a #GstCaps
  *
@@ -2058,7 +1908,7 @@ gst_caps_to_string (const GstCaps * caps)
 
   /* estimate a rough string length to avoid unnecessary reallocs in GString */
   slen = 0;
-  clen = caps->structs->len;
+  clen = GST_CAPS_LEN (caps);
   for (i = 0; i < clen; i++) {
     slen +=
         STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked (caps,
@@ -2091,7 +1941,7 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
   gchar *s;
 
   if (strcmp ("ANY", string) == 0) {
-    caps->flags = GST_CAPS_FLAGS_ANY;
+    GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY;
     return TRUE;
   }
   if (strcmp ("EMPTY", string) == 0) {
@@ -2158,13 +2008,3 @@ gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
   g_value_take_string (dest_value,
       gst_caps_to_string (gst_value_get_caps (src_value)));
 }
-
-static GstCaps *
-gst_caps_copy_conditional (GstCaps * src)
-{
-  if (src) {
-    return gst_caps_ref (src);
-  } else {
-    return NULL;
-  }
-}
index 17103e2..3204716 100644 (file)
 #define __GST_CAPS_H__
 
 #include <gst/gstconfig.h>
+#include <gst/gstminiobject.h>
 #include <gst/gststructure.h>
 #include <gst/glib-compat.h>
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_CAPS             (gst_caps_get_type())
-#define GST_CAPS(object)          ((GstCaps*)object)
-#define GST_IS_CAPS(object)       ((object) && (GST_CAPS(object)->type == GST_TYPE_CAPS))
+GST_EXPORT GType _gst_caps_type;
+
+#define GST_TYPE_CAPS             (_gst_caps_type)
+#define GST_IS_CAPS(obj)          (GST_IS_MINI_OBJECT_TYPE((obj), GST_TYPE_CAPS))
+#define GST_CAPS_CAST(obj)        ((GstCaps*)(obj))
+#define GST_CAPS(obj)             (GST_CAPS_CAST(obj))
 
 #define GST_TYPE_STATIC_CAPS      (gst_static_caps_get_type())
 
 /**
  * GstCapsFlags:
- * @GST_CAPS_FLAGS_NONE: no extra flags (Since 0.10.36)
- * @GST_CAPS_FLAGS_ANY: Caps has no specific content, but can contain
+ * @GST_CAPS_FLAG_ANY: Caps has no specific content, but can contain
  *    anything.
  *
  * Extra flags for a caps.
  */
 typedef enum {
-  GST_CAPS_FLAGS_NONE = 0,
-  GST_CAPS_FLAGS_ANY   = (1 << 0)
+  GST_CAPS_FLAG_ANY    = (GST_MINI_OBJECT_FLAG_LAST << 0)
 } GstCapsFlags;
 
 /**
@@ -81,16 +83,18 @@ typedef enum {
  * GST_CAPS_ANY:
  *
  * Means that the element/pad can output 'anything'. Useful for elements
- * that output unknown media, such as filesrc.
+ * that output unknown media, such as filesrc. This macro returns a singleton and
+ * should not be unreffed.
  */
-#define GST_CAPS_ANY              gst_caps_new_any()
+#define GST_CAPS_ANY              _gst_caps_any
 /**
  * GST_CAPS_NONE:
  *
  * The opposite of %GST_CAPS_ANY: it means that the pad/element outputs an
- * undefined media type that can not be detected.
+ * undefined media type that can not be detected. This macro returns a singleton
+ * and should not be unreffed.
  */
-#define GST_CAPS_NONE             gst_caps_new_empty()
+#define GST_CAPS_NONE             _gst_caps_none
 
 /**
  * GST_STATIC_CAPS_ANY:
@@ -116,21 +120,6 @@ typedef enum {
  */
 #define GST_CAPS_IS_SIMPLE(caps) (gst_caps_get_size(caps) == 1)
 
-#ifndef GST_DISABLE_DEPRECATED
-/**
- * GST_DEBUG_CAPS:
- * @string: a string that should be prepended to the caps data.
- * @caps: the #GstCaps instance to print
- *
- * Convenience macro for printing out the contents of caps with GST_DEBUG().
- *
- * Deprecated: do not use anymore
- */
-#define GST_DEBUG_CAPS(string, caps) \
-  GST_DEBUG ( string "%s: " GST_PTR_FORMAT, caps)
-
-#endif /* GST_DISABLE_DEPRECATED */
-
 /**
  * GST_STATIC_CAPS:
  * @string: the string describing the caps
@@ -140,7 +129,8 @@ typedef enum {
  */
 #define GST_STATIC_CAPS(string) \
 { \
-  /* caps */ { 0, 0, (GstCapsFlags) 0, NULL, GST_PADDING_INIT }, \
+  /* miniobject */ { { 0, 0, 0, 0, NULL, NULL, NULL, 0, NULL }, \
+  /* caps */ NULL }, \
   /* string */ string, \
   GST_PADDING_INIT \
 }
@@ -148,6 +138,16 @@ typedef enum {
 typedef struct _GstCaps GstCaps;
 typedef struct _GstStaticCaps GstStaticCaps;
 
+GST_EXPORT GstCaps * _gst_caps_any;
+GST_EXPORT GstCaps * _gst_caps_none;
+/**
+ * GST_CAPS_FLAGS:
+ * @caps: a #GstCaps.
+ *
+ * A flags word containing #GstCapsFlags flags set on this caps.
+ */
+#define GST_CAPS_FLAGS(caps)                    GST_MINI_OBJECT_FLAGS(caps)
+
 /* refcount */
 /**
  * GST_CAPS_REFCOUNT:
@@ -155,38 +155,199 @@ typedef struct _GstStaticCaps GstStaticCaps;
  *
  * Get access to the reference count field of the caps
  */
-#define GST_CAPS_REFCOUNT(caps)                 ((GST_CAPS(caps))->refcount)
+#define GST_CAPS_REFCOUNT(caps)                 GST_MINI_OBJECT_REFCOUNT(caps)
 /**
  * GST_CAPS_REFCOUNT_VALUE:
  * @caps: a #GstCaps
  *
  * Get the reference count value of the caps.
  */
-#define GST_CAPS_REFCOUNT_VALUE(caps)           (g_atomic_int_get (&(GST_CAPS(caps))->refcount))
+#define GST_CAPS_REFCOUNT_VALUE(caps)           GST_MINI_OBJECT_REFCOUNT_VALUE(caps)
 
 /**
- * GstCaps:
- * @type: GType of the caps
- * @refcount: the atomic refcount value
- * @flags: extra flags for the caps, read only.
+ * GST_CAPS_FLAG_IS_SET:
+ * @caps: a #GstCaps.
+ * @flag: the #GstCapsFlags to check.
  *
- * Object describing media types.
+ * Gives the status of a specific flag on a caps.
  */
-struct _GstCaps {
-  GType type;
+#define GST_CAPS_FLAG_IS_SET(caps,flag)        GST_MINI_OBJECT_FLAG_IS_SET (caps, flag)
+/**
+ * GST_CAPS_FLAG_SET:
+ * @caps: a #GstCaps.
+ * @flag: the #GstCapsFlags to set.
+ *
+ * Sets a caps flag on a caps.
+ */
+#define GST_CAPS_FLAG_SET(caps,flag)           GST_MINI_OBJECT_FLAG_SET (caps, flag)
+/**
+ * GST_CAPS_FLAG_UNSET:
+ * @caps: a #GstCaps.
+ * @flag: the #GstCapsFlags to clear.
+ *
+ * Clears a caps flag.
+ */
+#define GST_CAPS_FLAG_UNSET(caps,flag)         GST_MINI_OBJECT_FLAG_UNSET (caps, flag)
+
+/* refcounting */
+/**
+ * gst_caps_ref:
+ * @caps: the #GstCaps to reference
+ *
+ * Add a reference to a #GstCaps object.
+ *
+ * From this point on, until the caller calls gst_caps_unref() or
+ * gst_caps_make_writable(), it is guaranteed that the caps object will not
+ * change. This means its structures won't change, etc. To use a #GstCaps
+ * object, you must always have a refcount on it -- either the one made
+ * implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with
+ * this function.
+ *
+ * Returns: the same #GstCaps object.
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstCaps * gst_caps_ref (GstCaps * caps);
+#endif
 
-  /*< public >*/ /* with COW */
-  /* refcounting */
-  gint           refcount;
+static inline GstCaps *
+gst_caps_ref (GstCaps * caps)
+{
+  return (GstCaps *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps));
+}
 
-  /*< public >*/ /* read only */
-  GstCapsFlags flags;
+/**
+ * gst_caps_unref:
+ * @caps: a #GstCaps.
+ *
+ * Unref a #GstCaps and and free all its structures and the
+ * structures' values when the refcount reaches 0.
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_caps_unref (GstCaps * caps);
+#endif
 
-  /*< private >*/
-  GPtrArray *structs;
+static inline void
+gst_caps_unref (GstCaps * caps)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (caps));
+}
+
+/* copy caps */
+/**
+ * gst_caps_copy:
+ * @caps: a #GstCaps.
+ *
+ * Creates a new #GstCaps as a copy of the old @caps. The new caps will have a
+ * refcount of 1, owned by the caller. The structures are copied as well.
+ *
+ * Note that this function is the semantic equivalent of a gst_caps_ref()
+ * followed by a gst_caps_make_writable(). If you only want to hold on to a
+ * reference to the data, you should use gst_caps_ref().
+ *
+ * When you are finished with the caps, call gst_caps_unref() on it.
+ *
+ * Returns: the new #GstCaps
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstCaps * gst_caps_copy (const GstCaps * caps);
+#endif
+
+static inline GstCaps *
+gst_caps_copy (const GstCaps * caps)
+{
+  return GST_CAPS (gst_mini_object_copy (GST_MINI_OBJECT_CAST (caps)));
+}
+
+/**
+ * gst_caps_is_writable:
+ * @caps: a #GstCaps
+ *
+ * Tests if you can safely modify @caps. It is only safe to modify caps when
+ * there is only one owner of the caps - ie, the refcount is 1.
+ */
+#define         gst_caps_is_writable(caps)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (caps))
+
+/**
+ * gst_caps_make_writable:
+ * @caps: (transfer full): a #GstCaps
+ *
+ * Returns a writable copy of @caps.
+ *
+ * If there is only one reference count on @caps, the caller must be the owner,
+ * and so this function will return the caps object unchanged. If on the other
+ * hand there is more than one reference on the object, a new caps object will
+ * be returned. The caller's reference on @caps will be removed, and instead the
+ * caller will own a reference to the returned object.
+ *
+ * In short, this function unrefs the caps in the argument and refs the caps
+ * that it returns. Don't access the argument after calling this function. See
+ * also: gst_caps_ref().
+ *
+ * Returns: (transfer full): a writable caps which may or may not be the
+ *     same as @caps
+ */
+#define         gst_caps_make_writable(caps)   GST_CAPS_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (caps)))
+
+/**
+ * gst_caps_replace:
+ * @old_caps: (inout) (transfer full): pointer to a pointer to a #GstCaps to be
+ *     replaced.
+ * @new_caps: (transfer none) (allow-none): pointer to a #GstCaps that will
+ *     replace the caps pointed to by @ocaps.
+ *
+ * Modifies a pointer to a #GstCaps to point to a different #GstCaps. The
+ * modification is done atomically (so this is useful for ensuring thread safety
+ * in some cases), and the reference counts are updated appropriately (the old
+ * caps is unreffed, the new is reffed).
+ *
+ * Either @ncaps or the #GstCaps pointed to by @ocaps may be NULL.
+ *
+ * Returns: TRUE if @new_caps was different from @old_caps
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_caps_replace (GstCaps **old_caps, GstCaps *new_caps);
+#endif
+
+static inline gboolean
+gst_caps_replace (GstCaps **old_caps, GstCaps *new_caps)
+{
+    return gst_mini_object_replace ((GstMiniObject **) old_caps, (GstMiniObject *) new_caps);
+}
+
+/**
+ * gst_caps_take:
+ * @old_caps: (inout) (transfer full): pointer to a pointer to a #GstCaps to be
+ *     replaced.
+ * @new_caps: (transfer full) (allow-none): pointer to a #GstCaps that will
+ *     replace the caps pointed to by @ocaps.
+ *
+ * Modifies a pointer to a #GstCaps to point to a different #GstCaps. This
+ * function is similar to gst_caps_replace() except that it takes ownership
+ * of @new_caps.
+ *
+ * Returns: TRUE if @new_caps was different from @old_caps
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_caps_take (GstCaps **old_caps, GstCaps *new_caps);
+#endif
+
+static inline gboolean
+gst_caps_take (GstCaps **old_caps, GstCaps *new_caps)
+{
+    return gst_mini_object_take ((GstMiniObject **) old_caps, (GstMiniObject *) new_caps);
+}
+
+/**
+ * GstCaps:
+ * @mini_object: the parent type
+ *
+ * Object describing media types.
+ */
+struct _GstCaps {
+  GstMiniObject mini_object;
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer     priv;
 };
 
 /**
@@ -208,23 +369,21 @@ struct _GstStaticCaps {
 };
 
 GType             gst_caps_get_type                (void);
-GstCaps *         gst_caps_new_empty               (void) G_GNUC_MALLOC;
-GstCaps *         gst_caps_new_any                 (void) G_GNUC_MALLOC;
+
+GstCaps *         gst_caps_new_empty               (void);
+GstCaps *         gst_caps_new_any                 (void);
+GstCaps *         gst_caps_new_empty_simple        (const char    *media_type) G_GNUC_WARN_UNUSED_RESULT;
 GstCaps *         gst_caps_new_simple              (const char    *media_type,
                                                     const char    *fieldname,
-                                                    ...) G_GNUC_MALLOC;
-GstCaps *         gst_caps_new_full                (GstStructure  *struct1, ...) G_GNUC_MALLOC;
+                                                    ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
+GstCaps *         gst_caps_new_full                (GstStructure  *struct1,
+                                                    ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
 GstCaps *         gst_caps_new_full_valist         (GstStructure  *structure,
-                                                    va_list        var_args) G_GNUC_MALLOC;
-
-/* reference counting */
-GstCaps *         gst_caps_ref                     (GstCaps       *caps);
-GstCaps *         gst_caps_copy                    (const GstCaps *caps) G_GNUC_MALLOC;
-GstCaps *         gst_caps_make_writable           (GstCaps       *caps) G_GNUC_WARN_UNUSED_RESULT;
-void              gst_caps_unref                   (GstCaps       *caps);
+                                                    va_list        var_args) G_GNUC_WARN_UNUSED_RESULT;
 
 GType             gst_static_caps_get_type         (void);
 GstCaps *         gst_static_caps_get              (GstStaticCaps *static_caps);
+void              gst_static_caps_cleanup          (GstStaticCaps *static_caps);
 
 /* manipulation */
 void              gst_caps_append                  (GstCaps       *caps1,
@@ -241,7 +400,7 @@ GstStructure *    gst_caps_get_structure           (const GstCaps *caps,
                                                     guint          index);
 GstStructure *    gst_caps_steal_structure         (GstCaps *caps,
                                                     guint          index) G_GNUC_WARN_UNUSED_RESULT;
-GstCaps *         gst_caps_copy_nth                (const GstCaps *caps, guint nth) G_GNUC_MALLOC;
+GstCaps *         gst_caps_copy_nth                (const GstCaps *caps, guint nth) G_GNUC_WARN_UNUSED_RESULT;
 void              gst_caps_truncate                (GstCaps       *caps);
 void              gst_caps_set_value               (GstCaps       *caps,
                                                     const char    *field,
@@ -274,28 +433,22 @@ gboolean          gst_caps_is_strictly_equal         (const GstCaps *caps1,
 
 /* operations */
 GstCaps *         gst_caps_intersect               (const GstCaps *caps1,
-                                                   const GstCaps *caps2) G_GNUC_MALLOC;
+                                                   const GstCaps *caps2) G_GNUC_WARN_UNUSED_RESULT;
 GstCaps *         gst_caps_intersect_full          (const GstCaps *caps1,
                                                    const GstCaps *caps2,
-                                                    GstCapsIntersectMode mode) G_GNUC_MALLOC;
+                                                    GstCapsIntersectMode mode) G_GNUC_WARN_UNUSED_RESULT;
 GstCaps *         gst_caps_subtract               (const GstCaps *minuend,
-                                                   const GstCaps *subtrahend) G_GNUC_MALLOC;
+                                                   const GstCaps *subtrahend) G_GNUC_WARN_UNUSED_RESULT;
 GstCaps *         gst_caps_union                   (const GstCaps *caps1,
-                                                   const GstCaps *caps2) G_GNUC_MALLOC;
-GstCaps *         gst_caps_normalize               (const GstCaps *caps) G_GNUC_MALLOC;
+                                                   const GstCaps *caps2) G_GNUC_WARN_UNUSED_RESULT;
+GstCaps *         gst_caps_normalize               (const GstCaps *caps) G_GNUC_WARN_UNUSED_RESULT;
 gboolean          gst_caps_do_simplify             (GstCaps       *caps);
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED)
-xmlNodePtr        gst_caps_save_thyself            (const GstCaps *caps,
-                                                    xmlNodePtr     parent);
-GstCaps *         gst_caps_load_thyself            (xmlNodePtr     parent);
-#endif
+void              gst_caps_fixate                  (GstCaps       *caps);
 
 /* utility */
-void              gst_caps_replace                 (GstCaps      **caps,
-                                                    GstCaps       *newcaps);
 gchar *           gst_caps_to_string               (const GstCaps *caps) G_GNUC_MALLOC;
-GstCaps *         gst_caps_from_string             (const gchar   *string) G_GNUC_MALLOC;
+GstCaps *         gst_caps_from_string             (const gchar   *string) G_GNUC_WARN_UNUSED_RESULT;
 
 G_END_DECLS
 
index ebb2d14..fda5ce7 100644 (file)
 G_BEGIN_DECLS
 
 
-#define GST_TYPE_CHILD_PROXY                   (gst_child_proxy_get_type ())
-#define GST_CHILD_PROXY(obj)                   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CHILD_PROXY, GstChildProxy))
-#define GST_IS_CHILD_PROXY(obj)                        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CHILD_PROXY))
-#define GST_CHILD_PROXY_GET_INTERFACE(obj)     (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_CHILD_PROXY, GstChildProxyInterface))
+#define GST_TYPE_CHILD_PROXY               (gst_child_proxy_get_type ())
+#define GST_CHILD_PROXY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CHILD_PROXY, GstChildProxy))
+#define GST_IS_CHILD_PROXY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CHILD_PROXY))
+#define GST_CHILD_PROXY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_CHILD_PROXY, GstChildProxyInterface))
 
 /**
  * GstChildProxy:
@@ -54,12 +54,12 @@ struct _GstChildProxyInterface
   GTypeInterface parent;
 
   /* methods */
-  GstObject *(*get_child_by_index) (GstChildProxy * parent, guint index);
-  guint (*get_children_count) (GstChildProxy * parent);
+  GstObject * (*get_child_by_index) (GstChildProxy * parent, guint index);
+  guint       (*get_children_count) (GstChildProxy * parent);
   /*< private >*/
   /* signals */
-  void (*child_added) (GstChildProxy * parent, GstObject * child);
-  void (*child_removed) (GstChildProxy * parent, GstObject * child);
+  void        (*child_added)        (GstChildProxy * parent, GstObject * child);
+  void        (*child_removed)      (GstChildProxy * parent, GstObject * child);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -67,24 +67,34 @@ struct _GstChildProxyInterface
 
 GType gst_child_proxy_get_type (void);
 
-GstObject *gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name);
-GstObject *gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index);
-guint gst_child_proxy_get_children_count (GstChildProxy * parent);
-
-gboolean gst_child_proxy_lookup (GstObject *object, const gchar *name,
-    GstObject **target, GParamSpec **pspec);
-void gst_child_proxy_get_property (GstObject * object, const gchar *name, GValue *value);
-void gst_child_proxy_get_valist (GstObject * object,
-    const gchar * first_property_name, va_list var_args);
-void gst_child_proxy_get (GstObject * object, const gchar * first_property_name,
-    ...) G_GNUC_NULL_TERMINATED;
-void gst_child_proxy_set_property (GstObject * object, const gchar *name, const GValue *value);
-void gst_child_proxy_set_valist (GstObject* object,
-    const gchar * first_property_name, va_list var_args);
-void gst_child_proxy_set (GstObject * object, const gchar * first_property_name,
-    ...) G_GNUC_NULL_TERMINATED;
-void gst_child_proxy_child_added (GstObject * object, GstObject *  child);
-void gst_child_proxy_child_removed (GstObject * object, GstObject *  child);
+GstObject *  gst_child_proxy_get_child_by_name   (GstChildProxy * parent, const gchar * name);
+
+guint        gst_child_proxy_get_children_count  (GstChildProxy * parent);
+GstObject *  gst_child_proxy_get_child_by_index  (GstChildProxy * parent, guint index);
+
+gboolean     gst_child_proxy_lookup              (GstObject *object, const gchar *name,
+                                                  GstObject **target, GParamSpec **pspec);
+
+void         gst_child_proxy_get_property        (GstObject * object, const gchar *name,
+                                                  GValue *value);
+void         gst_child_proxy_get_valist          (GstObject * object,
+                                                  const gchar * first_property_name,
+                                                  va_list var_args);
+void         gst_child_proxy_get                 (GstObject * object,
+                                                  const gchar * first_property_name,
+                                                  ...) G_GNUC_NULL_TERMINATED;
+
+void         gst_child_proxy_set_property        (GstObject * object, const gchar *name,
+                                                  const GValue *value);
+void         gst_child_proxy_set_valist          (GstObject* object,
+                                                  const gchar * first_property_name,
+                                                  va_list var_args);
+void         gst_child_proxy_set                 (GstObject * object,
+                                                  const gchar * first_property_name,
+                                                  ...) G_GNUC_NULL_TERMINATED;
+
+void         gst_child_proxy_child_added         (GstObject * object, GstObject *  child);
+void         gst_child_proxy_child_removed       (GstObject * object, GstObject *  child);
 
 G_END_DECLS
 
index bd2eb8f..760feff 100644 (file)
@@ -141,13 +141,13 @@ struct _GstClockPrivate
 
 /* seqlocks */
 #define read_seqbegin(clock)                                   \
-  g_atomic_int_get (&clock->ABI.priv->post_count);
+  g_atomic_int_get (&clock->priv->post_count);
 
 static inline gboolean
 read_seqretry (GstClock * clock, gint seq)
 {
   /* no retry if the seqnum did not change */
-  if (G_LIKELY (seq == g_atomic_int_get (&clock->ABI.priv->pre_count)))
+  if (G_LIKELY (seq == g_atomic_int_get (&clock->priv->pre_count)))
     return FALSE;
 
   /* wait for the writer to finish and retry */
@@ -159,12 +159,12 @@ read_seqretry (GstClock * clock, gint seq)
 #define write_seqlock(clock)                      \
 G_STMT_START {                                    \
   GST_OBJECT_LOCK (clock);                        \
-  g_atomic_int_inc (&clock->ABI.priv->pre_count);     \
+  g_atomic_int_inc (&clock->priv->pre_count);     \
 } G_STMT_END;
 
 #define write_sequnlock(clock)                    \
 G_STMT_START {                                    \
-  g_atomic_int_inc (&clock->ABI.priv->post_count);    \
+  g_atomic_int_inc (&clock->priv->post_count);    \
   GST_OBJECT_UNLOCK (clock);                      \
 } G_STMT_END;
 
@@ -178,8 +178,6 @@ static void gst_clock_get_property (GObject * object, guint prop_id,
 static void gst_clock_update_stats (GstClock * clock);
 
 
-static GstObjectClass *parent_class = NULL;
-
 /* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
 
 static GstClockID
@@ -490,26 +488,10 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);
 
   /* if we have a wait_jitter function, use that */
-  if (G_LIKELY (cclass->wait_jitter)) {
-    res = cclass->wait_jitter (clock, entry, jitter);
-  } else {
-    /* check if we have a simple _wait function otherwise. The function without
-     * the jitter arg is less optimal as we need to do an additional _get_time()
-     * which is not atomic with the _wait() and a typical _wait() function does
-     * yet another _get_time() anyway. */
-    if (G_UNLIKELY (cclass->wait == NULL))
-      goto not_supported;
-
-    if (jitter) {
-      GstClockTime now = gst_clock_get_time (clock);
-
-      /* jitter is the diff against the clock when this entry is scheduled. Negative
-       * values mean that the entry was in time, a positive value means that the
-       * entry was too late. */
-      *jitter = GST_CLOCK_DIFF (requested, now);
-    }
-    res = cclass->wait (clock, entry);
-  }
+  if (G_UNLIKELY (cclass->wait == NULL))
+    goto not_supported;
+
+  res = cclass->wait (clock, entry, jitter);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
       "done waiting entry %p, res: %d", id, res);
@@ -666,6 +648,7 @@ gst_clock_id_unschedule (GstClockID id)
 /*
  * GstClock abstract base class implementation
  */
+#define gst_clock_parent_class parent_class
 G_DEFINE_TYPE (GstClock, gst_clock, GST_TYPE_OBJECT);
 
 static void
@@ -673,8 +656,6 @@ gst_clock_class_init (GstClockClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
 #ifndef GST_DISABLE_TRACE
   _gst_clock_entry_trace =
       gst_alloc_trace_register (GST_CLOCK_ENTRY_TRACE_NAME);
@@ -712,10 +693,10 @@ gst_clock_init (GstClock * clock)
 {
   clock->last_time = 0;
   clock->entries = NULL;
-  clock->entries_changed = g_cond_new ();
+  g_cond_init (&clock->entries_changed);
   clock->stats = FALSE;
 
-  clock->ABI.priv =
+  clock->priv =
       G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
 
   clock->internal_calibration = 0;
@@ -723,7 +704,7 @@ gst_clock_init (GstClock * clock)
   clock->rate_numerator = 1;
   clock->rate_denominator = 1;
 
-  clock->slave_lock = g_mutex_new ();
+  g_mutex_init (&clock->slave_lock);
   clock->window_size = DEFAULT_WINDOW_SIZE;
   clock->window_threshold = DEFAULT_WINDOW_THRESHOLD;
   clock->filling = TRUE;
@@ -761,8 +742,8 @@ gst_clock_finalize (GObject * object)
   clock->times = NULL;
   GST_CLOCK_SLAVE_UNLOCK (clock);
 
-  g_cond_free (clock->entries_changed);
-  g_mutex_free (clock->slave_lock);
+  g_cond_clear (&clock->entries_changed);
+  g_mutex_clear (&clock->slave_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
index 0af622b..6272221 100644 (file)
 #ifndef __GST_CLOCK_H__
 #define __GST_CLOCK_H__
 
-#include <gst/gstobject.h>
-
 G_BEGIN_DECLS
 
 /* --- standard type macros --- */
-#define GST_TYPE_CLOCK                 (gst_clock_get_type ())
-#define GST_CLOCK(clock)               (G_TYPE_CHECK_INSTANCE_CAST ((clock), GST_TYPE_CLOCK, GstClock))
-#define GST_IS_CLOCK(clock)            (G_TYPE_CHECK_INSTANCE_TYPE ((clock), GST_TYPE_CLOCK))
-#define GST_CLOCK_CLASS(cclass)                (G_TYPE_CHECK_CLASS_CAST ((cclass), GST_TYPE_CLOCK, GstClockClass))
-#define GST_IS_CLOCK_CLASS(cclass)     (G_TYPE_CHECK_CLASS_TYPE ((cclass), GST_TYPE_CLOCK))
-#define GST_CLOCK_GET_CLASS(clock)     (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass))
-#define GST_CLOCK_CAST(clock)          ((GstClock*)(clock))
+#define GST_TYPE_CLOCK                  (gst_clock_get_type ())
+#define GST_CLOCK(clock)                (G_TYPE_CHECK_INSTANCE_CAST ((clock), GST_TYPE_CLOCK, GstClock))
+#define GST_IS_CLOCK(clock)             (G_TYPE_CHECK_INSTANCE_TYPE ((clock), GST_TYPE_CLOCK))
+#define GST_CLOCK_CLASS(cclass)         (G_TYPE_CHECK_CLASS_CAST ((cclass), GST_TYPE_CLOCK, GstClockClass))
+#define GST_IS_CLOCK_CLASS(cclass)      (G_TYPE_CHECK_CLASS_TYPE ((cclass), GST_TYPE_CLOCK))
+#define GST_CLOCK_GET_CLASS(clock)      (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass))
+#define GST_CLOCK_CAST(clock)           ((GstClock*)(clock))
 
-#define GST_CLOCK_SLAVE_LOCK(clock)    g_mutex_lock (GST_CLOCK_CAST (clock)->slave_lock)
-#define GST_CLOCK_SLAVE_UNLOCK(clock)  g_mutex_unlock (GST_CLOCK_CAST (clock)->slave_lock)
+#define GST_CLOCK_SLAVE_LOCK(clock)     g_mutex_lock (&GST_CLOCK_CAST (clock)->slave_lock)
+#define GST_CLOCK_SLAVE_UNLOCK(clock)   g_mutex_unlock (&GST_CLOCK_CAST (clock)->slave_lock)
 
 /**
  * GstClockTime:
  *
  * A datatype to hold a time, measured in nanoseconds.
  */
-typedef guint64        GstClockTime;
+typedef guint64 GstClockTime;
 
 /**
  * GST_TYPE_CLOCK_TIME:
@@ -72,21 +70,21 @@ typedef gpointer GstClockID;
  *
  * Constant to define an undefined clock time.
  */
-#define GST_CLOCK_TIME_NONE            ((GstClockTime) -1)
+#define GST_CLOCK_TIME_NONE             ((GstClockTime) -1)
 /**
  * GST_CLOCK_TIME_IS_VALID:
  * @time: clock time to validate
  *
  * Tests if a given #GstClockTime represents a valid defined time.
  */
-#define GST_CLOCK_TIME_IS_VALID(time)  (((GstClockTime)(time)) != GST_CLOCK_TIME_NONE)
+#define GST_CLOCK_TIME_IS_VALID(time)   (((GstClockTime)(time)) != GST_CLOCK_TIME_NONE)
 
 /* FIXME: still need to explicitly force types on the defines below */
 /**
  * GST_SECOND:
  *
  * Constant that defines one GStreamer second.
- * 
+ *
  * Value: 1000000000
  *
  */
@@ -95,27 +93,27 @@ typedef gpointer GstClockID;
  * GST_MSECOND:
  *
  * Constant that defines one GStreamer millisecond.
- * 
+ *
  * Value: 1000000
- * 
+ *
  */
 #define GST_MSECOND (GST_SECOND / G_GINT64_CONSTANT (1000))
 /**
  * GST_USECOND:
  *
  * Constant that defines one GStreamer microsecond.
- * 
+ *
  * Value: 1000
- * 
+ *
  */
 #define GST_USECOND (GST_SECOND / G_GINT64_CONSTANT (1000000))
 /**
  * GST_NSECOND:
  *
  * Constant that defines one GStreamer nanosecond
- * 
+ *
  * Value: 1
- * 
+ *
  */
 #define GST_NSECOND (GST_SECOND / G_GINT64_CONSTANT (1000000000))
 
@@ -165,7 +163,7 @@ typedef gpointer GstClockID;
  * Calculate a difference between two clock times as a #GstClockTimeDiff.
  * The difference is calculated as @e - @s.
  */
-#define GST_CLOCK_DIFF(s, e)           (GstClockTimeDiff)((e) - (s))
+#define GST_CLOCK_DIFF(s, e)            (GstClockTimeDiff)((e) - (s))
 
 /**
  * GST_TIMEVAL_TO_TIME:
@@ -173,7 +171,7 @@ typedef gpointer GstClockID;
  *
  * Convert a #GTimeVal to a #GstClockTime.
  */
-#define GST_TIMEVAL_TO_TIME(tv)                (GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
+#define GST_TIMEVAL_TO_TIME(tv)         (GstClockTime)((tv).tv_sec * GST_SECOND + (tv).tv_usec * GST_USECOND)
 
 /**
  * GST_TIME_TO_TIMEVAL:
@@ -186,12 +184,12 @@ typedef gpointer GstClockID;
  * which is about 68 years.  Expect trouble if you want to schedule stuff
  * in your pipeline for 2038.</note>
  */
-#define GST_TIME_TO_TIMEVAL(t,tv)                              \
-G_STMT_START {                                                 \
-  (tv).tv_sec  = ((GstClockTime) (t)) / GST_SECOND;            \
-  (tv).tv_usec = (((GstClockTime) (t)) -                       \
-                  ((GstClockTime) (tv).tv_sec) * GST_SECOND)   \
-                 / GST_USECOND;                                        \
+#define GST_TIME_TO_TIMEVAL(t,tv)                               \
+G_STMT_START {                                                  \
+  (tv).tv_sec  = ((GstClockTime) (t)) / GST_SECOND;             \
+  (tv).tv_usec = (((GstClockTime) (t)) -                        \
+                  ((GstClockTime) (tv).tv_sec) * GST_SECOND)    \
+                 / GST_USECOND;                                 \
 } G_STMT_END
 
 /**
@@ -200,7 +198,7 @@ G_STMT_START {                                                      \
  *
  * Convert a struct timespec (see man pselect) to a #GstClockTime.
  */
-#define GST_TIMESPEC_TO_TIME(ts)       (GstClockTime)((ts).tv_sec * GST_SECOND + (ts).tv_nsec * GST_NSECOND)
+#define GST_TIMESPEC_TO_TIME(ts)        (GstClockTime)((ts).tv_sec * GST_SECOND + (ts).tv_nsec * GST_NSECOND)
 /**
  * GST_TIME_TO_TIMESPEC:
  * @t: The #GstClockTime to convert
@@ -208,10 +206,10 @@ G_STMT_START {                                                    \
  *
  * Convert a #GstClockTime to a struct timespec (see man pselect)
  */
-#define GST_TIME_TO_TIMESPEC(t,ts)                     \
-G_STMT_START {                                         \
-  (ts).tv_sec  =  (t) / GST_SECOND;                    \
-  (ts).tv_nsec = ((t) - (ts).tv_sec * GST_SECOND) / GST_NSECOND;       \
+#define GST_TIME_TO_TIMESPEC(t,ts)                      \
+G_STMT_START {                                          \
+  (ts).tv_sec  =  (t) / GST_SECOND;                     \
+  (ts).tv_nsec = ((t) - (ts).tv_sec * GST_SECOND) / GST_NSECOND;        \
 } G_STMT_END
 
 /* timestamp debugging macros */
@@ -252,10 +250,10 @@ G_STMT_START {                                            \
  */
 #define GST_CLOCK_ENTRY_TRACE_NAME "GstClockEntry"
 
-typedef struct _GstClockEntry  GstClockEntry;
-typedef struct _GstClock       GstClock;
-typedef struct _GstClockClass  GstClockClass;
-typedef struct _GstClockPrivate        GstClockPrivate;
+typedef struct _GstClockEntry   GstClockEntry;
+typedef struct _GstClock        GstClock;
+typedef struct _GstClockClass   GstClockClass;
+typedef struct _GstClockPrivate GstClockPrivate;
 
 /* --- prototype for async callbacks --- */
 /**
@@ -269,8 +267,8 @@ typedef struct _GstClockPrivate     GstClockPrivate;
  *
  * Returns: %TRUE or %FALSE (currently unused)
  */
-typedef gboolean       (*GstClockCallback)     (GstClock *clock, GstClockTime time,
-                                                GstClockID id, gpointer user_data);
+typedef gboolean        (*GstClockCallback)     (GstClock *clock, GstClockTime time,
+                                                 GstClockID id, gpointer user_data);
 /**
  * GstClockReturn:
  * @GST_CLOCK_OK: The operation succeeded.
@@ -286,14 +284,14 @@ typedef gboolean  (*GstClockCallback)     (GstClock *clock, GstClockTime time,
  */
 typedef enum
 {
-  GST_CLOCK_OK         =  0,
-  GST_CLOCK_EARLY      =  1,
-  GST_CLOCK_UNSCHEDULED        =  2,
-  GST_CLOCK_BUSY       =  3,
-  GST_CLOCK_BADTIME    =  4,
-  GST_CLOCK_ERROR      =  5,
-  GST_CLOCK_UNSUPPORTED        =  6,
-  GST_CLOCK_DONE       =  7
+  GST_CLOCK_OK          =  0,
+  GST_CLOCK_EARLY       =  1,
+  GST_CLOCK_UNSCHEDULED =  2,
+  GST_CLOCK_BUSY        =  3,
+  GST_CLOCK_BADTIME     =  4,
+  GST_CLOCK_ERROR       =  5,
+  GST_CLOCK_UNSUPPORTED =  6,
+  GST_CLOCK_DONE        =  7
 } GstClockReturn;
 
 /**
@@ -314,42 +312,42 @@ typedef enum {
  *
  * Cast to a clock entry
  */
-#define GST_CLOCK_ENTRY(entry)         ((GstClockEntry *)(entry))
+#define GST_CLOCK_ENTRY(entry)          ((GstClockEntry *)(entry))
 /**
  * GST_CLOCK_ENTRY_CLOCK:
  * @entry: the entry to query
  *
  * Get the owner clock of the entry
  */
-#define GST_CLOCK_ENTRY_CLOCK(entry)   ((entry)->clock)
+#define GST_CLOCK_ENTRY_CLOCK(entry)    ((entry)->clock)
 /**
  * GST_CLOCK_ENTRY_TYPE:
  * @entry: the entry to query
  *
  * Get the type of the clock entry
  */
-#define GST_CLOCK_ENTRY_TYPE(entry)    ((entry)->type)
+#define GST_CLOCK_ENTRY_TYPE(entry)     ((entry)->type)
 /**
  * GST_CLOCK_ENTRY_TIME:
  * @entry: the entry to query
  *
  * Get the requested time of this entry
  */
-#define GST_CLOCK_ENTRY_TIME(entry)    ((entry)->time)
+#define GST_CLOCK_ENTRY_TIME(entry)     ((entry)->time)
 /**
  * GST_CLOCK_ENTRY_INTERVAL:
  * @entry: the entry to query
  *
  * Get the interval of this periodic entry
  */
-#define GST_CLOCK_ENTRY_INTERVAL(entry)        ((entry)->interval)
+#define GST_CLOCK_ENTRY_INTERVAL(entry) ((entry)->interval)
 /**
  * GST_CLOCK_ENTRY_STATUS:
  * @entry: the entry to query
  *
  * The status of the entry
  */
-#define GST_CLOCK_ENTRY_STATUS(entry)  ((entry)->status)
+#define GST_CLOCK_ENTRY_STATUS(entry)   ((entry)->status)
 
 /**
  * GstClockEntry:
@@ -361,20 +359,24 @@ typedef enum {
  * not be extended or allocated using a custom allocator.
  */
 struct _GstClockEntry {
-  gint                 refcount;
+  gint                  refcount;
   /*< protected >*/
-  GstClock             *clock;
-  GstClockEntryType     type;
-  GstClockTime          time;
-  GstClockTime          interval;
-  GstClockReturn        status;
-  GstClockCallback      func;
-  gpointer              user_data;
-  GDestroyNotify        destroy_data;
+  GstClock              *clock;
+  GstClockEntryType      type;
+  GstClockTime           time;
+  GstClockTime           interval;
+  GstClockReturn         status;
+  GstClockCallback       func;
+  gpointer               user_data;
+  GDestroyNotify         destroy_data;
   gboolean               unscheduled;
   gboolean               woken_up;
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
+#include <gst/gstobject.h>
+
 /**
  * GstClockFlags:
  * @GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC: clock can do a single sync timeout request
@@ -395,7 +397,7 @@ typedef enum {
   GST_CLOCK_FLAG_CAN_SET_RESOLUTION     = (GST_OBJECT_FLAG_LAST << 4),
   GST_CLOCK_FLAG_CAN_SET_MASTER         = (GST_OBJECT_FLAG_LAST << 5),
   /* padding */
-  GST_CLOCK_FLAG_LAST                  = (GST_OBJECT_FLAG_LAST << 8)
+  GST_CLOCK_FLAG_LAST                   = (GST_OBJECT_FLAG_LAST << 8)
 } GstClockFlags;
 
 /**
@@ -407,20 +409,20 @@ typedef enum {
 #define GST_CLOCK_FLAGS(clock)  GST_OBJECT_FLAGS(clock)
 
 /**
- * GST_CLOCK_COND:
+ * GST_CLOCK_GET_COND:
  * @clock: the clock to query
  *
  * Gets the #GCond that gets signalled when the entries of the clock
  * changed.
  */
-#define GST_CLOCK_COND(clock)            (GST_CLOCK_CAST(clock)->entries_changed)
+#define GST_CLOCK_GET_COND(clock)        (&GST_CLOCK_CAST(clock)->entries_changed)
 /**
  * GST_CLOCK_WAIT:
  * @clock: the clock to wait on
  *
  * Wait on the clock until the entries changed.
  */
-#define GST_CLOCK_WAIT(clock)            g_cond_wait(GST_CLOCK_COND(clock),GST_OBJECT_GET_LOCK(clock))
+#define GST_CLOCK_WAIT(clock)            g_cond_wait(GST_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock))
 /**
  * GST_CLOCK_TIMED_WAIT:
  * @clock: the clock to wait on
@@ -429,14 +431,14 @@ typedef enum {
  * Wait on the clock until the entries changed or the specified timeout
  * occurred.
  */
-#define GST_CLOCK_TIMED_WAIT(clock,tv)   g_cond_timed_wait(GST_CLOCK_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
+#define GST_CLOCK_TIMED_WAIT(clock,tv)   g_cond_timed_wait(GST_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
 /**
  * GST_CLOCK_BROADCAST:
  * @clock: the clock to broadcast
  *
  * Signal that the entries in the clock have changed.
  */
-#define GST_CLOCK_BROADCAST(clock)       g_cond_broadcast(GST_CLOCK_COND(clock))
+#define GST_CLOCK_BROADCAST(clock)       g_cond_broadcast(GST_CLOCK_GET_COND(clock))
 
 /**
  * GstClock:
@@ -445,22 +447,22 @@ typedef enum {
  * protected for subclasses, use the methods to use the #GstClock.
  */
 struct _GstClock {
-  GstObject     object;
+  GstObject      object;
 
-  GMutex       *slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
+  GMutex         slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
 
   /*< protected >*/ /* with LOCK */
-  GstClockTime  internal_calibration;
-  GstClockTime  external_calibration;
-  GstClockTime  rate_numerator;
-  GstClockTime  rate_denominator;
-  GstClockTime  last_time;
-  GList                *entries;
-  GCond                *entries_changed;
+  GstClockTime   internal_calibration;
+  GstClockTime   external_calibration;
+  GstClockTime   rate_numerator;
+  GstClockTime   rate_denominator;
+  GstClockTime   last_time;
+  GList         *entries;
+  GCond          entries_changed;
 
   /*< private >*/ /* with LOCK */
-  GstClockTime  resolution;
-  gboolean      stats;
+  GstClockTime   resolution;
+  gboolean       stats;
 
   /* for master/slave clocks */
   GstClock      *master;
@@ -475,10 +477,9 @@ struct _GstClock {
   GstClockID     clockid;
 
   /*< private >*/
-  union {
-    GstClockPrivate *priv;
-    GstClockTime     _gst_reserved[GST_PADDING];
-  } ABI;
+  GstClockPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 /**
@@ -488,12 +489,11 @@ struct _GstClock {
  *                     be acceptable. The new resolution should be returned.
  * @get_resolution: get the resolution of the clock.
  * @get_internal_time: get the internal unadjusted time of the clock.
- * @wait: perform a blocking wait for the given #GstClockEntry. Deprecated,
  *        implement @wait_jitter instead.
+ * @wait: perform a blocking wait on the given #GstClockEntry and return
+ *               the jitter.
  * @wait_async: perform an asynchronous wait for the given #GstClockEntry.
  * @unschedule: unblock a blocking or async wait operation.
- * @wait_jitter: perform a blocking wait on the given #GstClockEntry and return
- *               the jitter. (Since: 0.10.10)
  *
  * GStreamer clock class. Override the vmethods to implement the clock
  * functionality.
@@ -505,85 +505,83 @@ struct _GstClockClass {
   /* vtable */
   GstClockTime          (*change_resolution)    (GstClock *clock,
                                                  GstClockTime old_resolution,
-                                                GstClockTime new_resolution);
+                                                 GstClockTime new_resolution);
   GstClockTime          (*get_resolution)       (GstClock *clock);
 
-  GstClockTime         (*get_internal_time)    (GstClock *clock);
+  GstClockTime          (*get_internal_time)    (GstClock *clock);
 
   /* waiting on an ID */
-  GstClockReturn        (*wait)                        (GstClock *clock, GstClockEntry *entry);
+  GstClockReturn        (*wait)                 (GstClock *clock, GstClockEntry *entry,
+                                                 GstClockTimeDiff *jitter);
   GstClockReturn        (*wait_async)           (GstClock *clock, GstClockEntry *entry);
-  void                  (*unschedule)          (GstClock *clock, GstClockEntry *entry);
+  void                  (*unschedule)           (GstClock *clock, GstClockEntry *entry);
 
-  /* ABI added to replace the deprecated wait */
-  GstClockReturn        (*wait_jitter)         (GstClock *clock, GstClockEntry *entry,
-                                                GstClockTimeDiff *jitter);
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
-GType                  gst_clock_get_type              (void);
+GType                   gst_clock_get_type              (void);
 
-GstClockTime           gst_clock_set_resolution        (GstClock *clock,
+GstClockTime            gst_clock_set_resolution        (GstClock *clock,
                                                          GstClockTime resolution);
-GstClockTime           gst_clock_get_resolution        (GstClock *clock);
+GstClockTime            gst_clock_get_resolution        (GstClock *clock);
 
-GstClockTime           gst_clock_get_time              (GstClock *clock);
-void                   gst_clock_set_calibration       (GstClock *clock, GstClockTime internal,
+GstClockTime            gst_clock_get_time              (GstClock *clock);
+void                    gst_clock_set_calibration       (GstClock *clock, GstClockTime internal,
                                                          GstClockTime external,
                                                          GstClockTime rate_num,
                                                          GstClockTime rate_denom);
-void                   gst_clock_get_calibration       (GstClock *clock, GstClockTime *internal,
+void                    gst_clock_get_calibration       (GstClock *clock, GstClockTime *internal,
                                                          GstClockTime *external,
                                                          GstClockTime *rate_num,
                                                          GstClockTime *rate_denom);
 
 /* master/slave clocks */
-gboolean               gst_clock_set_master            (GstClock *clock, GstClock *master);
-GstClock*              gst_clock_get_master            (GstClock *clock);
-gboolean               gst_clock_add_observation       (GstClock *clock, GstClockTime slave,
-                                                        GstClockTime master, gdouble *r_squared);
+gboolean                gst_clock_set_master            (GstClock *clock, GstClock *master);
+GstClock*               gst_clock_get_master            (GstClock *clock);
+gboolean                gst_clock_add_observation       (GstClock *clock, GstClockTime slave,
+                                                         GstClockTime master, gdouble *r_squared);
 
 
 /* getting and adjusting internal/external time */
-GstClockTime           gst_clock_get_internal_time     (GstClock *clock);
-GstClockTime           gst_clock_adjust_unlocked       (GstClock *clock, GstClockTime internal);
+GstClockTime            gst_clock_get_internal_time     (GstClock *clock);
+GstClockTime            gst_clock_adjust_unlocked       (GstClock *clock, GstClockTime internal);
 GstClockTime            gst_clock_unadjust_unlocked     (GstClock * clock, GstClockTime external);
 
 
 /* creating IDs that can be used to get notifications */
-GstClockID             gst_clock_new_single_shot_id    (GstClock *clock,
-                                                        GstClockTime time);
-GstClockID             gst_clock_new_periodic_id       (GstClock *clock,
-                                                        GstClockTime start_time,
-                                                        GstClockTime interval);
+GstClockID              gst_clock_new_single_shot_id    (GstClock *clock,
+                                                         GstClockTime time);
+GstClockID              gst_clock_new_periodic_id       (GstClock *clock,
+                                                         GstClockTime start_time,
+                                                         GstClockTime interval);
 
 /* reference counting */
 GstClockID              gst_clock_id_ref                (GstClockID id);
 void                    gst_clock_id_unref              (GstClockID id);
 
 /* operations on IDs */
-gint                   gst_clock_id_compare_func       (gconstpointer id1, gconstpointer id2);
-
-GstClockTime           gst_clock_id_get_time           (GstClockID id);
-GstClockReturn         gst_clock_id_wait               (GstClockID id,
-                                                        GstClockTimeDiff *jitter);
-GstClockReturn         gst_clock_id_wait_async         (GstClockID id,
-                                                        GstClockCallback func,
-                                                        gpointer user_data);
-GstClockReturn         gst_clock_id_wait_async_full    (GstClockID id,
-                                                        GstClockCallback func,
-                                                        gpointer user_data,
-                                                        GDestroyNotify destroy_data);
-void                   gst_clock_id_unschedule         (GstClockID id);
+gint                    gst_clock_id_compare_func       (gconstpointer id1, gconstpointer id2);
+
+GstClockTime            gst_clock_id_get_time           (GstClockID id);
+GstClockReturn          gst_clock_id_wait               (GstClockID id,
+                                                         GstClockTimeDiff *jitter);
+GstClockReturn          gst_clock_id_wait_async         (GstClockID id,
+                                                         GstClockCallback func,
+                                                         gpointer user_data);
+GstClockReturn          gst_clock_id_wait_async_full    (GstClockID id,
+                                                         GstClockCallback func,
+                                                         gpointer user_data,
+                                                         GDestroyNotify destroy_data);
+void                    gst_clock_id_unschedule         (GstClockID id);
 
 gboolean                gst_clock_single_shot_id_reinit (GstClock * clock,
-                                                        GstClockID id,
-                                                        GstClockTime time);
+                                                         GstClockID id,
+                                                         GstClockTime time);
 gboolean                gst_clock_periodic_id_reinit    (GstClock * clock,
-                                                        GstClockID id,
-                                                        GstClockTime start_time,
-                                                        GstClockTime interval);
+                                                         GstClockID id,
+                                                         GstClockTime start_time,
+                                                         GstClockTime interval);
 
 G_END_DECLS
 
index cf2d898..8fe8c52 100644 (file)
 
 G_BEGIN_DECLS
 
+/* added to ease the transition to 0.11 */
+#define gst_element_class_set_details_simple  gst_element_class_set_metadata
+
+#define gst_element_factory_get_longname(f)    gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_LONGNAME)
+#define gst_element_factory_get_klass(f)       gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_KLASS)
+#define gst_element_factory_get_description(f) gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_DESCRIPTION)
+#define gst_element_factory_get_author(f)      gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_AUTHOR)
+#define gst_element_factory_get_documentation_uri(f)  gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_DOC_URI)
+#define gst_element_factory_get_icon_name(f)   gst_element_factory_get_metadata(f, GST_ELEMENT_METADATA_ICON_NAME)
+
+#define gst_pad_get_caps_reffed(p)             gst_pad_get_caps(p)
+#define gst_pad_peer_get_caps_reffed(p)        gst_pad_peer_get_caps(p)
+
+//#define gst_buffer_create_sub(b,o,s)           gst_buffer_copy_region(b,GST_BUFFER_COPY_ALL,o,s)
+
+#define gst_buffer_new_and_alloc(s)            gst_buffer_new_allocate(NULL, s, 0)
+
+#define GST_BUFFER_TIMESTAMP          GST_BUFFER_PTS
+#define GST_BUFFER_TIMESTAMP_IS_VALID GST_BUFFER_PTS_IS_VALID
+
+#define gst_adapter_prev_timestamp    gst_adapter_prev_pts
+
 #ifndef GST_DISABLE_DEPRECATED
 
 #endif /* not GST_DISABLE_DEPRECATED */
index 37db17e..31ea674 100644 (file)
 
 #if 0
 #define GST_DISABLE_GST_DEBUG 1
-#define GST_DISABLE_LOADSAVE 1
 #define GST_DISABLE_PARSE 1
 #define GST_DISABLE_TRACE 1
 #define GST_DISABLE_ALLOC_TRACE 1
 #define GST_DISABLE_REGISTRY 1
 #define GST_DISABLE_PLUGIN 1
-#define GST_DISABLE_XML 1
-#define GST_DISABLE_LOADSAVE_REGISTRY 1
 #define GST_HAVE_GLIB_2_8 1
 #endif
 
 @GST_DISABLE_GST_DEBUG_DEFINE@
 
 /**
- * GST_DISABLE_LOADSAVE:
- *
- * Configures the inclusion of the plugin graph xml-serialisation
- * (was used in 0.8 by gst-editor)
- */
-@GST_DISABLE_LOADSAVE_DEFINE@
-
-/**
  * GST_DISABLE_PARSE:
  *
  * Configures the inclusion of the gst-lauch parser
  */
 @GST_DISABLE_REGISTRY_DEFINE@
 
-/**
- * GST_DISABLE_XML:
- *
- * Configures the use libxml2. This setting is derived from the settings of
- * %GST_DISABLE_LOADSAVE and %GST_DISABLE_REGISTRY (in the xml registry case).
- */
-@GST_DISABLE_XML_DEFINE@
-
 /* FIXME: test and document these! */
 /* Configures the use of external plugins */
 @GST_DISABLE_PLUGIN_DEFINE@
 /* whether or not the CPU supports unaligned access */
 @GST_HAVE_UNALIGNED_ACCESS_DEFINE@
 
-/* FIXME: 0.11 (remove)
- * whether or not we are using glib 2.8 api, e.g. atomic gobject
- * refcounting */
-@GST_HAVE_GLIB_2_8_DEFINE@
-
-/***** Deal with XML stuff, we have to handle both loadsave and registry *****/
-/* FIXME: move include to where we need it */
-/*#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )*/
-#ifndef GST_DISABLE_XML
-#ifndef GST_DISABLE_DEPRECATED
-# include <libxml/parser.h>
-#endif
-#else
-  /* FIXME: 0.11 (replace by GST_DISABLE_XML) */
-# define GST_DISABLE_LOADSAVE_REGISTRY
-#endif
-
 /**
  * GST_EXPORT:
  *
diff --git a/gst/gstcontrolbinding.c b/gst/gstcontrolbinding.c
new file mode 100644 (file)
index 0000000..f3aba1d
--- /dev/null
@@ -0,0 +1,321 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbinding.c: Attachment for control sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:gstcontrolbinding
+ * @short_description: attachment for control source sources
+ *
+ * A value mapping object that attaches control sources to gobject properties.
+ */
+
+#include "gst_private.h"
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gstcontrolbinding.h"
+
+#include <math.h>
+
+#define GST_CAT_DEFAULT control_binding_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolbinding", 0, \
+      "dynamic parameter control source attachment");
+
+static GObject *gst_control_binding_constructor (GType type,
+    guint n_construct_params, GObjectConstructParam * construct_params);
+static void gst_control_binding_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_control_binding_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_control_binding_dispose (GObject * object);
+static void gst_control_binding_finalize (GObject * object);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstControlBinding, gst_control_binding,
+    GST_TYPE_OBJECT, _do_init);
+
+enum
+{
+  PROP_0,
+  PROP_OBJECT,
+  PROP_NAME,
+  PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+static void
+gst_control_binding_class_init (GstControlBindingClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructor = gst_control_binding_constructor;
+  gobject_class->set_property = gst_control_binding_set_property;
+  gobject_class->get_property = gst_control_binding_get_property;
+  gobject_class->dispose = gst_control_binding_dispose;
+  gobject_class->finalize = gst_control_binding_finalize;
+
+  properties[PROP_OBJECT] =
+      g_param_spec_object ("object", "Object",
+      "The object of the property", GST_TYPE_OBJECT,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_NAME] =
+      g_param_spec_string ("name", "Name", "The name of the property", NULL,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
+}
+
+static void
+gst_control_binding_init (GstControlBinding * self)
+{
+}
+
+static GObject *
+gst_control_binding_constructor (GType type, guint n_construct_params,
+    GObjectConstructParam * construct_params)
+{
+  GstControlBinding *self;
+  GParamSpec *pspec;
+
+  self = GST_CONTROL_BINDING (G_OBJECT_CLASS (gst_control_binding_parent_class)
+      ->constructor (type, n_construct_params, construct_params));
+
+  GST_INFO_OBJECT (self->object, "trying to put property '%s' under control",
+      self->name);
+
+  /* check if the object has a property of that name */
+  if ((pspec =
+          g_object_class_find_property (G_OBJECT_GET_CLASS (self->object),
+              self->name))) {
+    GST_DEBUG_OBJECT (self->object, "  psec->flags : 0x%08x", pspec->flags);
+
+    /* check if this param is witable && controlable && !construct-only */
+    if ((pspec->flags & (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE |
+                G_PARAM_CONSTRUCT_ONLY)) ==
+        (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE)) {
+      self->pspec = pspec;
+    }
+  } else {
+    GST_WARNING_OBJECT (self->object, "class '%s' has no property '%s'",
+        G_OBJECT_TYPE_NAME (self->object), self->name);
+  }
+  return (GObject *) self;
+}
+
+static void
+gst_control_binding_dispose (GObject * object)
+{
+  GstControlBinding *self = GST_CONTROL_BINDING (object);
+
+  if (self->object)
+    gst_object_replace (&self->object, NULL);
+}
+
+static void
+gst_control_binding_finalize (GObject * object)
+{
+  GstControlBinding *self = GST_CONTROL_BINDING (object);
+
+  g_free (self->name);
+}
+
+static void
+gst_control_binding_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstControlBinding *self = GST_CONTROL_BINDING (object);
+
+  switch (prop_id) {
+    case PROP_OBJECT:
+      self->object = g_value_dup_object (value);
+      break;
+    case PROP_NAME:
+      self->name = g_value_dup_string (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_control_binding_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstControlBinding *self = GST_CONTROL_BINDING (object);
+
+  switch (prop_id) {
+    case PROP_OBJECT:
+      g_value_set_object (value, self->object);
+      break;
+    case PROP_NAME:
+      g_value_set_string (value, self->name);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* functions */
+
+/**
+ * gst_control_binding_sync_values:
+ * @self: the control binding
+ * @object: the object that has controlled properties
+ * @timestamp: the time that should be processed
+ * @last_sync: the last time this was called
+ *
+ * Sets the property of the @object, according to the #GstControlSources that
+ * handle them and for the given timestamp.
+ *
+ * If this function fails, it is most likely the application developers fault.
+ * Most probably the control sources are not setup correctly.
+ *
+ * Returns: %TRUE if the controller value could be applied to the object
+ * property, %FALSE otherwise
+ */
+gboolean
+gst_control_binding_sync_values (GstControlBinding * self, GstObject * object,
+    GstClockTime timestamp, GstClockTime last_sync)
+{
+  GstControlBindingClass *klass;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (self), FALSE);
+
+  if (self->disabled)
+    return TRUE;
+
+  klass = GST_CONTROL_BINDING_GET_CLASS (self);
+
+  if (G_LIKELY (klass->sync_values != NULL)) {
+    ret = klass->sync_values (self, object, timestamp, last_sync);
+  } else {
+    GST_WARNING_OBJECT (self, "missing sync_values implementation");
+  }
+  return ret;
+}
+
+/**
+ * gst_control_binding_get_value:
+ * @self: the control binding
+ * @timestamp: the time the control-change should be read from
+ *
+ * Gets the value for the given controlled property at the requested time.
+ *
+ * Returns: the GValue of the property at the given time, or %NULL if the
+ * property isn't controlled.
+ */
+GValue *
+gst_control_binding_get_value (GstControlBinding * self, GstClockTime timestamp)
+{
+  GstControlBindingClass *klass;
+  GValue *ret = NULL;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (self), NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
+
+  klass = GST_CONTROL_BINDING_GET_CLASS (self);
+
+  if (G_LIKELY (klass->get_value != NULL)) {
+    ret = klass->get_value (self, timestamp);
+  } else {
+    GST_WARNING_OBJECT (self, "missing get_value implementation");
+  }
+  return ret;
+}
+
+/**
+ * gst_control_binding_get_value_array:
+ * @self: the control binding
+ * @timestamp: the time that should be processed
+ * @interval: the time spacing between subsequent values
+ * @n_values: the number of values
+ * @values: array to put control-values in
+ *
+ * Gets a number of values for the given controllered property starting at the
+ * requested time. The array @values need to hold enough space for @n_values of
+ * the same type as the objects property's type.
+ *
+ * This function is useful if one wants to e.g. draw a graph of the control
+ * curve or apply a control curve sample by sample.
+ *
+ * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+ */
+gboolean
+gst_control_binding_get_value_array (GstControlBinding * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  GstControlBindingClass *klass;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+
+  klass = GST_CONTROL_BINDING_GET_CLASS (self);
+
+  if (G_LIKELY (klass->get_value_array != NULL)) {
+    ret = klass->get_value_array (self, timestamp, interval, n_values, values);
+  } else {
+    GST_WARNING_OBJECT (self, "missing get_value_array implementation");
+  }
+  return ret;
+}
+
+/**
+ * gst_control_binding_set_disabled:
+ * @self: the control binding
+ * @disabled: boolean that specifies whether to disable the controller
+ * or not.
+ *
+ * This function is used to disable a control binding for some time, i.e.
+ * gst_object_sync_values() will do nothing.
+ */
+void
+gst_control_binding_set_disabled (GstControlBinding * self, gboolean disabled)
+{
+  g_return_if_fail (GST_IS_CONTROL_BINDING (self));
+  self->disabled = disabled;
+}
+
+/**
+ * gst_control_binding_is_disabled:
+ * @self: the control binding
+ *
+ * Check if the control binding is disabled.
+ *
+ * Returns: %TRUE if the binding is inactive
+ */
+gboolean
+gst_control_binding_is_disabled (GstControlBinding * self)
+{
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (self), TRUE);
+  return (self->disabled == TRUE);
+}
diff --git a/gst/gstcontrolbinding.h b/gst/gstcontrolbinding.h
new file mode 100644 (file)
index 0000000..78b3661
--- /dev/null
@@ -0,0 +1,119 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbinding.h: Attachment for control sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_CONTROL_BINDING_H__
+#define __GST_CONTROL_BINDING_H__
+
+#include <gst/gstconfig.h>
+
+#include <glib-object.h>
+
+#include <gst/gstcontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CONTROL_BINDING \
+  (gst_control_binding_get_type())
+#define GST_CONTROL_BINDING(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_BINDING,GstControlBinding))
+#define GST_CONTROL_BINDING_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_BINDING,GstControlBindingClass))
+#define GST_IS_CONTROL_BINDING(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_BINDING))
+#define GST_IS_CONTROL_BINDING_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_BINDING))
+#define GST_CONTROL_BINDING_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlBindingClass))
+
+typedef struct _GstControlBinding GstControlBinding;
+typedef struct _GstControlBindingClass GstControlBindingClass;
+
+/**
+ * GstControlBindingConvert:
+ * @self: the #GstControlBinding instance
+ * @src_value: the value returned by the cotnrol source
+ * @dest_value: the target GValue
+ *
+ * Function to map a control-value to the target GValue.
+ */
+typedef void (* GstControlBindingConvert) (GstControlBinding *self, gdouble src_value, GValue *dest_value);
+
+/**
+ * GstControlBinding:
+ * @name: name of the property of this binding
+ *
+ * The instance structure of #GstControlBinding.
+ */
+struct _GstControlBinding {
+  GstObject parent;
+  
+  /*< public >*/
+  const gchar *name;            /* name of the property */
+  GParamSpec *pspec;            /* GParamSpec for this property */
+
+  /*< private >*/
+  GstObject *object;            /* GstObject owning the property
+                                 * (== parent when bound) */
+  gboolean disabled;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstControlBindingClass:
+ * @parent_class: Parent class
+ * @convert: Class method to convert control-values
+ *
+ * The class structure of #GstControlBinding.
+ */
+
+struct _GstControlBindingClass
+{
+  GstObjectClass parent_class;
+
+  /* virtual methods */
+  gboolean (* sync_values) (GstControlBinding *self, GstObject *object, GstClockTime timestamp, GstClockTime last_sync);
+  GValue * (* get_value) (GstControlBinding *self, GstClockTime timestamp);
+  gboolean (* get_value_array) (GstControlBinding *self, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values);
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+#define GST_CONTROL_BINDING_PSPEC(cb) (((GstControlBinding *) cb)->pspec)
+
+GType gst_control_binding_get_type (void);
+
+/* Functions */
+
+gboolean            gst_control_binding_sync_values        (GstControlBinding * self, GstObject *object, 
+                                                            GstClockTime timestamp, GstClockTime last_sync);
+GValue *            gst_control_binding_get_value          (GstControlBinding *binding,
+                                                            GstClockTime timestamp);
+gboolean            gst_control_binding_get_value_array    (GstControlBinding *binding, GstClockTime timestamp,
+                                                            GstClockTime interval, guint n_values, GValue *values);
+
+void                gst_control_binding_set_disabled       (GstControlBinding * self, gboolean disabled);
+gboolean            gst_control_binding_is_disabled        (GstControlBinding * self);
+G_END_DECLS
+
+#endif /* __GST_CONTROL_BINDING_H__ */
similarity index 65%
rename from libs/gst/controller/gstcontrolsource.c
rename to gst/gstcontrolsource.c
index 0d7d47a..6269dc4 100644 (file)
  *
  */
 
+#include "gst_private.h"
+
 #include <glib-object.h>
 #include <gst/gst.h>
 
 #include "gstcontrolsource.h"
 
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
+#define GST_CAT_DEFAULT control_source_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
-G_DEFINE_ABSTRACT_TYPE (GstControlSource, gst_control_source, G_TYPE_OBJECT);
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolsource", 0, \
+      "dynamic parameter control sources");
 
-static GObjectClass *parent_class = NULL;
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstControlSource, gst_control_source,
+    GST_TYPE_OBJECT, _do_init);
 
 static void
 gst_control_source_class_init (GstControlSourceClass * klass)
 {
-  //GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  /* Has to be implemented by children */
-  klass->bind = NULL;
 }
 
 static void
 gst_control_source_init (GstControlSource * self)
 {
-  /* Set default handlers that print a warning */
   self->get_value = NULL;
   self->get_value_array = NULL;
-  self->bound = FALSE;
 }
 
 /**
@@ -85,7 +82,7 @@ gst_control_source_init (GstControlSource * self)
  */
 gboolean
 gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp,
-    GValue * value)
+    gdouble * value)
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
 
@@ -100,56 +97,26 @@ gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp,
 /**
  * gst_control_source_get_value_array:
  * @self: the #GstControlSource object
- * @timestamp: the time that should be processed
+ * @timestamp: the first timestamp
+ * @interval: the time steps
+ * @n_values: the number of values to fetch
  * @value_array: array to put control-values in
  *
- * Gets an array of values for one element property.
- *
- * All fields of @value_array must be filled correctly. Especially the
- * @value_array->values array must be big enough to keep the requested amount
- * of values.
- *
- * The type of the values in the array is the same as the property's type.
+ * Gets an array of values for for this #GstControlSource.
  *
  * Returns: %TRUE if the given array could be filled, %FALSE otherwise
  */
 gboolean
 gst_control_source_get_value_array (GstControlSource * self,
-    GstClockTime timestamp, GstValueArray * value_array)
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
 {
   g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
 
   if (G_LIKELY (self->get_value_array)) {
-    return self->get_value_array (self, timestamp, value_array);
+    return self->get_value_array (self, timestamp, interval, n_values, values);
   } else {
     GST_ERROR ("Not bound to a specific property yet!");
     return FALSE;
   }
 }
-
-/**
- * gst_control_source_bind:
- * @self: the #GstControlSource object
- * @pspec: #GParamSpec for the property for which this #GstControlSource should generate values.
- *
- * Binds a #GstControlSource to a specific property. This must be called only once for a
- * #GstControlSource.
- *
- * Returns: %TRUE if the #GstControlSource was bound correctly, %FALSE otherwise.
- */
-gboolean
-gst_control_source_bind (GstControlSource * self, GParamSpec * pspec)
-{
-  gboolean ret = FALSE;
-
-  g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
-  g_return_val_if_fail (GST_CONTROL_SOURCE_GET_CLASS (self)->bind, FALSE);
-  g_return_val_if_fail (!self->bound, FALSE);
-
-  ret = GST_CONTROL_SOURCE_GET_CLASS (self)->bind (self, pspec);
-
-  if (ret)
-    self->bound = TRUE;
-
-  return ret;
-}
similarity index 71%
rename from libs/gst/controller/gstcontrolsource.h
rename to gst/gstcontrolsource.h
index 04fca18..5debda4 100644 (file)
 #ifndef __GST_CONTROL_SOURCE_H__
 #define __GST_CONTROL_SOURCE_H__
 
+#include <gst/gstconfig.h>
+
 #include <glib-object.h>
-#include <gst/gst.h>
+
+#include <gst/gstclock.h>
 
 G_BEGIN_DECLS
 
@@ -56,27 +59,10 @@ typedef struct _GstValueArray GstValueArray;
 struct _GstTimedValue
 {
   GstClockTime timestamp;
-  GValue value;
+  gdouble      value;
 };
 
 /**
- * GstValueArray:
- * @property_name: the name of the property this array belongs to
- * @nbsamples: number of samples requested
- * @sample_interval: interval between each sample
- * @values: pointer to the array
- *
- * Structure to receive multiple values at once.
- */
-struct _GstValueArray
-{
-  const gchar *property_name;
-  gint nbsamples;
-  GstClockTime sample_interval;
-  gpointer *values;
-};
-
-/** 
  * GstControlSourceGetValue
  * @self: the #GstControlSource instance
  * @timestamp: timestamp for which a value should be calculated
@@ -87,31 +73,24 @@ struct _GstValueArray
  * Returns: %TRUE if the value was successfully calculated.
  *
  */
-typedef gboolean (* GstControlSourceGetValue) (GstControlSource *self, GstClockTime timestamp, GValue *value);
+typedef gboolean (* GstControlSourceGetValue) (GstControlSource *self, 
+    GstClockTime timestamp, gdouble *value);
 
-/** 
+/**
  * GstControlSourceGetValueArray
  * @self: the #GstControlSource instance
  * @timestamp: timestamp for which a value should be calculated
- * @value_array: array to put control-values in
+ * @interval: the time spacing between subsequent values
+ * @n_values: the number of values
+ * @values: array to put control-values in
  *
- * Function for returning a #GstValueArray for a given timestamp.
+ * Function for returning an array of values for starting at a given timestamp.
  *
  * Returns: %TRUE if the values were successfully calculated.
  *
  */
-typedef gboolean (* GstControlSourceGetValueArray) (GstControlSource *self, GstClockTime timestamp, GstValueArray *value_array);
-
-/** 
- * GstControlSourceBind
- * @self: the #GstControlSource instance
- * @pspec: #GParamSpec that should be bound to
- *
- * Function for binding a #GstControlSource to a #GParamSpec.
- *
- * Returns: %TRUE if the property could be bound to the #GstControlSource, %FALSE otherwise.
- */
-typedef gboolean (* GstControlSourceBind) (GstControlSource *self, GParamSpec *pspec);
+typedef gboolean (* GstControlSourceGetValueArray) (GstControlSource *self, 
+    GstClockTime timestamp, GstClockTime interval, guint n_values, gdouble *values);
 
 /**
  * GstControlSource:
@@ -121,14 +100,13 @@ typedef gboolean (* GstControlSourceBind) (GstControlSource *self, GParamSpec *p
  * The instance structure of #GstControlSource.
  */
 struct _GstControlSource {
-  GObject parent;
+  GstObject parent;
 
   /*< public >*/
   GstControlSourceGetValue get_value;             /* Returns the value for a property at a given timestamp */
   GstControlSourceGetValueArray get_value_array;  /* Returns values for a property in a given timespan */
 
   /*< private >*/
-  gboolean bound;
   gpointer _gst_reserved[GST_PADDING];
 };
 
@@ -142,9 +120,7 @@ struct _GstControlSource {
 
 struct _GstControlSourceClass
 {
-  GObjectClass parent_class;
-  
-  GstControlSourceBind bind;  /* Binds the GstControlSource to a specific GParamSpec */
+  GstObjectClass parent_class;
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -153,11 +129,11 @@ struct _GstControlSourceClass
 GType gst_control_source_get_type (void);
 
 /* Functions */
-
-gboolean gst_control_source_get_value (GstControlSource *self, GstClockTime timestamp, GValue *value);
-gboolean gst_control_source_get_value_array (GstControlSource *self, GstClockTime timestamp, GstValueArray *value_array);
-gboolean gst_control_source_bind (GstControlSource *self, GParamSpec *pspec);
-
+gboolean       gst_control_source_get_value             (GstControlSource *self, GstClockTime timestamp,
+                                                         gdouble *value);
+gboolean       gst_control_source_get_value_array       (GstControlSource *self, GstClockTime timestamp,
+                                                         GstClockTime interval, guint n_values,
+                                                         gdouble *values);
 G_END_DECLS
 
 #endif /* __GST_CONTROL_SOURCE_H__ */
index 60f709f..7f6ba43 100644 (file)
 #define GST_DATE_TIME_USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
 #define GST_DATE_TIME_USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
 
+/* FIXME: this bug was resolved NOTGNOME */
 /* Jan 5th 2011 (Edward) : GLib's GDateTime is broken in regards to gmt offset
  * on macosx. Re-enable it once the following bug is fixed:
  * https://bugzilla.gnome.org/show_bug.cgi?id=638666 */
 #ifdef HAVE_OSX
 #undef GLIB_HAS_GDATETIME
+#else
+#define GLIB_HAS_GDATETIME
 #endif
 
 
index 442c353..96d8bbd 100644 (file)
@@ -36,31 +36,31 @@ G_BEGIN_DECLS
  */
 typedef struct _GstDateTime GstDateTime;
 
-gint   gst_date_time_get_year          (const GstDateTime * datetime);
-gint   gst_date_time_get_month         (const GstDateTime * datetime);
-gint   gst_date_time_get_day           (const GstDateTime * datetime);
-gint   gst_date_time_get_hour          (const GstDateTime * datetime);
-gint   gst_date_time_get_minute        (const GstDateTime * datetime);
-gint   gst_date_time_get_second        (const GstDateTime * datetime);
-gint   gst_date_time_get_microsecond   (const GstDateTime * datetime);
-gfloat gst_date_time_get_time_zone_offset (const GstDateTime * datetime);
+gint    gst_date_time_get_year             (const GstDateTime * datetime);
+gint    gst_date_time_get_month            (const GstDateTime * datetime);
+gint    gst_date_time_get_day              (const GstDateTime * datetime);
+gint    gst_date_time_get_hour             (const GstDateTime * datetime);
+gint    gst_date_time_get_minute           (const GstDateTime * datetime);
+gint    gst_date_time_get_second           (const GstDateTime * datetime);
+gint    gst_date_time_get_microsecond      (const GstDateTime * datetime);
+gfloat  gst_date_time_get_time_zone_offset (const GstDateTime * datetime);
 
-GstDateTime    *gst_date_time_new_from_unix_epoch_local_time (gint64 secs) G_GNUC_MALLOC;
-GstDateTime    *gst_date_time_new_from_unix_epoch_utc  (gint64 secs) G_GNUC_MALLOC;
-GstDateTime    *gst_date_time_new_local_time           (gint year, gint month,
-                                                        gint day, gint hour,
-                                                        gint minute,
-                                                        gdouble seconds) G_GNUC_MALLOC;
-GstDateTime    *gst_date_time_new                      (gfloat tzoffset,
-                                                        gint year, gint month,
-                                                        gint day, gint hour,
-                                                        gint minute,
-                                                        gdouble seconds) G_GNUC_MALLOC;
-GstDateTime    *gst_date_time_new_now_local_time (void) G_GNUC_MALLOC;
-GstDateTime    *gst_date_time_new_now_utc      (void) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new_from_unix_epoch_local_time (gint64 secs) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new_from_unix_epoch_utc   (gint64 secs) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new_local_time            (gint year, gint month,
+                                                         gint day, gint hour,
+                                                         gint minute,
+                                                         gdouble seconds) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new                       (gfloat tzoffset,
+                                                         gint year, gint month,
+                                                         gint day, gint hour,
+                                                         gint minute,
+                                                         gdouble seconds) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new_now_local_time (void) G_GNUC_MALLOC;
+GstDateTime *   gst_date_time_new_now_utc        (void) G_GNUC_MALLOC;
 
-GstDateTime    *gst_date_time_ref              (GstDateTime * datetime);
-void           gst_date_time_unref             (GstDateTime * datetime);
+GstDateTime *   gst_date_time_ref                (GstDateTime * datetime);
+void            gst_date_time_unref              (GstDateTime * datetime);
 
 G_END_DECLS
 #endif /* __GST_DATE_TIME_H__ */
index be8230e..eddfdac 100644 (file)
@@ -161,16 +161,17 @@ debug_dump_pad (GstPad * pad, const gchar * color_name,
     }
   }
   if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
-    gchar pad_flags[6];
+    gchar pad_flags[4];
     const gchar *activation_mode = "-><";
 
     /* check if pad flags */
-    pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b';
-    pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f';
-    pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g';
-    pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS) ? 'S' : 's';
-    pad_flags[4] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b';
-    pad_flags[5] = '\0';
+    pad_flags[0] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED) ? 'B' : 'b';
+    pad_flags[1] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING) ? 'F' : 'f';
+    pad_flags[2] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING) ? 'B' : 'b';
+    pad_flags[3] = '\0';
 
     fprintf (out,
         "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n",
@@ -348,10 +349,10 @@ debug_dump_element_pad_link (GstPad * pad, GstElement * element,
     if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
         (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
         ) {
-      caps = gst_pad_get_negotiated_caps (pad);
+      caps = gst_pad_get_current_caps (pad);
       if (!caps)
         caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-      peer_caps = gst_pad_get_negotiated_caps (peer_pad);
+      peer_caps = gst_pad_get_current_caps (peer_pad);
       if (!peer_caps)
         peer_caps = gst_caps_copy (gst_pad_get_pad_template_caps (peer_pad));
 
@@ -423,20 +424,22 @@ debug_dump_element_pads (GstIterator * pad_iter, GstPad * pad,
     GstElement * element, GstDebugGraphDetails details, FILE * out,
     const gint indent, guint * src_pads, guint * sink_pads)
 {
+  GValue item = { 0, };
   gboolean pads_done;
   GstPadDirection dir;
 
   pads_done = FALSE;
   while (!pads_done) {
-    switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
+    switch (gst_iterator_next (pad_iter, &item)) {
       case GST_ITERATOR_OK:
+        pad = g_value_get_object (&item);
         debug_dump_element_pad (pad, element, details, out, indent);
         dir = gst_pad_get_direction (pad);
         if (dir == GST_PAD_SRC)
           (*src_pads)++;
         else if (dir == GST_PAD_SINK)
           (*sink_pads)++;
-        gst_object_unref (pad);
+        g_value_reset (&item);
         break;
       case GST_ITERATOR_RESYNC:
         gst_iterator_resync (pad_iter);
@@ -455,7 +458,7 @@ debug_dump_element_pads (GstIterator * pad_iter, GstPad * pad,
  * @out: file to write to
  * @indent: level of graph indentation
  *
- * Helper for _gst_debug_bin_to_dot_file() to recursively dump a pipeline.
+ * Helper for gst_debug_bin_to_dot_file() to recursively dump a pipeline.
  */
 static void
 debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
@@ -463,8 +466,10 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
 {
   GstIterator *element_iter, *pad_iter;
   gboolean elements_done, pads_done;
+  GValue item = { 0, };
+  GValue item2 = { 0, };
   GstElement *element;
-  GstPad *pad;
+  GstPad *pad = NULL;
   guint src_pads, sink_pads;
   gchar *element_name;
   gchar *state_name = NULL;
@@ -474,8 +479,9 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
   element_iter = gst_bin_iterate_elements (bin);
   elements_done = FALSE;
   while (!elements_done) {
-    switch (gst_iterator_next (element_iter, (gpointer) & element)) {
+    switch (gst_iterator_next (element_iter, &item)) {
       case GST_ITERATOR_OK:
+        element = g_value_get_object (&item);
         element_name = debug_dump_make_object_name (GST_OBJECT (element));
 
         if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
@@ -533,8 +539,9 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
         if ((pad_iter = gst_element_iterate_pads (element))) {
           pads_done = FALSE;
           while (!pads_done) {
-            switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
+            switch (gst_iterator_next (pad_iter, &item2)) {
               case GST_ITERATOR_OK:
+                pad = g_value_get_object (&item2);
                 if (gst_pad_is_linked (pad)) {
                   if (gst_pad_get_direction (pad) == GST_PAD_SRC) {
                     debug_dump_element_pad_link (pad, element, details, out,
@@ -552,7 +559,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
                     }
                   }
                 }
-                gst_object_unref (pad);
+                g_value_reset (&item2);
                 break;
               case GST_ITERATOR_RESYNC:
                 gst_iterator_resync (pad_iter);
@@ -563,9 +570,10 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
                 break;
             }
           }
+          g_value_unset (&item2);
           gst_iterator_free (pad_iter);
         }
-        gst_object_unref (element);
+        g_value_reset (&item);
         break;
       case GST_ITERATOR_RESYNC:
         gst_iterator_resync (element_iter);
@@ -576,11 +584,13 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
         break;
     }
   }
+
+  g_value_unset (&item);
   gst_iterator_free (element_iter);
 }
 
 /*
- * _gst_debug_bin_to_dot_file:
+ * gst_debug_bin_to_dot_file:
  * @bin: the top-level pipeline that should be analyzed
  * @file_name: output base filename (e.g. "myplayer")
  *
@@ -592,7 +602,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
  * </programlisting></informalexample>
  */
 void
-_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
   gchar *full_file_name = NULL;
@@ -657,16 +667,16 @@ _gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
 }
 
 /*
- * _gst_debug_bin_to_dot_file_with_ts:
+ * gst_debug_bin_to_dot_file_with_ts:
  * @bin: the top-level pipeline that should be analyzed
  * @file_name: output base filename (e.g. "myplayer")
  *
- * This works like _gst_debug_bin_to_dot_file(), but adds the current timestamp
+ * This works like gst_debug_bin_to_dot_file(), but adds the current timestamp
  * to the filename, so that it can be used to take multiple snapshots.
  */
 void
-_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
-    const gchar * file_name)
+gst_debug_bin_to_dot_file_with_ts (GstBin * bin,
+    GstDebugGraphDetails details, const gchar * file_name)
 {
   gchar *ts_file_name = NULL;
   GstClockTime elapsed;
@@ -689,19 +699,19 @@ _gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
       g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed),
       file_name);
 
-  _gst_debug_bin_to_dot_file (bin, details, ts_file_name);
+  gst_debug_bin_to_dot_file (bin, details, ts_file_name);
   g_free (ts_file_name);
 }
 #else /* !GST_DISABLE_GST_DEBUG */
 #ifndef GST_REMOVE_DISABLED
 void
-_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
 }
 
 void
-_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
 }
index 1f18308..8420d3b 100644 (file)
@@ -53,8 +53,8 @@ typedef enum {
 
 /********** pipeline graphs **********/
 
-void _gst_debug_bin_to_dot_file (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name);
-void _gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name);
+void gst_debug_bin_to_dot_file (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name);
+void gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails details, const gchar *file_name);
 
 #ifndef GST_DISABLE_GST_DEBUG
 
@@ -78,7 +78,7 @@ void _gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails detai
  *
  * Since: 0.10.15
  */
-#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) _gst_debug_bin_to_dot_file (bin, details, file_name)
+#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) gst_debug_bin_to_dot_file (bin, details, file_name)
 
 /**
  * GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS:
@@ -92,7 +92,7 @@ void _gst_debug_bin_to_dot_file_with_ts (GstBin *bin, GstDebugGraphDetails detai
  *
  * Since: 0.10.15
  */
-#define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) _gst_debug_bin_to_dot_file_with_ts (bin, details, file_name)
+#define GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(bin, details, file_name) gst_debug_bin_to_dot_file_with_ts (bin, details, file_name)
 
 
 #else /* GST_DISABLE_GST_DEBUG */
index 9328dfe..91a4c4c 100644 (file)
  * Last reviewed on 2009-05-29 (0.10.24)
  */
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "gst_private.h"
 #include <glib.h>
 #include <stdarg.h>
 #include <gobject/gvaluecollector.h>
 
 #include "gstelement.h"
-#include "gstelementdetails.h"
+#include "gstelementmetadata.h"
 #include "gstenumtypes.h"
 #include "gstbus.h"
 #include "gstmarshal.h"
@@ -116,16 +113,6 @@ enum
       /* FILL ME */
 };
 
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#include <libxml/parser.h>
-xmlNodePtr gst_object_save_thyself (const GstObject * object,
-    xmlNodePtr parent);
-GstObject *gst_object_load_thyself (xmlNodePtr parent);
-void gst_pad_load_and_link (xmlNodePtr self, GstObject * parent);
-#endif
-#endif
-
 static void gst_element_class_init (GstElementClass * klass);
 static void gst_element_init (GstElement * element);
 static void gst_element_base_class_init (gpointer g_class);
@@ -140,6 +127,8 @@ static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
     GstState * state, GstState * pending, GstClockTime timeout);
 static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
     GstState state);
+static gboolean gst_element_set_clock_func (GstElement * element,
+    GstClock * clock);
 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
 
 static gboolean gst_element_default_send_event (GstElement * element,
@@ -151,17 +140,11 @@ static GstPadTemplate
     * gst_element_class_get_request_pad_template (GstElementClass *
     element_class, const gchar * name);
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static xmlNodePtr gst_element_save_thyself (GstObject * object,
-    xmlNodePtr parent);
-static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
-#endif
-
 static GstObjectClass *parent_class = NULL;
 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
 
 /* this is used in gstelementfactory.c:gst_element_register() */
-GQuark _gst_elementclass_factory = 0;
+GQuark __gst_elementclass_factory = 0;
 
 GType
 gst_element_get_type (void)
@@ -186,7 +169,7 @@ gst_element_get_type (void)
     _type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
         &element_info, G_TYPE_FLAG_ABSTRACT);
 
-    _gst_elementclass_factory =
+    __gst_elementclass_factory =
         g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
     g_once_init_leave (&gst_element_type, _type);
   }
@@ -196,10 +179,9 @@ gst_element_get_type (void)
 static void
 gst_element_class_init (GstElementClass * klass)
 {
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  GstObjectClass *gstobject_class = (GstObjectClass *) klass;
-#endif
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -245,18 +227,10 @@ gst_element_class_init (GstElementClass * klass)
   gobject_class->dispose = gst_element_dispose;
   gobject_class->finalize = gst_element_finalize;
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  gstobject_class->save_thyself =
-      ((gpointer (*)(GstObject * object,
-              gpointer self)) * GST_DEBUG_FUNCPTR (gst_element_save_thyself));
-  gstobject_class->restore_thyself =
-      ((void (*)(GstObject * object,
-              gpointer self)) *GST_DEBUG_FUNCPTR (gst_element_restore_thyself));
-#endif
-
   klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
   klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
   klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
+  klass->set_clock = GST_DEBUG_FUNCPTR (gst_element_set_clock_func);
   klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
   klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
   klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
@@ -269,24 +243,30 @@ static void
 gst_element_base_class_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  /* FIXME 0.11: Copy the element details and instead of clearing the
-   * pad template list copy the list and increase the refcount of
-   * the pad templates by one.
-   *
-   * This will make it possible to add pad templates and set element
-   * details in the class_init functions and is the real GObject way
-   * of doing things.
-   * See http://bugzilla.gnome.org/show_bug.cgi?id=491501
+  GList *node, *padtemplates;
+
+  /* Copy the element details here so elements can inherit the
+   * details from their base class and classes only need to set
+   * the details in class_init instead of base_init */
+  element_class->metadata =
+      element_class->metadata ? gst_structure_copy (element_class->metadata) :
+      gst_structure_new_empty ("metadata");
+
+  /* Copy the pad templates so elements inherit them
+   * from their base class but elements can add pad templates in class_init
+   * instead of base_init.
    */
-  memset (&element_class->details, 0, sizeof (GstElementDetails));
-  element_class->meta_data = NULL;
-  element_class->padtemplates = NULL;
+  padtemplates = g_list_copy (element_class->padtemplates);
+  for (node = padtemplates; node != NULL; node = node->next) {
+    GstPadTemplate *tmpl = (GstPadTemplate *) node->data;
+    gst_object_ref (tmpl);
+  }
+  element_class->padtemplates = padtemplates;
 
   /* set the factory, see gst_element_register() */
   element_class->elementfactory =
       g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
-      _gst_elementclass_factory);
+      __gst_elementclass_factory);
   GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
       element_class->elementfactory);
 }
@@ -298,11 +278,8 @@ gst_element_base_class_finalize (gpointer g_class)
 
   g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
   g_list_free (klass->padtemplates);
-  __gst_element_details_clear (&klass->details);
-  if (klass->meta_data) {
-    gst_structure_free (klass->meta_data);
-    klass->meta_data = NULL;
-  }
+
+  gst_structure_free (klass->metadata);
 }
 
 static void
@@ -314,10 +291,8 @@ gst_element_init (GstElement * element)
   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
   GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
 
-  /* FIXME 0.11: Store this directly in the instance struct */
-  element->state_lock = g_slice_new (GStaticRecMutex);
-  g_static_rec_mutex_init (element->state_lock);
-  element->state_cond = g_cond_new ();
+  g_rec_mutex_init (&element->state_lock);
+  g_cond_init (&element->state_cond);
 }
 
 /**
@@ -353,54 +328,6 @@ gst_element_release_request_pad (GstElement * element, GstPad * pad)
 }
 
 /**
- * gst_element_requires_clock:
- * @element: a #GstElement to query
- *
- * Query if the element requires a clock.
- *
- * Returns: %TRUE if the element requires a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_requires_clock (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
-
-  return result;
-}
-
-/**
- * gst_element_provides_clock:
- * @element: a #GstElement to query
- *
- * Query if the element provides a clock. A #GstClock provided by an
- * element can be used as the global #GstClock for the pipeline.
- * An element that can provide a clock is only required to do so in the PAUSED
- * state, this means when it is fully negotiated and has allocated the resources
- * to operate the clock.
- *
- * Returns: %TRUE if the element provides a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_provides_clock (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
-
-  return result;
-}
-
-/**
  * gst_element_provide_clock:
  * @element: a #GstElement to query
  *
@@ -429,6 +356,19 @@ gst_element_provide_clock (GstElement * element)
   return result;
 }
 
+static gboolean
+gst_element_set_clock_func (GstElement * element, GstClock * clock)
+{
+  GstClock **clock_p;
+
+  GST_OBJECT_LOCK (element);
+  clock_p = &element->clock;
+  gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
+  GST_OBJECT_UNLOCK (element);
+
+  return TRUE;
+}
+
 /**
  * gst_element_set_clock:
  * @element: a #GstElement to set the clock for.
@@ -448,8 +388,7 @@ gboolean
 gst_element_set_clock (GstElement * element, GstClock * clock)
 {
   GstElementClass *oclass;
-  gboolean res = TRUE;
-  GstClock **clock_p;
+  gboolean res = FALSE;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
   g_return_val_if_fail (clock == NULL || GST_IS_CLOCK (clock), FALSE);
@@ -461,13 +400,6 @@ gst_element_set_clock (GstElement * element, GstClock * clock)
   if (oclass->set_clock)
     res = oclass->set_clock (element, clock);
 
-  if (res) {
-    /* only update the clock pointer if the element accepted the clock */
-    GST_OBJECT_LOCK (element);
-    clock_p = &element->clock;
-    gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
-    GST_OBJECT_UNLOCK (element);
-  }
   return res;
 }
 
@@ -617,28 +549,7 @@ gst_element_get_start_time (GstElement * element)
   return result;
 }
 
-/**
- * gst_element_is_indexable:
- * @element: a #GstElement.
- *
- * Queries if the element can be indexed.
- *
- * Returns: TRUE if the element can be indexed.
- *
- * MT safe.
- */
-gboolean
-gst_element_is_indexable (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
-
-  return result;
-}
-
+#if 0
 /**
  * gst_element_set_index:
  * @element: a #GstElement.
@@ -689,6 +600,7 @@ gst_element_get_index (GstElement * element)
 
   return result;
 }
+#endif
 
 /**
  * gst_element_add_pad:
@@ -727,6 +639,7 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
       GST_STR_NULL (pad_name));
   flushing = GST_PAD_IS_FLUSHING (pad);
+  GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT);
   GST_OBJECT_UNLOCK (pad);
 
   /* then check to see if there's already a pad by that name here */
@@ -893,12 +806,15 @@ gst_element_remove_pad (GstElement * element, GstPad * pad)
   /* ERRORS */
 not_our_pad:
   {
-    /* FIXME, locking order? */
+    /* locking order is element > pad */
+    GST_OBJECT_UNLOCK (pad);
+
     GST_OBJECT_LOCK (element);
+    GST_OBJECT_LOCK (pad);
     g_critical ("Padname %s:%s does not belong to element %s when removing",
         GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
-    GST_OBJECT_UNLOCK (element);
     GST_OBJECT_UNLOCK (pad);
+    GST_OBJECT_UNLOCK (element);
     return FALSE;
   }
 }
@@ -1037,10 +953,8 @@ _gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
   }
 #endif
 
-  if (oclass->request_new_pad_full)
-    newpad = (oclass->request_new_pad_full) (element, templ, name, caps);
-  else if (oclass->request_new_pad)
-    newpad = (oclass->request_new_pad) (element, templ, name);
+  if (oclass->request_new_pad)
+    newpad = (oclass->request_new_pad) (element, templ, name, caps);
 
   if (newpad)
     gst_object_ref (newpad);
@@ -1163,10 +1077,6 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
  * Pad templates can be looked up using
  * gst_element_factory_get_static_pad_templates().
  *
- * If the @caps are specified and the element implements thew new
- * request_new_pad_full virtual method, the element will use them to select
- * which pad to create.
- *
  * The pad should be released with gst_element_release_request_pad().
  *
  * Returns: (transfer full): requested #GstPad if found, otherwise %NULL.
@@ -1184,63 +1094,15 @@ gst_element_request_pad (GstElement * element,
   return _gst_element_request_pad (element, templ, name, caps);
 }
 
-/**
- * gst_element_get_pad:
- * @element: a #GstElement.
- * @name: the name of the pad to retrieve.
- *
- * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
- * first, then gst_element_get_request_pad().
- *
- * Deprecated: This function is deprecated as it's unclear if the reference
- * to the result pad should be released with gst_object_unref() in case of a static pad
- * or gst_element_release_request_pad() in case of a request pad.
- * Use gst_element_get_static_pad() or gst_element_get_request_pad() instead.
- *
- * Returns: (transfer full): the #GstPad if found, otherwise %NULL. Unref or Release after usage,
- * depending on the type of the pad.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-GstPad *gst_element_get_pad (GstElement * element, const gchar * name);
-#endif
-GstPad *
-gst_element_get_pad (GstElement * element, const gchar * name)
-{
-  GstPad *pad;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-  g_return_val_if_fail (name != NULL, NULL);
-
-  pad = gst_element_get_static_pad (element, name);
-  if (!pad)
-    pad = gst_element_get_request_pad (element, name);
-
-  return pad;
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-static GstIteratorItem
-iterate_pad (GstIterator * it, GstPad * pad)
-{
-  gst_object_ref (pad);
-  return GST_ITERATOR_ITEM_PASS;
-}
-
 static GstIterator *
 gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
 {
   GstIterator *result;
 
   GST_OBJECT_LOCK (element);
-  gst_object_ref (element);
   result = gst_iterator_new_list (GST_TYPE_PAD,
       GST_OBJECT_GET_LOCK (element),
-      &element->pads_cookie,
-      padlist,
-      element,
-      (GstIteratorItemFunction) iterate_pad,
-      (GstIteratorDisposeFunction) gst_object_unref);
+      &element->pads_cookie, padlist, (GObject *) element, NULL);
   GST_OBJECT_UNLOCK (element);
 
   return result;
@@ -1308,140 +1170,66 @@ gst_element_iterate_sink_pads (GstElement * element)
 /**
  * gst_element_class_add_pad_template:
  * @klass: the #GstElementClass to add the pad template to.
- * @templ: (transfer none): a #GstPadTemplate to add to the element class.
+ * @templ: (transfer full): a #GstPadTemplate to add to the element class.
+ *
+ * Adds a padtemplate to an element class. This is mainly used in the _class_init
+ * functions of classes. If a pad template with the same name as an already
+ * existing one is added the old one is replaced by the new one.
  *
- * Adds a padtemplate to an element class. This is mainly used in the _base_init
- * functions of classes.
  */
 void
 gst_element_class_add_pad_template (GstElementClass * klass,
     GstPadTemplate * templ)
 {
-  g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
-  g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
-
-  /* FIXME 0.11: allow replacing the pad templates by
-   * calling this with the same name as an already existing pad
-   * template. For this we _must_ _not_ ref the added pad template
-   * a second time and _must_ document that this function takes
-   * ownership of the pad template. Otherwise we will leak pad templates
-   * or the caller unref's the pad template and it disappears */
-  /* avoid registering pad templates with the same name */
-  g_return_if_fail (gst_element_class_get_pad_template (klass,
-          templ->name_template) == NULL);
-
-  klass->padtemplates = g_list_append (klass->padtemplates,
-      gst_object_ref (templ));
-  klass->numpadtemplates++;
-}
-
-/**
- * gst_element_class_add_static_pad_template:
- * @klass: the #GstElementClass to add the pad template to.
- * @templ: (transfer none): a #GstStaticPadTemplate describing the pad
- * to add to the element class.
- *
- * Adds a padtemplate to an element class. This is mainly used in the _base_init
- * functions of classes.
- *
- * Since: 0.10.36
- */
-void
-gst_element_class_add_static_pad_template (GstElementClass * klass,
-    GstStaticPadTemplate * templ)
-{
-  GstPadTemplate *pt;
+  GList *template_list = klass->padtemplates;
 
   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+  g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
 
-  pt = gst_static_pad_template_get (templ);
-  gst_element_class_add_pad_template (klass, pt);
-  gst_object_unref (pt);
-}
+  /* If we already have a pad template with the same name replace the
+   * old one. */
+  while (template_list) {
+    GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data;
 
-static void
-gst_element_class_add_meta_data (GstElementClass * klass,
-    const gchar * key, const gchar * value)
-{
-  if (!klass->meta_data) {
-    /* FIXME: use a quark for "metadata" */
-    klass->meta_data = gst_structure_empty_new ("metadata");
+    /* Found pad with the same name, replace and return */
+    if (strcmp (templ->name_template, padtempl->name_template) == 0) {
+      gst_object_unref (padtempl);
+      template_list->data = templ;
+      return;
+    }
+    template_list = g_list_next (template_list);
   }
 
-  gst_structure_set ((GstStructure *) klass->meta_data,
-      key, G_TYPE_STRING, value, NULL);
-}
-
-/**
- * gst_element_class_set_documentation_uri:
- * @klass: class to set details for
- * @uri: uri of element documentation
- *
- * Set uri pointing to user documentation. Applications can use this to show
- * help for e.g. effects to users.
- *
- * Since: 0.10.31
- */
-void
-gst_element_class_set_documentation_uri (GstElementClass * klass,
-    const gchar * uri)
-{
-  g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
-
-  gst_element_class_add_meta_data (klass, "doc-uri", uri);
-}
-
-/**
- * gst_element_class_set_icon_name:
- * @klass: class to set details for
- * @name: name of an icon
- *
- * Elements that bridge to certain other products can include an icon of that
- * used product. Application can show the icon in menus/selectors to help
- * identifying specific elements.
- *
- * Since: 0.10.31
- */
-void
-gst_element_class_set_icon_name (GstElementClass * klass, const gchar * name)
-{
-  g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+  /* Take ownership of the floating ref */
+  gst_object_ref_sink (templ);
 
-  gst_element_class_add_meta_data (klass, "icon-name", name);
+  klass->padtemplates = g_list_append (klass->padtemplates, templ);
+  klass->numpadtemplates++;
 }
 
-/* FIXME-0.11: deprecate and remove gst_element_class_set_details*() */
 /**
- * gst_element_class_set_details:
- * @klass: class to set details for
- * @details: details to set
- *
- * Sets the detailed information for a #GstElementClass.
- * <note>This function is for use in _base_init functions only.</note>
+ * gst_element_class_add_metadata:
+ * @klass: class to set metadata for
+ * @key: the key to set
+ * @value: the value to set
  *
- * The @details are copied.
- *
- * Deprecated: Use gst_element_class_set_details_simple() instead.
+ * Set @key with @value as metadata in @klass.
  */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void gst_element_class_set_details (GstElementClass * klass,
-    const GstElementDetails * details);
-#endif
 void
-gst_element_class_set_details (GstElementClass * klass,
-    const GstElementDetails * details)
+gst_element_class_add_metadata (GstElementClass * klass,
+    const gchar * key, const gchar * value)
 {
   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
-  g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
+  g_return_if_fail (key != NULL);
+  g_return_if_fail (value != NULL);
 
-  __gst_element_details_copy (&klass->details, details);
+  gst_structure_set ((GstStructure *) klass->metadata,
+      key, G_TYPE_STRING, value, NULL);
 }
-#endif
 
 /**
- * gst_element_class_set_details_simple:
- * @klass: class to set details for
+ * gst_element_class_set_metadata:
+ * @klass: class to set metadata for
  * @longname: The long English name of the element. E.g. "File Sink"
  * @classification: String describing the type of element, as an unordered list
  * separated with slashes ('/'). See draft-klass.txt of the design docs
@@ -1449,29 +1237,41 @@ gst_element_class_set_details (GstElementClass * klass,
  * @description: Sentence describing the purpose of the element.
  * E.g: "Write stream to a file"
  * @author: Name and contact details of the author(s). Use \n to separate
- * multiple author details. E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
+ * multiple author metadata. E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
  *
- * Sets the detailed information for a #GstElementClass. Simpler version of
- * gst_element_class_set_details() that generates less linker overhead.
- * <note>This function is for use in _base_init functions only.</note>
- *
- * The detail parameter strings are copied into the #GstElementDetails for
- * the element class.
- *
- * Since: 0.10.14
+ * Sets the detailed information for a #GstElementClass.
+ * <note>This function is for use in _class_init functions only.</note>
  */
 void
-gst_element_class_set_details_simple (GstElementClass * klass,
+gst_element_class_set_metadata (GstElementClass * klass,
     const gchar * longname, const gchar * classification,
     const gchar * description, const gchar * author)
 {
-  const GstElementDetails details =
-      GST_ELEMENT_DETAILS ((gchar *) longname, (gchar *) classification,
-      (gchar *) description, (gchar *) author);
-
   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
 
-  __gst_element_details_copy (&klass->details, &details);
+  gst_structure_set ((GstStructure *) klass->metadata,
+      GST_ELEMENT_METADATA_LONGNAME, G_TYPE_STRING, longname,
+      GST_ELEMENT_METADATA_KLASS, G_TYPE_STRING, classification,
+      GST_ELEMENT_METADATA_DESCRIPTION, G_TYPE_STRING, description,
+      GST_ELEMENT_METADATA_AUTHOR, G_TYPE_STRING, author, NULL);
+}
+
+/**
+ * gst_element_class_get_metadata:
+ * @klass: class to get metadata for
+ * @key: the key to get
+ *
+ * Get metadata with @key in @klass.
+ *
+ * Returns: the metadata for @key.
+ */
+const gchar *
+gst_element_class_get_metadata (GstElementClass * klass, const gchar * key)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT_CLASS (klass), NULL);
+  g_return_val_if_fail (key != NULL, NULL);
+
+  return gst_structure_get_string ((GstStructure *) klass->metadata, key);
 }
 
 /**
@@ -1665,8 +1465,6 @@ gst_element_send_event (GstElement * element, GstEvent * event)
     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
         GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
     result = oclass->send_event (element, event);
-  } else {
-    result = gst_element_default_send_event (element, event);
   }
   GST_STATE_UNLOCK (element);
 
@@ -1709,48 +1507,6 @@ gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
   return result;
 }
 
-/**
- * gst_element_get_query_types:
- * @element: a #GstElement to query
- *
- * Get an array of query types from the element.
- * If the element doesn't implement a query types function,
- * the query will be forwarded to the peer of a random linked sink pad.
- *
- * Returns: An array of #GstQueryType elements that should not
- * be freed or modified.
- *
- * MT safe.
- */
-const GstQueryType *
-gst_element_get_query_types (GstElement * element)
-{
-  GstElementClass *oclass;
-  const GstQueryType *result = NULL;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
-  oclass = GST_ELEMENT_GET_CLASS (element);
-
-  if (oclass->get_query_types) {
-    result = oclass->get_query_types (element);
-  } else {
-    GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
-
-    if (pad) {
-      GstPad *peer = gst_pad_get_peer (pad);
-
-      if (peer) {
-        result = gst_pad_get_query_types (peer);
-
-        gst_object_unref (peer);
-      }
-      gst_object_unref (pad);
-    }
-  }
-  return result;
-}
-
 static gboolean
 gst_element_default_query (GstElement * element, GstQuery * query)
 {
@@ -1810,8 +1566,6 @@ gst_element_query (GstElement * element, GstQuery * query)
     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
         GST_ELEMENT_NAME (element));
     result = oclass->query (element, query);
-  } else {
-    result = gst_element_default_query (element, query);
   }
   return result;
 }
@@ -2014,7 +1768,7 @@ gst_element_is_locked_state (GstElement * element)
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
 
   GST_OBJECT_LOCK (element);
-  result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+  result = GST_ELEMENT_IS_LOCKED_STATE (element);
   GST_OBJECT_UNLOCK (element);
 
   return result;
@@ -2041,7 +1795,7 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state)
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
 
   GST_OBJECT_LOCK (element);
-  old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+  old = GST_ELEMENT_IS_LOCKED_STATE (element);
 
   if (G_UNLIKELY (old == locked_state))
     goto was_ok;
@@ -2049,11 +1803,11 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state)
   if (locked_state) {
     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
         GST_ELEMENT_NAME (element));
-    GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
+    GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
   } else {
     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
         GST_ELEMENT_NAME (element));
-    GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
+    GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
   }
   GST_OBJECT_UNLOCK (element);
 
@@ -2165,22 +1919,9 @@ gst_element_get_state_func (GstElement * element,
 
   old_pending = GST_STATE_PENDING (element);
   if (old_pending != GST_STATE_VOID_PENDING) {
-    GTimeVal *timeval, abstimeout;
+    gboolean signaled;
     guint32 cookie;
 
-    if (timeout != GST_CLOCK_TIME_NONE) {
-      glong add = timeout / 1000;
-
-      if (add == 0)
-        goto done;
-
-      /* make timeout absolute */
-      g_get_current_time (&abstimeout);
-      g_time_val_add (&abstimeout, add);
-      timeval = &abstimeout;
-    } else {
-      timeval = NULL;
-    }
     /* get cookie to detect state changes during waiting */
     cookie = element->state_cookie;
 
@@ -2188,7 +1929,17 @@ gst_element_get_state_func (GstElement * element,
         "waiting for element to commit state");
 
     /* we have a pending state change, wait for it to complete */
-    if (!GST_STATE_TIMED_WAIT (element, timeval)) {
+    if (timeout != GST_CLOCK_TIME_NONE) {
+      gint64 end_time;
+      /* make timeout absolute */
+      end_time = g_get_monotonic_time () + (timeout / 1000);
+      signaled = GST_STATE_WAIT_UNTIL (element, end_time);
+    } else {
+      GST_STATE_WAIT (element);
+      signaled = TRUE;
+    }
+
+    if (!signaled) {
       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
       /* timeout triggered */
       ret = GST_STATE_CHANGE_ASYNC;
@@ -2477,19 +2228,16 @@ complete:
 }
 
 /**
- * gst_element_lost_state_full:
+ * gst_element_lost_state:
  * @element: a #GstElement the state is lost of
- * @new_base_time: if a new base time should be distributed
  *
  * Brings the element to the lost state. The current state of the
  * element is copied to the pending state so that any call to
  * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
  *
- * An ASYNC_START message is posted with indication to distribute a new
- * base_time to the element when @new_base_time is %TRUE.
- * If the element was PLAYING, it will go to PAUSED. The element
- * will be restored to its PLAYING state by the parent pipeline when it
- * prerolls again.
+ * An ASYNC_START message is posted. If the element was PLAYING, it will
+ * go to PAUSED. The element will be restored to its PLAYING state by
+ * the parent pipeline when it prerolls again.
  *
  * This is mostly used for elements that lost their preroll buffer
  * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush,
@@ -2499,13 +2247,9 @@ complete:
  *
  * This function is used internally and should normally not be called from
  * plugins or applications.
- *
- * MT safe.
- *
- * Since: 0.10.24
  */
 void
-gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
+gst_element_lost_state (GstElement * element)
 {
   GstState old_state, new_state;
   GstMessage *message;
@@ -2537,14 +2281,11 @@ gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
   GST_STATE_NEXT (element) = new_state;
   GST_STATE_PENDING (element) = new_state;
   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
-  if (new_base_time)
-    GST_ELEMENT_START_TIME (element) = 0;
   GST_OBJECT_UNLOCK (element);
 
   _priv_gst_element_state_changed (element, new_state, new_state, new_state);
 
-  message =
-      gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time);
+  message = gst_message_new_async_start (GST_OBJECT_CAST (element));
   gst_element_post_message (element, message);
 
   return;
@@ -2558,31 +2299,13 @@ only_async_start:
   {
     GST_OBJECT_UNLOCK (element);
 
-    message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
+    message = gst_message_new_async_start (GST_OBJECT_CAST (element));
     gst_element_post_message (element, message);
     return;
   }
 }
 
 /**
- * gst_element_lost_state:
- * @element: a #GstElement the state is lost of
- *
- * Brings the element to the lost state. This function calls
- * gst_element_lost_state_full() with the new_base_time set to %TRUE.
- *
- * This function is used internally and should normally not be called from
- * plugins or applications.
- *
- * MT safe.
- */
-void
-gst_element_lost_state (GstElement * element)
-{
-  gst_element_lost_state_full (element, TRUE);
-}
-
-/**
  * gst_element_set_state:
  * @element: a #GstElement to change state of.
  * @state: the element's new #GstState.
@@ -2838,27 +2561,17 @@ invalid_return:
 /* gst_iterator_fold functions for pads_activate
  * Stop the iterator if activating one pad failed. */
 static gboolean
-activate_pads (GstPad * pad, GValue * ret, gboolean * active)
+activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
 {
+  GstPad *pad = g_value_get_object (vpad);
   gboolean cont = TRUE;
 
   if (!(cont = gst_pad_set_active (pad, *active)))
     g_value_set_boolean (ret, FALSE);
 
-  /* unref the object that was reffed for us by _fold */
-  gst_object_unref (pad);
   return cont;
 }
 
-/* set the caps on the pad to NULL */
-static gboolean
-clear_caps (GstPad * pad, GValue * ret, gboolean * active)
-{
-  gst_pad_set_caps (pad, NULL);
-  gst_object_unref (pad);
-  return TRUE;
-}
-
 /* returns false on error or early cutout of the fold, true if all
  * pads in @iter were (de)activated successfully. */
 static gboolean
@@ -2924,17 +2637,6 @@ gst_element_pads_activate (GstElement * element, gboolean active)
   if (G_UNLIKELY (!res))
     goto sink_failed;
 
-  if (!active) {
-    /* clear the caps on all pads, this should never fail */
-    iter = gst_element_iterate_pads (element);
-    res =
-        iterator_activate_fold_with_resync (iter,
-        (GstIteratorFoldFunction) clear_caps, &active);
-    gst_iterator_free (iter);
-    if (G_UNLIKELY (!res))
-      goto caps_failed;
-  }
-
   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
       "pads_activate successful");
 
@@ -2953,12 +2655,6 @@ sink_failed:
         "sink pads_activate failed");
     return FALSE;
   }
-caps_failed:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
-        "failed to clear caps on pads");
-    return FALSE;
-  }
 }
 
 /* is called with STATE_LOCK */
@@ -2967,7 +2663,6 @@ gst_element_change_state_func (GstElement * element, GstStateChange transition)
 {
   GstState state, next;
   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
-  GstClock **clock_p;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
 
@@ -3001,15 +2696,7 @@ gst_element_change_state_func (GstElement * element, GstStateChange transition)
          ready->paused but the element might not have made it to paused */
       if (!gst_element_pads_activate (element, FALSE)) {
         result = GST_STATE_CHANGE_FAILURE;
-      } else {
-        gst_element_set_base_time (element, 0);
       }
-
-      /* In null state release the reference to the clock */
-      GST_OBJECT_LOCK (element);
-      clock_p = &element->clock;
-      gst_object_replace ((GstObject **) clock_p, NULL);
-      GST_OBJECT_UNLOCK (element);
       break;
     default:
       /* this will catch real but unhandled state changes;
@@ -3096,7 +2783,7 @@ not_null:
   {
     gboolean is_locked;
 
-    is_locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+    is_locked = GST_ELEMENT_IS_LOCKED_STATE (element);
     g_critical
         ("\nTrying to dispose element %s, but it is in %s%s instead of the NULL"
         " state.\n"
@@ -3118,162 +2805,14 @@ gst_element_finalize (GObject * object)
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
 
-  GST_STATE_LOCK (element);
-  if (element->state_cond)
-    g_cond_free (element->state_cond);
-  element->state_cond = NULL;
-  GST_STATE_UNLOCK (element);
-  g_static_rec_mutex_free (element->state_lock);
-  g_slice_free (GStaticRecMutex, element->state_lock);
-  element->state_lock = NULL;
+  g_cond_clear (&element->state_cond);
+  g_rec_mutex_clear (&element->state_lock);
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-/**
- * gst_element_save_thyself:
- * @element: a #GstElement to save.
- * @parent: the xml parent node.
- *
- * Saves the element as part of the given XML structure.
- *
- * Returns: the new #xmlNodePtr.
- */
-static xmlNodePtr
-gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
-{
-  GList *pads;
-  GstElementClass *oclass;
-  GParamSpec **specs, *spec;
-  guint nspecs;
-  guint i;
-  GValue value = { 0, };
-  GstElement *element;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
-
-  element = GST_ELEMENT_CAST (object);
-
-  oclass = GST_ELEMENT_GET_CLASS (element);
-
-  xmlNewChild (parent, NULL, (xmlChar *) "name",
-      (xmlChar *) GST_ELEMENT_NAME (element));
-
-  if (oclass->elementfactory != NULL) {
-    GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
-
-    xmlNewChild (parent, NULL, (xmlChar *) "type",
-        (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
-  }
-
-  /* params */
-  specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
-
-  for (i = 0; i < nspecs; i++) {
-    spec = specs[i];
-    if (spec->flags & G_PARAM_READABLE) {
-      xmlNodePtr param;
-      char *contents;
-
-      g_value_init (&value, spec->value_type);
-
-      g_object_get_property (G_OBJECT (element), spec->name, &value);
-      param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
-      xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
-
-      if (G_IS_PARAM_SPEC_STRING (spec))
-        contents = g_value_dup_string (&value);
-      else if (G_IS_PARAM_SPEC_ENUM (spec))
-        contents = g_strdup_printf ("%d", g_value_get_enum (&value));
-      else if (G_IS_PARAM_SPEC_INT64 (spec))
-        contents = g_strdup_printf ("%" G_GINT64_FORMAT,
-            g_value_get_int64 (&value));
-      else if (GST_VALUE_HOLDS_STRUCTURE (&value)) {
-        if (g_value_get_boxed (&value) != NULL) {
-          contents = g_strdup_value_contents (&value);
-        } else {
-          contents = g_strdup ("NULL");
-        }
-      } else
-        contents = g_strdup_value_contents (&value);
-
-      xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
-      g_free (contents);
-
-      g_value_unset (&value);
-    }
-  }
-
-  g_free (specs);
-
-  pads = g_list_last (GST_ELEMENT_PADS (element));
-
-  while (pads) {
-    GstPad *pad = GST_PAD_CAST (pads->data);
-
-    /* figure out if it's a direct pad or a ghostpad */
-    if (GST_ELEMENT_CAST (GST_OBJECT_PARENT (pad)) == element) {
-      xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
-
-      gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
-    }
-    pads = g_list_previous (pads);
-  }
-
-  return parent;
-}
-
-static void
-gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
-{
-  xmlNodePtr children;
-  GstElement *element;
-  gchar *name = NULL;
-  gchar *value = NULL;
-
-  element = GST_ELEMENT_CAST (object);
-  g_return_if_fail (element != NULL);
-
-  /* parameters */
-  children = self->xmlChildrenNode;
-  while (children) {
-    if (!strcmp ((char *) children->name, "param")) {
-      xmlNodePtr child = children->xmlChildrenNode;
-
-      while (child) {
-        if (!strcmp ((char *) child->name, "name")) {
-          name = (gchar *) xmlNodeGetContent (child);
-        } else if (!strcmp ((char *) child->name, "value")) {
-          value = (gchar *) xmlNodeGetContent (child);
-        }
-        child = child->next;
-      }
-      /* FIXME: can this just be g_object_set ? */
-      gst_util_set_object_arg (G_OBJECT (element), name, value);
-      /* g_object_set (G_OBJECT (element), name, value, NULL); */
-      g_free (name);
-      g_free (value);
-    }
-    children = children->next;
-  }
-
-  /* pads */
-  children = self->xmlChildrenNode;
-  while (children) {
-    if (!strcmp ((char *) children->name, "pad")) {
-      gst_pad_load_and_link (children, GST_OBJECT_CAST (element));
-    }
-    children = children->next;
-  }
-
-  if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
-    (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
-}
-#endif /* GST_DISABLE_LOADSAVE */
-
 static void
 gst_element_set_bus_func (GstElement * element, GstBus * bus)
 {
index 5c3286f..594174e 100644 (file)
@@ -60,10 +60,9 @@ typedef enum {
 #include <gst/gstelementfactory.h>
 #include <gst/gstplugin.h>
 #include <gst/gstpluginfeature.h>
-#include <gst/gstindex.h>
-#include <gst/gstindexfactory.h>
 #include <gst/gstiterator.h>
 #include <gst/gstmessage.h>
+#include <gst/gstquery.h>
 #include <gst/gsttaglist.h>
 
 G_BEGIN_DECLS
@@ -131,7 +130,7 @@ typedef enum {
  *
  * Since: 0.10.13
  */
-#define GST_STATE_TARGET(elem)          (GST_ELEMENT_CAST(elem)->abidata.ABI.target_state)
+#define GST_STATE_TARGET(elem)          (GST_ELEMENT_CAST(elem)->target_state)
 
 /**
  * GST_STATE_RETURN:
@@ -253,7 +252,7 @@ typedef enum {
  *     Sinks unblock any #GstClock wait calls.
  *   </para></listitem>
  *   <listitem><para>
- *     When a sink does not have a pending buffer to play, it returns 
+ *     When a sink does not have a pending buffer to play, it returns
  *     %GST_STATE_CHANGE_ASYNC from this state change and completes the state
  *     change when it receives a new buffer or an %GST_EVENT_EOS.
  *   </para></listitem>
@@ -314,23 +313,29 @@ typedef enum /*< flags=0 >*/
 
 /**
  * GstElementFlags:
- * @GST_ELEMENT_LOCKED_STATE: ignore state changes from parent
- * @GST_ELEMENT_IS_SINK: the element is a sink
- * @GST_ELEMENT_UNPARENTING: Child is being removed from the parent bin.
+ * @GST_ELEMENT_FLAG_UNPARENTING: Child is being removed from the parent bin.
  *  gst_bin_remove() on a child already being removed immediately returns FALSE
- * @GST_ELEMENT_IS_SOURCE: the element is a source. Since 0.10.31
+ * @GST_ELEMENT_FLAG_LOCKED_STATE: ignore state changes from parent
+ * @GST_ELEMENT_FLAG_SINK: the element is a sink
+ * @GST_ELEMENT_FLAG_SOURCE: the element is a source. Since 0.10.31
+ * @GST_ELEMENT_FLAG_PROVIDE_CLOCK: the element can provide a clock
+ * @GST_ELEMENT_FLAG_REQUIRE_CLOCK: the element requires a clock
+ * @GST_ELEMENT_FLAG_INDEXABLE: the element can use an index
  * @GST_ELEMENT_FLAG_LAST: offset to define more flags
  *
  * The standard flags that an element may have.
  */
 typedef enum
 {
-  GST_ELEMENT_LOCKED_STATE      = (GST_OBJECT_FLAG_LAST << 0),
-  GST_ELEMENT_IS_SINK           = (GST_OBJECT_FLAG_LAST << 1),
-  GST_ELEMENT_UNPARENTING       = (GST_OBJECT_FLAG_LAST << 2),
-  GST_ELEMENT_IS_SOURCE         = (GST_OBJECT_FLAG_LAST << 3),
+  GST_ELEMENT_FLAG_UNPARENTING    = (GST_OBJECT_FLAG_LAST << 0),
+  GST_ELEMENT_FLAG_LOCKED_STATE   = (GST_OBJECT_FLAG_LAST << 1),
+  GST_ELEMENT_FLAG_SINK           = (GST_OBJECT_FLAG_LAST << 2),
+  GST_ELEMENT_FLAG_SOURCE         = (GST_OBJECT_FLAG_LAST << 3),
+  GST_ELEMENT_FLAG_PROVIDE_CLOCK  = (GST_OBJECT_FLAG_LAST << 4),
+  GST_ELEMENT_FLAG_REQUIRE_CLOCK  = (GST_OBJECT_FLAG_LAST << 5),
+  GST_ELEMENT_FLAG_INDEXABLE      = (GST_OBJECT_FLAG_LAST << 6),
   /* padding */
-  GST_ELEMENT_FLAG_LAST         = (GST_OBJECT_FLAG_LAST << 16)
+  GST_ELEMENT_FLAG_LAST           = (GST_OBJECT_FLAG_LAST << 16)
 } GstElementFlags;
 
 /**
@@ -340,7 +345,7 @@ typedef enum
  * Check if the element is in the locked state and therefore will ignore state
  * changes from its parent object.
  */
-#define GST_ELEMENT_IS_LOCKED_STATE(elem)        (GST_OBJECT_FLAG_IS_SET(elem,GST_ELEMENT_LOCKED_STATE))
+#define GST_ELEMENT_IS_LOCKED_STATE(elem)        (GST_OBJECT_FLAG_IS_SET(elem,GST_ELEMENT_FLAG_LOCKED_STATE))
 
 /**
  * GST_ELEMENT_NAME:
@@ -392,7 +397,7 @@ typedef enum
  *
  * Since: 0.10.24
  */
-#define GST_ELEMENT_START_TIME(elem)            (GST_ELEMENT_CAST(elem)->abidata.ABI.start_time)
+#define GST_ELEMENT_START_TIME(elem)            (GST_ELEMENT_CAST(elem)->start_time)
 
 /**
  * GST_ELEMENT_ERROR:
@@ -487,24 +492,24 @@ G_STMT_START {                                                          \
  * This lock is used by the core.  It is taken while getting or setting
  * the state, during state changes, and while finalizing.
  */
-#define GST_STATE_GET_LOCK(elem)               (GST_ELEMENT_CAST(elem)->state_lock)
+#define GST_STATE_GET_LOCK(elem)               (&(GST_ELEMENT_CAST(elem)->state_lock))
 /**
  * GST_STATE_GET_COND:
  * @elem: a #GstElement
  *
  * Get the conditional used to signal the completion of a state change.
  */
-#define GST_STATE_GET_COND(elem)               (GST_ELEMENT_CAST(elem)->state_cond)
+#define GST_STATE_GET_COND(elem)               (&GST_ELEMENT_CAST(elem)->state_cond)
 
-#define GST_STATE_LOCK(elem)                   g_static_rec_mutex_lock(GST_STATE_GET_LOCK(elem))
-#define GST_STATE_TRYLOCK(elem)                g_static_rec_mutex_trylock(GST_STATE_GET_LOCK(elem))
-#define GST_STATE_UNLOCK(elem)                 g_static_rec_mutex_unlock(GST_STATE_GET_LOCK(elem))
-#define GST_STATE_UNLOCK_FULL(elem)            g_static_rec_mutex_unlock_full(GST_STATE_GET_LOCK(elem))
-#define GST_STATE_LOCK_FULL(elem,t)            g_static_rec_mutex_lock_full(GST_STATE_GET_LOCK(elem), t)
+#define GST_STATE_LOCK(elem)                   g_rec_mutex_lock(GST_STATE_GET_LOCK(elem))
+#define GST_STATE_TRYLOCK(elem)                g_rec_mutex_trylock(GST_STATE_GET_LOCK(elem))
+#define GST_STATE_UNLOCK(elem)                 g_rec_mutex_unlock(GST_STATE_GET_LOCK(elem))
+#define GST_STATE_UNLOCK_FULL(elem)            g_rec_mutex_unlock_full(GST_STATE_GET_LOCK(elem))
+#define GST_STATE_LOCK_FULL(elem,t)            g_rec_mutex_lock_full(GST_STATE_GET_LOCK(elem), t)
 #define GST_STATE_WAIT(elem)                   g_cond_wait (GST_STATE_GET_COND (elem), \
                                                         GST_OBJECT_GET_LOCK (elem))
-#define GST_STATE_TIMED_WAIT(elem, timeval)    g_cond_timed_wait (GST_STATE_GET_COND (elem), \
-                                                        GST_OBJECT_GET_LOCK (elem), timeval)
+#define GST_STATE_WAIT_UNTIL(elem, end_time)   g_cond_wait_until (GST_STATE_GET_COND (elem), \
+                                                        GST_OBJECT_GET_LOCK (elem), end_time)
 #define GST_STATE_SIGNAL(elem)                 g_cond_signal (GST_STATE_GET_COND (elem));
 #define GST_STATE_BROADCAST(elem)              g_cond_broadcast (GST_STATE_GET_COND (elem));
 
@@ -514,6 +519,7 @@ G_STMT_START {                                                          \
  * @state_cond: Used to signal completion of a state change
  * @state_cookie: Used to detect concurrent execution of
  * gst_element_set_state() and gst_element_get_state()
+ * @target_state: the target state of an element as set by the application
  * @current_state: the current state of an element
  * @next_state: the next state of an element, can be #GST_STATE_VOID_PENDING if
  * the element is in the correct state.
@@ -527,6 +533,7 @@ G_STMT_START {                                                          \
  * @base_time: the time of the clock right before the element is set to
  * PLAYING. Subtracting @base_time from the current clock time in the PLAYING
  * state will yield the running_time against the clock.
+ * @start_time: the running_time of the last PAUSED state
  * @numpads: number of pads of the element, includes both source and sink pads.
  * @pads: list of pads
  * @numsrcpads: number of source pads of the element.
@@ -542,11 +549,12 @@ struct _GstElement
   GstObject             object;
 
   /*< public >*/ /* with LOCK */
-  GStaticRecMutex      *state_lock;
+  GRecMutex             state_lock;
 
   /* element state */
-  GCond                *state_cond;
+  GCond                 state_cond;
   guint32               state_cookie;
+  GstState              target_state;
   GstState              current_state;
   GstState              next_state;
   GstState              pending_state;
@@ -557,6 +565,7 @@ struct _GstElement
   /* allocated clock */
   GstClock             *clock;
   GstClockTimeDiff      base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
+  GstClockTime          start_time;
 
   /* element pads, these lists can only be iterated while holding
    * the LOCK or checking the cookie after each LOCK. */
@@ -569,22 +578,13 @@ struct _GstElement
   guint32               pads_cookie;
 
   /*< private >*/
-  union {
-    struct {
-      /* state set by application */
-      GstState              target_state;
-      /* running time of the last PAUSED state */
-      GstClockTime          start_time;
-    } ABI;
-    /* adding + 0 to mark ABI change to be undone later */
-    gpointer _gst_reserved[GST_PADDING + 0];
-  } abidata;
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 /**
  * GstElementClass:
  * @parent_class: the parent class structure
- * @details: #GstElementDetails for elements of this class
+ * @metadata: metadata for elements of this class
  * @elementfactory: the #GstElementFactory that creates these elements
  * @padtemplates: a #GList of #GstPadTemplate
  * @numpadtemplates: the number of padtemplates
@@ -597,13 +597,9 @@ struct _GstElement
  * @set_bus: set a #GstBus on the element
  * @provide_clock: gets the #GstClock provided by the element
  * @set_clock: set the #GstClock on the element
- * @get_index: set a #GstIndex on the element
- * @set_index: get the #GstIndex of an element
  * @send_event: send a #GstEvent to the element
- * @get_query_types: get the supported #GstQueryType of this element
  * @query: perform a #GstQuery on the element
- * @request_new_pad_full: called when a new pad is requested. Since: 0.10.32.
- * @state_changed: called immediately after a new state was set. Since: 0.10.36.
+ * @state_changed: called immediately after a new state was set.
  *
  * GStreamer element class. Override the vmethods to implement the element
  * functionality.
@@ -613,9 +609,8 @@ struct _GstElementClass
   GstObjectClass         parent_class;
 
   /*< public >*/
-  /* the element details */
-  /* FIXME-0.11: deprecate this in favour of meta_data */
-  GstElementDetails      details;
+  /* the element metadata */
+  gpointer              metadata;
 
   /* factory that the element was created from */
   GstElementFactory     *elementfactory;
@@ -635,7 +630,8 @@ struct _GstElementClass
   /* virtual methods for subclasses */
 
   /* request/release pads */
-  GstPad*               (*request_new_pad)      (GstElement *element, GstPadTemplate *templ, const gchar* name);
+  GstPad*               (*request_new_pad)      (GstElement *element, GstPadTemplate *templ,
+                                                 const gchar* name, const GstCaps *caps);
   void                  (*release_pad)          (GstElement *element, GstPad *pad);
 
   /* state changes */
@@ -643,6 +639,8 @@ struct _GstElementClass
                                                  GstState * pending, GstClockTime timeout);
   GstStateChangeReturn (*set_state)             (GstElement *element, GstState state);
   GstStateChangeReturn (*change_state)          (GstElement *element, GstStateChange transition);
+  void                 (*state_changed)         (GstElement *element, GstState oldstate,
+                                                 GstState newstate, GstState pending);
 
   /* bus */
   void                  (*set_bus)              (GstElement * element, GstBus * bus);
@@ -651,50 +649,31 @@ struct _GstElementClass
   GstClock*             (*provide_clock)        (GstElement *element);
   gboolean              (*set_clock)            (GstElement *element, GstClock *clock);
 
-  /* index */
-  GstIndex*             (*get_index)            (GstElement *element);
-  void                  (*set_index)            (GstElement *element, GstIndex *index);
-
   /* query functions */
   gboolean              (*send_event)           (GstElement *element, GstEvent *event);
 
-  const GstQueryType*   (*get_query_types)      (GstElement *element);
   gboolean              (*query)                (GstElement *element, GstQuery *query);
 
   /*< private >*/
-  /* FIXME-0.11: move up and replace details */
-  gpointer             meta_data;
-
-  /*< public >*/
-  /* Virtual method for subclasses (additions) */
-  /* FIXME-0.11 Make this the default behaviour */
-  GstPad*              (*request_new_pad_full) (GstElement *element, GstPadTemplate *templ,
-                                                const gchar* name, const GstCaps *caps);
-
-  void                  (*state_changed)        (GstElement *element, GstState oldstate,
-                                                 GstState newstate, GstState pending);
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING-3];
+  gpointer _gst_reserved[GST_PADDING_LARGE];
 };
 
 /* element class pad templates */
 void                    gst_element_class_add_pad_template      (GstElementClass *klass, GstPadTemplate *templ);
-void                    gst_element_class_add_static_pad_template      (GstElementClass *klass, GstStaticPadTemplate *templ);
 GstPadTemplate*         gst_element_class_get_pad_template      (GstElementClass *element_class, const gchar *name);
 GList*                  gst_element_class_get_pad_template_list (GstElementClass *element_class);
 
 /* element class meta data */
-void                    gst_element_class_set_documentation_uri (GstElementClass * klass, const gchar *uri);
-void                    gst_element_class_set_icon_name         (GstElementClass * klass, const gchar *name);
-#ifndef GST_DISABLE_DEPRECATED
-void                    gst_element_class_set_details           (GstElementClass *klass, const GstElementDetails *details);
-#endif
-void                    gst_element_class_set_details_simple    (GstElementClass *klass,
+void                    gst_element_class_set_metadata          (GstElementClass *klass,
                                                                  const gchar     *longname,
                                                                  const gchar     *classification,
                                                                  const gchar     *description,
                                                                  const gchar     *author);
+void                    gst_element_class_add_metadata          (GstElementClass * klass,
+                                                                 const gchar * key, const gchar * value);
+const gchar *           gst_element_class_get_metadata          (GstElementClass * klass,
+                                                                 const gchar * key);
+
 
 /* element instance */
 GType                   gst_element_get_type            (void);
@@ -744,8 +723,6 @@ GType                   gst_element_get_type            (void);
 #define                 gst_element_set_parent(elem,parent)     gst_object_set_parent(GST_OBJECT_CAST(elem),parent)
 
 /* clocking */
-gboolean                gst_element_requires_clock      (GstElement *element);
-gboolean                gst_element_provides_clock      (GstElement *element);
 GstClock*               gst_element_provide_clock       (GstElement *element);
 GstClock*               gst_element_get_clock           (GstElement *element);
 gboolean                gst_element_set_clock           (GstElement *element, GstClock *clock);
@@ -754,11 +731,6 @@ GstClockTime            gst_element_get_base_time       (GstElement *element);
 void                    gst_element_set_start_time      (GstElement *element, GstClockTime time);
 GstClockTime            gst_element_get_start_time      (GstElement *element);
 
-/* indexes */
-gboolean                gst_element_is_indexable        (GstElement *element);
-void                    gst_element_set_index           (GstElement *element, GstIndex *index);
-GstIndex*               gst_element_get_index           (GstElement *element);
-
 /* bus */
 void                    gst_element_set_bus             (GstElement * element, GstBus * bus);
 GstBus *                gst_element_get_bus             (GstElement * element);
@@ -768,13 +740,9 @@ gboolean                gst_element_add_pad             (GstElement *element, Gs
 gboolean                gst_element_remove_pad          (GstElement *element, GstPad *pad);
 void                    gst_element_no_more_pads        (GstElement *element);
 
-#ifndef GST_DISABLE_DEPRECATED
-GstPad*                 gst_element_get_pad             (GstElement *element, const gchar *name);
-#endif /* GST_DISABLE_DEPRECATED */
 GstPad*                 gst_element_get_static_pad      (GstElement *element, const gchar *name);
 GstPad*                 gst_element_get_request_pad     (GstElement *element, const gchar *name);
-GstPad*                 gst_element_request_pad         (GstElement *element,
-                                                        GstPadTemplate *templ,
+GstPad*                 gst_element_request_pad         (GstElement *element, GstPadTemplate *templ,
                                                         const gchar * name, const GstCaps *caps);
 void                    gst_element_release_request_pad (GstElement *element, GstPad *pad);
 
@@ -788,7 +756,6 @@ gboolean                gst_element_seek                (GstElement *element, gd
                                                          GstFormat format, GstSeekFlags flags,
                                                          GstSeekType cur_type, gint64 cur,
                                                          GstSeekType stop_type, gint64 stop);
-const GstQueryType*     gst_element_get_query_types     (GstElement *element);
 gboolean                gst_element_query               (GstElement *element, GstQuery *query);
 
 /* messages */
@@ -823,7 +790,6 @@ GstStateChangeReturn    gst_element_change_state        (GstElement * element,
 GstStateChangeReturn    gst_element_continue_state      (GstElement * element,
                                                          GstStateChangeReturn ret);
 void                    gst_element_lost_state          (GstElement * element);
-void                    gst_element_lost_state_full     (GstElement * element, gboolean new_base_time);
 
 /* factory management */
 GstElementFactory*      gst_element_get_factory         (GstElement *element);
diff --git a/gst/gstelementdetails.h b/gst/gstelementdetails.h
deleted file mode 100644 (file)
index fe946ba..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *               2000,2004 Wim Taymans <wim@fluendo.com>
- *
- * gstelement.h: Header for GstElement
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_ELEMENT_DETAILS_H__
-#define __GST_ELEMENT_DETAILS_H__
-
-G_BEGIN_DECLS
-
-static inline void
-__gst_element_details_clear (GstElementDetails * dp)
-{
-  g_free (dp->longname);
-  g_free (dp->klass);
-  g_free (dp->description);
-  g_free (dp->author);
-  memset (dp, 0, sizeof (GstElementDetails));
-}
-
-static inline void
-__gst_element_details_copy (GstElementDetails * dest,
-    const GstElementDetails * src)
-{
-  g_free (dest->longname);
-  dest->longname = g_strdup (src->longname);
-
-  g_free (dest->klass);
-  dest->klass = g_strdup (src->klass);
-
-  g_free (dest->description);
-  dest->description = g_strdup (src->description);
-
-  g_free (dest->author);
-  dest->author = g_strdup (src->author);
-}
-
-G_END_DECLS
-
-#endif /* __GST_ELEMENT_DETAILS_H__ */
index a74183c..e18d0f3 100644 (file)
@@ -60,7 +60,7 @@
 #include "gst_private.h"
 
 #include "gstelement.h"
-#include "gstelementdetails.h"
+#include "gstelementmetadata.h"
 #include "gstinfo.h"
 #include "gsturi.h"
 #include "gstregistry.h"
@@ -77,7 +77,7 @@ static void gst_element_factory_cleanup (GstElementFactory * factory);
 /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */
 
 /* this is defined in gstelement.c */
-extern GQuark _gst_elementclass_factory;
+extern GQuark __gst_elementclass_factory;
 
 #define _do_init \
 { \
@@ -134,7 +134,7 @@ gst_element_factory_find (const gchar * name)
 
   g_return_val_if_fail (name != NULL, NULL);
 
-  feature = gst_registry_find_feature (gst_registry_get_default (), name,
+  feature = gst_registry_find_feature (gst_registry_get (), name,
       GST_TYPE_ELEMENT_FACTORY);
   if (feature)
     return GST_ELEMENT_FACTORY (feature);
@@ -150,10 +150,9 @@ gst_element_factory_cleanup (GstElementFactory * factory)
 {
   GList *item;
 
-  __gst_element_details_clear (&factory->details);
-  if (factory->meta_data) {
-    gst_structure_free ((GstStructure *) factory->meta_data);
-    factory->meta_data = NULL;
+  if (factory->metadata) {
+    gst_structure_free ((GstStructure *) factory->metadata);
+    factory->metadata = NULL;
   }
   if (factory->type) {
     factory->type = G_TYPE_INVALID;
@@ -161,21 +160,8 @@ gst_element_factory_cleanup (GstElementFactory * factory)
 
   for (item = factory->staticpadtemplates; item; item = item->next) {
     GstStaticPadTemplate *templ = item->data;
-    GstCaps *caps = (GstCaps *) & (templ->static_caps);
 
-    /* FIXME: this is not threadsafe */
-    if (caps->refcount == 1) {
-      GstStructure *structure;
-      guint i;
-
-      for (i = 0; i < caps->structs->len; i++) {
-        structure = (GstStructure *) gst_caps_get_structure (caps, i);
-        gst_structure_set_parent_refcount (structure, NULL);
-        gst_structure_free (structure);
-      }
-      g_ptr_array_free (caps->structs, TRUE);
-      caps->refcount = 0;
-    }
+    gst_static_caps_cleanup (&templ->static_caps);
     g_slice_free (GstStaticPadTemplate, templ);
   }
   g_list_free (factory->staticpadtemplates);
@@ -220,7 +206,7 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
   g_return_val_if_fail (name != NULL, FALSE);
   g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE);
 
-  registry = gst_registry_get_default ();
+  registry = gst_registry_get ();
 
   /* check if feature already exists, if it exists there is no need to update it
    * when the registry is getting updated, outdated plugins and all their
@@ -233,7 +219,7 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
     factory = GST_ELEMENT_FACTORY_CAST (existing_feature);
     factory->type = type;
     existing_feature->loaded = TRUE;
-    g_type_set_qdata (type, _gst_elementclass_factory, factory);
+    g_type_set_qdata (type, __gst_elementclass_factory, factory);
     gst_object_unref (existing_feature);
     return TRUE;
   }
@@ -246,19 +232,18 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
       g_type_name (type));
 
   /* provide info needed during class structure setup */
-  g_type_set_qdata (type, _gst_elementclass_factory, factory);
+  g_type_set_qdata (type, __gst_elementclass_factory, factory);
   klass = GST_ELEMENT_CLASS (g_type_class_ref (type));
+#if 0
+  /* FIXME */
   if ((klass->details.longname == NULL) ||
       (klass->details.klass == NULL) || (klass->details.author == NULL))
     goto detailserror;
+#endif
 
   factory->type = type;
-  __gst_element_details_copy (&factory->details, &klass->details);
-  if (klass->meta_data) {
-    factory->meta_data = gst_structure_copy ((GstStructure *) klass->meta_data);
-  } else {
-    factory->meta_data = NULL;
-  }
+  factory->metadata = gst_structure_copy ((GstStructure *) klass->metadata);
+
   for (item = klass->padtemplates; item; item = item->next) {
     GstPadTemplate *templ = item->data;
     GstStaticPadTemplate *newt;
@@ -268,7 +253,7 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
     newt->name_template = g_intern_string (templ->name_template);
     newt->direction = templ->direction;
     newt->presence = templ->presence;
-    newt->static_caps.caps.refcount = 0;
+    newt->static_caps.caps.mini_object.refcount = 0;
     newt->static_caps.string = g_intern_string (caps_string);
     factory->staticpadtemplates =
         g_list_append (factory->staticpadtemplates, newt);
@@ -282,19 +267,18 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
     GstURIHandlerInterface *iface = (GstURIHandlerInterface *)
         g_type_interface_peek (klass, GST_TYPE_URI_HANDLER);
 
-    if (!iface || (!iface->get_type && !iface->get_type_full) ||
-        (!iface->get_protocols && !iface->get_protocols_full))
+    if (!iface || !iface->get_type || !iface->get_protocols)
       goto urierror;
     if (iface->get_type)
-      factory->uri_type = iface->get_type ();
-    else if (iface->get_type_full)
-      factory->uri_type = iface->get_type_full (factory->type);
+      factory->uri_type = iface->get_type (factory->type);
     if (!GST_URI_TYPE_IS_VALID (factory->uri_type))
       goto urierror;
-    if (iface->get_protocols)
-      factory->uri_protocols = g_strdupv (iface->get_protocols ());
-    else if (iface->get_protocols_full)
-      factory->uri_protocols = iface->get_protocols_full (factory->type);
+    if (iface->get_protocols) {
+      const gchar *const *protocols;
+
+      protocols = iface->get_protocols (factory->type);
+      factory->uri_protocols = g_strdupv ((gchar **) protocols);
+    }
     if (!factory->uri_protocols)
       goto urierror;
   }
@@ -329,6 +313,7 @@ urierror:
     return FALSE;
   }
 
+#if 0
 detailserror:
   {
     GST_WARNING_OBJECT (factory,
@@ -336,6 +321,7 @@ detailserror:
     gst_element_factory_cleanup (factory);
     return FALSE;
   }
+#endif
 }
 
 /**
@@ -348,7 +334,7 @@ detailserror:
  * It will be given the name supplied, since all elements require a name as
  * their first argument.
  *
- * Returns: (transfer full): new #GstElement or NULL if the element couldn't
+ * Returns: (transfer floating): new #GstElement or NULL if the element couldn't
  *     be created
  */
 GstElement *
@@ -371,9 +357,9 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
 
   if (name)
     GST_INFO ("creating element \"%s\" named \"%s\"",
-        GST_PLUGIN_FEATURE_NAME (factory), GST_STR_NULL (name));
+        GST_OBJECT_NAME (factory), GST_STR_NULL (name));
   else
-    GST_INFO ("creating element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory));
+    GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory));
 
   if (factory->type == 0)
     goto no_type;
@@ -395,11 +381,11 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
    * an element at the same moment
    */
   oclass = GST_ELEMENT_GET_CLASS (element);
-  if (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (&oclass->elementfactory, NULL,
+  if (!g_atomic_pointer_compare_and_exchange (&oclass->elementfactory, NULL,
           factory))
     gst_object_unref (factory);
 
-  GST_DEBUG ("created element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory));
+  GST_DEBUG ("created element \"%s\"", GST_OBJECT_NAME (factory));
 
   return element;
 
@@ -435,7 +421,7 @@ no_element:
  * consisting of the element factory name and a number.
  * If name is given, it will be given the name supplied.
  *
- * Returns: (transfer full): new #GstElement or NULL if unable to create element
+ * Returns: (transfer floating): new #GstElement or NULL if unable to create element
  */
 GstElement *
 gst_element_factory_make (const gchar * factoryname, const gchar * name)
@@ -506,113 +492,11 @@ gst_element_factory_get_element_type (GstElementFactory * factory)
   return factory->type;
 }
 
-/**
- * gst_element_factory_get_longname:
- * @factory: a #GstElementFactory
- *
- * Gets the longname for this factory
- *
- * Returns: the longname
- */
 const gchar *
-gst_element_factory_get_longname (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-
-  return factory->details.longname;
-}
-
-/**
- * gst_element_factory_get_klass:
- * @factory: a #GstElementFactory
- *
- * Gets the class for this factory.
- *
- * Returns: the class
- */
-const gchar *
-gst_element_factory_get_klass (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-
-  return factory->details.klass;
-}
-
-/**
- * gst_element_factory_get_description:
- * @factory: a #GstElementFactory
- *
- * Gets the description for this factory.
- *
- * Returns: the description
- */
-const gchar *
-gst_element_factory_get_description (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-
-  return factory->details.description;
-}
-
-/**
- * gst_element_factory_get_author:
- * @factory: a #GstElementFactory
- *
- * Gets the author for this factory.
- *
- * Returns: the author
- */
-const gchar *
-gst_element_factory_get_author (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-
-  return factory->details.author;
-}
-
-static const gchar *
-gst_element_factory_get_meta_data (GstElementFactory * factory,
+gst_element_factory_get_metadata (GstElementFactory * factory,
     const gchar * key)
 {
-  if (!factory->meta_data)
-    return NULL;
-
-  /* FIXME: do we want to support other types? */
-  return gst_structure_get_string ((GstStructure *) factory->meta_data, key);
-}
-
-/**
- * gst_element_factory_get_documentation_uri:
- * @factory: a #GstElementFactory
- *
- * Gets documentation uri for this factory if set.
- *
- * Since: 0.10.31
- *
- * Returns: the documentation uri
- */
-const gchar *
-gst_element_factory_get_documentation_uri (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-  return gst_element_factory_get_meta_data (factory, "doc-uri");
-}
-
-/**
- * gst_element_factory_get_icon_name:
- * @factory: a #GstElementFactory
- *
- * Gets icon name for this factory if set.
- *
- * Since: 0.10.31
- *
- * Returns: the icon name
- */
-const gchar *
-gst_element_factory_get_icon_name (GstElementFactory * factory)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-  return gst_element_factory_get_meta_data (factory, "icon-name");
+  return gst_structure_get_string ((GstStructure *) factory->metadata, key);
 }
 
 /**
@@ -677,7 +561,7 @@ gst_element_factory_get_static_pad_templates (GstElementFactory * factory)
  *
  * Returns: type of URIs this element supports
  */
-gint
+GstURIType
 gst_element_factory_get_uri_type (GstElementFactory * factory)
 {
   g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), GST_URI_UNKNOWN);
@@ -697,12 +581,12 @@ gst_element_factory_get_uri_type (GstElementFactory * factory)
  * Returns: (transfer none) (array zero-terminated=1): the supported protocols
  *     or NULL
  */
-gchar **
+const gchar *const *
 gst_element_factory_get_uri_protocols (GstElementFactory * factory)
 {
   g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
 
-  return factory->uri_protocols;
+  return (const gchar * const *) factory->uri_protocols;
 }
 
 /**
@@ -759,7 +643,8 @@ gst_element_factory_list_is_type (GstElementFactory * factory,
   gboolean res = FALSE;
   const gchar *klass;
 
-  klass = gst_element_factory_get_klass (factory);
+  klass =
+      gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
 
   /* Filter by element type first, as soon as it matches
    * one type, we skip all other tests */
@@ -854,8 +739,8 @@ gst_element_factory_list_get_elements (GstElementFactoryListType type,
   data.minrank = minrank;
 
   /* get the feature list using the filter */
-  result = gst_default_registry_feature_filter ((GstPluginFeatureFilter)
-      element_filter, FALSE, &data);
+  result = gst_registry_feature_filter (gst_registry_get (),
+      (GstPluginFeatureFilter) element_filter, FALSE, &data);
 
   /* sort on rank and name */
   result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
index ac14450..b2dff92 100644 (file)
@@ -32,72 +32,12 @@ typedef struct _GstElementFactoryClass GstElementFactoryClass;
 #include <gst/gstobject.h>
 #include <gst/gstplugin.h>
 #include <gst/gstpluginfeature.h>
+#include <gst/gstpadtemplate.h>
 #include <gst/gstiterator.h>
+#include <gst/gsturi.h>
 
 G_BEGIN_DECLS
 
-/* FIXME 0.11: Move GstElementDetails into a private header and use it internally
- * in GstElementFactory, GstElementClass and the registry
- */
-
-typedef struct _GstElementDetails GstElementDetails;
-
-/**
- * GstElementDetails:
- * @longname: long, english name
- * @klass: string describing the type of element, as an unordered list
- * separated with slashes ('/'). See draft-klass.txt of the design docs
- * for more details and common types
- * @description: what the element is about
- * @author: who wrote this thing?
- *
- * This struct defines the public information about a #GstElement. It contains
- * meta-data about the element that is mostly for the benefit of editors.
- *
- * The @klass member can be used by applications to filter elements based
- * on functionality.
- */
-/* FIXME: need translatable stuff in here (how handle in registry)?
- * can't we use _N("long name") in element implementations and use _(longname)
- * in gst_element_factory_get_longname()
- */
-struct _GstElementDetails
-{
-  /*< public > */
-  gchar *longname;
-  gchar *klass;
-  gchar *description;
-  gchar *author;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GST_ELEMENT_DETAILS:
- * @longname: long, english name
- * @klass: string describing the type of element, as an unordered list
- * separated with slashes ('/'). See draft-klass.txt of the design docs
- * for more details and common types
- * @description: what the element is about
- * @author: who wrote this element
- *
- * Macro to initialize #GstElementDetails.
- */
-#define GST_ELEMENT_DETAILS(longname,klass,description,author)          \
-  { longname, klass, description, author, {NULL} }
-
-/**
- * GST_IS_ELEMENT_DETAILS:
- * @details: the #GstElementDetails to check
- *
- * Tests if element details are initialized.
- */
-/* FIXME: what about adding '&& (*__gst_reserved==NULL)' */
-#define GST_IS_ELEMENT_DETAILS(details) (                                       \
-  (details) && ((details)->longname != NULL) && ((details)->klass != NULL)      \
-  && ((details)->description != NULL) && ((details)->author != NULL))
-
 #define GST_TYPE_ELEMENT_FACTORY                (gst_element_factory_get_type())
 #define GST_ELEMENT_FACTORY(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENT_FACTORY,\
                                                  GstElementFactory))
@@ -117,22 +57,19 @@ struct _GstElementFactory {
 
   GType                 type;                   /* unique GType of element or 0 if not loaded */
 
-  /* FIXME-0.11: deprecate this in favour of meta_data */
-  GstElementDetails     details;
+  gpointer              metadata;
 
   GList *               staticpadtemplates;     /* GstStaticPadTemplate list */
   guint                 numpadtemplates;
 
   /* URI interface stuff */
-  guint                 uri_type;
+  GstURIType            uri_type;
   gchar **              uri_protocols;
 
   GList *               interfaces;             /* interface type names this element implements */
 
   /*< private >*/
-  /* FIXME-0.11: move up and replace details */
-  gpointer             meta_data;
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstElementFactoryClass {
@@ -146,16 +83,15 @@ GType                   gst_element_factory_get_type            (void);
 GstElementFactory *     gst_element_factory_find                (const gchar *name);
 
 GType                   gst_element_factory_get_element_type    (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_longname        (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_klass           (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_description     (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_author          (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_documentation_uri (GstElementFactory *factory);
-const gchar *           gst_element_factory_get_icon_name       (GstElementFactory *factory);
+
+const gchar *           gst_element_factory_get_metadata        (GstElementFactory *factory, const gchar *key);
+
 guint                   gst_element_factory_get_num_pad_templates (GstElementFactory *factory);
 const GList *           gst_element_factory_get_static_pad_templates (GstElementFactory *factory);
-gint                    gst_element_factory_get_uri_type        (GstElementFactory *factory);
-gchar **                gst_element_factory_get_uri_protocols   (GstElementFactory *factory);
+
+GstURIType              gst_element_factory_get_uri_type        (GstElementFactory *factory);
+const gchar * const *   gst_element_factory_get_uri_protocols   (GstElementFactory *factory);
+
 gboolean                gst_element_factory_has_interface       (GstElementFactory *factory,
                                                                  const gchar *interfacename);
 
@@ -163,11 +99,6 @@ GstElement*             gst_element_factory_create              (GstElementFacto
                                                                  const gchar *name) G_GNUC_MALLOC;
 GstElement*             gst_element_factory_make                (const gchar *factoryname, const gchar *name) G_GNUC_MALLOC;
 
-/* FIXME 0.11: move these two into our private headers */
-void                    __gst_element_factory_add_static_pad_template (GstElementFactory *elementfactory,
-                                                                 GstStaticPadTemplate *templ);
-void                    __gst_element_factory_add_interface     (GstElementFactory *elementfactory,
-                                                                 const gchar *interfacename);
 gboolean                gst_element_register                    (GstPlugin *plugin, const gchar *name,
                                                                  guint rank, GType type);
 
@@ -237,7 +168,7 @@ typedef guint64 GstElementFactoryListType;
  * Elements matching any of the defined GST_ELEMENT_FACTORY_TYPE_MEDIA types
  *
  * Note: Do not use this if you wish to not filter against any of the defined
- * media types. If you wish to do this, simply don't specify any 
+ * media types. If you wish to do this, simply don't specify any
  * GST_ELEMENT_FACTORY_TYPE_MEDIA flag.
  *
  * Since: 0.10.31
@@ -282,33 +213,33 @@ typedef guint64 GstElementFactoryListType;
   (GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER | GST_ELEMENT_FACTORY_TYPE_PARSER)
 
 /* Element klass defines */
-#define GST_ELEMENT_FACTORY_KLASS_DECODER              "Decoder"
-#define GST_ELEMENT_FACTORY_KLASS_ENCODER              "Encoder"
-#define GST_ELEMENT_FACTORY_KLASS_SINK                 "Sink"
-#define GST_ELEMENT_FACTORY_KLASS_SRC                  "Source"
-#define GST_ELEMENT_FACTORY_KLASS_MUXER                        "Muxer"
-#define GST_ELEMENT_FACTORY_KLASS_DEMUXER              "Demuxer"
-#define GST_ELEMENT_FACTORY_KLASS_PARSER               "Parser"
-#define GST_ELEMENT_FACTORY_KLASS_PAYLOADER            "Payloader"
-#define GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER          "Depayloader"
-#define GST_ELEMENT_FACTORY_KLASS_FORMATTER            "Formatter"
-
-#define GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO          "Video"
-#define GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO          "Audio"
-#define GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE          "Image"
-#define GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE       "Subtitle"
-#define GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA       "Metadata"
+#define GST_ELEMENT_FACTORY_KLASS_DECODER               "Decoder"
+#define GST_ELEMENT_FACTORY_KLASS_ENCODER               "Encoder"
+#define GST_ELEMENT_FACTORY_KLASS_SINK                  "Sink"
+#define GST_ELEMENT_FACTORY_KLASS_SRC                   "Source"
+#define GST_ELEMENT_FACTORY_KLASS_MUXER                 "Muxer"
+#define GST_ELEMENT_FACTORY_KLASS_DEMUXER               "Demuxer"
+#define GST_ELEMENT_FACTORY_KLASS_PARSER                "Parser"
+#define GST_ELEMENT_FACTORY_KLASS_PAYLOADER             "Payloader"
+#define GST_ELEMENT_FACTORY_KLASS_DEPAYLOADER           "Depayloader"
+#define GST_ELEMENT_FACTORY_KLASS_FORMATTER             "Formatter"
+
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_VIDEO           "Video"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_AUDIO           "Audio"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_IMAGE           "Image"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_SUBTITLE        "Subtitle"
+#define GST_ELEMENT_FACTORY_KLASS_MEDIA_METADATA        "Metadata"
 
 gboolean      gst_element_factory_list_is_type      (GstElementFactory *factory,
-                                                    GstElementFactoryListType type);
+                                                     GstElementFactoryListType type);
 
 GList *       gst_element_factory_list_get_elements (GstElementFactoryListType type,
-                                                    GstRank minrank) G_GNUC_MALLOC;
+                                                     GstRank minrank) G_GNUC_MALLOC;
 
 
 GList *       gst_element_factory_list_filter       (GList *list, const GstCaps *caps,
-                                                    GstPadDirection direction,
-                                                    gboolean subsetonly) G_GNUC_MALLOC;
+                                                     GstPadDirection direction,
+                                                     gboolean subsetonly) G_GNUC_MALLOC;
 G_END_DECLS
 
 #endif /* __GST_ELEMENT_FACTORY_H__ */
diff --git a/gst/gstelementmetadata.h b/gst/gstelementmetadata.h
new file mode 100644 (file)
index 0000000..6c331d9
--- /dev/null
@@ -0,0 +1,77 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2000,2004 Wim Taymans <wim@fluendo.com>
+ *
+ * gstelementmetadata.h: Metadata for GstElement classes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_ELEMENT_METADATA_H__
+#define __GST_ELEMENT_METADATA_H__
+
+G_BEGIN_DECLS
+
+/**
+ * GST_ELEMENT_METADATA_LONGNAME:
+ *
+ * The long English name of the element. E.g. "File Sink"
+ */
+#define GST_ELEMENT_METADATA_LONGNAME      "long-name"
+/**
+ * GST_ELEMENT_METADATA_KLASS:
+ *
+ * String describing the type of element, as an unordered list
+ * separated with slashes ('/'). See draft-klass.txt of the design docs
+ * for more details and common types. E.g: "Sink/File"
+ */
+#define GST_ELEMENT_METADATA_KLASS         "klass"
+
+/**
+ * GST_ELEMENT_METADATA_DESCRIPTION:
+ *
+ * Sentence describing the purpose of the element.
+ * E.g: "Write stream to a file"
+ */
+#define GST_ELEMENT_METADATA_DESCRIPTION   "description"
+/**
+ * GST_ELEMENT_METADATA_AUTHOR:
+ *
+ * Name and contact details of the author(s). Use \n to separate
+ * multiple author details.
+ * E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
+ */
+#define GST_ELEMENT_METADATA_AUTHOR        "author"
+
+/**
+ * GST_ELEMENT_METADATA_DOC_URI:
+ *
+ * Set uri pointing to user documentation. Applications can use this to show
+ * help for e.g. effects to users.
+ */
+#define GST_ELEMENT_METADATA_DOC_URI       "doc-uri"
+/**
+ * GST_ELEMENT_METADATA_ICON_NAME:
+ *
+ * Elements that bridge to certain other products can include an icon of that
+ * used product. Application can show the icon in menus/selectors to help
+ * identifying specific elements.
+ */
+#define GST_ELEMENT_METADATA_ICON_NAME     "icon-name"
+
+G_END_DECLS
+
+#endif /* __GST_ELEMENT_METADATA_H__ */
index f3f2d22..17ec81f 100644 (file)
@@ -122,22 +122,6 @@ GQuark gst_ ## string ## _error_quark (void) {                          \
     quark = g_quark_from_static_string ("gst-" # string "-error-quark"); \
   return quark; }
 
-/* FIXME: Deprecate when we depend on GLib 2.26 */
-GType
-gst_g_error_get_type (void)
-{
-#if GLIB_CHECK_VERSION(2,25,2)
-  return g_error_get_type ();
-#else
-  static GType type = 0;
-
-  if (G_UNLIKELY (type == 0))
-    type = g_boxed_type_register_static ("GstGError",
-        (GBoxedCopyFunc) g_error_copy, (GBoxedFreeFunc) g_error_free);
-  return type;
-#endif
-}
-
 #define FILE_A_BUG "  Please file a bug at " PACKAGE_BUGREPORT "."
 
 static const gchar *
index d722ce0..eab6c00 100644 (file)
@@ -197,8 +197,6 @@ typedef enum
   GST_STREAM_ERROR_NUM_ERRORS
 } GstStreamError;
 
-#define GST_TYPE_G_ERROR    (gst_g_error_get_type ())
-
 /**
  * GST_LIBRARY_ERROR:
  *
@@ -240,11 +238,6 @@ typedef enum
  */
 #define GST_ERROR_SYSTEM    ("system error: %s", g_strerror (errno))
 
-/* Hide this compatibility type from introspection */
-#ifndef __GI_SCANNER__
-GType gst_g_error_get_type (void);
-#endif
-
 gchar *gst_error_get_message (GQuark domain, gint code);
 GQuark gst_stream_error_quark (void);
 GQuark gst_core_error_quark (void);
index 8c323aa..4ee64fc 100644 (file)
 #include "gstutils.h"
 #include "gstquark.h"
 
-#define GST_EVENT_SEQNUM(e) ((GstEvent*)e)->abidata.seqnum
+GType _gst_event_type = 0;
 
-static void gst_event_finalize (GstEvent * event);
-static GstEvent *_gst_event_copy (GstEvent * event);
+typedef struct
+{
+  GstEvent event;
 
-static GstMiniObjectClass *parent_class = NULL;
+  GstStructure *structure;
+} GstEventImpl;
 
-void
-_gst_event_initialize (void)
-{
-  g_type_class_ref (gst_event_get_type ());
-  g_type_class_ref (gst_seek_flags_get_type ());
-  g_type_class_ref (gst_seek_type_get_type ());
-}
+#define GST_EVENT_STRUCTURE(e)  (((GstEventImpl *)(e))->structure)
 
 typedef struct
 {
@@ -112,7 +108,8 @@ static GstEventQuarks event_quarks[] = {
   {GST_EVENT_FLUSH_START, "flush-start", 0},
   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
   {GST_EVENT_EOS, "eos", 0},
-  {GST_EVENT_NEWSEGMENT, "newsegment", 0},
+  {GST_EVENT_CAPS, "caps", 0},
+  {GST_EVENT_SEGMENT, "segment", 0},
   {GST_EVENT_TAG, "tag", 0},
   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
   {GST_EVENT_SINK_MESSAGE, "sink-message", 0},
@@ -121,15 +118,34 @@ static GstEventQuarks event_quarks[] = {
   {GST_EVENT_NAVIGATION, "navigation", 0},
   {GST_EVENT_LATENCY, "latency", 0},
   {GST_EVENT_STEP, "step", 0},
+  {GST_EVENT_RECONFIGURE, "reconfigure", 0},
   {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
   {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
   {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
+  {GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, "custom-downstream-sticky", 0},
   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
 
   {0, NULL, 0}
 };
 
+GST_DEFINE_MINI_OBJECT_TYPE (GstEvent, gst_event);
+
+void
+_priv_gst_event_initialize (void)
+{
+  gint i;
+
+  _gst_event_type = gst_event_get_type ();
+
+  g_type_class_ref (gst_seek_flags_get_type ());
+  g_type_class_ref (gst_seek_type_get_type ());
+
+  for (i = 0; event_quarks[i].name; i++) {
+    event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
+  }
+}
+
 /**
  * gst_event_type_get_name:
  * @type: the event type
@@ -183,97 +199,83 @@ gst_event_type_get_flags (GstEventType type)
 {
   GstEventTypeFlags ret;
 
-  ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);
+  ret = type & ((1 << GST_EVENT_STICKY_SHIFT) - 1);
 
   return ret;
 }
 
-#define _do_init \
-{ \
-  gint i; \
-  \
-  for (i = 0; event_quarks[i].name; i++) { \
-    event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name); \
-  } \
-}
-
-G_DEFINE_TYPE_WITH_CODE (GstEvent, gst_event, GST_TYPE_MINI_OBJECT, _do_init);
-
-static void
-gst_event_class_init (GstEventClass * klass)
-{
-  parent_class = g_type_class_peek_parent (klass);
-
-  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
-  klass->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_event_finalize;
-}
-
 static void
-gst_event_init (GstEvent * event)
+_gst_event_free (GstEvent * event)
 {
-  GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
-}
+  GstStructure *s;
 
-static void
-gst_event_finalize (GstEvent * event)
-{
   g_return_if_fail (event != NULL);
   g_return_if_fail (GST_IS_EVENT (event));
 
   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
       GST_EVENT_TYPE_NAME (event));
 
-  if (GST_EVENT_SRC (event)) {
-    gst_object_unref (GST_EVENT_SRC (event));
-    GST_EVENT_SRC (event) = NULL;
-  }
-  if (event->structure) {
-    gst_structure_set_parent_refcount (event->structure, NULL);
-    gst_structure_free (event->structure);
+  s = GST_EVENT_STRUCTURE (event);
+
+  if (s) {
+    gst_structure_set_parent_refcount (s, NULL);
+    gst_structure_free (s);
   }
 
-/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event)); */
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (event), event);
 }
 
+static void gst_event_init (GstEventImpl * event, gsize size,
+    GstEventType type);
+
 static GstEvent *
 _gst_event_copy (GstEvent * event)
 {
-  GstEvent *copy;
+  GstEventImpl *copy;
+  GstStructure *s;
 
-  copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
+  copy = g_slice_new0 (GstEventImpl);
+
+  gst_event_init (copy, sizeof (GstEventImpl), GST_EVENT_TYPE (event));
 
-  GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
   GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event);
 
-  if (GST_EVENT_SRC (event)) {
-    GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
-  }
-  if (event->structure) {
-    copy->structure = gst_structure_copy (event->structure);
-    gst_structure_set_parent_refcount (copy->structure,
-        &copy->mini_object.refcount);
+  s = GST_EVENT_STRUCTURE (event);
+  if (s) {
+    GST_EVENT_STRUCTURE (copy) = gst_structure_copy (s);
+    gst_structure_set_parent_refcount (GST_EVENT_STRUCTURE (copy),
+        &copy->event.mini_object.refcount);
   }
-  return copy;
+  return GST_EVENT_CAST (copy);
+}
+
+static void
+gst_event_init (GstEventImpl * event, gsize size, GstEventType type)
+{
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (event), _gst_event_type, size);
+
+  event->event.mini_object.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
+  event->event.mini_object.free = (GstMiniObjectFreeFunction) _gst_event_free;
+
+  GST_EVENT_TYPE (event) = type;
+  GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
+  GST_EVENT_SEQNUM (event) = gst_util_seqnum_next ();
 }
 
 static GstEvent *
 gst_event_new (GstEventType type)
 {
-  GstEvent *event;
+  GstEventImpl *event;
 
-  event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
+  event = g_slice_new0 (GstEventImpl);
 
   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
       gst_event_type_get_name (type), type);
 
-  event->type = type;
-  event->src = NULL;
-  event->structure = NULL;
-  GST_EVENT_SEQNUM (event) = gst_util_seqnum_next ();
+  gst_event_init (event, sizeof (GstEventImpl), type);
 
-  return event;
+  return GST_EVENT_CAST (event);
 }
 
 /**
@@ -301,15 +303,23 @@ gst_event_new_custom (GstEventType type, GstStructure * structure)
   GstEvent *event;
 
   /* structure must not have a parent */
-  if (structure)
-    g_return_val_if_fail (structure->parent_refcount == NULL, NULL);
-
   event = gst_event_new (type);
   if (structure) {
-    gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
-    event->structure = structure;
+    if (!gst_structure_set_parent_refcount (structure,
+            &event->mini_object.refcount))
+      goto had_parent;
+
+    GST_EVENT_STRUCTURE (event) = structure;
   }
   return event;
+
+  /* ERRORS */
+had_parent:
+  {
+    gst_event_unref (event);
+    g_warning ("structure is already owned by another object");
+    return NULL;
+  }
 }
 
 /**
@@ -329,7 +339,40 @@ gst_event_get_structure (GstEvent * event)
 {
   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
 
-  return event->structure;
+  return GST_EVENT_STRUCTURE (event);
+}
+
+/**
+ * gst_event_writable_structure:
+ * @event: The #GstEvent.
+ *
+ * Get a writable version of the structure.
+ *
+ * Returns: The structure of the event. The structure is still
+ * owned by the event, which means that you should not free it and
+ * that the pointer becomes invalid when you free the event.
+ * This function checks if @event is writable and will never return NULL.
+ *
+ * MT safe.
+ */
+GstStructure *
+gst_event_writable_structure (GstEvent * event)
+{
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_IS_EVENT (event), NULL);
+  g_return_val_if_fail (gst_event_is_writable (event), NULL);
+
+  structure = GST_EVENT_STRUCTURE (event);
+
+  if (structure == NULL) {
+    structure =
+        gst_structure_new_id_empty (gst_event_type_to_quark (GST_EVENT_TYPE
+            (event)));
+    gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
+    GST_EVENT_STRUCTURE (event) = structure;
+  }
+  return structure;
 }
 
 /**
@@ -349,10 +392,10 @@ gst_event_has_name (GstEvent * event, const gchar * name)
 {
   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
 
-  if (event->structure == NULL)
+  if (GST_EVENT_STRUCTURE (event) == NULL)
     return FALSE;
 
-  return gst_structure_has_name (event->structure, name);
+  return gst_structure_has_name (GST_EVENT_STRUCTURE (event), name);
 }
 
 /**
@@ -441,6 +484,7 @@ gst_event_new_flush_start (void)
 
 /**
  * gst_event_new_flush_stop:
+ * @reset_time: if time should be reset
  *
  * Allocate a new flush stop event. The flush stop event can be sent
  * upstream and downstream and travels serialized with the dataflow.
@@ -456,9 +500,39 @@ gst_event_new_flush_start (void)
  * Returns: (transfer full): a new flush stop event.
  */
 GstEvent *
-gst_event_new_flush_stop (void)
+gst_event_new_flush_stop (gboolean reset_time)
+{
+  GstEvent *event;
+
+  GST_CAT_INFO (GST_CAT_EVENT, "creating flush stop %d", reset_time);
+
+  event = gst_event_new_custom (GST_EVENT_FLUSH_STOP,
+      gst_structure_new_id (GST_QUARK (EVENT_FLUSH_STOP),
+          GST_QUARK (RESET_TIME), G_TYPE_BOOLEAN, reset_time, NULL));
+
+  return event;
+}
+
+/**
+ * gst_event_parse_flush_stop:
+ * @event: The event to parse
+ * @reset_time: (out): if time should be reset
+ *
+ * Parse the FLUSH_STOP event and retrieve the @reset_time member.
+ */
+void
+gst_event_parse_flush_stop (GstEvent * event, gboolean * reset_time)
 {
-  return gst_event_new (GST_EVENT_FLUSH_STOP);
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP);
+
+  structure = GST_EVENT_STRUCTURE (event);
+  if (G_LIKELY (reset_time))
+    *reset_time =
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (RESET_TIME)));
 }
 
 /**
@@ -487,65 +561,62 @@ gst_event_new_eos (void)
 }
 
 /**
- * gst_event_new_new_segment:
- * @update: is this segment an update to a previous one
- * @rate: a new rate for playback
- * @format: The format of the segment values
- * @start: the start value of the segment
- * @stop: the stop value of the segment
- * @position: stream position
- *
- * Allocate a new newsegment event with the given format/values tripplets
+ * gst_event_new_caps:
+ * @caps: (transfer none): a #GstCaps
  *
- * This method calls gst_event_new_new_segment_full() passing a default
- * value of 1.0 for applied_rate
+ * Create a new CAPS event for @caps. The caps event can only travel downstream
+ * synchronized with the buffer flow and contains the format of the buffers
+ * that will follow after the event.
  *
- * Returns: (transfer full): a new newsegment event.
+ * Returns: (transfer full): the new CAPS event.
  */
 GstEvent *
-gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
-    gint64 start, gint64 stop, gint64 position)
+gst_event_new_caps (GstCaps * caps)
 {
-  return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
-      stop, position);
+  GstEvent *event;
+
+  g_return_val_if_fail (caps != NULL, NULL);
+  g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
+
+  GST_CAT_INFO (GST_CAT_EVENT, "creating caps event %" GST_PTR_FORMAT, caps);
+
+  event = gst_event_new_custom (GST_EVENT_CAPS,
+      gst_structure_new_id (GST_QUARK (EVENT_CAPS),
+          GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL));
+
+  return event;
 }
 
 /**
- * gst_event_parse_new_segment:
- * @event: The event to query
- * @update: (out): A pointer to the update flag of the segment
- * @rate: (out): A pointer to the rate of the segment
- * @format: (out): A pointer to the format of the newsegment values
- * @start: (out): A pointer to store the start value in
- * @stop: (out): A pointer to store the stop value in
- * @position: (out): A pointer to store the stream time in
- *
- * Get the update flag, rate, format, start, stop and position in the 
- * newsegment event. In general, gst_event_parse_new_segment_full() should
- * be used instead of this, to also retrieve the applied_rate value of the
- * segment. See gst_event_new_new_segment_full() for a full description 
- * of the newsegment event.
+ * gst_event_parse_caps:
+ * @event: The event to parse
+ * @caps: (out): A pointer to the caps
+ *
+ * Get the caps from @event. The caps remains valid as long as @event remains
+ * valid.
  */
 void
-gst_event_parse_new_segment (GstEvent * event, gboolean * update,
-    gdouble * rate, GstFormat * format, gint64 * start,
-    gint64 * stop, gint64 * position)
+gst_event_parse_caps (GstEvent * event, GstCaps ** caps)
 {
-  gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
-      stop, position);
+  GstStructure *structure;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
+
+  structure = GST_EVENT_STRUCTURE (event);
+  if (G_LIKELY (caps))
+    *caps =
+        g_value_get_boxed (gst_structure_id_get_value (structure,
+            GST_QUARK (CAPS)));
 }
 
 /**
- * gst_event_new_new_segment_full:
- * @update: Whether this segment is an update to a previous one
- * @rate: A new rate for playback
- * @applied_rate: The rate factor which has already been applied
- * @format: The format of the segment values
- * @start: The start value of the segment
- * @stop: The stop value of the segment
- * @position: stream position
+ * gst_event_new_segment:
+ * @segment: (transfer none): a #GstSegment
  *
- * Allocate a new newsegment event with the given format/values triplets.
+ * Create a new SEGMENT event for @segment. The segment event can only travel
+ * downstream synchronized with the buffer flow and contains timing information
+ * and playback properties for the buffers that will follow.
  *
  * The newsegment event marks the range of buffers to be processed. All
  * data not within the segment range is not to be processed. This can be
@@ -553,133 +624,94 @@ gst_event_parse_new_segment (GstEvent * event, gboolean * update,
  * unneeded data. The valid range is expressed with the @start and @stop
  * values.
  *
- * The position value of the segment is used in conjunction with the start
- * value to convert the buffer timestamps into the stream time. This is 
- * usually done in sinks to report the current stream_time. 
- * @position represents the stream_time of a buffer carrying a timestamp of 
- * @start. @position cannot be -1.
+ * The time value of the segment is used in conjunction with the start
+ * value to convert the buffer timestamps into the stream time. This is
+ * usually done in sinks to report the current stream_time.
+ * @time represents the stream_time of a buffer carrying a timestamp of
+ * @start. @time cannot be -1.
  *
  * @start cannot be -1, @stop can be -1. If there
- * is a valid @stop given, it must be greater or equal the @start, including 
+ * is a valid @stop given, it must be greater or equal the @start, including
  * when the indicated playback @rate is < 0.
  *
  * The @applied_rate value provides information about any rate adjustment that
- * has already been made to the timestamps and content on the buffers of the 
- * stream. (@rate * @applied_rate) should always equal the rate that has been 
- * requested for playback. For example, if an element has an input segment 
- * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust 
- * incoming timestamps and buffer content by half and output a newsegment event 
+ * has already been made to the timestamps and content on the buffers of the
+ * stream. (@rate * @applied_rate) should always equal the rate that has been
+ * requested for playback. For example, if an element has an input segment
+ * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust
+ * incoming timestamps and buffer content by half and output a newsegment event
  * with @rate of 1.0 and @applied_rate of 2.0
  *
  * After a newsegment event, the buffer stream time is calculated with:
  *
- *   position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
- *
- * Returns: (transfer full): a new newsegment event.
+ *   time + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
  *
- * Since: 0.10.6
+ * Returns: (transfer full): the new SEGMENT event.
  */
 GstEvent *
-gst_event_new_new_segment_full (gboolean update, gdouble rate,
-    gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
-    gint64 position)
+gst_event_new_segment (const GstSegment * segment)
 {
   GstEvent *event;
-  GstStructure *structure;
-
-  g_return_val_if_fail (rate != 0.0, NULL);
-  g_return_val_if_fail (applied_rate != 0.0, NULL);
-  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, NULL);
 
-  if (format == GST_FORMAT_TIME) {
-    GST_CAT_INFO (GST_CAT_EVENT,
-        "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
-        "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
-        ", position %" GST_TIME_FORMAT,
-        update, rate, GST_TIME_ARGS (start),
-        GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
-  } else {
-    GST_CAT_INFO (GST_CAT_EVENT,
-        "creating newsegment update %d, rate %lf, format %s, "
-        "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
-        G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
-        stop, position);
-  }
+  g_return_val_if_fail (segment != NULL, NULL);
+  g_return_val_if_fail (segment->rate != 0.0, NULL);
+  g_return_val_if_fail (segment->applied_rate != 0.0, NULL);
+  g_return_val_if_fail (segment->format != GST_FORMAT_UNDEFINED, NULL);
 
-  g_return_val_if_fail (position != -1, NULL);
-  g_return_val_if_fail (start != -1, NULL);
-  if (stop != -1)
-    g_return_val_if_fail (start <= stop, NULL);
+  GST_CAT_INFO (GST_CAT_EVENT, "creating segment event %" GST_SEGMENT_FORMAT,
+      segment);
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_NEWSEGMENT),
-      GST_QUARK (UPDATE), G_TYPE_BOOLEAN, update,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, applied_rate,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START), G_TYPE_INT64, start,
-      GST_QUARK (STOP), G_TYPE_INT64, stop,
-      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
-  event = gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure);
+  event = gst_event_new_custom (GST_EVENT_SEGMENT,
+      gst_structure_new_id (GST_QUARK (EVENT_SEGMENT),
+          GST_QUARK (SEGMENT), GST_TYPE_SEGMENT, segment, NULL));
 
   return event;
 }
 
 /**
- * gst_event_parse_new_segment_full:
- * @event: The event to query
- * @update: (out): A pointer to the update flag of the segment
- * @rate: (out): A pointer to the rate of the segment
- * @applied_rate: (out): A pointer to the applied_rate of the segment
- * @format: (out): A pointer to the format of the newsegment values
- * @start: (out): A pointer to store the start value in
- * @stop: (out): A pointer to store the stop value in
- * @position: (out): A pointer to store the stream time in
- *
- * Get the update, rate, applied_rate, format, start, stop and 
- * position in the newsegment event. See gst_event_new_new_segment_full() 
- * for a full description of the newsegment event.
- *
- * Since: 0.10.6
+ * gst_event_parse_segment:
+ * @event: The event to parse
+ * @segment: (out) (transfer none): a pointer to a #GstSegment
+ *
+ * Parses a segment @event and stores the result in the given @segment location.
+ * @segment remains valid only until the @event is freed. Don't modify the segment
+ * and make a copy if you want to modify it or store it for later use.
  */
 void
-gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
-    gdouble * rate, gdouble * applied_rate, GstFormat * format,
-    gint64 * start, gint64 * stop, gint64 * position)
+gst_event_parse_segment (GstEvent * event, const GstSegment ** segment)
 {
-  const GstStructure *structure;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_EVENT (event));
-  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
 
-  structure = event->structure;
-  if (G_LIKELY (update))
-    *update =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (UPDATE)));
-  if (G_LIKELY (rate))
-    *rate =
-        g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (RATE)));
-  if (G_LIKELY (applied_rate))
-    *applied_rate =
-        g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (APPLIED_RATE)));
-  if (G_LIKELY (format))
-    *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
-  if (G_LIKELY (start))
-    *start =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (START)));
-  if (G_LIKELY (stop))
-    *stop =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (STOP)));
-  if (G_LIKELY (position))
-    *position =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (POSITION)));
+  if (segment) {
+    structure = GST_EVENT_STRUCTURE (event);
+    *segment = g_value_get_boxed (gst_structure_id_get_value (structure,
+            GST_QUARK (SEGMENT)));
+  }
+}
+
+/**
+ * gst_event_copy_segment:
+ * @event: The event to parse
+ * @segment: a pointer to a #GstSegment
+ *
+ * Parses a segment @event and copies the #GstSegment into the location
+ * given by @segment.
+ */
+void
+gst_event_copy_segment (GstEvent * event, GstSegment * segment)
+{
+  const GstSegment *src;
+
+  g_return_if_fail (GST_IS_EVENT (event));
+  g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
+
+  if (segment) {
+    gst_event_parse_segment (event, &src);
+    gst_segment_copy_into (src, segment);
+  }
 }
 
 /**
@@ -716,7 +748,7 @@ gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
 
   if (taglist)
-    *taglist = (GstTagList *) event->structure;
+    *taglist = (GstTagList *) GST_EVENT_STRUCTURE (event);
 }
 
 /* buffersize event */
@@ -746,7 +778,7 @@ gst_event_new_buffer_size (GstFormat format, gint64 minsize,
       ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
       minsize, maxsize, async);
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_BUFFER_SIZE),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_BUFFER_SIZE),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
       GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
@@ -775,7 +807,7 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format = (GstFormat)
         g_value_get_enum (gst_structure_id_get_value (structure,
@@ -796,33 +828,6 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
 
 /**
  * gst_event_new_qos:
- * @proportion: the proportion of the qos message
- * @diff: The time difference of the last Clock sync
- * @timestamp: The timestamp of the buffer
- *
- * Allocate a new qos event with the given values. This function calls
- * gst_event_new_qos_full() with the type set to #GST_QOS_TYPE_OVERFLOW
- * when diff is negative (buffers are in time) and #GST_QOS_TYPE_UNDERFLOW
- * when @diff is positive (buffers are late).
- *
- * Returns: (transfer full): a new QOS event.
- */
-GstEvent *
-gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
-    GstClockTime timestamp)
-{
-  GstQOSType type;
-
-  if (diff <= 0)
-    type = GST_QOS_TYPE_OVERFLOW;
-  else
-    type = GST_QOS_TYPE_UNDERFLOW;
-
-  return gst_event_new_qos_full (type, proportion, diff, timestamp);
-}
-
-/**
- * gst_event_new_qos_full:
  * @type: the QoS type
  * @proportion: the proportion of the qos message
  * @diff: The time difference of the last Clock sync
@@ -872,11 +877,9 @@ gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
  * event and implement custom application specific QoS handling.
  *
  * Returns: (transfer full): a new QOS event.
- *
- * Since: 0.10.33
  */
 GstEvent *
-gst_event_new_qos_full (GstQOSType type, gdouble proportion,
+gst_event_new_qos (GstQOSType type, gdouble proportion,
     GstClockTimeDiff diff, GstClockTime timestamp)
 {
   GstEvent *event;
@@ -885,12 +888,12 @@ gst_event_new_qos_full (GstQOSType type, gdouble proportion,
   /* diff must be positive or timestamp + diff must be positive */
   g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL);
 
-  GST_CAT_INFO (GST_CAT_EVENT,
+  GST_CAT_LOG (GST_CAT_EVENT,
       "creating qos type %d, proportion %lf, diff %" G_GINT64_FORMAT
       ", timestamp %" GST_TIME_FORMAT, type, proportion,
       diff, GST_TIME_ARGS (timestamp));
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_QOS),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_QOS),
       GST_QUARK (TYPE), GST_TYPE_QOS_TYPE, type,
       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
       GST_QUARK (DIFF), G_TYPE_INT64, diff,
@@ -903,35 +906,16 @@ gst_event_new_qos_full (GstQOSType type, gdouble proportion,
 /**
  * gst_event_parse_qos:
  * @event: The event to query
- * @proportion: (out): A pointer to store the proportion in
- * @diff: (out): A pointer to store the diff in
- * @timestamp: (out): A pointer to store the timestamp in
- *
- * Get the proportion, diff and timestamp in the qos event. See
- * gst_event_new_qos() for more information about the different QoS values.
- */
-void
-gst_event_parse_qos (GstEvent * event, gdouble * proportion,
-    GstClockTimeDiff * diff, GstClockTime * timestamp)
-{
-  gst_event_parse_qos_full (event, NULL, proportion, diff, timestamp);
-}
-
-/**
- * gst_event_parse_qos_full:
- * @event: The event to query
  * @type: (out): A pointer to store the QoS type in
  * @proportion: (out): A pointer to store the proportion in
  * @diff: (out): A pointer to store the diff in
  * @timestamp: (out): A pointer to store the timestamp in
  *
  * Get the type, proportion, diff and timestamp in the qos event. See
- * gst_event_new_qos_full() for more information about the different QoS values.
- *
- * Since: 0.10.33
+ * gst_event_new_qos() for more information about the different QoS values.
  */
 void
-gst_event_parse_qos_full (GstEvent * event, GstQOSType * type,
+gst_event_parse_qos (GstEvent * event, GstQOSType * type,
     gdouble * proportion, GstClockTimeDiff * diff, GstClockTime * timestamp)
 {
   const GstStructure *structure;
@@ -939,7 +923,7 @@ gst_event_parse_qos_full (GstEvent * event, GstQOSType * type,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (type)
     *type = (GstQOSType)
         g_value_get_enum (gst_structure_id_get_value (structure,
@@ -1027,7 +1011,7 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
         stop);
   }
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_SEEK),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_SEEK),
       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
@@ -1063,7 +1047,7 @@ gst_event_parse_seek (GstEvent * event, gdouble * rate,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (rate)
     *rate =
         g_value_get_double (gst_structure_id_get_value (structure,
@@ -1135,7 +1119,7 @@ gst_event_new_latency (GstClockTime latency)
   GST_CAT_INFO (GST_CAT_EVENT,
       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_LATENCY),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_LATENCY),
       GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
   event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
 
@@ -1159,8 +1143,8 @@ gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
 
   if (latency)
     *latency =
-        g_value_get_uint64 (gst_structure_id_get_value (event->structure,
-            GST_QUARK (LATENCY)));
+        g_value_get_uint64 (gst_structure_id_get_value (GST_EVENT_STRUCTURE
+            (event), GST_QUARK (LATENCY)));
 }
 
 /**
@@ -1200,7 +1184,7 @@ gst_event_new_step (GstFormat format, guint64 amount, gdouble rate,
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating step event");
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_STEP),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_STEP),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
@@ -1234,7 +1218,7 @@ gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -1254,6 +1238,30 @@ gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
 }
 
 /**
+ * gst_event_new_reconfigure:
+
+ * Create a new reconfigure event. The purpose of the reconfingure event is
+ * to travel upstream and make elements renegotiate their caps or reconfigure
+ * their buffer pools. This is useful when changing properties on elements
+ * or changing the topology of the pipeline.
+ *
+ * Returns: (transfer full): a new #GstEvent
+ *
+ * Since: 0.11.0
+ */
+GstEvent *
+gst_event_new_reconfigure (void)
+{
+  GstEvent *event;
+
+  GST_CAT_INFO (GST_CAT_EVENT, "creating reconfigure event");
+
+  event = gst_event_new_custom (GST_EVENT_RECONFIGURE, NULL);
+
+  return event;
+}
+
+/**
  * gst_event_new_sink_message:
  * @msg: (transfer none): the #GstMessage to be posted
  *
@@ -1276,7 +1284,7 @@ gst_event_new_sink_message (GstMessage * msg)
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating sink-message event");
 
-  structure = gst_structure_id_new (GST_QUARK (EVENT_SINK_MESSAGE),
+  structure = gst_structure_new_id (GST_QUARK (EVENT_SINK_MESSAGE),
       GST_QUARK (MESSAGE), GST_TYPE_MESSAGE, msg, NULL);
   event = gst_event_new_custom (GST_EVENT_SINK_MESSAGE, structure);
 
@@ -1295,11 +1303,14 @@ gst_event_new_sink_message (GstMessage * msg)
 void
 gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
 {
+  const GstStructure *structure;
+
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE);
 
+  structure = GST_EVENT_STRUCTURE (event);
   if (msg)
     *msg =
-        GST_MESSAGE (gst_value_dup_mini_object (gst_structure_id_get_value
-            (event->structure, GST_QUARK (MESSAGE))));
+        GST_MESSAGE (g_value_dup_boxed (gst_structure_id_get_value
+            (structure, GST_QUARK (MESSAGE))));
 }
index 20e8ef0..d9db2c6 100644 (file)
 #ifndef __GST_EVENT_H__
 #define __GST_EVENT_H__
 
-#include <gst/gstminiobject.h>
-#include <gst/gstformat.h>
-#include <gst/gstobject.h>
-#include <gst/gstclock.h>
-#include <gst/gststructure.h>
-#include <gst/gsttaglist.h>
-
-G_BEGIN_DECLS
+typedef struct _GstEvent GstEvent;
 
 /**
  * GstEventTypeFlags:
- * @GST_EVENT_TYPE_UPSTREAM:   Set if the event can travel upstream.
- * @GST_EVENT_TYPE_DOWNSTREAM: Set if the event can travel downstream.
- * @GST_EVENT_TYPE_SERIALIZED: Set if the event should be serialized with data
- *                             flow.
+ * @GST_EVENT_TYPE_UPSTREAM:     Set if the event can travel upstream.
+ * @GST_EVENT_TYPE_DOWNSTREAM:   Set if the event can travel downstream.
+ * @GST_EVENT_TYPE_SERIALIZED:   Set if the event should be serialized with data
+ *                               flow.
+ * @GST_EVENT_TYPE_STICKY:       Set if the event is sticky on the pads.
+ * @GST_EVENT_TYPE_STICKY_MULTI: Multiple sticky events can be on a pad, each
+ *                               identified by the event name.
  *
  * #GstEventTypeFlags indicate the aspects of the different #GstEventType
  * values. You can get the type flags of a #GstEventType with the
@@ -48,7 +44,9 @@ G_BEGIN_DECLS
 typedef enum {
   GST_EVENT_TYPE_UPSTREAM       = 1 << 0,
   GST_EVENT_TYPE_DOWNSTREAM     = 1 << 1,
-  GST_EVENT_TYPE_SERIALIZED     = 1 << 2
+  GST_EVENT_TYPE_SERIALIZED     = 1 << 2,
+  GST_EVENT_TYPE_STICKY         = 1 << 3,
+  GST_EVENT_TYPE_STICKY_MULTI   = 1 << 4
 } GstEventTypeFlags;
 
 /**
@@ -59,21 +57,27 @@ typedef enum {
 #define GST_EVENT_TYPE_BOTH \
     (GST_EVENT_TYPE_UPSTREAM | GST_EVENT_TYPE_DOWNSTREAM)
 
-#define GST_EVENT_TYPE_SHIFT    4
+#define GST_EVENT_MAX_STICKY    16
+#define GST_EVENT_STICKY_SHIFT  8
+#define GST_EVENT_NUM_SHIFT     (GST_EVENT_STICKY_SHIFT + 4)
 
 /**
  * GST_EVENT_MAKE_TYPE:
  * @num: the event number to create
+ * @idx: the index in the sticky array
  * @flags: the event flags
  *
  * when making custom event types, use this macro with the num and
  * the given flags
  */
-#define GST_EVENT_MAKE_TYPE(num,flags) \
-    (((num) << GST_EVENT_TYPE_SHIFT) | (flags))
+#define GST_EVENT_MAKE_TYPE(num,idx,flags) \
+    (((num) << GST_EVENT_NUM_SHIFT) | ((idx) << GST_EVENT_STICKY_SHIFT) | (flags))
 
 #define FLAG(name) GST_EVENT_TYPE_##name
 
+#define GST_EVENT_STICKY_IDX_TYPE(type)  (((type) >> GST_EVENT_STICKY_SHIFT) & 0xf)
+#define GST_EVENT_STICKY_IDX(ev)         GST_EVENT_STICKY_IDX_TYPE(GST_EVENT_TYPE(ev))
+
 /**
  * GstEventType:
  * @GST_EVENT_UNKNOWN: unknown event.
@@ -81,9 +85,8 @@ typedef enum {
  *                 from the pipeline and unblock all streaming threads.
  * @GST_EVENT_FLUSH_STOP: Stop a flush operation. This event resets the
  *                 running-time of the pipeline.
- * @GST_EVENT_EOS: End-Of-Stream. No more data is to be expected to follow
- *                 without a NEWSEGMENT event.
- * @GST_EVENT_NEWSEGMENT: A new media segment follows in the dataflow. The
+ * @GST_EVENT_CAPS: #GstCaps event. Notify the pad of a new media type.
+ * @GST_EVENT_SEGMENT: A new media segment follows in the dataflow. The
  *                 segment events contains information for clipping buffers and
  *                 converting buffer timestamps to running-time and
  *                 stream-time.
@@ -94,6 +97,8 @@ typedef enum {
  *                          send messages that should be emitted in sync with
  *                          rendering.
  *                          Since: 0.10.26
+ * @GST_EVENT_EOS: End-Of-Stream. No more data is to be expected to follow
+ *                 without a SEGMENT event.
  * @GST_EVENT_QOS: A quality message. Used to indicate to upstream elements
  *                 that the downstream elements should adjust their processing
  *                 rate.
@@ -106,10 +111,13 @@ typedef enum {
  *                     Since: 0.10.12
  * @GST_EVENT_STEP: A request for stepping through the media. Sinks will usually
  *                  execute the step operation. Since: 0.10.24
+ * @GST_EVENT_RECONFIGURE: A request for upstream renegotiating caps and reconfiguring.
+ *                         Since: 0.11.0
  * @GST_EVENT_CUSTOM_UPSTREAM: Upstream custom event
  * @GST_EVENT_CUSTOM_DOWNSTREAM: Downstream custom event that travels in the
  *                        data flow.
  * @GST_EVENT_CUSTOM_DOWNSTREAM_OOB: Custom out-of-band downstream event.
+ * @GST_EVENT_CUSTOM_DOWNSTREAM_STICKY: Custom sticky downstream event.
  * @GST_EVENT_CUSTOM_BOTH: Custom upstream or downstream event.
  *                         In-band when travelling downstream.
  * @GST_EVENT_CUSTOM_BOTH_OOB: Custom upstream or downstream out-of-band event.
@@ -124,32 +132,55 @@ typedef enum {
  */
 /* NOTE: keep in sync with quark registration in gstevent.c */
 typedef enum {
-  GST_EVENT_UNKNOWN               = GST_EVENT_MAKE_TYPE (0, 0),
+  GST_EVENT_UNKNOWN               = GST_EVENT_MAKE_TYPE (0, 0, 0),
   /* bidirectional events */
-  GST_EVENT_FLUSH_START           = GST_EVENT_MAKE_TYPE (1, FLAG(BOTH)),
-  GST_EVENT_FLUSH_STOP            = GST_EVENT_MAKE_TYPE (2, FLAG(BOTH) | FLAG(SERIALIZED)),
+  GST_EVENT_FLUSH_START           = GST_EVENT_MAKE_TYPE (1, 0, FLAG(BOTH)),
+  GST_EVENT_FLUSH_STOP            = GST_EVENT_MAKE_TYPE (2, 0, FLAG(BOTH) | FLAG(SERIALIZED)),
   /* downstream serialized events */
-  GST_EVENT_EOS                   = GST_EVENT_MAKE_TYPE (5, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_NEWSEGMENT            = GST_EVENT_MAKE_TYPE (6, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_TAG                   = GST_EVENT_MAKE_TYPE (7, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_BUFFERSIZE            = GST_EVENT_MAKE_TYPE (8, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_SINK_MESSAGE          = GST_EVENT_MAKE_TYPE (9, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
+  GST_EVENT_CAPS                  = GST_EVENT_MAKE_TYPE (5, 1, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
+  GST_EVENT_SEGMENT               = GST_EVENT_MAKE_TYPE (6, 2, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
+  GST_EVENT_TAG                   = GST_EVENT_MAKE_TYPE (7, 3, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
+  GST_EVENT_BUFFERSIZE            = GST_EVENT_MAKE_TYPE (8, 4, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
+  GST_EVENT_SINK_MESSAGE          = GST_EVENT_MAKE_TYPE (9, 5, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
+  GST_EVENT_EOS                   = GST_EVENT_MAKE_TYPE (10, 6, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)),
+
   /* upstream events */
-  GST_EVENT_QOS                   = GST_EVENT_MAKE_TYPE (15, FLAG(UPSTREAM)),
-  GST_EVENT_SEEK                  = GST_EVENT_MAKE_TYPE (16, FLAG(UPSTREAM)),
-  GST_EVENT_NAVIGATION            = GST_EVENT_MAKE_TYPE (17, FLAG(UPSTREAM)),
-  GST_EVENT_LATENCY               = GST_EVENT_MAKE_TYPE (18, FLAG(UPSTREAM)),
-  GST_EVENT_STEP                  = GST_EVENT_MAKE_TYPE (19, FLAG(UPSTREAM)),
+  GST_EVENT_QOS                   = GST_EVENT_MAKE_TYPE (15, 0, FLAG(UPSTREAM)),
+  GST_EVENT_SEEK                  = GST_EVENT_MAKE_TYPE (16, 0, FLAG(UPSTREAM)),
+  GST_EVENT_NAVIGATION            = GST_EVENT_MAKE_TYPE (17, 0, FLAG(UPSTREAM)),
+  GST_EVENT_LATENCY               = GST_EVENT_MAKE_TYPE (18, 0, FLAG(UPSTREAM)),
+  GST_EVENT_STEP                  = GST_EVENT_MAKE_TYPE (19, 0, FLAG(UPSTREAM)),
+  GST_EVENT_RECONFIGURE           = GST_EVENT_MAKE_TYPE (20, 0, FLAG(UPSTREAM)),
 
   /* custom events start here */
-  GST_EVENT_CUSTOM_UPSTREAM       = GST_EVENT_MAKE_TYPE (32, FLAG(UPSTREAM)),
-  GST_EVENT_CUSTOM_DOWNSTREAM     = GST_EVENT_MAKE_TYPE (32, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
-  GST_EVENT_CUSTOM_DOWNSTREAM_OOB = GST_EVENT_MAKE_TYPE (32, FLAG(DOWNSTREAM)),
-  GST_EVENT_CUSTOM_BOTH           = GST_EVENT_MAKE_TYPE (32, FLAG(BOTH) | FLAG(SERIALIZED)),
-  GST_EVENT_CUSTOM_BOTH_OOB       = GST_EVENT_MAKE_TYPE (32, FLAG(BOTH))
+  GST_EVENT_CUSTOM_UPSTREAM          = GST_EVENT_MAKE_TYPE (32, 0, FLAG(UPSTREAM)),
+  GST_EVENT_CUSTOM_DOWNSTREAM        = GST_EVENT_MAKE_TYPE (32, 0, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
+  GST_EVENT_CUSTOM_DOWNSTREAM_OOB    = GST_EVENT_MAKE_TYPE (32, 0, FLAG(DOWNSTREAM)),
+  GST_EVENT_CUSTOM_DOWNSTREAM_STICKY = GST_EVENT_MAKE_TYPE (32, 0, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)),
+  GST_EVENT_CUSTOM_BOTH              = GST_EVENT_MAKE_TYPE (32, 0, FLAG(BOTH) | FLAG(SERIALIZED)),
+  GST_EVENT_CUSTOM_BOTH_OOB          = GST_EVENT_MAKE_TYPE (32, 0, FLAG(BOTH))
 } GstEventType;
 #undef FLAG
 
+#include <gst/gstminiobject.h>
+#include <gst/gstformat.h>
+#include <gst/gstobject.h>
+#include <gst/gstclock.h>
+#include <gst/gststructure.h>
+#include <gst/gsttaglist.h>
+#include <gst/gstsegment.h>
+#include <gst/gstsegment.h>
+#include <gst/gstmessage.h>
+
+G_BEGIN_DECLS
+
+GST_EXPORT GType _gst_event_type;
+
+#define GST_TYPE_EVENT                  (_gst_event_type)
+#define GST_IS_EVENT(obj)               (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_EVENT))
+#define GST_EVENT_CAST(obj)             ((GstEvent *)(obj))
+#define GST_EVENT(obj)                  (GST_EVENT_CAST(obj))
+
 /**
  * GST_EVENT_TRACE_NAME:
  *
@@ -157,17 +188,6 @@ typedef enum {
  */
 #define GST_EVENT_TRACE_NAME    "GstEvent"
 
-typedef struct _GstEvent GstEvent;
-typedef struct _GstEventClass GstEventClass;
-
-#define GST_TYPE_EVENT                  (gst_event_get_type())
-#define GST_IS_EVENT(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVENT))
-#define GST_IS_EVENT_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_EVENT))
-#define GST_EVENT_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_EVENT, GstEventClass))
-#define GST_EVENT(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVENT, GstEvent))
-#define GST_EVENT_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_EVENT, GstEventClass))
-#define GST_EVENT_CAST(obj)             ((GstEvent *)(obj))
-
 /**
  * GST_EVENT_TYPE:
  * @event: the event to query
@@ -194,12 +214,12 @@ typedef struct _GstEventClass GstEventClass;
 #define GST_EVENT_TIMESTAMP(event)      (GST_EVENT_CAST(event)->timestamp)
 
 /**
- * GST_EVENT_SRC:
+ * GST_EVENT_SEQNUM:
  * @event: the event to query
  *
- * The source #GstObject that generated this event.
+ * The sequence number of @event.
  */
-#define GST_EVENT_SRC(event)            (GST_EVENT_CAST(event)->src)
+#define GST_EVENT_SEQNUM(event)         (GST_EVENT_CAST(event)->seqnum)
 
 /**
  * GST_EVENT_IS_UPSTREAM:
@@ -222,8 +242,35 @@ typedef struct _GstEventClass GstEventClass;
  * Check if an event is serialized with the data stream.
  */
 #define GST_EVENT_IS_SERIALIZED(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_SERIALIZED)
+/**
+ * GST_EVENT_IS_STICKY:
+ * @ev: the event to query
+ *
+ * Check if an event is sticky on the pads.
+ */
+#define GST_EVENT_IS_STICKY(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_STICKY)
 
 /**
+ * gst_event_is_writable:
+ * @ev: a #GstEvent
+ *
+ * Tests if you can safely write data into a event's structure or validly
+ * modify the seqnum and timestamp field.
+ */
+#define         gst_event_is_writable(ev)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ev))
+/**
+ * gst_event_make_writable:
+ * @ev: (transfer full): a #GstEvent
+ *
+ * Makes a writable event from the given event. If the source event is
+ * already writable, this will simply return the same event. A copy will
+ * otherwise be made using gst_event_copy().
+ *
+ * Returns: (transfer full): a writable event which may or may not be the
+ *     same as @ev
+ */
+#define         gst_event_make_writable(ev)   GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ev)))
+/**
  * gst_event_replace:
  * @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent
  *     to be replaced.
@@ -237,88 +284,62 @@ typedef struct _GstEventClass GstEventClass;
  *
  * Either @new_event or the #GstEvent pointed to by @old_event may be NULL.
  *
- * Since: 0.10.3
+ * Returns: TRUE if @new_event was different from @old_event
  */
 #ifdef _FOOL_GTK_DOC_
-G_INLINE_FUNC void gst_event_replace (GstEvent **old_event, GstEvent *new_event);
+G_INLINE_FUNC gboolean gst_event_replace (GstEvent **old_event, GstEvent *new_event);
 #endif
 
-static inline void
+static inline gboolean
 gst_event_replace (GstEvent **old_event, GstEvent *new_event)
 {
-  gst_mini_object_replace ((GstMiniObject **) old_event, (GstMiniObject *) new_event);
+  return gst_mini_object_replace ((GstMiniObject **) old_event, (GstMiniObject *) new_event);
 }
 
 /**
- * GstSeekType:
- * @GST_SEEK_TYPE_NONE: no change in position is required
- * @GST_SEEK_TYPE_CUR: change relative to currently configured segment. This
- *    can't be used to seek relative to the current playback position - do a
- *    position query, calculate the desired position and then do an absolute
- *    position seek instead if that's what you want to do.
- * @GST_SEEK_TYPE_SET: absolute position is requested
- * @GST_SEEK_TYPE_END: relative position to duration is requested
- *
- * The different types of seek events. When constructing a seek event with
- * gst_event_new_seek(), a format, a seek method and optional flags are to
- * be provided. The seek event is then inserted into the graph with
- * gst_pad_send_event() or gst_element_send_event().
+ * gst_event_steal:
+ * @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent
+ *     to be stolen.
+ *
+ * Atomically replace the #GstEvent pointed to by @old_event with NULL and
+ * return the original event.
+ *
+ * Returns: the #GstEvent that was in @old_event
  */
-typedef enum {
-  /* one of these */
-  GST_SEEK_TYPE_NONE            = 0,
-  GST_SEEK_TYPE_CUR             = 1,
-  GST_SEEK_TYPE_SET             = 2,
-  GST_SEEK_TYPE_END             = 3
-} GstSeekType;
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstEvent * gst_event_steal (GstEvent **old_event);
+#endif
+
+static inline GstEvent *
+gst_event_steal (GstEvent **old_event)
+{
+  return GST_EVENT_CAST (gst_mini_object_steal ((GstMiniObject **) old_event));
+}
 
 /**
- * GstSeekFlags:
- * @GST_SEEK_FLAG_NONE: no flag
- * @GST_SEEK_FLAG_FLUSH: flush pipeline
- * @GST_SEEK_FLAG_ACCURATE: accurate position is requested, this might
- *                     be considerably slower for some formats.
- * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be
- *                     faster but less accurate.
- * @GST_SEEK_FLAG_SEGMENT: perform a segment seek.
- * @GST_SEEK_FLAG_SKIP: when doing fast foward or fast reverse playback, allow
- *                     elements to skip frames instead of generating all
- *                     frames. Since 0.10.22.
- *
- * Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags
- * can be used together.
- *
- * A non flushing seek might take some time to perform as the currently
- * playing data in the pipeline will not be cleared.
- *
- * An accurate seek might be slower for formats that don't have any indexes
- * or timestamp markers in the stream. Specifying this flag might require a
- * complete scan of the file in those cases.
- *
- * When performing a segment seek: after the playback of the segment completes,
- * no EOS will be emmited by the element that performed the seek, but a
- * #GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element.
- * When this message is posted, it is possible to send a new seek event to
- * continue playback. With this seek method it is possible to perform seamless
- * looping or simple linear editing.
- *
- * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode
- * playback, the @GST_SEEK_FLAG_SKIP flag can be used to instruct decoders
- * and demuxers to adjust the playback rate by skipping frames. This can improve
- * performance and decrease CPU usage because not all frames need to be decoded.
- *
- * Also see part-seeking.txt in the GStreamer design documentation for more
- * details on the meaning of these flags and the behaviour expected of
- * elements that handle them.
+ * gst_event_take:
+ * @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent
+ *     to be stolen.
+ * @new_event: (allow-none) (transfer full): pointer to a #GstEvent that will
+ *     replace the event pointed to by @old_event.
+ *
+ * Modifies a pointer to a #GstEvent to point to a different #GstEvent. This
+ * function is similar to gst_event_replace() except that it takes ownership of
+ * @new_event.
+ *
+ * Either @new_event or the #GstEvent pointed to by @old_event may be NULL.
+ *
+ * Returns: TRUE if @new_event was different from @old_event
  */
-typedef enum {
-  GST_SEEK_FLAG_NONE            = 0,
-  GST_SEEK_FLAG_FLUSH           = (1 << 0),
-  GST_SEEK_FLAG_ACCURATE        = (1 << 1),
-  GST_SEEK_FLAG_KEY_UNIT        = (1 << 2),
-  GST_SEEK_FLAG_SEGMENT         = (1 << 3),
-  GST_SEEK_FLAG_SKIP            = (1 << 4)
-} GstSeekFlags;
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_event_take (GstEvent **old_event, GstEvent *new_event);
+#endif
+
+static inline gboolean
+gst_event_take (GstEvent **old_event, GstEvent *new_event)
+{
+  return gst_mini_object_take ((GstMiniObject **) old_event, (GstMiniObject *) new_event);
+}
 
 /**
  * GstQOSType:
@@ -328,12 +349,12 @@ typedef enum {
  *    type is also used when buffers arrive early or in time.
  * @GST_QOS_TYPE_UNDERFLOW: The QoS event type that is produced when downstream
  *    elements are producing data too slowly and need to speed up their processing
- *    rate. 
+ *    rate.
  * @GST_QOS_TYPE_THROTTLE: The QoS event type that is produced when the
  *    application enabled throttling to limit the datarate.
  *
- * The different types of QoS events that can be given to the 
- * gst_event_new_qos_full() method. 
+ * The different types of QoS events that can be given to the
+ * gst_event_new_qos() method.
  *
  * Since: 0.10.33
  */
@@ -348,8 +369,7 @@ typedef enum {
  * @mini_object: the parent structure
  * @type: the #GstEventType of the event
  * @timestamp: the timestamp of the event
- * @src: the src of the event
- * @structure: the #GstStructure containing the event info.
+ * @seqnum: the sequence number of the event
  *
  * A #GstEvent.
  */
@@ -359,22 +379,7 @@ struct _GstEvent {
   /*< public >*/ /* with COW */
   GstEventType  type;
   guint64       timestamp;
-  GstObject     *src;
-
-  GstStructure  *structure;
-
-  /*< private >*/
-  union {
-    guint32 seqnum;
-    gpointer _gst_reserved;
-  } abidata;
-};
-
-struct _GstEventClass {
-  GstMiniObjectClass mini_object_class;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  guint32       seqnum;
 };
 
 const gchar*    gst_event_type_get_name         (GstEventType type);
@@ -383,8 +388,6 @@ GstEventTypeFlags
                 gst_event_type_get_flags        (GstEventType type);
 
 
-GType           gst_event_get_type              (void);
-
 /* refcounting */
 /**
  * gst_event_ref:
@@ -439,12 +442,14 @@ gst_event_copy (const GstEvent * event)
   return GST_EVENT_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (event)));
 }
 
+GType           gst_event_get_type              (void);
 
 /* custom event */
 GstEvent*       gst_event_new_custom            (GstEventType type, GstStructure *structure) G_GNUC_MALLOC;
 
 const GstStructure *
                 gst_event_get_structure         (GstEvent *event);
+GstStructure *  gst_event_writable_structure    (GstEvent *event);
 
 gboolean        gst_event_has_name              (GstEvent *event, const gchar *name);
 
@@ -454,34 +459,21 @@ void            gst_event_set_seqnum            (GstEvent *event, guint32 seqnum
 
 /* flush events */
 GstEvent *      gst_event_new_flush_start       (void) G_GNUC_MALLOC;
-GstEvent *      gst_event_new_flush_stop        (void) G_GNUC_MALLOC;
+
+GstEvent *      gst_event_new_flush_stop        (gboolean reset_time) G_GNUC_MALLOC;
+void            gst_event_parse_flush_stop      (GstEvent *event, gboolean *reset_time);
 
 /* EOS event */
 GstEvent *      gst_event_new_eos               (void) G_GNUC_MALLOC;
 
-/* newsegment events */
-GstEvent*       gst_event_new_new_segment       (gboolean update, gdouble rate,
-                                                 GstFormat format,
-                                                 gint64 start, gint64 stop,
-                                                 gint64 position) G_GNUC_MALLOC;
-GstEvent*       gst_event_new_new_segment_full  (gboolean update, gdouble rate,
-                                                 gdouble applied_rate,
-                                                 GstFormat format,
-                                                 gint64 start, gint64 stop,
-                                                 gint64 position) G_GNUC_MALLOC;
-void            gst_event_parse_new_segment     (GstEvent *event,
-                                                 gboolean *update,
-                                                 gdouble *rate,
-                                                 GstFormat *format,
-                                                 gint64 *start, gint64 *stop,
-                                                 gint64 *position);
-void            gst_event_parse_new_segment_full (GstEvent *event,
-                                                 gboolean *update,
-                                                 gdouble *rate,
-                                                 gdouble *applied_rate,
-                                                 GstFormat *format,
-                                                 gint64 *start, gint64 *stop,
-                                                 gint64 *position);
+/* Caps events */
+GstEvent *      gst_event_new_caps              (GstCaps *caps) G_GNUC_MALLOC;
+void            gst_event_parse_caps            (GstEvent *event, GstCaps **caps);
+
+/* segment event */
+GstEvent*       gst_event_new_segment           (const GstSegment *segment) G_GNUC_MALLOC;
+void            gst_event_parse_segment         (GstEvent *event, const GstSegment **segment);
+void            gst_event_copy_segment          (GstEvent *event, GstSegment *segment);
 
 /* tag event */
 GstEvent*       gst_event_new_tag               (GstTagList *taglist) G_GNUC_MALLOC;
@@ -493,14 +485,14 @@ GstEvent *      gst_event_new_buffer_size       (GstFormat format, gint64 minsiz
 void            gst_event_parse_buffer_size     (GstEvent *event, GstFormat *format, gint64 *minsize,
                                                  gint64 *maxsize, gboolean *async);
 
+/* sink message */
+GstEvent*       gst_event_new_sink_message      (GstMessage *msg) G_GNUC_MALLOC;
+void            gst_event_parse_sink_message    (GstEvent *event, GstMessage **msg);
+
 /* QOS events */
-GstEvent*       gst_event_new_qos               (gdouble proportion, GstClockTimeDiff diff,
-                                                 GstClockTime timestamp) G_GNUC_MALLOC;
-GstEvent*       gst_event_new_qos_full          (GstQOSType type, gdouble proportion,
+GstEvent*       gst_event_new_qos               (GstQOSType type, gdouble proportion,
                                                  GstClockTimeDiff diff, GstClockTime timestamp) G_GNUC_MALLOC;
-void            gst_event_parse_qos             (GstEvent *event, gdouble *proportion, GstClockTimeDiff *diff,
-                                                 GstClockTime *timestamp);
-void            gst_event_parse_qos_full        (GstEvent *event, GstQOSType *type,
+void            gst_event_parse_qos             (GstEvent *event, GstQOSType *type,
                                                  gdouble *proportion, GstClockTimeDiff *diff,
                                                  GstClockTime *timestamp);
 /* seek event */
@@ -511,6 +503,7 @@ void            gst_event_parse_seek            (GstEvent *event, gdouble *rate,
                                                  GstSeekFlags *flags,
                                                  GstSeekType *start_type, gint64 *start,
                                                  GstSeekType *stop_type, gint64 *stop);
+
 /* navigation event */
 GstEvent*       gst_event_new_navigation        (GstStructure *structure) G_GNUC_MALLOC;
 
@@ -524,6 +517,9 @@ GstEvent*       gst_event_new_step              (GstFormat format, guint64 amoun
 void            gst_event_parse_step            (GstEvent *event, GstFormat *format, guint64 *amount,
                                                  gdouble *rate, gboolean *flush, gboolean *intermediate);
 
+/* renegotiate event */
+GstEvent*       gst_event_new_reconfigure       (void) G_GNUC_MALLOC;
+
 G_END_DECLS
 
 #endif /* __GST_EVENT_H__ */
diff --git a/gst/gstfilter.c b/gst/gstfilter.c
deleted file mode 100644 (file)
index 67ae840..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstfilter
- * @short_description: A utility function to filter GLists.
- *
- * <example>
- * <title>Filtering a list</title>
- *   <programlisting>
- *     GList *node;
- *     GstObject *result = NULL;
- *     
- *     node = gst_filter_run (list, (GstFilterFunc) my_filter, TRUE, NULL);
- *     if (node) {
- *       result = GST_OBJECT (node->data);
- *       gst_object_ref (result);
- *       g_list_free (node);
- *     }
- *   </programlisting>
- * </example>
- */
-#include "gst_private.h"
-#include <gst/gstfilter.h>
-
-/**
- * gst_filter_run:
- * @list: a linked list
- * @func: (scope call): the function to execute for each item
- * @first: flag to stop execution after a successful item
- * @user_data: (closure): user data
- *
- * Iterates over the elements in @list, calling @func with the
- * list item data for each item.  If @func returns TRUE, @data is
- * prepended to the list of results returned.  If @first is true,
- * the search is halted after the first result is found.
- *
- * Since gst_filter_run() knows nothing about the type of @data, no
- * reference will be taken (if @data refers to an object) and no copy of
- * @data wil be made in any other way when prepending @data to the list of
- * results.
- *
- * Returns: (transfer container): the list of results. Free with g_list_free()
- *     when no longer needed (the data contained in the list is a flat copy
- *     and does need to be unreferenced or freed).
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-typedef gboolean (*GstFilterFunc) (gpointer obj, gpointer user_data);
-GList *gst_filter_run (const GList * list, GstFilterFunc func, gboolean first,
-    gpointer user_data);
-#endif
-GList *
-gst_filter_run (const GList * list, GstFilterFunc func, gboolean first,
-    gpointer user_data)
-{
-  const GList *walk = list;
-  GList *result = NULL;
-
-  while (walk) {
-    gboolean res = TRUE;
-    gpointer data = walk->data;
-
-    walk = g_list_next (walk);
-
-    if (func)
-      res = func (data, user_data);
-
-    if (res) {
-      result = g_list_prepend (result, data);
-
-      if (first)
-        break;
-    }
-  }
-
-  return result;
-}
-#endif /* GST_REMOVE_DEPRECATED */
diff --git a/gst/gstfilter.h b/gst/gstfilter.h
deleted file mode 100644 (file)
index 6ff1454..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_FILTER_H__
-#define __GST_FILTER_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstFilterFunc:
- * @obj: the object
- * @user_data: filter data
- *
- * Function prototype for a filter callback that can be use in gst_filter_run().
- * The function should apply its filtering to @obj. Additional data passed to
- * gst_filter_run() are in @data.
- *
- * Returns: %TRUE for success.
- */
-#ifndef GST_DISABLE_DEPRECATED
-typedef gboolean (*GstFilterFunc)      (gpointer obj, gpointer user_data);
-#endif
-
-#ifndef GST_DISABLE_DEPRECATED
-GList* gst_filter_run  (const GList *list, GstFilterFunc func, gboolean first, gpointer user_data);
-#endif
-
-G_END_DECLS
-
-#endif /* __GST_FILTER_H_ */
index e3bbba9..3e50d33 100644 (file)
@@ -37,7 +37,7 @@
 #include "gstformat.h"
 #include "gstenumtypes.h"
 
-static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+static GMutex mutex;
 static GList *_gst_formats = NULL;
 static GHashTable *_nick_to_format = NULL;
 static GHashTable *_format_to_nick = NULL;
@@ -53,11 +53,11 @@ static GstFormatDefinition standard_definitions[] = {
 };
 
 void
-_gst_format_initialize (void)
+_priv_gst_format_initialize (void)
 {
   GstFormatDefinition *standards = standard_definitions;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   if (_nick_to_format == NULL) {
     _nick_to_format = g_hash_table_new (g_str_hash, g_str_equal);
     _format_to_nick = g_hash_table_new (NULL, NULL);
@@ -76,7 +76,7 @@ _gst_format_initialize (void)
   }
   /* getting the type registers the enum */
   g_type_class_ref (gst_format_get_type ());
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 }
 
 /**
@@ -151,7 +151,7 @@ gst_format_register (const gchar * nick, const gchar * description)
   if (query != GST_FORMAT_UNDEFINED)
     return query;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   format = g_slice_new (GstFormatDefinition);
   format->value = (GstFormat) _n_values;
   format->nick = g_strdup (nick);
@@ -163,7 +163,7 @@ gst_format_register (const gchar * nick, const gchar * description)
       format);
   _gst_formats = g_list_append (_gst_formats, format);
   _n_values++;
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   return format->value;
 }
@@ -184,9 +184,9 @@ gst_format_get_by_nick (const gchar * nick)
 
   g_return_val_if_fail (nick != NULL, GST_FORMAT_UNDEFINED);
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   format = g_hash_table_lookup (_nick_to_format, nick);
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   if (format != NULL)
     return format->value;
@@ -234,9 +234,9 @@ gst_format_get_details (GstFormat format)
 {
   const GstFormatDefinition *result;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   result = g_hash_table_lookup (_format_to_nick, GINT_TO_POINTER (format));
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   return result;
 }
@@ -254,12 +254,11 @@ gst_format_iterate_definitions (void)
 {
   GstIterator *result;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   /* FIXME: register a boxed type for GstFormatDefinition */
   result = gst_iterator_new_list (G_TYPE_POINTER,
-      g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_formats,
-      NULL, NULL, NULL);
-  g_static_mutex_unlock (&mutex);
+      &mutex, &_n_values, &_gst_formats, NULL, NULL);
+  g_mutex_unlock (&mutex);
 
   return result;
 }
index 9f8b362..13dad03 100644 (file)
@@ -50,12 +50,12 @@ G_BEGIN_DECLS
 /* NOTE: don't forget to update the table in gstformat.c when changing
  * this enum */
 typedef enum {
-  GST_FORMAT_UNDEFINED         =  0, /* must be first in list */
-  GST_FORMAT_DEFAULT           =  1,
-  GST_FORMAT_BYTES     =  2,
-  GST_FORMAT_TIME      =  3,
-  GST_FORMAT_BUFFERS   =  4,
-  GST_FORMAT_PERCENT   =  5
+  GST_FORMAT_UNDEFINED  =  0, /* must be first in list */
+  GST_FORMAT_DEFAULT    =  1,
+  GST_FORMAT_BYTES      =  2,
+  GST_FORMAT_TIME       =  3,
+  GST_FORMAT_BUFFERS    =  4,
+  GST_FORMAT_PERCENT    =  5
 } GstFormat;
 
 /* a percentage is always relative to 1000000 */
@@ -64,14 +64,14 @@ typedef enum {
  *
  * The PERCENT format is between 0 and this value
  */
-#define        GST_FORMAT_PERCENT_MAX          G_GINT64_CONSTANT (1000000)
+#define GST_FORMAT_PERCENT_MAX          G_GINT64_CONSTANT (1000000)
 /**
  * GST_FORMAT_PERCENT_SCALE:
  *
  * The value used to scale down the reported PERCENT format value to
  * its real value.
  */
-#define        GST_FORMAT_PERCENT_SCALE        G_GINT64_CONSTANT (10000)
+#define GST_FORMAT_PERCENT_SCALE        G_GINT64_CONSTANT (10000)
 
 typedef struct _GstFormatDefinition GstFormatDefinition;
 
@@ -96,17 +96,17 @@ const gchar*    gst_format_get_name             (GstFormat format);
 GQuark          gst_format_to_quark             (GstFormat format);
 
 /* register a new format */
-GstFormat      gst_format_register             (const gchar *nick,
-                                                const gchar *description);
-GstFormat      gst_format_get_by_nick          (const gchar *nick);
+GstFormat       gst_format_register             (const gchar *nick,
+                                                 const gchar *description);
+GstFormat       gst_format_get_by_nick          (const gchar *nick);
 
 /* check if a format is in an array of formats */
-gboolean       gst_formats_contains            (const GstFormat *formats, GstFormat format);
+gboolean        gst_formats_contains            (const GstFormat *formats, GstFormat format);
 
 /* query for format details */
 const GstFormatDefinition*
-               gst_format_get_details          (GstFormat format);
-GstIterator*   gst_format_iterate_definitions  (void);
+                gst_format_get_details          (GstFormat format);
+GstIterator*    gst_format_iterate_definitions  (void);
 
 G_END_DECLS
 
index d8fb3ea..1dd430e 100644 (file)
@@ -66,49 +66,10 @@ G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
 
 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#ifdef GST_DISABLE_DEPRECATED
-#include <libxml/parser.h>
-#endif
-static xmlNodePtr gst_proxy_pad_save_thyself (GstObject * object,
-    xmlNodePtr parent);
-#endif
-
-static void on_src_target_notify (GstPad * target,
-    GParamSpec * unused, gpointer user_data);
-
-static GParamSpec *pspec_caps = NULL;
-
-/**
- * gst_proxy_pad_query_type_default:
- * @pad: a #GstPad.
- *
- * Invoke the default query type handler of the proxy pad.
- *
- * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
- *     of #GstQueryType.
- *
- * Since: 0.10.36
- */
-const GstQueryType *
-gst_proxy_pad_query_type_default (GstPad * pad)
-{
-  GstPad *target;
-  const GstQueryType *res = NULL;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
-
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    res = gst_pad_get_query_types (target);
-    gst_object_unref (target);
-  }
-  return res;
-}
-
 /**
  * gst_proxy_pad_event_default:
  * @pad: a #GstPad to push the event to.
+ * @parent: the parent of @pad or NULL
  * @event: (transfer full): the #GstEvent to send to the pad.
  *
  * Invoke the default event of the proxy pad.
@@ -118,27 +79,105 @@ gst_proxy_pad_query_type_default (GstPad * pad)
  * Since: 0.10.36
  */
 gboolean
-gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
+gst_proxy_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  gboolean res = FALSE;
+  gboolean res;
   GstPad *internal;
 
   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
 
-  internal =
-      GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
-  if (internal) {
-    res = gst_pad_push_event (internal, event);
-    gst_object_unref (internal);
+  internal = GST_PROXY_PAD_INTERNAL (pad);
+  res = gst_pad_push_event (internal, event);
+
+  return res;
+}
+
+static gboolean
+gst_proxy_pad_query_caps (GstPad * pad, GstQuery * query)
+{
+  gboolean res;
+  GstPad *target;
+  GstCaps *result;
+  GstPadTemplate *templ;
+
+  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+
+  templ = GST_PAD_PAD_TEMPLATE (pad);
+  target = gst_proxy_pad_get_target (pad);
+  if (target) {
+    /* if we have a real target, proxy the call */
+    res = gst_pad_query (target, query);
+
+    GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
+        GST_DEBUG_PAD_NAME (target), query);
+
+    gst_object_unref (target);
+
+    /* filter against the template */
+    if (templ && res) {
+      GstCaps *filt, *tmp;
+
+      filt = GST_PAD_TEMPLATE_CAPS (templ);
+      if (filt) {
+        gst_query_parse_caps_result (query, &result);
+        tmp = gst_caps_intersect_full (result, filt, GST_CAPS_INTERSECT_FIRST);
+        gst_query_set_caps_result (query, tmp);
+        GST_DEBUG_OBJECT (pad,
+            "filtered against template gives %" GST_PTR_FORMAT, tmp);
+        gst_caps_unref (tmp);
+      }
+    }
+  } else {
+    GstCaps *filter;
+
+    res = TRUE;
+
+    gst_query_parse_caps (query, &filter);
+
+    /* else, if we have a template, use its caps. */
+    if (templ) {
+      result = GST_PAD_TEMPLATE_CAPS (templ);
+      GST_DEBUG_OBJECT (pad,
+          "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
+          result);
+
+      if (filter) {
+        GstCaps *intersection;
+
+        GST_DEBUG_OBJECT (pad, "intersect with filter");
+        intersection =
+            gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+        gst_query_set_caps_result (query, intersection);
+        gst_caps_unref (intersection);
+      } else {
+        gst_query_set_caps_result (query, result);
+      }
+      goto done;
+    }
+
+    /* If there's a filter, return that */
+    if (filter != NULL) {
+      GST_DEBUG_OBJECT (pad, "return filter");
+      gst_query_set_caps_result (query, filter);
+      goto done;
+    }
+
+    /* last resort, any caps */
+    GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
+    result = gst_caps_new_any ();
+    gst_query_set_caps_result (query, result);
+    gst_caps_unref (result);
   }
 
+done:
   return res;
 }
 
 /**
  * gst_proxy_pad_query_default:
  * @pad: a #GstPad to invoke the default query on.
+ * @parent: the parent of @pad or NULL
  * @query: (transfer none): the #GstQuery to perform.
  *
  * Invoke the default query function of the proxy pad.
@@ -148,26 +187,55 @@ gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
  * Since: 0.10.36
  */
 gboolean
-gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
+gst_proxy_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  gboolean res = FALSE;
+  gboolean res;
   GstPad *target;
 
   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
 
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    res = gst_pad_query (target, query);
-    gst_object_unref (target);
-  }
 
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ACCEPT_CAPS:
+    {
+      target = gst_proxy_pad_get_target (pad);
+      if (target) {
+        res = gst_pad_query (target, query);
+        gst_object_unref (target);
+      } else {
+        GST_DEBUG_OBJECT (pad, "no target");
+        /* We don't have a target, we return TRUE and we assume that any future
+         * target will be able to deal with any configured caps. */
+        res = TRUE;
+      }
+      break;
+    }
+    case GST_QUERY_CAPS:
+    {
+      res = gst_proxy_pad_query_caps (pad, query);
+      break;
+    }
+    default:
+    {
+      target = gst_proxy_pad_get_target (pad);
+      if (target) {
+        res = gst_pad_query (target, query);
+        gst_object_unref (target);
+      } else {
+        GST_DEBUG_OBJECT (pad, "no target pad");
+        res = FALSE;
+      }
+      break;
+    }
+  }
   return res;
 }
 
 /**
  * gst_proyx_pad_iterate_internal_links_default:
  * @pad: the #GstPad to get the internal links of.
+ * @parent: the parent of @pad or NULL
  *
  * Invoke the default iterate internal links function of the proxy pad.
  *
@@ -177,68 +245,27 @@ gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
  * Since: 0.10.36
  */
 GstIterator *
-gst_proxy_pad_iterate_internal_links_default (GstPad * pad)
+gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
 {
   GstIterator *res = NULL;
   GstPad *internal;
+  GValue v = { 0, };
 
   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
 
-  internal =
-      GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
-
-  if (internal) {
-    res =
-        gst_iterator_new_single (GST_TYPE_PAD, internal,
-        (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
-    gst_object_unref (internal);
-  }
+  internal = GST_PROXY_PAD_INTERNAL (pad);
+  g_value_init (&v, GST_TYPE_PAD);
+  g_value_set_object (&v, internal);
+  res = gst_iterator_new_single (GST_TYPE_PAD, &v);
+  g_value_unset (&v);
 
   return res;
 }
 
 /**
- * gst_proxy_pad_bufferalloc_default:
- * @pad: a source #GstPad
- * @offset: the offset of the new buffer in the stream
- * @size: the size of the new buffer
- * @caps: the caps of the new buffer
- * @buf: a newly allocated buffer
- *
- * Invoke the default bufferalloc function of the proxy pad.
- *
- * Returns: a result code indicating success of the operation. Any
- * result code other than #GST_FLOW_OK is an error and @buf should
- * not be used.
- * An error can occur if the pad is not connected or when the downstream
- * peer elements cannot provide an acceptable buffer.
- *
- * Since: 0.10.36
- */
-GstFlowReturn
-gst_proxy_pad_bufferalloc_default (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstFlowReturn result = GST_FLOW_WRONG_STATE;
-  GstPad *internal;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), GST_FLOW_ERROR);
-  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
-  internal =
-      GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
-  if (internal) {
-    result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
-    gst_object_unref (internal);
-  }
-
-  return result;
-}
-
-/**
  * gst_proxy_pad_chain_default:
  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
+ * @parent: the parent of @pad or NULL
  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
  *     if not.
  *
@@ -249,7 +276,8 @@ gst_proxy_pad_bufferalloc_default (GstPad * pad, guint64 offset, guint size,
  * Since: 0.10.36
  */
 GstFlowReturn
-gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
+gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer)
 {
   GstFlowReturn res;
   GstPad *internal;
@@ -266,6 +294,7 @@ gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
 /**
  * gst_proxy_pad_chain_list_default:
  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
+ * @parent: the parent of @pad or NULL
  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
  *     if not.
  *
@@ -276,7 +305,8 @@ gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
  * Since: 0.10.36
  */
 GstFlowReturn
-gst_proxy_pad_chain_list_default (GstPad * pad, GstBufferList * list)
+gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent,
+    GstBufferList * list)
 {
   GstFlowReturn res;
   GstPad *internal;
@@ -305,8 +335,8 @@ gst_proxy_pad_chain_list_default (GstPad * pad, GstBufferList * list)
  * Since: 0.10.36
  */
 GstFlowReturn
-gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
-    GstBuffer ** buffer)
+gst_proxy_pad_getrange_default (GstPad * pad, GstObject * parent,
+    guint64 offset, guint size, GstBuffer ** buffer)
 {
   GstFlowReturn res;
   GstPad *internal;
@@ -320,185 +350,6 @@ gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
   return res;
 }
 
-/**
- * gst_proxy_pad_checkgetrange_default:
- * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
- *
- * Invoke the default checkgetrange function of the proxy pad.
- *
- * Returns: a #gboolean from the pad.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_proxy_pad_checkgetrange_default (GstPad * pad)
-{
-  gboolean result;
-  GstPad *internal;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
-
-  internal = GST_PROXY_PAD_INTERNAL (pad);
-  result = gst_pad_check_pull_range (internal);
-
-  return result;
-}
-
-/**
- * gst_proxy_pad_getcaps_default:
- * @pad: a  #GstPad to get the capabilities of.
- *
- * Invoke the default getcaps function of the proxy pad.
- *
- * Returns: (transfer full): the caps of the pad with incremented ref-count
- *
- * Since: 0.10.36
- */
-GstCaps *
-gst_proxy_pad_getcaps_default (GstPad * pad)
-{
-  GstPad *target;
-  GstCaps *res;
-  GstPadTemplate *templ;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
-
-  templ = GST_PAD_PAD_TEMPLATE (pad);
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    /* if we have a real target, proxy the call */
-    res = gst_pad_get_caps_reffed (target);
-
-    GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
-        GST_DEBUG_PAD_NAME (target), res);
-
-    gst_object_unref (target);
-
-    /* filter against the template */
-    if (templ && res) {
-      GstCaps *filt, *tmp;
-
-      filt = GST_PAD_TEMPLATE_CAPS (templ);
-      if (filt) {
-        tmp = gst_caps_intersect (filt, res);
-        gst_caps_unref (res);
-        res = tmp;
-        GST_DEBUG_OBJECT (pad,
-            "filtered against template gives %" GST_PTR_FORMAT, res);
-      }
-    }
-  } else {
-    /* else, if we have a template, use its caps. */
-    if (templ) {
-      res = GST_PAD_TEMPLATE_CAPS (templ);
-      GST_DEBUG_OBJECT (pad,
-          "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
-          res);
-      res = gst_caps_ref (res);
-      goto done;
-    }
-
-    /* last resort, any caps */
-    GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
-    res = gst_caps_new_any ();
-  }
-
-done:
-  return res;
-}
-
-/**
- * gst_proxy_pad_acceptcaps_default:
- * @pad: a #GstPad to check
- * @caps: a #GstCaps to check on the pad
- *
- * Invoke the default acceptcaps function of the proxy pad.
- *
- * Returns: TRUE if the pad can accept the caps.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
-{
-  GstPad *target;
-  gboolean res;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
-  g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
-
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    res = gst_pad_accept_caps (target, caps);
-    gst_object_unref (target);
-  } else {
-    /* We don't have a target, we return TRUE and we assume that any future
-     * target will be able to deal with any configured caps. */
-    res = TRUE;
-  }
-
-  return res;
-}
-
-/**
- * gst_proxy_pad_fixatecaps_default:
- * @pad: a  #GstPad to fixate
- * @caps: the  #GstCaps to fixate
- *
- * Invoke the default fixatecaps function of the proxy pad.
- *
- * Since: 0.10.36
- */
-void
-gst_proxy_pad_fixatecaps_default (GstPad * pad, GstCaps * caps)
-{
-  GstPad *target;
-
-  g_return_if_fail (GST_IS_PROXY_PAD (pad));
-  g_return_if_fail (GST_IS_CAPS (caps));
-
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    gst_pad_fixate_caps (target, caps);
-    gst_object_unref (target);
-  }
-}
-
-/**
- * gst_proxy_pad_setcaps_default:
- * @pad: a  #GstPad to set the capabilities of.
- * @caps: (transfer none): a #GstCaps to set.
- *
- * Invoke the default setcaps function of the proxy pad.
- *
- * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
- * or bad parameters were provided to this function.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_proxy_pad_setcaps_default (GstPad * pad, GstCaps * caps)
-{
-  GstPad *target;
-  gboolean res;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
-  g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
-
-  target = gst_proxy_pad_get_target (pad);
-  if (target) {
-    res = gst_pad_set_caps (target, caps);
-    gst_object_unref (target);
-  } else {
-    /* We don't have any target, but we shouldn't return FALSE since this
-     * would stop the actual push of a buffer (which might trigger a pad block
-     * or probe, or properly return GST_FLOW_NOT_LINKED.
-     */
-    res = TRUE;
-  }
-  return res;
-}
-
 static GstPad *
 gst_proxy_pad_get_target (GstPad * pad)
 {
@@ -563,31 +414,14 @@ gst_proxy_pad_class_init (GstProxyPadClass * klass)
 {
   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  {
-    GstObjectClass *gstobject_class = (GstObjectClass *) klass;
-
-    gstobject_class->save_thyself =
-        ((gpointer (*)(GstObject * object,
-                gpointer self)) *
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_save_thyself));
-  }
-#endif
   /* Register common function pointer descriptions */
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_fixatecaps_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_setcaps_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_bufferalloc_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_checkgetrange_default);
 }
 
 static void
@@ -598,73 +432,14 @@ gst_proxy_pad_init (GstProxyPad * ppad)
   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
 
-  gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
   gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
   gst_pad_set_query_function (pad, gst_proxy_pad_query_default);
   gst_pad_set_iterate_internal_links_function (pad,
       gst_proxy_pad_iterate_internal_links_default);
 
-  gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
-  gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_acceptcaps_default);
-  gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_fixatecaps_default);
-  gst_pad_set_setcaps_function (pad, gst_proxy_pad_setcaps_default);
   gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
 }
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-/**
- * gst_proxy_pad_save_thyself:
- * @pad: a ghost #GstPad to save.
- * @parent: the parent #xmlNodePtr to save the description in.
- *
- * Saves the ghost pad into an xml representation.
- *
- * Returns: the #xmlNodePtr representation of the pad.
- */
-static xmlNodePtr
-gst_proxy_pad_save_thyself (GstObject * object, xmlNodePtr parent)
-{
-  xmlNodePtr self;
-  GstProxyPad *proxypad;
-  GstPad *pad;
-  GstPad *peer;
-
-  g_return_val_if_fail (GST_IS_PROXY_PAD (object), NULL);
-
-  self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
-  xmlNewChild (self, NULL, (xmlChar *) "name",
-      (xmlChar *) GST_OBJECT_NAME (object));
-  xmlNewChild (self, NULL, (xmlChar *) "parent",
-      (xmlChar *) GST_OBJECT_NAME (GST_OBJECT_PARENT (object)));
-
-  proxypad = GST_PROXY_PAD_CAST (object);
-  pad = GST_PAD_CAST (proxypad);
-  peer = GST_PAD_CAST (pad->peer);
-
-  if (GST_IS_PAD (pad)) {
-    if (GST_PAD_IS_SRC (pad))
-      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "source");
-    else if (GST_PAD_IS_SINK (pad))
-      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "sink");
-    else
-      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
-  } else {
-    xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
-  }
-  if (GST_IS_PAD (peer)) {
-    gchar *content = g_strdup_printf ("%s.%s",
-        GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));
-
-    xmlNewChild (self, NULL, (xmlChar *) "peer", (xmlChar *) content);
-    g_free (content);
-  } else {
-    xmlNewChild (self, NULL, (xmlChar *) "peer", NULL);
-  }
-
-  return self;
-}
-#endif /* GST_DISABLE_LOADSAVE */
-
 
 /***********************************************************************
  * Ghost pads, implemented as a pair of proxy pads (sort of)
@@ -676,8 +451,6 @@ gst_proxy_pad_save_thyself (GstObject * object, xmlNodePtr parent)
 struct _GstGhostPadPrivate
 {
   /* with PROXY_LOCK */
-  gulong notify_id;
-
   gboolean constructed;
 };
 
@@ -685,57 +458,31 @@ G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
 
 static void gst_ghost_pad_dispose (GObject * object);
 
-/**
- * gst_ghost_pad_internal_activate_push_default:
- * @pad: the #GstPad to activate or deactivate.
- * @active: whether the pad should be active or not.
- *
- * Invoke the default activate push function of a proxy pad that is
- * owned by a ghost pad.
- *
- * Returns: %TRUE if the operation was successful.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active)
+static gboolean
+gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean ret;
   GstPad *other;
 
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
-
   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
 
   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
    * will be activated later (or already in case of a ghost sinkpad). */
   other = GST_PROXY_PAD_INTERNAL (pad);
-  ret = gst_pad_activate_push (other, active);
+  ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
 
   return ret;
 }
 
-/**
- * gst_ghost_pad_internal_activate_pull_default:
- * @pad: the #GstPad to activate or deactivate.
- * @active: whether the pad should be active or not.
- *
- * Invoke the default activate pull function of a proxy pad that is
- * owned by a ghost pad.
- *
- * Returns: %TRUE if the operation was successful.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
+static gboolean
+gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean ret;
   GstPad *other;
 
-  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
-
   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
       GST_DEBUG_PAD_NAME (pad));
 
@@ -747,12 +494,12 @@ gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
      * further upstream */
     GST_LOG_OBJECT (pad, "pad is src, activate internal");
     other = GST_PROXY_PAD_INTERNAL (pad);
-    ret = gst_pad_activate_pull (other, active);
+    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
      * since we hold a pointer to the upstream peer. */
     GST_LOG_OBJECT (pad, "activating peer");
-    ret = gst_pad_activate_pull (other, active);
+    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
     gst_object_unref (other);
   } else {
     /* this is failure, we can't activate pull if there is no peer */
@@ -764,18 +511,43 @@ gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
 }
 
 /**
- * gst_ghost_pad_activate_push_default:
+ * gst_ghost_pad_internal_activate_mode_default:
  * @pad: the #GstPad to activate or deactivate.
+ * @parent: the parent of @pad or NULL
+ * @mode: the requested activation mode
  * @active: whether the pad should be active or not.
  *
- * Invoke the default activate push function of a ghost pad.
+ * Invoke the default activate mode function of a proxy pad that is
+ * owned by a ghost pad.
  *
  * Returns: %TRUE if the operation was successful.
- *
- * Since: 0.10.36
  */
 gboolean
-gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
+gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_ghost_pad_internal_activate_pull_default (pad, parent, active);
+      break;
+    case GST_PAD_MODE_PUSH:
+      res = gst_ghost_pad_internal_activate_push_default (pad, parent, active);
+      break;
+    default:
+      GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
+static gboolean
+gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean ret;
   GstPad *other;
@@ -787,30 +559,18 @@ gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
 
   /* just activate the internal pad */
   other = GST_PROXY_PAD_INTERNAL (pad);
-  ret = gst_pad_activate_push (other, active);
+  ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
 
   return ret;
 }
 
-/**
- * gst_ghost_pad_activate_pull_default:
- * @pad: the #GstPad to activate or deactivate.
- * @active: whether the pad should be active or not.
- *
- * Invoke the default activate pull function of a ghost pad.
- *
- * Returns: %TRUE if the operation was successful.
- *
- * Since: 0.10.36
- */
-gboolean
-gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
+static gboolean
+gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean ret;
   GstPad *other;
 
-  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
-
   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
       GST_DEBUG_PAD_NAME (pad));
 
@@ -820,12 +580,12 @@ gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
      * upstream */
     GST_LOG_OBJECT (pad, "pad is src, activate internal");
     other = GST_PROXY_PAD_INTERNAL (pad);
-    ret = gst_pad_activate_pull (other, active);
+    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
     /* We are SINK and activated by the internal pad, propagate activation
      * upstream because we hold a ref to the upstream peer */
     GST_LOG_OBJECT (pad, "activating peer");
-    ret = gst_pad_activate_pull (other, active);
+    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
     gst_object_unref (other);
   } else {
     /* no peer, we fail */
@@ -837,6 +597,40 @@ gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
 }
 
 /**
+ * gst_ghost_pad_activate_mode_default:
+ * @pad: the #GstPad to activate or deactivate.
+ * @parent: the parent of @pad or NULL
+ * @mode: the requested activation mode
+ * @active: whether the pad should be active or not.
+ *
+ * Invoke the default activate mode function of a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful.
+ */
+gboolean
+gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_ghost_pad_activate_pull_default (pad, parent, active);
+      break;
+    case GST_PAD_MODE_PUSH:
+      res = gst_ghost_pad_activate_push_default (pad, parent, active);
+      break;
+    default:
+      GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
+/**
  * gst_ghost_pad_link_default:
  * @pad: the #GstPad to link.
  * @peer: the #GstPad peer
@@ -887,101 +681,14 @@ gst_ghost_pad_unlink_default (GstPad * pad)
 }
 
 static void
-on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
-{
-  GstCaps *caps;
-
-  g_object_get (internal, "caps", &caps, NULL);
-
-  GST_DEBUG_OBJECT (pad, "notified %p %" GST_PTR_FORMAT, caps, caps);
-  gst_pad_set_caps (GST_PAD_CAST (pad), caps);
-
-  if (caps)
-    gst_caps_unref (caps);
-}
-
-static void
-on_src_target_notify (GstPad * target, GParamSpec * unused, gpointer user_data)
-{
-  GstProxyPad *proxypad;
-  GstGhostPad *gpad;
-  GstCaps *caps;
-
-  g_object_get (target, "caps", &caps, NULL);
-
-  GST_OBJECT_LOCK (target);
-  /* First check if the peer is still available and our proxy pad */
-  if (!GST_PAD_PEER (target) || !GST_IS_PROXY_PAD (GST_PAD_PEER (target))) {
-    GST_OBJECT_UNLOCK (target);
-    goto done;
-  }
-
-  proxypad = GST_PROXY_PAD (GST_PAD_PEER (target));
-  GST_OBJECT_LOCK (proxypad);
-  /* Now check if the proxypad's internal pad is still there and
-   * a ghostpad */
-  if (!GST_PROXY_PAD_INTERNAL (proxypad) ||
-      !GST_IS_GHOST_PAD (GST_PROXY_PAD_INTERNAL (proxypad))) {
-    GST_OBJECT_UNLOCK (proxypad);
-    GST_OBJECT_UNLOCK (target);
-    goto done;
-  }
-  gpad = GST_GHOST_PAD (GST_PROXY_PAD_INTERNAL (proxypad));
-  g_object_ref (gpad);
-  GST_OBJECT_UNLOCK (proxypad);
-  GST_OBJECT_UNLOCK (target);
-
-  gst_pad_set_caps (GST_PAD_CAST (gpad), caps);
-
-  g_object_unref (gpad);
-
-done:
-  if (caps)
-    gst_caps_unref (caps);
-}
-
-static void
-on_src_target_unlinked (GstPad * pad, GstPad * peer, gpointer user_data)
-{
-  g_signal_handlers_disconnect_by_func (pad,
-      (gpointer) on_src_target_notify, NULL);
-}
-
-/**
- * gst_ghost_pad_setcaps_default:
- * @pad: the #GstPad to link.
- * @caps: (transfer none): the #GstCaps to set
- *
- * Invoke the default setcaps function of a ghost pad.
- *
- * Returns: %TRUE if the operation was successful
- *
- * Since: 0.10.36
- */
-gboolean
-gst_ghost_pad_setcaps_default (GstPad * pad, GstCaps * caps)
-{
-  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
-  g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
-
-  if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
-    return TRUE;
-
-  return gst_proxy_pad_setcaps_default (pad, caps);
-}
-
-static void
 gst_ghost_pad_class_init (GstGhostPadClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
 
   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
 
-  pspec_caps = g_object_class_find_property (gobject_class, "caps");
-
   gobject_class->dispose = gst_ghost_pad_dispose;
 
-  GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_setcaps_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_link_default);
@@ -993,12 +700,8 @@ gst_ghost_pad_init (GstGhostPad * pad)
   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
 
-  gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
-      gst_ghost_pad_setcaps_default);
-  gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
-      gst_ghost_pad_activate_pull_default);
-  gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
-      gst_ghost_pad_activate_push_default);
+  gst_pad_set_activatemode_function (GST_PAD_CAST (pad),
+      gst_ghost_pad_activate_mode_default);
 }
 
 static void
@@ -1029,11 +732,7 @@ gst_ghost_pad_dispose (GObject * object)
   GST_OBJECT_LOCK (pad);
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
-  gst_pad_set_activatepull_function (internal, NULL);
-  gst_pad_set_activatepush_function (internal, NULL);
-
-  g_signal_handler_disconnect (internal,
-      GST_GHOST_PAD_PRIVATE (pad)->notify_id);
+  gst_pad_set_activatemode_function (internal, NULL);
 
   /* disposes of the internal pad, since the ghostpad is the only possible object
    * that has a refcount on the internal pad. */
@@ -1079,13 +778,10 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
 
   /* Set directional padfunctions for ghostpad */
   if (dir == GST_PAD_SINK) {
-    gst_pad_set_bufferalloc_function (pad, gst_proxy_pad_bufferalloc_default);
     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
   } else {
     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
-    gst_pad_set_checkgetrange_function (pad,
-        gst_proxy_pad_checkgetrange_default);
   }
 
   /* link/unlink functions */
@@ -1109,15 +805,11 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
 
   /* Set directional padfunctions for internal pad */
   if (dir == GST_PAD_SRC) {
-    gst_pad_set_bufferalloc_function (internal,
-        gst_proxy_pad_bufferalloc_default);
     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
     gst_pad_set_chain_list_function (internal,
         gst_proxy_pad_chain_list_default);
   } else {
     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
-    gst_pad_set_checkgetrange_function (internal,
-        gst_proxy_pad_checkgetrange_default);
   }
 
   GST_OBJECT_LOCK (pad);
@@ -1138,23 +830,12 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
   GST_PROXY_PAD_INTERNAL (pad) = internal;
   GST_PROXY_PAD_INTERNAL (internal) = pad;
 
-  /* could be more general here, iterating over all writable properties...
-   * taking the short road for now tho */
-  GST_GHOST_PAD_PRIVATE (pad)->notify_id =
-      g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
-      pad);
-
   /* special activation functions for the internal pad */
-  gst_pad_set_activatepull_function (internal,
-      gst_ghost_pad_internal_activate_pull_default);
-  gst_pad_set_activatepush_function (internal,
-      gst_ghost_pad_internal_activate_push_default);
+  gst_pad_set_activatemode_function (internal,
+      gst_ghost_pad_internal_activate_mode_default);
 
   GST_OBJECT_UNLOCK (pad);
 
-  /* call function to init values of the pad caps */
-  on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad));
-
   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
   return TRUE;
 
@@ -1408,13 +1089,6 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
   }
 
   if (newtarget) {
-    if (GST_PAD_IS_SRC (newtarget)) {
-      g_signal_connect (newtarget, "notify::caps",
-          G_CALLBACK (on_src_target_notify), NULL);
-      g_signal_connect (newtarget, "unlinked",
-          G_CALLBACK (on_src_target_unlinked), NULL);
-    }
-
     /* and link to internal pad without any checks */
     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
 
index 0d86044..6aa4d26 100644 (file)
@@ -62,27 +62,26 @@ GType gst_proxy_pad_get_type (void);
 GstProxyPad*     gst_proxy_pad_get_internal     (GstProxyPad *pad);
 
 
-const GstQueryType* gst_proxy_pad_query_type_default             (GstPad *pad);
-gboolean            gst_proxy_pad_event_default                  (GstPad *pad, GstEvent *event);
-gboolean            gst_proxy_pad_query_default                  (GstPad *pad, GstQuery *query);
-GstIterator*        gst_proxy_pad_iterate_internal_links_default (GstPad *pad) G_GNUC_MALLOC;
-GstFlowReturn       gst_proxy_pad_bufferalloc_default            (GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf);
-GstFlowReturn       gst_proxy_pad_chain_default                  (GstPad *pad, GstBuffer *buffer);
-GstFlowReturn       gst_proxy_pad_chain_list_default             (GstPad *pad, GstBufferList *list);
-GstFlowReturn       gst_proxy_pad_getrange_default               (GstPad *pad, guint64 offset, guint size, GstBuffer **buffer);
-gboolean            gst_proxy_pad_checkgetrange_default          (GstPad *pad);
-GstCaps*            gst_proxy_pad_getcaps_default                (GstPad *pad);
-gboolean            gst_proxy_pad_acceptcaps_default             (GstPad *pad, GstCaps *caps);
-void                gst_proxy_pad_fixatecaps_default             (GstPad *pad, GstCaps *caps);
-gboolean            gst_proxy_pad_setcaps_default                (GstPad *pad, GstCaps *caps);
+gboolean            gst_proxy_pad_event_default                  (GstPad *pad, GstObject *parent,
+                                                                  GstEvent *event);
+gboolean            gst_proxy_pad_query_default                  (GstPad *pad, GstObject *parent,
+                                                                  GstQuery *query);
+GstIterator*        gst_proxy_pad_iterate_internal_links_default (GstPad *pad, GstObject *parent) G_GNUC_MALLOC;
+GstFlowReturn       gst_proxy_pad_chain_default                  (GstPad *pad, GstObject *parent,
+                                                                  GstBuffer *buffer);
+GstFlowReturn       gst_proxy_pad_chain_list_default             (GstPad *pad, GstObject *parent,
+                                                                  GstBufferList *list);
+GstFlowReturn       gst_proxy_pad_getrange_default               (GstPad *pad, GstObject *parent,
+                                                                  guint64 offset, guint size,
+                                                                  GstBuffer **buffer);
 void                gst_proxy_pad_unlink_default                 (GstPad * pad);
 
-#define GST_TYPE_GHOST_PAD             (gst_ghost_pad_get_type ())
-#define GST_IS_GHOST_PAD(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
-#define GST_IS_GHOST_PAD_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
-#define GST_GHOST_PAD(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
-#define GST_GHOST_PAD_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
-#define GST_GHOST_PAD_CAST(obj)                ((GstGhostPad*)(obj))
+#define GST_TYPE_GHOST_PAD              (gst_ghost_pad_get_type ())
+#define GST_IS_GHOST_PAD(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
+#define GST_IS_GHOST_PAD_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
+#define GST_GHOST_PAD(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
+#define GST_GHOST_PAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
+#define GST_GHOST_PAD_CAST(obj)         ((GstGhostPad*)(obj))
 
 /**
  * GstGhostPad:
@@ -110,27 +109,27 @@ struct _GstGhostPadClass
 };
 
 
-GType           gst_ghost_pad_get_type         (void);
+GType            gst_ghost_pad_get_type          (void);
 
-GstPad*                 gst_ghost_pad_new              (const gchar *name, GstPad *target) G_GNUC_MALLOC;
-GstPad*                 gst_ghost_pad_new_no_target    (const gchar *name, GstPadDirection dir) G_GNUC_MALLOC;
+GstPad*          gst_ghost_pad_new               (const gchar *name, GstPad *target) G_GNUC_MALLOC;
+GstPad*          gst_ghost_pad_new_no_target     (const gchar *name, GstPadDirection dir) G_GNUC_MALLOC;
 
-GstPad*                 gst_ghost_pad_new_from_template (const gchar *name, GstPad * target, GstPadTemplate * templ) G_GNUC_MALLOC;
-GstPad*                 gst_ghost_pad_new_no_target_from_template (const gchar *name, GstPadTemplate * templ) G_GNUC_MALLOC;
+GstPad*          gst_ghost_pad_new_from_template (const gchar *name, GstPad * target, GstPadTemplate * templ) G_GNUC_MALLOC;
+GstPad*          gst_ghost_pad_new_no_target_from_template (const gchar *name, GstPadTemplate * templ) G_GNUC_MALLOC;
 
-GstPad*                 gst_ghost_pad_get_target       (GstGhostPad *gpad);
-gboolean        gst_ghost_pad_set_target       (GstGhostPad *gpad, GstPad *newtarget);
+GstPad*          gst_ghost_pad_get_target        (GstGhostPad *gpad);
+gboolean         gst_ghost_pad_set_target        (GstGhostPad *gpad, GstPad *newtarget);
 
-gboolean        gst_ghost_pad_construct        (GstGhostPad *gpad);
+gboolean         gst_ghost_pad_construct         (GstGhostPad *gpad);
 
-gboolean         gst_ghost_pad_setcaps_default        (GstPad * pad, GstCaps * caps);
 void             gst_ghost_pad_unlink_default         (GstPad * pad);
 GstPadLinkReturn gst_ghost_pad_link_default           (GstPad * pad, GstPad * peer);
-gboolean         gst_ghost_pad_activate_pull_default  (GstPad * pad, gboolean active);
-gboolean         gst_ghost_pad_activate_push_default  (GstPad * pad, gboolean active);
 
-gboolean         gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active);
-gboolean         gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active);
+gboolean         gst_ghost_pad_activate_mode_default  (GstPad * pad, GstObject * parent,
+                                                       GstPadMode mode, gboolean active);
+
+gboolean         gst_ghost_pad_internal_activate_mode_default   (GstPad * pad, GstObject * parent,
+                                                                 GstPadMode mode, gboolean active);
 
 G_END_DECLS
 
diff --git a/gst/gstindexfactory.c b/gst/gstindexfactory.c
deleted file mode 100644 (file)
index 2b96e05..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/* GStreamer
- * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/)
- * Written by Erik Walthinsen <omega@ridgerun.com>
- *
- * gstindexfactory.c: Index for mappings and other data
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstindexfactory
- * @short_description: Create GstIndexes from a factory
- * @see_also: #GstIndex
- *
- * GstIndexFactory is used to dynamically create GstIndex implementations.
- */
-
-
-#include "gst_private.h"
-
-#include "gstinfo.h"
-#include "gstindex.h"
-#include "gstindexfactory.h"
-#include "gstmarshal.h"
-#include "gstregistry.h"
-
-static void gst_index_factory_finalize (GObject * object);
-
-static GstPluginFeatureClass *factory_parent_class = NULL;
-
-/* static guint gst_index_factory_signals[LAST_SIGNAL] = { 0 }; */
-G_DEFINE_TYPE (GstIndexFactory, gst_index_factory, GST_TYPE_PLUGIN_FEATURE);
-
-static void
-gst_index_factory_class_init (GstIndexFactoryClass * klass)
-{
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-
-  factory_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->finalize = gst_index_factory_finalize;
-}
-
-static void
-gst_index_factory_init (GstIndexFactory * factory)
-{
-}
-
-static void
-gst_index_factory_finalize (GObject * object)
-{
-  GstIndexFactory *factory = GST_INDEX_FACTORY (object);
-
-  g_free (factory->longdesc);
-
-  G_OBJECT_CLASS (factory_parent_class)->finalize (object);
-
-}
-
-/**
- * gst_index_factory_new:
- * @name: name of indexfactory to create
- * @longdesc: long description of indexfactory to create
- * @type: the GType of the GstIndex element of this factory
- *
- * Create a new indexfactory with the given parameters
- *
- * Returns: (transfer full): a new #GstIndexFactory.
- */
-GstIndexFactory *
-gst_index_factory_new (const gchar * name, const gchar * longdesc, GType type)
-{
-  GstIndexFactory *factory;
-
-  g_return_val_if_fail (name != NULL, NULL);
-  factory = GST_INDEX_FACTORY (g_object_newv (GST_TYPE_INDEX_FACTORY, 0, NULL));
-
-  gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name);
-  if (factory->longdesc)
-    g_free (factory->longdesc);
-  factory->longdesc = g_strdup (longdesc);
-  factory->type = type;
-
-  return factory;
-}
-
-/**
- * gst_index_factory_destroy:
- * @factory: factory to destroy
- *
- * Removes the index from the global list.
- */
-void
-gst_index_factory_destroy (GstIndexFactory * factory)
-{
-  g_return_if_fail (factory != NULL);
-
-  /* we don't free the struct bacause someone might  have a handle to it.. */
-  /* FIXME: gst_index_factory_destroy */
-}
-
-/**
- * gst_index_factory_find:
- * @name: name of indexfactory to find
- *
- * Search for an indexfactory of the given name.
- *
- * Returns: (transfer full): #GstIndexFactory if found, NULL otherwise
- */
-GstIndexFactory *
-gst_index_factory_find (const gchar * name)
-{
-  GstPluginFeature *feature;
-
-  g_return_val_if_fail (name != NULL, NULL);
-
-  GST_DEBUG ("gstindex: find \"%s\"", name);
-
-  feature = gst_registry_find_feature (gst_registry_get_default (), name,
-      GST_TYPE_INDEX_FACTORY);
-  if (feature)
-    return GST_INDEX_FACTORY (feature);
-
-  return NULL;
-}
-
-/**
- * gst_index_factory_create:
- * @factory: the factory used to create the instance
- *
- * Create a new #GstIndex instance from the
- * given indexfactory.
- *
- * Returns: (transfer full): a new #GstIndex instance.
- */
-GstIndex *
-gst_index_factory_create (GstIndexFactory * factory)
-{
-  GstIndexFactory *newfactory;
-  GstIndex *new = NULL;
-
-  g_return_val_if_fail (factory != NULL, NULL);
-
-  newfactory =
-      GST_INDEX_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
-          (factory)));
-  if (newfactory == NULL)
-    return NULL;
-
-  new = GST_INDEX (g_object_newv (newfactory->type, 0, NULL));
-
-  gst_object_unref (newfactory);
-
-  return new;
-}
-
-/**
- * gst_index_factory_make:
- * @name: the name of the factory used to create the instance
- *
- * Create a new #GstIndex instance from the
- * indexfactory with the given name.
- *
- * Returns: (transfer full): a new #GstIndex instance.
- */
-GstIndex *
-gst_index_factory_make (const gchar * name)
-{
-  GstIndexFactory *factory;
-  GstIndex *index;
-
-  g_return_val_if_fail (name != NULL, NULL);
-
-  factory = gst_index_factory_find (name);
-
-  if (factory == NULL)
-    goto no_factory;
-
-  index = gst_index_factory_create (factory);
-
-  if (index == NULL)
-    goto create_failed;
-
-  gst_object_unref (factory);
-  return index;
-
-  /* ERRORS */
-no_factory:
-  {
-    GST_INFO ("no such index factory \"%s\"!", name);
-    return NULL;
-  }
-create_failed:
-  {
-    GST_INFO_OBJECT (factory, "couldn't create instance!");
-    gst_object_unref (factory);
-    return NULL;
-  }
-}
diff --git a/gst/gstindexfactory.h b/gst/gstindexfactory.h
deleted file mode 100644 (file)
index b04e14c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wim.taymans@chello.be>
- *
- * gstindexfactory.h: Header for GstIndexFactory, base class to handle efficient
- *                    storage or caching of seeking information.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_INDEX_FACTORY_H__
-#define __GST_INDEX_FACTORY_H__
-
-#include <gst/gstobject.h>
-#include <gst/gstformat.h>
-#include <gst/gstpluginfeature.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_INDEX_FACTORY                 (gst_index_factory_get_type())
-#define GST_INDEX_FACTORY(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INDEX_FACTORY, GstIndexFactory))
-#define GST_IS_INDEX_FACTORY(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INDEX_FACTORY))
-#define GST_INDEX_FACTORY_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INDEX_FACTORY, GstIndexFactoryClass))
-#define GST_IS_INDEX_FACTORY_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INDEX_FACTORY))
-#define GST_INDEX_FACTORY_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_INDEX_FACTORY, GstIndexFactoryClass))
-
-typedef struct _GstIndexFactory GstIndexFactory;
-typedef struct _GstIndexFactoryClass GstIndexFactoryClass;
-
-/**
- * GstIndexFactory:
- *
- * The GstIndexFactory object
- */
-struct _GstIndexFactory {
-  GstPluginFeature feature;
-
-  gchar *longdesc;            /* long description of the index (well, don't overdo it..) */
-  GType type;                 /* unique GType of the index */
-
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstIndexFactoryClass {
-  GstPluginFeatureClass parent;
-
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-GType                  gst_index_factory_get_type      (void);
-
-GstIndexFactory*       gst_index_factory_new           (const gchar *name,
-                                                        const gchar *longdesc, GType type) G_GNUC_MALLOC;
-void                   gst_index_factory_destroy       (GstIndexFactory *factory);
-
-GstIndexFactory*       gst_index_factory_find          (const gchar *name);
-
-GstIndex*              gst_index_factory_create        (GstIndexFactory *factory) G_GNUC_MALLOC;
-GstIndex*              gst_index_factory_make          (const gchar *name) G_GNUC_MALLOC;
-
-G_END_DECLS
-
-#endif /* __GST_INDEX_FACTORY_H__ */
index 266feed..1c09c04 100644 (file)
 
 /* disabled by default, as soon as some threshold is set > NONE,
  * it becomes enabled. */
-gboolean __gst_debug_enabled = FALSE;
-GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
+gboolean _gst_debug_enabled = FALSE;
+GstDebugLevel _gst_debug_min = GST_LEVEL_NONE;
 
 GstDebugCategory *GST_CAT_DEFAULT = NULL;
 
@@ -158,7 +158,6 @@ GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
 GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
 GstDebugCategory *GST_CAT_PROPERTIES = NULL;
 GstDebugCategory *GST_CAT_TYPES = NULL;
-GstDebugCategory *GST_CAT_XML = NULL;
 GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
 GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
 GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
@@ -240,7 +239,7 @@ struct _GstDebugMessage
 };
 
 /* list of all name/level pairs from --gst-debug and GST_DEBUG */
-static GStaticMutex __level_name_mutex = G_STATIC_MUTEX_INIT;
+static GMutex __level_name_mutex;
 static GSList *__level_name = NULL;
 typedef struct
 {
@@ -250,7 +249,7 @@ typedef struct
 LevelNameEntry;
 
 /* list of all categories */
-static GStaticMutex __cat_mutex = G_STATIC_MUTEX_INIT;
+static GMutex __cat_mutex;
 static GSList *__categories = NULL;
 
 /* all registered debug handlers */
@@ -260,7 +259,7 @@ typedef struct
   gpointer user_data;
 }
 LogFuncEntry;
-static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
+static GMutex __log_func_mutex;
 static GSList *__log_functions = NULL;
 
 #define PRETTY_TAGS_DEFAULT  TRUE
@@ -304,14 +303,9 @@ _priv_gst_in_valgrind (void)
   return (in_valgrind == GST_VG_INSIDE);
 }
 
-/**
- * _gst_debug_init:
- *
- * Initializes the debugging system.
- * Normally you don't want to call this, because gst_init() does it for you.
- */
+/* Initialize the debugging system */
 void
-_gst_debug_init (void)
+_priv_gst_debug_init (void)
 {
   const gchar *env;
 
@@ -394,8 +388,6 @@ _gst_debug_init (void)
       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL);
   GST_CAT_TYPES = _gst_debug_category_new ("GST_TYPES",
       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
-  GST_CAT_XML = _gst_debug_category_new ("GST_XML",
-      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
   GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION",
       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
   GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING",
@@ -596,7 +588,7 @@ structure_to_pretty_string (const GstStructure * s)
 }
 
 static inline gchar *
-gst_info_structure_to_string (GstStructure * s)
+gst_info_structure_to_string (const GstStructure * s)
 {
   if (G_UNLIKELY (pretty_tags && s->name == GST_QUARK (TAGLIST)))
     return structure_to_pretty_string (s);
@@ -627,26 +619,23 @@ gst_debug_print_object (gpointer ptr)
     return g_strdup ("(NULL)");
   }
   if (*(GType *) ptr == GST_TYPE_CAPS) {
-    return gst_caps_to_string ((GstCaps *) ptr);
+    return gst_caps_to_string ((const GstCaps *) ptr);
   }
   if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
-    return gst_info_structure_to_string ((GstStructure *) ptr);
+    return gst_info_structure_to_string ((const GstStructure *) ptr);
   }
   if (GST_IS_BUFFER (ptr)) {
     GstBuffer *buf = (GstBuffer *) ptr;
-    gchar *caps, *ret;
+    gchar *ret;
 
-    caps = gst_caps_to_string (GST_BUFFER_CAPS (buf));
     ret =
-        g_strdup_printf ("%p, data %p, malloc %p, ts %" GST_TIME_FORMAT
-        ", dur %" GST_TIME_FORMAT ", size %u, offset %" G_GUINT64_FORMAT
-        ", offset_end %" G_GUINT64_FORMAT ", caps: %s", buf,
-        GST_BUFFER_DATA (buf), GST_BUFFER_MALLOCDATA (buf),
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
-        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf),
-        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), caps);
-
-    g_free (caps);
+        g_strdup_printf ("%p, pts %" GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT
+        ", dur %" GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT ", offset %"
+        G_GUINT64_FORMAT ", offset_end %" G_GUINT64_FORMAT, buf,
+        GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
+        GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), gst_buffer_get_size (buf),
+        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
     return ret;
   }
 #ifdef USE_POISONING
@@ -666,9 +655,12 @@ gst_debug_print_object (gpointer ptr)
   if (GST_IS_MESSAGE (object)) {
     GstMessage *msg = GST_MESSAGE_CAST (object);
     gchar *s, *ret;
+    const GstStructure *structure;
+
+    structure = gst_message_get_structure (msg);
 
-    if (msg->structure) {
-      s = gst_info_structure_to_string (msg->structure);
+    if (structure) {
+      s = gst_info_structure_to_string (structure);
     } else {
       s = g_strdup ("(NULL)");
     }
@@ -681,9 +673,12 @@ gst_debug_print_object (gpointer ptr)
   }
   if (GST_IS_QUERY (object)) {
     GstQuery *query = GST_QUERY_CAST (object);
+    const GstStructure *structure;
+
+    structure = gst_query_get_structure (query);
 
-    if (query->structure) {
-      return gst_info_structure_to_string (query->structure);
+    if (structure) {
+      return gst_info_structure_to_string (structure);
     } else {
       const gchar *query_type_name;
 
@@ -698,18 +693,18 @@ gst_debug_print_object (gpointer ptr)
   if (GST_IS_EVENT (object)) {
     GstEvent *event = GST_EVENT_CAST (object);
     gchar *s, *ret;
+    GstStructure *structure;
 
-    if (event->structure) {
-      s = gst_info_structure_to_string (event->structure);
+    structure = (GstStructure *) gst_event_get_structure (event);
+    if (structure) {
+      s = gst_info_structure_to_string (structure);
     } else {
       s = g_strdup ("(NULL)");
     }
 
-    ret = g_strdup_printf ("%s event from '%s' at time %"
+    ret = g_strdup_printf ("%s event at time %"
         GST_TIME_FORMAT ": %s",
-        GST_EVENT_TYPE_NAME (event), (event->src != NULL) ?
-        GST_OBJECT_NAME (event->src) : "(NULL)",
-        GST_TIME_ARGS (event->timestamp), s);
+        GST_EVENT_TYPE_NAME (event), GST_TIME_ARGS (event->timestamp), s);
     g_free (s);
     return ret;
   }
@@ -735,13 +730,11 @@ gst_debug_print_segment (gpointer ptr)
     }
     case GST_FORMAT_TIME:{
       return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT
-          ", stop=%" GST_TIME_FORMAT ", last_stop=%" GST_TIME_FORMAT
-          ", duration=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f"
-          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
+          ", stop=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f"
+          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", base=%" GST_TIME_FORMAT,
           GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
-          GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (segment->duration),
           segment->rate, segment->applied_rate, (guint) segment->flags,
-          GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->accum));
+          GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->base));
     }
     default:{
       const gchar *format_name;
@@ -750,13 +743,11 @@ gst_debug_print_segment (gpointer ptr)
       if (G_UNLIKELY (format_name == NULL))
         format_name = "(UNKNOWN FORMAT)";
       return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT
-          ", stop=%" G_GINT64_FORMAT ", last_stop=%" G_GINT64_FORMAT
-          ", duration=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f"
-          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
-          format_name, segment->start, segment->stop, segment->last_stop,
-          segment->duration, segment->rate, segment->applied_rate,
-          (guint) segment->flags, GST_TIME_ARGS (segment->time),
-          GST_TIME_ARGS (segment->accum));
+          ", stop=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f"
+          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", base=%" GST_TIME_FORMAT,
+          format_name, segment->start, segment->stop, segment->rate,
+          segment->applied_rate, (guint) segment->flags,
+          GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->base));
     }
   }
 }
@@ -986,13 +977,13 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
     /* colors, windows. We take a lock to keep colors and content together.
      * Maybe there is a better way but for now this will do the right
      * thing. */
-    static GStaticMutex win_print_mutex = G_STATIC_MUTEX_INIT;
+    static GMutex win_print_mutex;
     const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
 #define SET_COLOR(c) G_STMT_START { \
   if (log_file == stderr) \
     SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c)); \
   } G_STMT_END
-    g_static_mutex_lock (&win_print_mutex);
+    g_mutex_lock (&win_print_mutex);
     /* timestamp */
     fprintf (log_file, "%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed));
     fflush (log_file);
@@ -1018,7 +1009,7 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
     SET_COLOR (clear);
     fprintf (log_file, " %s\n", gst_debug_message_get (message));
     fflush (log_file);
-    g_static_mutex_unlock (&win_print_mutex);
+    g_mutex_unlock (&win_print_mutex);
 #endif
   } else {
     /* no color, all platforms */
@@ -1096,10 +1087,10 @@ gst_debug_add_log_function (GstLogFunction func, gpointer data)
    * It'd probably be clever to use some kind of RCU here, but I don't know
    * anything about that.
    */
-  g_static_mutex_lock (&__log_func_mutex);
+  g_mutex_lock (&__log_func_mutex);
   list = g_slist_copy (__log_functions);
   __log_functions = g_slist_prepend (list, entry);
-  g_static_mutex_unlock (&__log_func_mutex);
+  g_mutex_unlock (&__log_func_mutex);
 
   GST_DEBUG ("prepended log function %p (user data %p) to log functions",
       func, data);
@@ -1128,7 +1119,7 @@ gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
   GSList *new;
   guint removals = 0;
 
-  g_static_mutex_lock (&__log_func_mutex);
+  g_mutex_lock (&__log_func_mutex);
   new = __log_functions;
   while ((found = g_slist_find_custom (new, data, func))) {
     if (new == __log_functions) {
@@ -1143,7 +1134,7 @@ gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
   }
   /* FIXME: We leak the old list here. See _add_log_function for why. */
   __log_functions = new;
-  g_static_mutex_unlock (&__log_func_mutex);
+  g_mutex_unlock (&__log_func_mutex);
 
   return removals;
 }
@@ -1236,11 +1227,11 @@ gst_debug_is_colored (void)
 void
 gst_debug_set_active (gboolean active)
 {
-  __gst_debug_enabled = active;
+  _gst_debug_enabled = active;
   if (active)
-    __gst_debug_min = GST_LEVEL_COUNT;
+    _gst_debug_min = GST_LEVEL_COUNT;
   else
-    __gst_debug_min = GST_LEVEL_NONE;
+    _gst_debug_min = GST_LEVEL_NONE;
 }
 
 /**
@@ -1253,7 +1244,7 @@ gst_debug_set_active (gboolean active)
 gboolean
 gst_debug_is_active (void)
 {
-  return __gst_debug_enabled;
+  return _gst_debug_enabled;
 }
 
 /**
@@ -1291,7 +1282,7 @@ gst_debug_reset_threshold (gpointer category, gpointer unused)
   GstDebugCategory *cat = (GstDebugCategory *) category;
   GSList *walk;
 
-  g_static_mutex_lock (&__level_name_mutex);
+  g_mutex_lock (&__level_name_mutex);
   walk = __level_name;
   while (walk) {
     LevelNameEntry *entry = walk->data;
@@ -1307,15 +1298,15 @@ gst_debug_reset_threshold (gpointer category, gpointer unused)
   gst_debug_category_set_threshold (cat, gst_debug_get_default_threshold ());
 
 exit:
-  g_static_mutex_unlock (&__level_name_mutex);
+  g_mutex_unlock (&__level_name_mutex);
 }
 
 static void
 gst_debug_reset_all_thresholds (void)
 {
-  g_static_mutex_lock (&__cat_mutex);
+  g_mutex_lock (&__cat_mutex);
   g_slist_foreach (__categories, gst_debug_reset_threshold, NULL);
-  g_static_mutex_unlock (&__cat_mutex);
+  g_mutex_unlock (&__cat_mutex);
 }
 
 static void
@@ -1351,12 +1342,12 @@ gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
   entry = g_slice_new (LevelNameEntry);
   entry->pat = pat;
   entry->level = level;
-  g_static_mutex_lock (&__level_name_mutex);
+  g_mutex_lock (&__level_name_mutex);
   __level_name = g_slist_prepend (__level_name, entry);
-  g_static_mutex_unlock (&__level_name_mutex);
-  g_static_mutex_lock (&__cat_mutex);
+  g_mutex_unlock (&__level_name_mutex);
+  g_mutex_lock (&__cat_mutex);
   g_slist_foreach (__categories, for_each_threshold_by_entry, entry);
-  g_static_mutex_unlock (&__cat_mutex);
+  g_mutex_unlock (&__cat_mutex);
 }
 
 /**
@@ -1374,7 +1365,7 @@ gst_debug_unset_threshold_for_name (const gchar * name)
   g_return_if_fail (name != NULL);
 
   pat = g_pattern_spec_new (name);
-  g_static_mutex_lock (&__level_name_mutex);
+  g_mutex_lock (&__level_name_mutex);
   walk = __level_name;
   /* improve this if you want, it's mighty slow */
   while (walk) {
@@ -1388,7 +1379,7 @@ gst_debug_unset_threshold_for_name (const gchar * name)
       walk = __level_name;
     }
   }
-  g_static_mutex_unlock (&__level_name_mutex);
+  g_mutex_unlock (&__level_name_mutex);
   g_pattern_spec_free (pat);
   gst_debug_reset_all_thresholds ();
 }
@@ -1413,9 +1404,9 @@ _gst_debug_category_new (const gchar * name, guint color,
   gst_debug_reset_threshold (cat, NULL);
 
   /* add to category list */
-  g_static_mutex_lock (&__cat_mutex);
+  g_mutex_lock (&__cat_mutex);
   __categories = g_slist_prepend (__categories, cat);
-  g_static_mutex_unlock (&__cat_mutex);
+  g_mutex_unlock (&__cat_mutex);
 
   return cat;
 }
@@ -1433,9 +1424,9 @@ gst_debug_category_free (GstDebugCategory * category)
     return;
 
   /* remove from category list */
-  g_static_mutex_lock (&__cat_mutex);
+  g_mutex_lock (&__cat_mutex);
   __categories = g_slist_remove (__categories, category);
-  g_static_mutex_unlock (&__cat_mutex);
+  g_mutex_unlock (&__cat_mutex);
 
   g_free ((gpointer) category->name);
   g_free ((gpointer) category->description);
@@ -1462,9 +1453,9 @@ gst_debug_category_set_threshold (GstDebugCategory * category,
 {
   g_return_if_fail (category != NULL);
 
-  if (level > __gst_debug_min) {
-    __gst_debug_enabled = TRUE;
-    __gst_debug_min = level;
+  if (level > _gst_debug_min) {
+    _gst_debug_enabled = TRUE;
+    _gst_debug_min = level;
   }
 
   g_atomic_int_set (&category->threshold, level);
@@ -1558,9 +1549,9 @@ gst_debug_get_all_categories (void)
 {
   GSList *ret;
 
-  g_static_mutex_lock (&__cat_mutex);
+  g_mutex_lock (&__cat_mutex);
   ret = g_slist_copy (__categories);
-  g_static_mutex_unlock (&__cat_mutex);
+  g_mutex_unlock (&__cat_mutex);
 
   return ret;
 }
@@ -1583,7 +1574,7 @@ _gst_debug_get_category (const gchar * name)
 /*** FUNCTION POINTERS ********************************************************/
 
 static GHashTable *__gst_function_pointers;     /* NULL */
-static GStaticMutex __dbg_functions_mutex = G_STATIC_MUTEX_INIT;
+static GMutex __dbg_functions_mutex;
 
 /* This function MUST NOT return NULL */
 const gchar *
@@ -1598,14 +1589,14 @@ _gst_debug_nameof_funcptr (GstDebugFuncPtr func)
   if (G_UNLIKELY (func == NULL))
     return "(NULL)";
 
-  g_static_mutex_lock (&__dbg_functions_mutex);
+  g_mutex_lock (&__dbg_functions_mutex);
   if (G_LIKELY (__gst_function_pointers)) {
     ptrname = g_hash_table_lookup (__gst_function_pointers, (gpointer) func);
-    g_static_mutex_unlock (&__dbg_functions_mutex);
+    g_mutex_unlock (&__dbg_functions_mutex);
     if (G_LIKELY (ptrname))
       return ptrname;
   } else {
-    g_static_mutex_unlock (&__dbg_functions_mutex);
+    g_mutex_unlock (&__dbg_functions_mutex);
   }
   /* we need to create an entry in the hash table for this one so we don't leak
    * the name */
@@ -1630,14 +1621,14 @@ _gst_debug_register_funcptr (GstDebugFuncPtr func, const gchar * ptrname)
 {
   gpointer ptr = (gpointer) func;
 
-  g_static_mutex_lock (&__dbg_functions_mutex);
+  g_mutex_lock (&__dbg_functions_mutex);
 
   if (!__gst_function_pointers)
     __gst_function_pointers = g_hash_table_new (g_direct_hash, g_direct_equal);
   if (!g_hash_table_lookup (__gst_function_pointers, ptr))
     g_hash_table_insert (__gst_function_pointers, ptr, (gpointer) ptrname);
 
-  g_static_mutex_unlock (&__dbg_functions_mutex);
+  g_mutex_unlock (&__dbg_functions_mutex);
 }
 
 /*** PRINTF EXTENSIONS ********************************************************/
index f841cd7..5b8f87c 100644 (file)
@@ -42,6 +42,11 @@ G_BEGIN_DECLS
  *  that could lead to problems or weird behaviour later on. An example of this
  *  would be clocking issues ("your computer is pretty slow") or broken input
  *  data ("Can't synchronize to stream.")
+ * @GST_LEVEL_FIXME: Fixme messages are messages that indicate that something
+ *  in the executed code path is not fully implemented or handled yet. Note
+ *  that this does not replace proper error handling in any way, the purpose
+ *  of this message is to make it easier to spot incomplete/unfinished pieces
+ *  of code when reading the debug log. (Since: 0.10.23)
  * @GST_LEVEL_INFO: Informational messages should be used to keep the developer
  *  updated about what is happening.
  *  Examples where this should be used are when a typefind function has
@@ -58,11 +63,6 @@ G_BEGIN_DECLS
  *  should never output anything else but LOG messages. Use this log level to
  *  log recurring information in chain functions and loop functions, for
  *  example.
- * @GST_LEVEL_FIXME: Fixme messages are messages that indicate that something
- *  in the executed code path is not fully implemented or handled yet. Note
- *  that this does not replace proper error handling in any way, the purpose
- *  of this message is to make it easier to spot incomplete/unfinished pieces
- *  of code when reading the debug log. (Since: 0.10.23)
  * @GST_LEVEL_TRACE: Tracing-related messages (Since: 0.10.30)
  *  Examples for this are referencing/dereferencing of objects.
  * @GST_LEVEL_MEMDUMP: memory dump messages are used to log (small) chunks of
@@ -75,12 +75,12 @@ G_BEGIN_DECLS
  */
 typedef enum {
   GST_LEVEL_NONE = 0,
-  GST_LEVEL_ERROR,
-  GST_LEVEL_WARNING,
-  GST_LEVEL_INFO,
-  GST_LEVEL_DEBUG,
-  GST_LEVEL_LOG,
-  GST_LEVEL_FIXME = 6,
+  GST_LEVEL_ERROR = 1,
+  GST_LEVEL_WARNING = 2,
+  GST_LEVEL_FIXME = 3,
+  GST_LEVEL_INFO = 4,
+  GST_LEVEL_DEBUG = 5,
+  GST_LEVEL_LOG = 6,
   GST_LEVEL_TRACE = 7,
   /* add more */
   GST_LEVEL_MEMDUMP = 9,
@@ -256,11 +256,6 @@ typedef void (*GstLogFunction)  (GstDebugCategory * category,
                                  GstDebugMessage  * message,
                                  gpointer           data);
 
-
-/* FIXME 0.11: move this into private headers */
-void            _gst_debug_init (void);
-
-
 #ifdef GST_USING_PRINTF_EXTENSION
 
 /* not using G_GNUC_PRINTF, since gcc will choke on GST_PTR_FORMAT being %P */
@@ -490,11 +485,11 @@ G_STMT_START{                                 \
  */
 GST_EXPORT GstDebugCategory *  GST_CAT_DEFAULT;
 /* this symbol may not be used */
-extern gboolean                        __gst_debug_enabled;
+GST_EXPORT gboolean                    _gst_debug_enabled;
 
 /* since 0.10.7, the min debug level, used for quickly discarding debug
  * messages that fall under the threshold. */
-GST_EXPORT GstDebugLevel            __gst_debug_min;
+GST_EXPORT GstDebugLevel            _gst_debug_min;
 
 /**
  * GST_CAT_LEVEL_LOG:
@@ -509,7 +504,7 @@ GST_EXPORT GstDebugLevel            __gst_debug_min;
  */
 #ifdef G_HAVE_ISO_VARARGS
 #define GST_CAT_LEVEL_LOG(cat,level,object,...) G_STMT_START{          \
-  if (G_UNLIKELY (level <= __gst_debug_min)) {                                         \
+  if (G_UNLIKELY (level <= _gst_debug_min)) {                                          \
     gst_debug_log ((cat), (level), __FILE__, GST_FUNCTION, __LINE__,   \
         (GObject *) (object), __VA_ARGS__);                            \
   }                                                                    \
@@ -517,7 +512,7 @@ GST_EXPORT GstDebugLevel            __gst_debug_min;
 #else /* G_HAVE_GNUC_VARARGS */
 #ifdef G_HAVE_GNUC_VARARGS
 #define GST_CAT_LEVEL_LOG(cat,level,object,args...) G_STMT_START{      \
-  if (G_UNLIKELY (level <= __gst_debug_min)) {                                         \
+  if (G_UNLIKELY (level <= _gst_debug_min)) {                                          \
     gst_debug_log ((cat), (level), __FILE__, GST_FUNCTION, __LINE__,   \
         (GObject *) (object), ##args );                                        \
   }                                                                    \
@@ -527,7 +522,7 @@ static inline void
 GST_CAT_LEVEL_LOG_valist (GstDebugCategory * cat,
     GstDebugLevel level, gpointer object, const char *format, va_list varargs)
 {
-  if (G_UNLIKELY (level <= __gst_debug_min)) {
+  if (G_UNLIKELY (level <= _gst_debug_min)) {
     gst_debug_log_valist (cat, level, "", "", 0, (GObject *) object, format,
         varargs);
   }
@@ -550,7 +545,7 @@ GST_CAT_LEVEL_LOG (GstDebugCategory * cat, GstDebugLevel level,
  * other macros and hence in a separate block right here. Docs chunks are
  * with the other doc chunks below though. */
 #define __GST_CAT_MEMDUMP_LOG(cat,object,msg,data,length) G_STMT_START{       \
-  if (G_UNLIKELY (GST_LEVEL_MEMDUMP <= __gst_debug_min)) {                    \
+  if (G_UNLIKELY (GST_LEVEL_MEMDUMP <= _gst_debug_min)) {                    \
     _gst_debug_dump_mem ((cat), __FILE__, GST_FUNCTION, __LINE__,             \
         (GObject *) (object), (msg), (data), (length));                       \
   }                                                                           \
@@ -1260,9 +1255,7 @@ GST_TRACE (const char *format, ...)
 #  pragma GCC poison _gst_debug_category_new
 #endif
 
-#define __gst_debug_min GST_LEVEL_NONE
-
-#define _gst_debug_init()                              G_STMT_START{ }G_STMT_END
+#define _gst_debug_min GST_LEVEL_NONE
 
 #define gst_debug_set_default_threshold(level)         G_STMT_START{ }G_STMT_END
 #define gst_debug_get_default_threshold()              (GST_LEVEL_NONE)
diff --git a/gst/gstinterface.c b/gst/gstinterface.c
deleted file mode 100644 (file)
index 0df005b..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *
- * gstinterface.c: Interface functions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstimplementsinterface
- * @short_description: Core interface implemented by #GstElement instances that
- * allows runtime querying of interface availability
- * @see_also: #GstElement
- *
- * Provides interface functionality on per instance basis and not per class
- * basis, which is the case for gobject.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst_private.h"
-#include "gstinterface.h"
-
-static void
-gst_implements_interface_class_init (GstImplementsInterfaceClass * ifklass);
-static gboolean
-gst_implements_interface_supported_default (GstImplementsInterface * iface,
-    GType iface_type);
-
-GType
-gst_implements_interface_get_type (void)
-{
-  static volatile gsize gst_interface_type = 0;
-
-  if (g_once_init_enter (&gst_interface_type)) {
-    GType _type;
-    static const GTypeInfo gst_interface_info = {
-      sizeof (GstImplementsInterfaceClass),
-      (GBaseInitFunc) gst_implements_interface_class_init,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      0,
-      0,
-      NULL,
-      NULL
-    };
-
-    _type = g_type_register_static (G_TYPE_INTERFACE,
-        "GstImplementsInterface", &gst_interface_info, 0);
-
-    g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT);
-    g_once_init_leave (&gst_interface_type, _type);
-  }
-
-  return gst_interface_type;
-}
-
-static void
-gst_implements_interface_class_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = gst_implements_interface_supported_default;
-}
-
-static gboolean
-gst_implements_interface_supported_default (GstImplementsInterface * interface,
-    GType iface_type)
-{
-  /* Well, if someone didn't set the virtual function,
-   * then something is clearly wrong. So big no-no here */
-
-  return FALSE;
-}
-
-/**
- * gst_element_implements_interface:
- * @element: #GstElement to check for the implementation of the interface
- * @iface_type: (final) type of the interface which we want to be implemented
- *
- * Test whether the given element implements a certain interface of type
- * iface_type, and test whether it is supported for this specific instance.
- *
- * Returns: whether or not the element implements the interface.
- */
-
-gboolean
-gst_element_implements_interface (GstElement * element, GType iface_type)
-{
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (element), iface_type)) {
-    GstImplementsInterface *iface;
-    GstImplementsInterfaceClass *ifclass;
-
-    iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
-        iface_type, GstImplementsInterface);
-    ifclass = GST_IMPLEMENTS_INTERFACE_GET_CLASS (iface);
-
-    /* element implements iface_type but not GstImplementsInterface, so
-     * just assume the other interface is implemented unconditionally */
-    if (ifclass == NULL)
-      return TRUE;
-
-    if (ifclass->supported != NULL &&
-        ifclass->supported (iface, iface_type) == TRUE) {
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-/**
- * gst_implements_interface_cast:
- * @from: the object (any sort) from which to cast to the interface
- * @type: the interface type to cast to
- *
- * cast a given object to an interface type, and check whether this
- * interface is supported for this specific instance.
- *
- * Returns: (transfer none): a gpointer to the interface type
- */
-
-gpointer
-gst_implements_interface_cast (gpointer from, GType iface_type)
-{
-  GstImplementsInterface *iface;
-
-  /* check cast, give warning+fail if it's invalid */
-  if (!(iface = G_TYPE_CHECK_INSTANCE_CAST (from, iface_type,
-              GstImplementsInterface))) {
-    return NULL;
-  }
-
-  /* if we're an element, take care that this interface
-   * is actually implemented */
-  if (GST_IS_ELEMENT (from)) {
-    g_return_val_if_fail (gst_element_implements_interface (GST_ELEMENT (from),
-            iface_type), NULL);
-  }
-
-  return iface;
-}
-
-/**
- * gst_implements_interface_check:
- * @from: the object (any sort) from which to check from for the interface
- * @type: the interface type to check for
- *
- * check a given object for an interface implementation, and check
- * whether this interface is supported for this specific instance.
- *
- * Returns: whether or not the object implements the given interface
- */
-
-gboolean
-gst_implements_interface_check (gpointer from, GType type)
-{
-  /* check cast, return FALSE if it fails, don't give a warning... */
-  if (!G_TYPE_CHECK_INSTANCE_TYPE (from, type)) {
-    return FALSE;
-  }
-
-  /* now, if we're an element (or derivative), is this thing
-   * actually implemented for real? */
-  if (GST_IS_ELEMENT (from)) {
-    if (!gst_element_implements_interface (GST_ELEMENT (from), type)) {
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
diff --git a/gst/gstinterface.h b/gst/gstinterface.h
deleted file mode 100644 (file)
index 860d9de..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *
- * gstinterface.h: Declarations of interface stuff
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_IMPLEMENTS_INTERFACE_H__
-#define __GST_IMPLEMENTS_INTERFACE_H__
-
-#include <gst/gstelement.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_IMPLEMENTS_INTERFACE \
-  (gst_implements_interface_get_type ())
-#define GST_IMPLEMENTS_INTERFACE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_IMPLEMENTS_INTERFACE, \
-                                     GstImplementsInterface))
-#define GST_IS_IMPLEMENTS_INTERFACE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_IMPLEMENTS_INTERFACE))
-#define GST_IMPLEMENTS_INTERFACE_GET_CLASS(inst) \
-  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_IMPLEMENTS_INTERFACE, \
-                                 GstImplementsInterfaceClass))
-
-/**
- * GstImplementsInterface:
- *
- * Opaque #GstImplementsInterface structure.
- */
-typedef struct _GstImplementsInterface GstImplementsInterface;
-
-typedef struct _GstImplementsInterfaceClass GstImplementsInterfaceClass;
-
-/* This small extra virtual function is here to provide an
- * interface functionality on a per-instance basis rather
- * than a per-class basis, which is the case for glib.
- */
-struct _GstImplementsInterfaceClass {
-  GTypeInterface parent;
-
-  /* virtual functions */
-  gboolean (* supported) (GstImplementsInterface *iface,
-                         GType                   iface_type);
-
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-#define GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST(obj, type, cast_t) \
-  ((cast_t *) gst_implements_interface_cast ((obj), (type)))
-#define GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE(obj, type) \
-  (gst_implements_interface_check ((obj), (type)))
-
-GType   gst_implements_interface_get_type    (void);
-
-/* wrapper functions to check for functionality implementation */
-gboolean gst_element_implements_interface     (GstElement *element,
-                                              GType       iface_type);
-gpointer gst_implements_interface_cast       (gpointer    from,
-                                              GType       type);
-gboolean gst_implements_interface_check              (gpointer    from,
-                                              GType       type);
-
-G_END_DECLS
-
-#endif /* __GST_IMPLEMENTS_INTERFACE_H__ */
index f616282..6940349 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2011 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * gstiterator.h: Base class for iterating datastructures.
  *
@@ -46,7 +47,7 @@
  *      switch (gst_iterator_next (it, &amp;item)) {
  *        case GST_ITERATOR_OK:
  *          ... use/change item here...
- *          gst_object_unref (item);
+ *          g_value_reset (&amp;item);
  *          break;
  *        case GST_ITERATOR_RESYNC:
  *          ...rollback changes to items...
@@ -61,6 +62,7 @@
  *          break;
  *      }
  *    }
+ *    g_value_unset (&amp;item);
  *    gst_iterator_free (it);
  *   </programlisting>
  * </example>
 #include "gst_private.h"
 #include <gst/gstiterator.h>
 
-/* FIXME 0.11: Store the size inside the iterator, use GSlice for allocation
- * and let gst_iterator_free() free the memory while the free-func only frees
- * additional resources (maybe call it finalize?).
- */
+GstIterator *
+gst_iterator_copy (const GstIterator * it)
+{
+  GstIterator *copy;
+
+  copy = g_slice_copy (it->size, it);
+  if (it->copy)
+    it->copy (it, copy);
+
+  return copy;
+}
+
+GType
+gst_iterator_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0))
+    type = g_boxed_type_register_static ("GstIterator",
+        (GBoxedCopyFunc) gst_iterator_copy, (GBoxedFreeFunc) gst_iterator_free);
+  return type;
+}
 
 static void
 gst_iterator_init (GstIterator * it,
+    guint size,
     GType type,
     GMutex * lock,
     guint32 * master_cookie,
+    GstIteratorCopyFunction copy,
     GstIteratorNextFunction next,
     GstIteratorItemFunction item,
     GstIteratorResyncFunction resync, GstIteratorFreeFunction free)
 {
+  it->size = size;
   it->type = type;
   it->lock = lock;
   it->master_cookie = master_cookie;
   it->cookie = *master_cookie;
+  it->copy = copy;
   it->next = next;
   it->item = item;
   it->resync = resync;
@@ -97,12 +121,13 @@ gst_iterator_init (GstIterator * it,
 }
 
 /**
- * gst_iterator_new:
+ * gst_iterator_new: (skip)
  * @size: the size of the iterator structure
  * @type: #GType of children
  * @lock: pointer to a #GMutex.
  * @master_cookie: pointer to a guint32 that is changed when the items in the
  *    iterator changed.
+ * @copy: copy function
  * @next: function to get next item
  * @item: function to call on each item retrieved
  * @resync: function to resync the iterator
@@ -123,6 +148,7 @@ gst_iterator_new (guint size,
     GType type,
     GMutex * lock,
     guint32 * master_cookie,
+    GstIteratorCopyFunction copy,
     GstIteratorNextFunction next,
     GstIteratorItemFunction item,
     GstIteratorResyncFunction resync, GstIteratorFreeFunction free)
@@ -136,9 +162,9 @@ gst_iterator_new (guint size,
   g_return_val_if_fail (resync != NULL, NULL);
   g_return_val_if_fail (free != NULL, NULL);
 
-  result = g_malloc (size);
-  gst_iterator_init (result, type, lock, master_cookie, next, item, resync,
-      free);
+  result = g_slice_alloc0 (size);
+  gst_iterator_init (result, size, type, lock, master_cookie, copy, next, item,
+      resync, free);
 
   return result;
 }
@@ -149,21 +175,33 @@ gst_iterator_new (guint size,
 typedef struct _GstListIterator
 {
   GstIterator iterator;
-  gpointer owner;
+  GObject *owner;
   GList **orig;
   GList *list;                  /* pointer in list */
-  GstIteratorDisposeFunction freefunc;
+
+  void (*set_value) (GValue * value, gpointer item);
 } GstListIterator;
 
+static void
+gst_list_iterator_copy (const GstListIterator * it, GstListIterator * copy)
+{
+  if (copy->owner)
+    g_object_ref (copy->owner);
+}
+
 static GstIteratorResult
-gst_list_iterator_next (GstListIterator * it, gpointer * elem)
+gst_list_iterator_next (GstListIterator * it, GValue * elem)
 {
+  gpointer data;
+
   if (it->list == NULL)
     return GST_ITERATOR_DONE;
 
-  *elem = it->list->data;
+  data = it->list->data;
   it->list = g_list_next (it->list);
 
+  it->set_value (elem, data);
+
   return GST_ITERATOR_OK;
 }
 
@@ -176,22 +214,19 @@ gst_list_iterator_resync (GstListIterator * it)
 static void
 gst_list_iterator_free (GstListIterator * it)
 {
-  if (it->freefunc) {
-    it->freefunc (it->owner);
-  }
-  g_free (it);
+  if (it->owner)
+    g_object_unref (it->owner);
 }
 
 /**
- * gst_iterator_new_list:
+ * gst_iterator_new_list: (skip)
  * @type: #GType of elements
  * @lock: pointer to a #GMutex protecting the list.
  * @master_cookie: pointer to a guint32 that is incremented when the list
  *     is changed.
  * @list: pointer to the list
  * @owner: object owning the list
- * @item: function to call for each item
- * @free: function to call when the iterator is freed
+ * @item: function to call on each item retrieved
  *
  * Create a new iterator designed for iterating @list.
  *
@@ -201,46 +236,52 @@ gst_list_iterator_free (GstListIterator * it)
  * The iterator will use @lock to retrieve the next item of the list and it
  * will then call the @item function before releasing @lock again.
  *
- * The @item function usualy makes sure that the item remains alive while
- * @lock is released and the application is using the item. The application is
- * responsible for freeing/unreffing the item after usage as explained in
- * gst_iterator_next().
- *
  * When a concurrent update to the list is performed, usually by @owner while
  * holding @lock, @master_cookie will be updated. The iterator implementation
  * will notice the update of the cookie and will return %GST_ITERATOR_RESYNC to
  * the user of the iterator in the next call to gst_iterator_next().
  *
- * @owner will be passed to the @free function when the iterator is freed.
- *
  * Returns: the new #GstIterator for @list.
  *
  * MT safe.
  */
 GstIterator *
 gst_iterator_new_list (GType type,
-    GMutex * lock,
-    guint32 * master_cookie,
-    GList ** list,
-    gpointer owner,
-    GstIteratorItemFunction item, GstIteratorDisposeFunction free)
+    GMutex * lock, guint32 * master_cookie, GList ** list, GObject * owner,
+    GstIteratorItemFunction item)
 {
   GstListIterator *result;
+  gpointer set_value;
+
+  if (g_type_is_a (type, G_TYPE_OBJECT)) {
+    set_value = g_value_set_object;
+  } else if (g_type_is_a (type, G_TYPE_BOXED)) {
+    set_value = g_value_set_boxed;
+  } else if (g_type_is_a (type, G_TYPE_POINTER)) {
+    set_value = g_value_set_pointer;
+  } else if (g_type_is_a (type, G_TYPE_STRING)) {
+    set_value = g_value_set_string;
+  } else {
+    g_critical ("List iterators can only be created for lists containing "
+        "instances of GObject, boxed types, pointer types and strings");
+    return NULL;
+  }
 
   /* no need to lock, nothing can change here */
   result = (GstListIterator *) gst_iterator_new (sizeof (GstListIterator),
       type,
       lock,
       master_cookie,
+      (GstIteratorCopyFunction) gst_list_iterator_copy,
       (GstIteratorNextFunction) gst_list_iterator_next,
       (GstIteratorItemFunction) item,
       (GstIteratorResyncFunction) gst_list_iterator_resync,
       (GstIteratorFreeFunction) gst_list_iterator_free);
 
-  result->owner = owner;
+  result->owner = owner ? g_object_ref (owner) : NULL;
   result->orig = list;
   result->list = *list;
-  result->freefunc = free;
+  result->set_value = set_value;
 
   return GST_ITERATOR (result);
 }
@@ -257,14 +298,15 @@ gst_iterator_pop (GstIterator * it)
 /**
  * gst_iterator_next:
  * @it: The #GstIterator to iterate
- * @elem: pointer to hold next element
+ * @elem: (out caller-allocates): pointer to hold next element
  *
  * Get the next item from the iterator in @elem. 
  *
  * Only when this function returns %GST_ITERATOR_OK, @elem will contain a valid
- * value. For iterators that return refcounted objects, the returned object
- * will have its refcount increased and should therefore be unreffed after
- * usage.
+ * value. @elem must have been initialized to the type of the iterator or
+ * initialized to zeroes with g_value_unset(). The caller is responsible for
+ * unsetting or resetting @elem with g_value_unset() or g_value_reset()
+ * after usage.
  *
  * When this function returns %GST_ITERATOR_DONE, no more elements can be
  * retrieved from @it.
@@ -275,18 +317,22 @@ gst_iterator_pop (GstIterator * it)
  *
  * A return value of %GST_ITERATOR_ERROR indicates an unrecoverable fatal error.
  *
- * Returns: The result of the iteration. Unref @elem after usage if this
- * is a refcounted object.
+ * Returns: The result of the iteration. Unset @elem after usage.
  *
  * MT safe.
  */
 GstIteratorResult
-gst_iterator_next (GstIterator * it, gpointer * elem)
+gst_iterator_next (GstIterator * it, GValue * elem)
 {
   GstIteratorResult result;
 
   g_return_val_if_fail (it != NULL, GST_ITERATOR_ERROR);
   g_return_val_if_fail (elem != NULL, GST_ITERATOR_ERROR);
+  g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID
+      || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR);
+
+  if (G_VALUE_TYPE (elem) == G_TYPE_INVALID)
+    g_value_init (elem, it->type);
 
 restart:
   if (it->pushed) {
@@ -312,14 +358,16 @@ restart:
   if (result == GST_ITERATOR_OK && it->item) {
     GstIteratorItem itemres;
 
-    itemres = it->item (it, *elem);
+    itemres = it->item (it, elem);
     switch (itemres) {
       case GST_ITERATOR_ITEM_SKIP:
         if (G_LIKELY (it->lock))
           g_mutex_unlock (it->lock);
+        g_value_reset (elem);
         goto restart;
       case GST_ITERATOR_ITEM_END:
         result = GST_ITERATOR_DONE;
+        g_value_reset (elem);
         break;
       case GST_ITERATOR_ITEM_PASS:
         break;
@@ -376,6 +424,8 @@ gst_iterator_free (GstIterator * it)
   gst_iterator_pop (it);
 
   it->free (it);
+
+  g_slice_free1 (it->size, it);
 }
 
 /**
@@ -410,29 +460,28 @@ typedef struct _GstIteratorFilter
   GstIterator *slave;
 
   GCompareFunc func;
-  gpointer user_data;
+  GValue user_data;
+  gboolean have_user_data;
 } GstIteratorFilter;
 
 static GstIteratorResult
-filter_next (GstIteratorFilter * it, gpointer * elem)
+filter_next (GstIteratorFilter * it, GValue * elem)
 {
   GstIteratorResult result = GST_ITERATOR_ERROR;
   gboolean done = FALSE;
-
-  *elem = NULL;
+  GValue item = { 0, };
 
   while (G_LIKELY (!done)) {
-    gpointer item;
-
     result = gst_iterator_next (it->slave, &item);
     switch (result) {
       case GST_ITERATOR_OK:
         if (G_LIKELY (GST_ITERATOR (it)->lock))
           g_mutex_unlock (GST_ITERATOR (it)->lock);
-        if (it->func (item, it->user_data) == 0) {
-          *elem = item;
+        if (it->func (&item, &it->user_data) == 0) {
+          g_value_copy (&item, elem);
           done = TRUE;
         }
+        g_value_reset (&item);
         if (G_LIKELY (GST_ITERATOR (it)->lock))
           g_mutex_lock (GST_ITERATOR (it)->lock);
         break;
@@ -445,27 +494,34 @@ filter_next (GstIteratorFilter * it, gpointer * elem)
         break;
     }
   }
+  g_value_unset (&item);
   return result;
 }
 
 static void
-filter_resync (GstIteratorFilter * it)
+filter_copy (const GstIteratorFilter * it, GstIteratorFilter * copy)
 {
-  gst_iterator_resync (it->slave);
+  copy->slave = gst_iterator_copy (it->slave);
+
+  if (it->have_user_data) {
+    memset (&copy->user_data, 0, sizeof (copy->user_data));
+    g_value_init (&copy->user_data, G_VALUE_TYPE (&it->user_data));
+    g_value_copy (&it->user_data, &copy->user_data);
+  }
 }
 
 static void
-filter_uninit (GstIteratorFilter * it)
+filter_resync (GstIteratorFilter * it)
 {
-  it->slave->lock = GST_ITERATOR (it)->lock;
+  gst_iterator_resync (it->slave);
 }
 
 static void
 filter_free (GstIteratorFilter * it)
 {
-  filter_uninit (it);
+  if (it->have_user_data)
+    g_value_unset (&it->user_data);
   gst_iterator_free (it->slave);
-  g_free (it);
 }
 
 /**
@@ -476,8 +532,9 @@ filter_free (GstIteratorFilter * it)
  *
  * Create a new iterator from an existing iterator. The new iterator
  * will only return those elements that match the given compare function @func.
- * @func should return 0 for elements that should be included
- * in the iterator.
+ * The first parameter that is passed to @func is the #GValue of the current
+ * iterator element and the second parameter is @user_data. @func should
+ * return 0 for elements that should be included in the filtered iterator.
  *
  * When this iterator is freed, @it will also be freed.
  *
@@ -486,7 +543,8 @@ filter_free (GstIteratorFilter * it)
  * MT safe.
  */
 GstIterator *
-gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data)
+gst_iterator_filter (GstIterator * it, GCompareFunc func,
+    const GValue * user_data)
 {
   GstIteratorFilter *result;
 
@@ -495,13 +553,21 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data)
 
   result = (GstIteratorFilter *) gst_iterator_new (sizeof (GstIteratorFilter),
       it->type, it->lock, it->master_cookie,
+      (GstIteratorCopyFunction) filter_copy,
       (GstIteratorNextFunction) filter_next,
       (GstIteratorItemFunction) NULL,
       (GstIteratorResyncFunction) filter_resync,
       (GstIteratorFreeFunction) filter_free);
+
   it->lock = NULL;
   result->func = func;
-  result->user_data = user_data;
+  if (user_data) {
+    g_value_init (&result->user_data, G_VALUE_TYPE (user_data));
+    g_value_copy (user_data, &result->user_data);
+    result->have_user_data = TRUE;
+  } else {
+    result->have_user_data = FALSE;
+  }
   result->slave = it;
 
   return GST_ITERATOR (result);
@@ -517,8 +583,7 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, gpointer user_data)
  * Folds @func over the elements of @iter. That is to say, @func will be called
  * as @func (object, @ret, @user_data) for each object in @it. The normal use
  * of this procedure is to accumulate the results of operating on the objects in
- * @ret.  If object is a refcounted object its refcount will be increased 
- * before @func is called, and it should be unrefed after use in @func.
+ * @ret.
  *
  * This procedure can be used (and is used internally) to implement the
  * gst_iterator_foreach() and gst_iterator_find_custom() operations.
@@ -539,17 +604,18 @@ GstIteratorResult
 gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func,
     GValue * ret, gpointer user_data)
 {
-  gpointer item;
+  GValue item = { 0, };
   GstIteratorResult result;
 
   while (1) {
     result = gst_iterator_next (it, &item);
     switch (result) {
       case GST_ITERATOR_OK:
-        if (!func (item, ret, user_data))
+        if (!func (&item, ret, user_data))
           goto fold_done;
-        else
-          break;
+
+        g_value_reset (&item);
+        break;
       case GST_ITERATOR_RESYNC:
       case GST_ITERATOR_ERROR:
         goto fold_done;
@@ -559,17 +625,19 @@ gst_iterator_fold (GstIterator * it, GstIteratorFoldFunction func,
   }
 
 fold_done:
+  g_value_unset (&item);
+
   return result;
 }
 
 typedef struct
 {
-  GFunc func;
+  GstIteratorForeachFunction func;
   gpointer user_data;
 } ForeachFoldData;
 
 static gboolean
-foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data)
+foreach_fold_func (const GValue * item, GValue * unused, ForeachFoldData * data)
 {
   data->func (item, data->user_data);
   return TRUE;
@@ -582,9 +650,7 @@ foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data)
  * @user_data: (closure): user data passed to the function
  *
  * Iterate over all element of @it and call the given function @func for
- * each element.  As in gst_iterator_fold(), the refcount of a refcounted 
- * object will be increased before @func is called, and should be unrefed
- * after use.
+ * each element.
  *
  * Returns: the result call to gst_iterator_fold(). The iterator will not be
  * freed.
@@ -592,7 +658,8 @@ foreach_fold_func (gpointer item, GValue * unused, ForeachFoldData * data)
  * MT safe.
  */
 GstIteratorResult
-gst_iterator_foreach (GstIterator * it, GFunc func, gpointer user_data)
+gst_iterator_foreach (GstIterator * it, GstIteratorForeachFunction func,
+    gpointer user_data)
 {
   ForeachFoldData data;
 
@@ -607,93 +674,105 @@ typedef struct
 {
   GCompareFunc func;
   gpointer user_data;
+  gboolean found;
 } FindCustomFoldData;
 
 static gboolean
-find_custom_fold_func (gpointer item, GValue * ret, FindCustomFoldData * data)
+find_custom_fold_func (const GValue * item, GValue * ret,
+    FindCustomFoldData * data)
 {
   if (data->func (item, data->user_data) == 0) {
-    g_value_set_pointer (ret, item);
+    data->found = TRUE;
+    g_value_copy (item, ret);
     return FALSE;
   } else {
     return TRUE;
   }
 }
 
-/* FIXME 0.11:
- * We should store ref/unref (or copy/free) functions for the type
- * in GstIterator. The unref but only if it's not a match behaviour
- * of find_custom() is very bad for bindings. The ref/unref functions
- * are also useful for the fold and filter cases.
- */
-
 /**
  * gst_iterator_find_custom:
  * @it: The #GstIterator to iterate
  * @func: (scope call): the compare function to use
+ * @elem: (out): pointer to a #GValue where to store the result
  * @user_data: (closure): user data passed to the compare function
  *
  * Find the first element in @it that matches the compare function @func.
- * @func should return 0 when the element is found.  As in gst_iterator_fold(),
- * the refcount of a refcounted object will be increased before @func is 
- * called, and should be unrefed after use in @func unless it is the matching
- * element.
+ * @func should return 0 when the element is found. The first parameter
+ * to @func will be the current element of the iterator and the
+ * second parameter will be @user_data.
+ * The result will be stored in @elem if a result is found.
  *
  * The iterator will not be freed.
  *
- * This function will return NULL if an error happened to the iterator.
+ * This function will return FALSE if an error happened to the iterator
+ * or if the element wasn't found.
  *
- * Returns: (transfer full): The element in the iterator that matches the compare
- * function or NULL when no element matched.
+ * Returns: Returns TRUE if the element was found, else FALSE.
  *
  * MT safe.
  */
-gpointer
+gboolean
 gst_iterator_find_custom (GstIterator * it, GCompareFunc func,
-    gpointer user_data)
+    GValue * elem, gpointer user_data)
 {
-  GValue ret = { 0, };
   GstIteratorResult res;
   FindCustomFoldData data;
 
-  g_value_init (&ret, G_TYPE_POINTER);
+  g_return_val_if_fail (G_VALUE_TYPE (elem) == G_TYPE_INVALID
+      || G_VALUE_HOLDS (elem, it->type), GST_ITERATOR_ERROR);
+
+  if (G_VALUE_TYPE (elem) == G_TYPE_INVALID)
+    g_value_init (elem, it->type);
+
   data.func = func;
   data.user_data = user_data;
+  data.found = FALSE;
 
   do {
     res =
         gst_iterator_fold (it, (GstIteratorFoldFunction) find_custom_fold_func,
-        &ret, &data);
+        elem, &data);
     if (res == GST_ITERATOR_RESYNC)
       gst_iterator_resync (it);
   } while (res == GST_ITERATOR_RESYNC);
 
-  /* no need to unset, it's just a pointer */
-  return g_value_get_pointer (&ret);
+  if (!data.found)
+    g_value_unset (elem);
+
+  return data.found;
 }
 
 typedef struct
 {
   GstIterator parent;
-  gpointer object;
-  GstCopyFunction copy;
-  GFreeFunc free;
+  GValue object;
   gboolean visited;
+  gboolean empty;
 } GstSingleObjectIterator;
 
 static guint32 _single_object_dummy_cookie = 0;
 
+static void
+gst_single_object_iterator_copy (const GstSingleObjectIterator * it,
+    GstSingleObjectIterator * copy)
+{
+  if (!it->empty) {
+    memset (&copy->object, 0, sizeof (copy->object));
+    g_value_init (&copy->object, it->parent.type);
+    g_value_copy (&it->object, &copy->object);
+  }
+}
+
 static GstIteratorResult
-gst_single_object_iterator_iterator_next (GstSingleObjectIterator * it,
-    gpointer * result)
+gst_single_object_iterator_next (GstSingleObjectIterator * it, GValue * result)
 {
-  if (it->visited || !it->object) {
-    *result = NULL;
+  if (it->visited || it->empty)
     return GST_ITERATOR_DONE;
-  }
 
-  *result = it->copy (it->object);
+  g_value_copy (&it->object, result);
   it->visited = TRUE;
+
   return GST_ITERATOR_OK;
 }
 
@@ -706,17 +785,14 @@ gst_single_object_iterator_resync (GstSingleObjectIterator * it)
 static void
 gst_single_object_iterator_free (GstSingleObjectIterator * it)
 {
-  if (it->object)
-    it->free (it->object);
-  g_free (it);
+  if (!it->empty)
+    g_value_unset (&it->object);
 }
 
 /**
  * gst_iterator_new_single:
  * @type: #GType of the passed object
  * @object: object that this iterator should return
- * @copy: Function that returns a copy of @object or increases its refcount
- * @free: Function to be called for freeing @object
  *
  * This #GstIterator is a convenient iterator for the common
  * case where a #GstIterator needs to be returned but only
@@ -728,25 +804,27 @@ gst_single_object_iterator_free (GstSingleObjectIterator * it)
  * Since: 0.10.25
  */
 GstIterator *
-gst_iterator_new_single (GType type, gpointer object, GstCopyFunction copy,
-    GFreeFunc free)
+gst_iterator_new_single (GType type, const GValue * object)
 {
   GstSingleObjectIterator *result;
 
-  g_return_val_if_fail (copy != NULL, NULL);
-  g_return_val_if_fail (free != NULL, NULL);
-
   result = (GstSingleObjectIterator *)
       gst_iterator_new (sizeof (GstSingleObjectIterator),
       type, NULL, &_single_object_dummy_cookie,
-      (GstIteratorNextFunction) gst_single_object_iterator_iterator_next, NULL,
+      (GstIteratorCopyFunction) gst_single_object_iterator_copy,
+      (GstIteratorNextFunction) gst_single_object_iterator_next,
+      (GstIteratorItemFunction) NULL,
       (GstIteratorResyncFunction) gst_single_object_iterator_resync,
       (GstIteratorFreeFunction) gst_single_object_iterator_free);
 
-  result->object = (object) ? copy (object) : NULL;
-  result->copy = copy;
-  result->free = free;
+  if (object) {
+    g_value_init (&result->object, type);
+    g_value_copy (object, &result->object);
+    result->empty = FALSE;
+  } else {
+    result->empty = TRUE;
+  }
   result->visited = FALSE;
 
-  return (GstIterator *) result;
+  return GST_ITERATOR (result);
 }
index 6c52975..2a21f8b 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2011 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * gstiterator.h: Header for GstIterator
  *
@@ -27,6 +28,8 @@
 
 G_BEGIN_DECLS
 
+#define GST_TYPE_ITERATOR (gst_iterator_get_type ())
+
 /**
  * GstIteratorResult:
  * @GST_ITERATOR_DONE:   No more items in the iterator
@@ -37,10 +40,10 @@ G_BEGIN_DECLS
  * The result of gst_iterator_next().
  */
 typedef enum {
-  GST_ITERATOR_DONE    = 0,
-  GST_ITERATOR_OK      = 1,
-  GST_ITERATOR_RESYNC  = 2,
-  GST_ITERATOR_ERROR   = 3
+  GST_ITERATOR_DONE     = 0,
+  GST_ITERATOR_OK       = 1,
+  GST_ITERATOR_RESYNC   = 2,
+  GST_ITERATOR_ERROR    = 3
 } GstIteratorResult;
 
 typedef struct _GstIterator GstIterator;
@@ -54,43 +57,44 @@ typedef struct _GstIterator GstIterator;
  * The result of a #GstIteratorItemFunction.
  */
 typedef enum {
-  GST_ITERATOR_ITEM_SKIP       = 0,
-  GST_ITERATOR_ITEM_PASS       = 1,
-  GST_ITERATOR_ITEM_END                = 2
+  GST_ITERATOR_ITEM_SKIP        = 0,
+  GST_ITERATOR_ITEM_PASS        = 1,
+  GST_ITERATOR_ITEM_END         = 2
 } GstIteratorItem;
 
 /**
- * GstIteratorDisposeFunction:
- * @owner: the owner of the iterator
+ * GstIteratorCopyFunction:
+ * @it: The original iterator
+ * @copy: The copied iterator
  *
- * The function that will be called when a #GList iterator is freed. The
- * owner of the #GList iterator can then clean up its resources.
+ * This function will be called when creating a copy of @it and should
+ * create a copy of all custom iterator fields or increase their
+ * reference counts.
  */
-typedef void             (*GstIteratorDisposeFunction) (gpointer owner);
+typedef void              (*GstIteratorCopyFunction) (const GstIterator *it, GstIterator *copy);
 
 /**
- * GstIteratorNextFunction:
+ * GstIteratorItemFunction:
  * @it: the iterator
- * @result: a pointer to hold the next item
+ * @item: the item being retrieved.
  *
- * The function that will be called when the next element of the iterator
- * should be retrieved. 
+ * The function that will be called after the next item of the iterator
+ * has been retrieved. This function can be used to skip items or stop
+ * the iterator.
  *
- * Implementors of a #GstIterator should implement this
- * function and pass it to the constructor of the custom iterator.
  * The function will be called with the iterator lock held.
  *
  * Returns: the result of the operation.
  */
-typedef GstIteratorResult (*GstIteratorNextFunction)   (GstIterator *it, gpointer *result);
+typedef GstIteratorItem   (*GstIteratorItemFunction)    (GstIterator *it, const GValue * item);
+
 /**
- * GstIteratorItemFunction:
+ * GstIteratorNextFunction:
  * @it: the iterator
- * @item: the item being retrieved.
+ * @result: a pointer to hold the next item
  *
- * The function that will be called after the next item of the iterator
- * has been retrieved. This function will typically increase the refcount
- * of the item or make a copy.
+ * The function that will be called when the next element of the iterator
+ * should be retrieved.
  *
  * Implementors of a #GstIterator should implement this
  * function and pass it to the constructor of the custom iterator.
@@ -98,7 +102,7 @@ typedef GstIteratorResult (*GstIteratorNextFunction) (GstIterator *it, gpointer
  *
  * Returns: the result of the operation.
  */
-typedef GstIteratorItem          (*GstIteratorItemFunction)    (GstIterator *it, gpointer item);
+typedef GstIteratorResult (*GstIteratorNextFunction)    (GstIterator *it, GValue *result);
 /**
  * GstIteratorResyncFunction:
  * @it: the iterator
@@ -112,7 +116,7 @@ typedef GstIteratorItem       (*GstIteratorItemFunction)    (GstIterator *it, gpointer
  * function and pass it to the constructor of the custom iterator.
  * The function will be called with the iterator lock held.
  */
-typedef void             (*GstIteratorResyncFunction)  (GstIterator *it);
+typedef void              (*GstIteratorResyncFunction)  (GstIterator *it);
 /**
  * GstIteratorFreeFunction:
  * @it: the iterator
@@ -123,7 +127,16 @@ typedef void                 (*GstIteratorResyncFunction)  (GstIterator *it);
  * function and pass it to the constructor of the custom iterator.
  * The function will be called with the iterator lock held.
  */
-typedef void             (*GstIteratorFreeFunction)    (GstIterator *it);
+typedef void              (*GstIteratorFreeFunction)    (GstIterator *it);
+
+/**
+ * GstIteratorForeachFunction:
+ * @item: The item
+ * @user_data: User data
+ *
+ * A function that is called by gst_iterator_foreach() for every element.
+ */
+typedef void         (*GstIteratorForeachFunction)     (const GValue * item, gpointer user_data);
 
 /**
  * GstIteratorFoldFunction:
@@ -135,20 +148,7 @@ typedef void                 (*GstIteratorFreeFunction)    (GstIterator *it);
  *
  * Returns: TRUE if the fold should continue, FALSE if it should stop.
  */
-typedef gboolean         (*GstIteratorFoldFunction)    (gpointer item, GValue *ret, gpointer user_data);
-
-/**
- * GstCopyFunction:
- * @object: The object to copy
- *
- * A function to create a copy of some object or
- * increase its reference count.
- *
- * Returns: a copy of the object or the same object with increased reference count
- *
- * Since: 0.10.25
- */
-typedef gpointer          (*GstCopyFunction)             (gpointer object);
+typedef gboolean          (*GstIteratorFoldFunction)    (const GValue * item, GValue * ret, gpointer user_data);
 
 /**
  * GST_ITERATOR:
@@ -156,14 +156,14 @@ typedef gpointer          (*GstCopyFunction)             (gpointer object);
  *
  * Macro to cast to a #GstIterator
  */
-#define GST_ITERATOR(it)               ((GstIterator*)(it))
+#define GST_ITERATOR(it)                ((GstIterator*)(it))
 /**
  * GST_ITERATOR_LOCK:
  * @it: the #GstIterator to get the lock of
  *
  * Macro to get the lock protecting the datastructure being iterated.
  */
-#define GST_ITERATOR_LOCK(it)          (GST_ITERATOR(it)->lock)
+#define GST_ITERATOR_LOCK(it)           (GST_ITERATOR(it)->lock)
 /**
  * GST_ITERATOR_COOKIE:
  * @it: the #GstIterator to get the cookie of
@@ -175,7 +175,7 @@ typedef gpointer          (*GstCopyFunction)             (gpointer object);
  * value of the master cookie. If they are different, a concurrent
  * modification happened to the iterator and a resync is needed.
  */
-#define GST_ITERATOR_COOKIE(it)                (GST_ITERATOR(it)->cookie)
+#define GST_ITERATOR_COOKIE(it)         (GST_ITERATOR(it)->cookie)
 /**
  * GST_ITERATOR_ORIG_COOKIE:
  * @it: the #GstIterator to get the master cookie of
@@ -184,10 +184,11 @@ typedef gpointer          (*GstCopyFunction)             (gpointer object);
  * master cookie protects the structure being iterated and gets updated
  * whenever the datastructure changes.
  */
-#define GST_ITERATOR_ORIG_COOKIE(it)   (GST_ITERATOR(it)->master_cookie)
+#define GST_ITERATOR_ORIG_COOKIE(it)    (GST_ITERATOR(it)->master_cookie)
 
 /**
  * GstIterator:
+ * @copy: The function to copy the iterator
  * @next: The function to get the next item in the iterator
  * @item: The function to be called for each item retrieved
  * @resync: The function to call when a resync is needed.
@@ -198,69 +199,74 @@ typedef gpointer          (*GstCopyFunction)             (gpointer object);
  * @cookie: The cookie; the value of the master_cookie when this iterator was
  *          created.
  * @master_cookie: A pointer to the master cookie.
+ * @size: the size of the iterator
  *
- * #GstIterator base structure. The values of this structure are 
+ * #GstIterator base structure. The values of this structure are
  * protected for subclasses, use the methods to use the #GstIterator.
  */
 struct _GstIterator {
   /*< protected >*/
+  GstIteratorCopyFunction copy;
   GstIteratorNextFunction next;
   GstIteratorItemFunction item;
   GstIteratorResyncFunction resync;
   GstIteratorFreeFunction free;
 
-  GstIterator *pushed;         /* pushed iterator */
+  GstIterator *pushed;          /* pushed iterator */
 
   GType     type;
   GMutex   *lock;
-  guint32   cookie;            /* cookie of the iterator */
-  guint32  *master_cookie;     /* pointer to guint32 holding the cookie when this
-                                  iterator was created */
+  guint32   cookie;             /* cookie of the iterator */
+  guint32  *master_cookie;      /* pointer to guint32 holding the cookie when this
+                                   iterator was created */
+  guint     size;
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 
+GType                   gst_iterator_get_type           (void);
+
 /* creating iterators */
-GstIterator*           gst_iterator_new                (guint size,
-                                                        GType type,
-                                                        GMutex *lock,
-                                                        guint32 *master_cookie,
-                                                        GstIteratorNextFunction next,
-                                                        GstIteratorItemFunction item,
-                                                        GstIteratorResyncFunction resync,
-                                                        GstIteratorFreeFunction free) G_GNUC_MALLOC;
+GstIterator*            gst_iterator_new                (guint size,
+                                                         GType type,
+                                                         GMutex *lock,
+                                                         guint32 *master_cookie,
+                                                         GstIteratorCopyFunction copy,
+                                                         GstIteratorNextFunction next,
+                                                         GstIteratorItemFunction item,
+                                                         GstIteratorResyncFunction resync,
+                                                         GstIteratorFreeFunction free) G_GNUC_MALLOC;
 
-GstIterator*           gst_iterator_new_list           (GType type,
-                                                        GMutex *lock,
-                                                        guint32 *master_cookie,
-                                                        GList **list,
-                                                        gpointer owner,
-                                                        GstIteratorItemFunction item,
-                                                        GstIteratorDisposeFunction free) G_GNUC_MALLOC;
+GstIterator*            gst_iterator_new_list           (GType type,
+                                                         GMutex *lock,
+                                                         guint32 *master_cookie,
+                                                         GList **list,
+                                                         GObject * owner,
+                                                         GstIteratorItemFunction item) G_GNUC_MALLOC;
 
 GstIterator*            gst_iterator_new_single         (GType type,
-                                                         gpointer object,
-                                                         GstCopyFunction copy,
-                                                         GFreeFunc free) G_GNUC_MALLOC;
+                                                         const GValue * object) G_GNUC_MALLOC;
+
+GstIterator*            gst_iterator_copy               (const GstIterator *it) G_GNUC_MALLOC;
 
 /* using iterators */
-GstIteratorResult      gst_iterator_next               (GstIterator *it, gpointer *elem);
-void                   gst_iterator_resync             (GstIterator *it);
-void                   gst_iterator_free               (GstIterator *it);
+GstIteratorResult       gst_iterator_next               (GstIterator *it, GValue * elem);
+void                    gst_iterator_resync             (GstIterator *it);
+void                    gst_iterator_free               (GstIterator *it);
 
-void                   gst_iterator_push               (GstIterator *it, GstIterator *other);
+void                    gst_iterator_push               (GstIterator *it, GstIterator *other);
 
 /* higher-order functions that operate on iterators */
-GstIterator*           gst_iterator_filter             (GstIterator *it, GCompareFunc func,
-                                                         gpointer user_data) G_GNUC_MALLOC;
-GstIteratorResult      gst_iterator_fold               (GstIterator *it,
+GstIterator*            gst_iterator_filter             (GstIterator *it, GCompareFunc func,
+                                                         const GValue * user_data) G_GNUC_MALLOC;
+GstIteratorResult       gst_iterator_fold               (GstIterator *it,
                                                          GstIteratorFoldFunction func,
                                                          GValue *ret, gpointer user_data);
-GstIteratorResult      gst_iterator_foreach            (GstIterator *it,
-                                                         GFunc func, gpointer user_data);
-gpointer               gst_iterator_find_custom        (GstIterator *it, GCompareFunc func,
-                                                         gpointer user_data);
+GstIteratorResult       gst_iterator_foreach            (GstIterator *it,
+                                                         GstIteratorForeachFunction func, gpointer user_data);
+gboolean                gst_iterator_find_custom        (GstIterator *it, GCompareFunc func,
+                                                         GValue *elem, gpointer user_data);
 
 G_END_DECLS
 
index 7d34089..3889568 100644 (file)
@@ -4,7 +4,6 @@ VOID:INT
 VOID:STRING
 VOID:BOXED
 VOID:BOXED,OBJECT
-VOID:POINTER
 VOID:POINTER,OBJECT
 VOID:OBJECT
 VOID:OBJECT,OBJECT
@@ -20,5 +19,6 @@ VOID:UINT,BOXED
 VOID:UINT,POINTER
 BOOLEAN:VOID
 BOOLEAN:POINTER
+BOOLEAN:BOXED
 POINTER:POINTER
 BOXED:BOXED
diff --git a/gst/gstmemory.c b/gst/gstmemory.c
new file mode 100644 (file)
index 0000000..5172e97
--- /dev/null
@@ -0,0 +1,776 @@
+/* GStreamer
+ * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.be>
+ *
+ * gstmemory.c: memory block handling
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstmemory
+ * @short_description: refcounted wrapper for memory blocks
+ * @see_also: #GstBuffer
+ *
+ * GstMemory is a lightweight refcounted object that wraps a region of memory.
+ * They are typically used to manage the data of a #GstBuffer.
+ *
+ * A GstMemory object has an allocated region of memory of maxsize. The maximum
+ * size does not change during the lifetime of the memory object. The memory
+ * also has an offset and size property that specifies the valid range of memory
+ * in the allocated region.
+ *
+ * Memory is usually created by allocators with a gst_allocator_alloc()
+ * method call. When NULL is used as the allocator, the default allocator will
+ * be used.
+ *
+ * New allocators can be registered with gst_allocator_register().
+ * Allocators are identified by name and can be retrieved with
+ * gst_allocator_find().
+ *
+ * New memory can be created with gst_memory_new_wrapped() that wraps the memory
+ * allocated elsewhere.
+ *
+ * Refcounting of the memory block is performed with gst_memory_ref() and
+ * gst_memory_unref().
+ *
+ * The size of the memory can be retrieved and changed with
+ * gst_memory_get_sizes() and gst_memory_resize() respectively.
+ *
+ * Getting access to the data of the memory is performed with gst_memory_map().
+ * The call will return a pointer to offset bytes into the region of memory.
+ * After the memory access is completed, gst_memory_unmap() should be called.
+ *
+ * Memory can be copied with gst_memory_copy(), which will returnn a writable
+ * copy. gst_memory_share() will create a new memory block that shares the
+ * memory with an existing memory block at a custom offset and with a custom
+ * size.
+ *
+ * Memory can be efficiently merged when gst_memory_is_span() returns TRUE.
+ *
+ * Last reviewed on 2011-06-08 (0.11.0)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst_private.h"
+#include "gstmemory.h"
+
+G_DEFINE_BOXED_TYPE (GstMemory, gst_memory, (GBoxedCopyFunc) gst_memory_ref,
+    (GBoxedFreeFunc) gst_memory_unref);
+
+/**
+ * gst_memory_alignment:
+ *
+ * The default memory alignment in bytes - 1
+ * an alignment of 7 would be the same as what malloc() guarantees.
+ */
+#if defined(MEMORY_ALIGNMENT_MALLOC)
+size_t gst_memory_alignment = 7;
+#elif defined(MEMORY_ALIGNMENT_PAGESIZE)
+/* we fill this in in the _init method */
+size_t gst_memory_alignment = 0;
+#elif defined(MEMORY_ALIGNMENT)
+size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
+#else
+#error "No memory alignment configured"
+size_t gst_memory_alignment = 0;
+#endif
+
+struct _GstAllocator
+{
+  GQuark name;
+
+  GstMemoryInfo info;
+};
+
+/* default memory implementation */
+typedef struct
+{
+  GstMemory mem;
+  gsize slice_size;
+  guint8 *data;
+  GFreeFunc free_func;
+} GstMemoryDefault;
+
+/* the default allocator */
+static const GstAllocator *_default_allocator;
+
+/* our predefined allocators */
+static const GstAllocator *_default_mem_impl;
+
+/* initialize the fields */
+static void
+_default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
+    GstMemory * parent, gsize slice_size, gpointer data,
+    GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
+{
+  mem->mem.allocator = _default_mem_impl;
+  mem->mem.flags = flags;
+  mem->mem.refcount = 1;
+  mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
+  mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? 0x5 : 0);
+  mem->mem.maxsize = maxsize;
+  mem->mem.offset = offset;
+  mem->mem.size = size;
+  mem->slice_size = slice_size;
+  mem->data = data;
+  mem->free_func = free_func;
+}
+
+/* create a new memory block that manages the given memory */
+static GstMemoryDefault *
+_default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
+    GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
+{
+  GstMemoryDefault *mem;
+  gsize slice_size;
+
+  slice_size = sizeof (GstMemoryDefault);
+
+  mem = g_slice_alloc (slice_size);
+  _default_mem_init (mem, flags, parent, slice_size,
+      data, free_func, maxsize, offset, size);
+
+  return mem;
+}
+
+/* allocate the memory and structure in one block */
+static GstMemoryDefault *
+_default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
+{
+  GstMemoryDefault *mem;
+  gsize aoffset, slice_size;
+  guint8 *data;
+
+  /* ensure configured alignment */
+  align |= gst_memory_alignment;
+  /* allocate more to compensate for alignment */
+  maxsize += align;
+  /* alloc header and data in one block */
+  slice_size = sizeof (GstMemoryDefault) + maxsize;
+
+  mem = g_slice_alloc (slice_size);
+  if (mem == NULL)
+    return NULL;
+
+  data = (guint8 *) mem + sizeof (GstMemoryDefault);
+
+  if ((aoffset = ((guintptr) data & align)))
+    aoffset = (align + 1) - aoffset;
+
+  _default_mem_init (mem, 0, NULL, slice_size, data, NULL, maxsize,
+      aoffset + offset, size);
+
+  return mem;
+}
+
+static GstMemory *
+_default_mem_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
+{
+  return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
+}
+
+static gpointer
+_default_mem_map (GstMemoryDefault * mem, GstMapFlags flags)
+{
+  return mem->data;
+}
+
+static gboolean
+_default_mem_unmap (GstMemoryDefault * mem)
+{
+  return TRUE;
+}
+
+static void
+_default_mem_free (GstMemoryDefault * mem)
+{
+  if (mem->mem.parent)
+    gst_memory_unref (mem->mem.parent);
+
+  if (mem->free_func)
+    mem->free_func (mem->data);
+
+  g_slice_free1 (mem->slice_size, mem);
+}
+
+static GstMemoryDefault *
+_default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
+{
+  GstMemoryDefault *copy;
+
+  if (size == -1)
+    size = mem->mem.size > offset ? mem->mem.size - offset : 0;
+
+  copy =
+      _default_mem_new_block (mem->mem.maxsize, 0, mem->mem.offset + offset,
+      size);
+  memcpy (copy->data, mem->data, mem->mem.maxsize);
+
+  return copy;
+}
+
+static GstMemoryDefault *
+_default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
+{
+  GstMemoryDefault *sub;
+  GstMemory *parent;
+
+  /* find the real parent */
+  if ((parent = mem->mem.parent) == NULL)
+    parent = (GstMemory *) mem;
+
+  if (size == -1)
+    size = mem->mem.size - offset;
+
+  sub =
+      _default_mem_new (parent->flags, parent, mem->data, NULL,
+      mem->mem.maxsize, mem->mem.offset + offset, size);
+
+  return sub;
+}
+
+static gboolean
+_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
+    gsize * offset)
+{
+
+  if (offset) {
+    GstMemoryDefault *parent;
+
+    parent = (GstMemoryDefault *) mem1->mem.parent;
+
+    *offset = mem1->mem.offset - parent->mem.offset;
+  }
+
+  /* and memory is contiguous */
+  return mem1->data + mem1->mem.offset + mem1->mem.size ==
+      mem2->data + mem2->mem.offset;
+}
+
+static GstMemory *
+_fallback_copy (GstMemory * mem, gssize offset, gssize size)
+{
+  GstMemory *copy;
+  guint8 *data, *dest;
+  gsize msize;
+
+  data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
+  if (data == NULL)
+    return NULL;
+  if (size == -1)
+    size = msize > offset ? msize - offset : 0;
+  /* use the same allocator as the memory we copy  */
+  copy = gst_allocator_alloc (mem->allocator, size, mem->align);
+  dest = gst_memory_map (copy, NULL, NULL, GST_MAP_WRITE);
+  memcpy (dest, data + offset, size);
+  gst_memory_unmap (copy);
+  gst_memory_unmap (mem);
+
+  return (GstMemory *) copy;
+}
+
+static gboolean
+_fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
+{
+  return FALSE;
+}
+
+static GRWLock lock;
+static GHashTable *allocators;
+
+void
+_priv_gst_memory_initialize (void)
+{
+  static const GstMemoryInfo _mem_info = {
+    (GstMemoryAllocFunction) _default_mem_alloc,
+    (GstMemoryMapFunction) _default_mem_map,
+    (GstMemoryUnmapFunction) _default_mem_unmap,
+    (GstMemoryFreeFunction) _default_mem_free,
+    (GstMemoryCopyFunction) _default_mem_copy,
+    (GstMemoryShareFunction) _default_mem_share,
+    (GstMemoryIsSpanFunction) _default_mem_is_span,
+    NULL
+  };
+
+  g_rw_lock_init (&lock);
+  allocators = g_hash_table_new (g_str_hash, g_str_equal);
+
+#ifdef HAVE_GETPAGESIZE
+#ifdef MEMORY_ALIGNMENT_PAGESIZE
+  gst_memory_alignment = getpagesize () - 1;
+#endif
+#endif
+
+  GST_DEBUG ("memory alignment: %" G_GSIZE_FORMAT, gst_memory_alignment);
+
+  _default_mem_impl = gst_allocator_register (GST_ALLOCATOR_SYSMEM, &_mem_info);
+
+  _default_allocator = _default_mem_impl;
+}
+
+/**
+ * gst_memory_new_wrapped:
+ * @flags: #GstMemoryFlags
+ * @data: data to wrap
+ * @free_func: function to free @data
+ * @maxsize: allocated size of @data
+ * @offset: offset in @data
+ * @size: size of valid data
+ *
+ * Allocate a new memory block that wraps the given @data.
+ *
+ * Returns: a new #GstMemory.
+ */
+GstMemory *
+gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
+    GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
+{
+  GstMemoryDefault *mem;
+
+  g_return_val_if_fail (data != NULL, NULL);
+  g_return_val_if_fail (offset + size <= maxsize, NULL);
+
+  mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
+
+  return (GstMemory *) mem;
+}
+
+/**
+ * gst_memory_ref:
+ * @mem: a #GstMemory
+ *
+ * Increases the refcount of @mem.
+ *
+ * Returns: @mem with increased refcount
+ */
+GstMemory *
+gst_memory_ref (GstMemory * mem)
+{
+  g_return_val_if_fail (mem != NULL, NULL);
+
+  g_atomic_int_inc (&mem->refcount);
+
+  return mem;
+}
+
+/**
+ * gst_memory_unref:
+ * @mem: a #GstMemory
+ *
+ * Decreases the refcount of @mem. When the refcount reaches 0, the free
+ * function of @mem will be called.
+ */
+void
+gst_memory_unref (GstMemory * mem)
+{
+  g_return_if_fail (mem != NULL);
+  g_return_if_fail (mem->allocator != NULL);
+
+  if (g_atomic_int_dec_and_test (&mem->refcount))
+    mem->allocator->info.free (mem);
+}
+
+/**
+ * gst_memory_get_sizes:
+ * @mem: a #GstMemory
+ * @offset: pointer to offset
+ * @maxsize: pointer to maxsize
+ *
+ * Get the current @size, @offset and @maxsize of @mem.
+ *
+ * Returns: the current sizes of @mem
+ */
+gsize
+gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
+{
+  g_return_val_if_fail (mem != NULL, 0);
+
+  if (offset)
+    *offset = mem->offset;
+  if (maxsize)
+    *maxsize = mem->maxsize;
+
+  return mem->size;
+}
+
+/**
+ * gst_memory_resize:
+ * @mem: a #GstMemory
+ * @offset: a new offset
+ * @size: a new size
+ *
+ * Resize the memory region. @mem should be writable and offset + size should be
+ * less than the maxsize of @mem.
+ */
+void
+gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
+{
+  g_return_if_fail (mem != NULL);
+  g_return_if_fail (gst_memory_is_writable (mem));
+  g_return_if_fail (offset >= 0 || mem->offset >= -offset);
+  g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
+
+  mem->offset += offset;
+  mem->size = size;
+}
+
+/**
+ * gst_memory_is_writable:
+ * @mem: a #GstMemory
+ *
+ * Check if @mem is writable.
+ *
+ * Returns: %TRUE is @mem is writable.
+ */
+gboolean
+gst_memory_is_writable (GstMemory * mem)
+{
+  g_return_val_if_fail (mem != NULL, FALSE);
+
+  return (mem->refcount == 1) &&
+      ((mem->parent == NULL) || (mem->parent->refcount == 1)) &&
+      ((mem->flags & GST_MEMORY_FLAG_READONLY) == 0);
+}
+
+static gboolean
+gst_memory_lock (GstMemory * mem, GstMapFlags flags)
+{
+  gint access_mode, state, newstate;
+
+  access_mode = flags & 3;
+
+  do {
+    state = g_atomic_int_get (&mem->state);
+    if (state == 0) {
+      /* nothing mapped, set access_mode and refcount */
+      newstate = 4 | access_mode;
+    } else {
+      /* access_mode must match */
+      if ((state & access_mode) != access_mode)
+        goto lock_failed;
+      /* increase refcount */
+      newstate = state + 4;
+    }
+  } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+
+  return TRUE;
+
+lock_failed:
+  {
+    GST_DEBUG ("lock failed %p: state %d, access_mode %d", mem, state,
+        access_mode);
+    return FALSE;
+  }
+}
+
+static void
+gst_memory_unlock (GstMemory * mem)
+{
+  gint state, newstate;
+
+  do {
+    state = g_atomic_int_get (&mem->state);
+    /* decrease the refcount */
+    newstate = state - 4;
+    /* last refcount, unset access_mode */
+    if (newstate < 4)
+      newstate = 0;
+  } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+}
+
+/**
+ * gst_memory_map:
+ * @mem: a #GstMemory
+ * @size: (out) (allow-none): pointer for size
+ * @maxsize: (out) (allow-none): pointer for maxsize
+ * @flags: mapping flags
+ *
+ * Get a pointer to the memory of @mem that can be accessed according to @flags.
+ *
+ * @size and @maxsize will contain the size of the memory and the maximum
+ * allocated memory of @mem respectively. They can be set to NULL.
+ *
+ * This function can return NULL for various reasons:
+ * - the memory backed by @mem is not accessible with the given @flags.
+ * - the memory was already mapped with a different mapping.
+ *
+ * @pointer remains valid for as long as @mem is alive and until
+ * gst_memory_unmap() is called.
+ *
+ * For each gst_memory_map() call, a corresponding gst_memory_unmap() call
+ * should be done.
+ *
+ * Returns: (transfer none): a pointer to the memory of @mem.
+ */
+gpointer
+gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
+    GstMapFlags flags)
+{
+  guint8 *res;
+
+  g_return_val_if_fail (mem != NULL, NULL);
+
+  if (!gst_memory_lock (mem, flags))
+    goto lock_failed;
+
+  res = mem->allocator->info.map (mem, mem->maxsize, flags);
+
+  if (G_UNLIKELY (res == NULL))
+    goto error;
+
+  if (size)
+    *size = mem->size;
+  if (maxsize)
+    *maxsize = mem->maxsize - mem->offset;
+
+  return res + mem->offset;
+
+  /* ERRORS */
+lock_failed:
+  {
+    g_critical ("memory %p: failed to lock memory", mem);
+    return NULL;
+  }
+error:
+  {
+    /* something went wrong, restore the orginal state again */
+    GST_ERROR ("mem %p: map failed", mem);
+    gst_memory_unlock (mem);
+    return NULL;
+  }
+}
+
+/**
+ * gst_memory_unmap:
+ * @mem: a #GstMemory
+ *
+ * Release the memory obtained with gst_memory_map()
+ */
+void
+gst_memory_unmap (GstMemory * mem)
+{
+  g_return_if_fail (mem != NULL);
+  /* there must be a ref */
+  g_return_if_fail (g_atomic_int_get (&mem->state) >= 4);
+
+  mem->allocator->info.unmap (mem);
+  gst_memory_unlock (mem);
+}
+
+/**
+ * gst_memory_copy:
+ * @mem: a #GstMemory
+ * @offset: an offset to copy
+ * @size: size to copy or -1 to copy all bytes from offset
+ *
+ * Return a copy of @size bytes from @mem starting from @offset. This copy is
+ * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
+ * from @offset.
+ *
+ * Returns: a new #GstMemory.
+ */
+GstMemory *
+gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
+{
+  GstMemory *copy;
+
+  g_return_val_if_fail (mem != NULL, NULL);
+  g_return_val_if_fail (gst_memory_lock (mem, GST_MAP_READ), NULL);
+
+  copy = mem->allocator->info.copy (mem, offset, size);
+
+  gst_memory_unlock (mem);
+
+  return copy;
+}
+
+/**
+ * gst_memory_share:
+ * @mem: a #GstMemory
+ * @offset: an offset to share
+ * @size: size to share or -1 to share bytes from offset
+ *
+ * Return a shared copy of @size bytes from @mem starting from @offset. No
+ * memory copy is performed and the memory region is simply shared. The result
+ * is guaranteed to be not-writable. @size can be set to -1 to return a share
+ * all bytes from @offset.
+ *
+ * Returns: a new #GstMemory.
+ */
+GstMemory *
+gst_memory_share (GstMemory * mem, gssize offset, gssize size)
+{
+  g_return_val_if_fail (mem != NULL, NULL);
+
+  return mem->allocator->info.share (mem, offset, size);
+}
+
+/**
+ * gst_memory_is_span:
+ * @mem1: a #GstMemory
+ * @mem2: a #GstMemory
+ * @offset: a pointer to a result offset
+ *
+ * Check if @mem1 and mem2 share the memory with a common parent memory object
+ * and that the memory is contiguous.
+ *
+ * If this is the case, the memory of @mem1 and @mem2 can be merged
+ * efficiently by performing gst_memory_share() on the parent object from
+ * the returned @offset.
+ *
+ * Returns: %TRUE if the memory is contiguous and of a common parent.
+ */
+gboolean
+gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
+{
+  g_return_val_if_fail (mem1 != NULL, FALSE);
+  g_return_val_if_fail (mem2 != NULL, FALSE);
+
+  /* need to have the same allocators */
+  if (mem1->allocator != mem2->allocator)
+    return FALSE;
+
+  /* need to have the same parent */
+  if (mem1->parent == NULL || mem1->parent != mem2->parent)
+    return FALSE;
+
+  /* and memory is contiguous */
+  if (!mem1->allocator->info.is_span (mem1, mem2, offset))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * gst_allocator_register:
+ * @name: the name of the allocator
+ * @info: #GstMemoryInfo
+ *
+ * Registers the memory allocator with @name and implementation functions
+ * @info.
+ *
+ * All functions in @info are mandatory exept the copy and is_span
+ * functions, which will have a default implementation when left NULL.
+ *
+ * The user_data field in @info will be passed to all calls of the alloc
+ * function.
+ *
+ * Returns: a new #GstAllocator.
+ */
+const GstAllocator *
+gst_allocator_register (const gchar * name, const GstMemoryInfo * info)
+{
+  GstAllocator *allocator;
+
+#define INSTALL_FALLBACK(_t) \
+  if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (info != NULL, NULL);
+  g_return_val_if_fail (info->alloc != NULL, NULL);
+  g_return_val_if_fail (info->map != NULL, NULL);
+  g_return_val_if_fail (info->unmap != NULL, NULL);
+  g_return_val_if_fail (info->free != NULL, NULL);
+  g_return_val_if_fail (info->share != NULL, NULL);
+
+  allocator = g_slice_new (GstAllocator);
+  allocator->name = g_quark_from_string (name);
+  allocator->info = *info;
+  INSTALL_FALLBACK (copy);
+  INSTALL_FALLBACK (is_span);
+#undef INSTALL_FALLBACK
+
+  GST_DEBUG ("registering allocator \"%s\"", name);
+
+  g_rw_lock_writer_lock (&lock);
+  g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
+  g_rw_lock_writer_unlock (&lock);
+
+  return allocator;
+}
+
+/**
+ * gst_allocator_find:
+ * @name: the name of the allocator
+ *
+ * Find a previously registered allocator with @name. When @name is NULL, the
+ * default allocator will be returned.
+ *
+ * Returns: a #GstAllocator or NULL when the allocator with @name was not
+ * registered.
+ */
+const GstAllocator *
+gst_allocator_find (const gchar * name)
+{
+  const GstAllocator *allocator;
+
+  g_rw_lock_reader_lock (&lock);
+  if (name) {
+    allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
+  } else {
+    allocator = _default_allocator;
+  }
+  g_rw_lock_reader_unlock (&lock);
+
+  return allocator;
+}
+
+/**
+ * gst_allocator_set_default:
+ * @allocator: a #GstAllocator
+ *
+ * Set the default allocator.
+ */
+void
+gst_allocator_set_default (const GstAllocator * allocator)
+{
+  g_return_if_fail (allocator != NULL);
+
+  g_rw_lock_writer_lock (&lock);
+  _default_allocator = allocator;
+  g_rw_lock_writer_unlock (&lock);
+}
+
+/**
+ * gst_allocator_alloc:
+ * @allocator: (transfer none) (allow-none): a #GstAllocator to use
+ * @maxsize: allocated size of @data
+ * @align: alignment for the data
+ *
+ * Use @allocator to allocate a new memory block with memory that is at least
+ * @maxsize big and has the given alignment.
+ *
+ * When @allocator is NULL, the default allocator will be used.
+ *
+ * @align is given as a bitmask so that @align + 1 equals the amount of bytes to
+ * align to. For example, to align to 8 bytes, use an alignment of 7.
+ *
+ * Returns: (transfer full): a new #GstMemory.
+ */
+GstMemory *
+gst_allocator_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
+{
+  g_return_val_if_fail (((align + 1) & align) == 0, NULL);
+
+  if (allocator == NULL)
+    allocator = _default_allocator;
+
+  return allocator->info.alloc (allocator, maxsize, align,
+      allocator->info.user_data);
+}
diff --git a/gst/gstmemory.h b/gst/gstmemory.h
new file mode 100644 (file)
index 0000000..4e000fe
--- /dev/null
@@ -0,0 +1,276 @@
+/* GStreamer
+ * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.be>
+ *
+ * gstmemory.h: Header for memory blocks
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_MEMORY_H__
+#define __GST_MEMORY_H__
+
+#include <gst/gstconfig.h>
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_MEMORY (gst_memory_get_type())
+GType gst_memory_get_type(void);
+
+typedef struct _GstMemory GstMemory;
+typedef struct _GstMemoryInfo GstMemoryInfo;
+typedef struct _GstAllocator GstAllocator;
+
+GST_EXPORT gsize gst_memory_alignment;
+
+/**
+ * GstMemoryFlags:
+ * @GST_MEMORY_FLAG_READONLY: memory is readonly. It is not allowed to map the
+ * memory with #GST_MAP_WRITE.
+ * @GST_MEMORY_FLAG_NO_SHARE: memory must not be shared. Copies will have to be
+ * made when this memory needs to be shared between buffers.
+ * @GST_MEMORY_FLAG_LAST: first flag that can be used for custom purposes
+ *
+ * Flags for wrapped memory.
+ */
+typedef enum {
+  GST_MEMORY_FLAG_READONLY = (1 << 0),
+  GST_MEMORY_FLAG_NO_SHARE = (1 << 1),
+
+  GST_MEMORY_FLAG_LAST     = (1 << 16)
+} GstMemoryFlags;
+
+/**
+ * GstMemory:
+ * @allocator: pointer to the #GstAllocator
+ * @flags: memory flags
+ * @refcount: refcount
+ * @parent: parent memory block
+ * @state: private state
+ * @maxsize: the maximum size allocated
+ * @align: the alignment of the memory
+ * @offset: the offset where valid data starts
+ * @size: the size of valid data
+ *
+ * Base structure for memory implementations. Custom memory will put this structure
+ * as the first member of their structure.
+ */
+struct _GstMemory {
+  const GstAllocator *allocator;
+
+  GstMemoryFlags  flags;
+  gint            refcount;
+  GstMemory      *parent;
+  volatile gint   state;
+  gsize           maxsize;
+  gsize           align;
+  gsize           offset;
+  gsize           size;
+};
+
+/**
+ * GstMapFlags:
+ * @GST_MAP_READ: map for read access
+ * @GST_MAP_WRITE: map for write access
+ * @GST_MAP_FLAG_LAST: first flag that can be used for custom purposes
+ *
+ * Flags used when mapping memory
+ */
+typedef enum {
+  GST_MAP_READ      = (1 << 0),
+  GST_MAP_WRITE     = (1 << 1),
+
+  GST_MAP_FLAG_LAST = (1 << 16)
+} GstMapFlags;
+
+/**
+ * GST_MAP_READWRITE:
+ *
+ * Map for readwrite access
+ */
+#define GST_MAP_READWRITE      (GST_MAP_READ | GST_MAP_WRITE)
+
+/**
+ * GST_ALLOCATOR_SYSMEM:
+ *
+ * The allocator name for the default system memory allocator
+ */
+#define GST_ALLOCATOR_SYSMEM   "SystemMemory"
+
+/**
+ * GstMemoryAllocFunction:
+ * @allocator: a #GstAllocator
+ * @maxsize: the maxsize
+ * @align: the alignment
+ * @user_data: user data
+ *
+ * Allocate a new #GstMemory from @allocator that can hold at least @maxsize bytes
+ * and is aligned to (@align + 1) bytes.
+ *
+ * @user_data is the data that was used when registering @allocator.
+ *
+ * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
+ */
+typedef GstMemory *  (*GstMemoryAllocFunction)  (const GstAllocator *allocator,
+                                                 gsize maxsize, gsize align,
+                                                 gpointer user_data);
+
+/**
+ * GstMemoryMapFunction:
+ * @mem: a #GstMemory
+ * @maxsize: size to map
+ * @flags: access mode for the memory
+ *
+ * Get the memory of @mem that can be accessed according to the mode specified
+ * in @flags. The function should return a pointer that contains at least
+ * @maxsize bytes.
+ *
+ * Returns: a pointer to memory of which at least @maxsize bytes can be
+ * accessed according to the access pattern in @flags.
+ */
+typedef gpointer    (*GstMemoryMapFunction)       (GstMemory *mem, gsize maxsize, GstMapFlags flags);
+
+/**
+ * GstMemoryUnmapFunction:
+ * @mem: a #GstMemory
+ *
+ * Return the pointer previously retrieved with gst_memory_map().
+ *
+ * Returns: %TRUE on success.
+ */
+typedef void        (*GstMemoryUnmapFunction)     (GstMemory *mem);
+
+/**
+ * GstMemoryFreeFunction:
+ * @mem: a #GstMemory
+ *
+ * Free the memory used by @mem. This function is usually called when the
+ * refcount of the @mem has reached 0.
+ */
+typedef void        (*GstMemoryFreeFunction)      (GstMemory *mem);
+
+/**
+ * GstMemoryCopyFunction:
+ * @mem: a #GstMemory
+ * @offset: an offset
+ * @size: a size or -1
+ *
+ * Copy @size bytes from @mem starting at @offset and return them wrapped in a
+ * new GstMemory object.
+ * If @size is set to -1, all bytes starting at @offset are copied.
+ *
+ * Returns: a new #GstMemory object wrapping a copy of the requested region in
+ * @mem.
+ */
+typedef GstMemory * (*GstMemoryCopyFunction)      (GstMemory *mem, gssize offset, gssize size);
+
+/**
+ * GstMemoryShareFunction:
+ * @mem: a #GstMemory
+ * @offset: an offset
+ * @size: a size or -1
+ *
+ * Share @size bytes from @mem starting at @offset and return them wrapped in a
+ * new GstMemory object. If @size is set to -1, all bytes starting at @offset are
+ * shared. This function does not make a copy of the bytes in @mem.
+ *
+ * Returns: a new #GstMemory object sharing the requested region in @mem.
+ */
+typedef GstMemory * (*GstMemoryShareFunction)     (GstMemory *mem, gssize offset, gssize size);
+
+/**
+ * GstMemoryIsSpanFunction:
+ * @mem1: a #GstMemory
+ * @mem2: a #GstMemory
+ * @offset: a result offset
+ *
+ * Check if @mem1 and @mem2 occupy contiguous memory and return the offset of
+ * @mem1 in the parent buffer in @offset.
+ *
+ * Returns: %TRUE if @mem1 and @mem2 are in contiguous memory.
+ */
+typedef gboolean    (*GstMemoryIsSpanFunction)    (GstMemory *mem1, GstMemory *mem2, gsize *offset);
+
+/**
+ * GstMemoryInfo:
+ * @alloc: the implementation of the GstMemoryAllocFunction
+ * @map: the implementation of the GstMemoryMapFunction
+ * @unmap: the implementation of the GstMemoryUnmapFunction
+ * @free: the implementation of the GstMemoryFreeFunction
+ * @copy: the implementation of the GstMemoryCopyFunction
+ * @share: the implementation of the GstMemoryShareFunction
+ * @is_span: the implementation of the GstMemoryIsSpanFunction
+ * @user_data: generic user data for the allocator
+ *
+ * The #GstMemoryInfo is used to register new memory allocators and contain
+ * the implementations for various memory operations.
+ */
+struct _GstMemoryInfo {
+  GstMemoryAllocFunction    alloc;
+  GstMemoryMapFunction      map;
+  GstMemoryUnmapFunction    unmap;
+  GstMemoryFreeFunction     free;
+
+  GstMemoryCopyFunction     copy;
+  GstMemoryShareFunction    share;
+  GstMemoryIsSpanFunction   is_span;
+
+  gpointer user_data;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/* allocators */
+const GstAllocator *  gst_allocator_register    (const gchar *name, const GstMemoryInfo *info);
+const GstAllocator *  gst_allocator_find        (const gchar *name);
+
+void                  gst_allocator_set_default (const GstAllocator * allocator);
+
+/* allocating memory blocks */
+GstMemory * gst_allocator_alloc        (const GstAllocator * allocator,
+                                        gsize maxsize, gsize align);
+
+GstMemory * gst_memory_new_wrapped     (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
+                                        gsize maxsize, gsize offset, gsize size);
+
+/* refcounting */
+GstMemory * gst_memory_ref         (GstMemory *mem);
+void        gst_memory_unref       (GstMemory *mem);
+
+/* getting/setting memory properties */
+gsize       gst_memory_get_sizes   (GstMemory *mem, gsize *offset, gsize *maxsize);
+void        gst_memory_resize      (GstMemory *mem, gssize offset, gsize size);
+
+/* retrieving data */
+gboolean    gst_memory_is_writable (GstMemory *mem);
+
+gpointer    gst_memory_map         (GstMemory *mem, gsize *size, gsize *maxsize,
+                                    GstMapFlags flags);
+void        gst_memory_unmap       (GstMemory *mem);
+
+/* copy and subregions */
+GstMemory * gst_memory_copy        (GstMemory *mem, gssize offset, gssize size);
+GstMemory * gst_memory_share       (GstMemory *mem, gssize offset, gssize size);
+
+/* span memory */
+gboolean    gst_memory_is_span     (GstMemory *mem1, GstMemory *mem2, gsize *offset);
+
+G_END_DECLS
+
+#endif /* __GST_MEMORY_H__ */
index 423ebc2..9c28a3a 100644 (file)
 #include "gstquark.h"
 
 
-#define GST_MESSAGE_SEQNUM(e) ((GstMessage*)e)->abidata.ABI.seqnum
-
-static void gst_message_finalize (GstMessage * message);
-static GstMessage *_gst_message_copy (GstMessage * message);
-
-static GstMiniObjectClass *parent_class = NULL;
-
-void
-_gst_message_initialize (void)
+typedef struct
 {
-  GST_CAT_INFO (GST_CAT_GST_INIT, "init messages");
+  GstMessage message;
 
-  /* the GstMiniObject types need to be class_ref'd once before it can be
-   * done from multiple threads;
-   * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
-  g_type_class_ref (gst_message_get_type ());
-}
+  GstStructure *structure;
+} GstMessageImpl;
+
+#define GST_MESSAGE_STRUCTURE(m) (((GstMessageImpl *)(m))->structure)
 
 typedef struct
 {
@@ -116,6 +107,29 @@ static GstMessageQuarks message_quarks[] = {
   {0, NULL, 0}
 };
 
+static GType _gst_message_type = 0;
+GST_DEFINE_MINI_OBJECT_TYPE (GstMessage, gst_message);
+
+void
+_priv_gst_message_initialize (void)
+{
+  gint i;
+
+  GST_CAT_INFO (GST_CAT_GST_INIT, "init messages");
+
+  /* the GstMiniObject types need to be class_ref'd once before it can be
+   * done from multiple threads;
+   * see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
+  gst_message_get_type ();
+
+  for (i = 0; message_quarks[i].name; i++) {
+    message_quarks[i].quark =
+        g_quark_from_static_string (message_quarks[i].name);
+  }
+
+  _gst_message_type = gst_message_get_type ();
+}
+
 /**
  * gst_message_type_get_name:
  * @type: the message type
@@ -156,39 +170,11 @@ gst_message_type_to_quark (GstMessageType type)
   return 0;
 }
 
-#define _do_init \
-{ \
-  gint i; \
-  \
-  for (i = 0; message_quarks[i].name; i++) { \
-    message_quarks[i].quark = \
-        g_quark_from_static_string (message_quarks[i].name); \
-  } \
-}
-
-G_DEFINE_TYPE_WITH_CODE (GstMessage, gst_message, GST_TYPE_MINI_OBJECT,
-    _do_init);
-
 static void
-gst_message_class_init (GstMessageClass * klass)
+_gst_message_free (GstMessage * message)
 {
-  parent_class = g_type_class_peek_parent (klass);
-
-  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_message_copy;
-  klass->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_message_finalize;
-}
-
-static void
-gst_message_init (GstMessage * message)
-{
-  GST_CAT_LOG (GST_CAT_MESSAGE, "new message %p", message);
-  GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
-}
+  GstStructure *structure;
 
-static void
-gst_message_finalize (GstMessage * message)
-{
   g_return_if_fail (message != NULL);
 
   GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p, %s from %s", message,
@@ -199,51 +185,56 @@ gst_message_finalize (GstMessage * message)
     GST_MESSAGE_SRC (message) = NULL;
   }
 
-  if (message->lock) {
+  if (message->lock.p) {
     GST_MESSAGE_LOCK (message);
     GST_MESSAGE_SIGNAL (message);
     GST_MESSAGE_UNLOCK (message);
   }
 
-  if (message->structure) {
-    gst_structure_set_parent_refcount (message->structure, NULL);
-    gst_structure_free (message->structure);
+  structure = GST_MESSAGE_STRUCTURE (message);
+  if (structure) {
+    gst_structure_set_parent_refcount (structure, NULL);
+    gst_structure_free (structure);
   }
 
-/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (message)); */
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (message), message);
 }
 
 static GstMessage *
 _gst_message_copy (GstMessage * message)
 {
-  GstMessage *copy;
+  GstMessageImpl *copy;
+  GstStructure *structure;
 
   GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p, %s from %s", message,
       GST_MESSAGE_TYPE_NAME (message),
       GST_OBJECT_NAME (GST_MESSAGE_SRC (message)));
 
-  copy = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);
+  copy = g_slice_new0 (GstMessageImpl);
+
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (copy),
+      _gst_message_type, sizeof (GstMessageImpl));
 
-  /* FIXME, need to copy relevant data from the miniobject. */
-  //memcpy (copy, message, sizeof (GstMessage));
+  copy->message.mini_object.copy =
+      (GstMiniObjectCopyFunction) _gst_message_copy;
+  copy->message.mini_object.free =
+      (GstMiniObjectFreeFunction) _gst_message_free;
 
-  GST_MESSAGE_GET_LOCK (copy) = GST_MESSAGE_GET_LOCK (message);
-  GST_MESSAGE_COND (copy) = GST_MESSAGE_COND (message);
   GST_MESSAGE_TYPE (copy) = GST_MESSAGE_TYPE (message);
   GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
   GST_MESSAGE_SEQNUM (copy) = GST_MESSAGE_SEQNUM (message);
-
   if (GST_MESSAGE_SRC (message)) {
     GST_MESSAGE_SRC (copy) = gst_object_ref (GST_MESSAGE_SRC (message));
   }
 
-  if (message->structure) {
-    copy->structure = gst_structure_copy (message->structure);
+  structure = GST_MESSAGE_STRUCTURE (message);
+  if (structure) {
+    copy->structure = gst_structure_copy (structure);
     gst_structure_set_parent_refcount (copy->structure,
-        &copy->mini_object.refcount);
+        &copy->message.mini_object.refcount);
   }
 
-  return copy;
+  return GST_MESSAGE_CAST (copy);
 }
 
 /**
@@ -265,29 +256,36 @@ GstMessage *
 gst_message_new_custom (GstMessageType type, GstObject * src,
     GstStructure * structure)
 {
-  GstMessage *message;
+  GstMessageImpl *message;
+
+  message = g_slice_new0 (GstMessageImpl);
 
-  message = (GstMessage *) gst_mini_object_new (GST_TYPE_MESSAGE);
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (message),
+      _gst_message_type, sizeof (GstMessageImpl));
+
+  message->message.mini_object.copy =
+      (GstMiniObjectCopyFunction) _gst_message_copy;
+  message->message.mini_object.free =
+      (GstMiniObjectFreeFunction) _gst_message_free;
 
   GST_CAT_LOG (GST_CAT_MESSAGE, "source %s: creating new message %p %s",
       (src ? GST_OBJECT_NAME (src) : "NULL"), message,
       gst_message_type_get_name (type));
 
-  message->type = type;
-
+  GST_MESSAGE_TYPE (message) = type;
   if (src)
     gst_object_ref (src);
-  message->src = src;
+  GST_MESSAGE_SRC (message) = src;
+  GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
+  GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
 
   if (structure) {
     gst_structure_set_parent_refcount (structure,
-        &message->mini_object.refcount);
+        &message->message.mini_object.refcount);
   }
   message->structure = structure;
 
-  GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
-
-  return message;
+  return GST_MESSAGE_CAST (message);
 }
 
 /**
@@ -387,8 +385,8 @@ gst_message_new_error (GstObject * src, GError * error, const gchar * debug)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_ERROR),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_ERROR),
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure);
 
@@ -414,8 +412,8 @@ gst_message_new_warning (GstObject * src, GError * error, const gchar * debug)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_WARNING),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_WARNING),
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure);
 
@@ -443,8 +441,8 @@ gst_message_new_info (GstObject * src, GError * error, const gchar * debug)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_INFO),
-      GST_QUARK (GERROR), GST_TYPE_G_ERROR, error,
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_INFO),
+      GST_QUARK (GERROR), G_TYPE_ERROR, error,
       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure);
 
@@ -477,39 +475,6 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list)
 }
 
 /**
- * gst_message_new_tag_full:
- * @src: (transfer none): the object originating the message.
- * @pad: (transfer none): the originating pad for the tag.
- * @tag_list: (transfer full): the tag list for the message.
- *
- * Create a new tag message. The message will take ownership of the tag list.
- * The message is posted by elements that discovered a new taglist.
- *
- * MT safe.
- *
- * Returns: (transfer full): the new tag message.
- *
- * Since: 0.10.24
- */
-GstMessage *
-gst_message_new_tag_full (GstObject * src, GstPad * pad, GstTagList * tag_list)
-{
-  GstMessage *message;
-  GstStructure *s;
-
-  g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL);
-  g_return_val_if_fail (pad == NULL || GST_IS_PAD (pad), NULL);
-
-  s = (GstStructure *) tag_list;
-  if (pad)
-    gst_structure_set (s, "source-pad", GST_TYPE_PAD, pad, NULL);
-
-  message = gst_message_new_custom (GST_MESSAGE_TAG, src, s);
-
-  return message;
-}
-
-/**
  * gst_message_new_buffering:
  * @src: (transfer none): The object originating the message.
  * @percent: The buffering percent
@@ -539,7 +504,7 @@ gst_message_new_buffering (GstObject * src, gint percent)
 
   g_return_val_if_fail (percent >= 0 && percent <= 100, NULL);
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_BUFFERING),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_BUFFERING),
       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent,
       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
@@ -572,7 +537,7 @@ gst_message_new_state_changed (GstObject * src,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STATE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE),
       GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate,
       GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate,
       GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL);
@@ -627,7 +592,7 @@ gst_message_new_clock_provide (GstObject * src, GstClock * clock,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_CLOCK_PROVIDE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_PROVIDE),
       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock,
       GST_QUARK (READY), G_TYPE_BOOLEAN, ready, NULL);
   message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src, structure);
@@ -657,7 +622,7 @@ gst_message_new_clock_lost (GstObject * src, GstClock * clock)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_CLOCK_LOST),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_LOST),
       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
   message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src, structure);
 
@@ -682,7 +647,7 @@ gst_message_new_new_clock (GstObject * src, GstClock * clock)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_NEW_CLOCK),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEW_CLOCK),
       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
   message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src, structure);
 
@@ -719,7 +684,7 @@ gst_message_new_structure_change (GstObject * src, GstStructureChangeType type,
   /* g_return_val_if_fail (GST_PAD_DIRECTION (src) == GST_PAD_SINK, NULL); */
   g_return_val_if_fail (GST_IS_ELEMENT (owner), NULL);
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STRUCTURE_CHANGE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STRUCTURE_CHANGE),
       GST_QUARK (TYPE), GST_TYPE_STRUCTURE_CHANGE_TYPE, type,
       GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner,
       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, NULL);
@@ -752,7 +717,7 @@ gst_message_new_segment_start (GstObject * src, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_SEGMENT_START),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_START),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src, structure);
@@ -782,7 +747,7 @@ gst_message_new_segment_done (GstObject * src, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_SEGMENT_DONE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_DONE),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src, structure);
@@ -854,7 +819,7 @@ gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_DURATION),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_DURATION),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
   message = gst_message_new_custom (GST_MESSAGE_DURATION, src, structure);
@@ -865,27 +830,19 @@ gst_message_new_duration (GstObject * src, GstFormat format, gint64 duration)
 /**
  * gst_message_new_async_start:
  * @src: (transfer none): The object originating the message.
- * @new_base_time: if a new base_time should be set on the element
  *
- * This message is posted by elements when they start an ASYNC state change. 
- * @new_base_time is set to TRUE when the element lost its state when it was
- * PLAYING.
+ * This message is posted by elements when they start an ASYNC state change.
  *
  * Returns: (transfer full): The new async_start message.
  *
  * MT safe.
- *
- * Since: 0.10.13
  */
 GstMessage *
-gst_message_new_async_start (GstObject * src, gboolean new_base_time)
+gst_message_new_async_start (GstObject * src)
 {
   GstMessage *message;
-  GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_ASYNC_START),
-      GST_QUARK (NEW_BASE_TIME), G_TYPE_BOOLEAN, new_base_time, NULL);
-  message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, structure);
+  message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, NULL);
 
   return message;
 }
@@ -893,21 +850,25 @@ gst_message_new_async_start (GstObject * src, gboolean new_base_time)
 /**
  * gst_message_new_async_done:
  * @src: (transfer none): The object originating the message.
+ * @reset_time: if the running_time should be reset
  *
  * The message is posted when elements completed an ASYNC state change.
+ * @reset_time is set to TRUE when the element requests a new running_time
+ * before going to PLAYING.
  *
  * Returns: (transfer full): The new async_done message.
  *
  * MT safe.
- *
- * Since: 0.10.13
  */
 GstMessage *
-gst_message_new_async_done (GstObject * src)
+gst_message_new_async_done (GstObject * src, gboolean reset_time)
 {
   GstMessage *message;
+  GstStructure *structure;
 
-  message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, NULL);
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_ASYNC_DONE),
+      GST_QUARK (RESET_TIME), G_TYPE_BOOLEAN, reset_time, NULL);
+  message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure);
 
   return message;
 }
@@ -956,7 +917,7 @@ gst_message_new_request_state (GstObject * src, GstState state)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_REQUEST_STATE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_REQUEST_STATE),
       GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) state, NULL);
   message = gst_message_new_custom (GST_MESSAGE_REQUEST_STATE, src, structure);
 
@@ -980,7 +941,33 @@ gst_message_get_structure (GstMessage * message)
 {
   g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
 
-  return message->structure;
+  return GST_MESSAGE_STRUCTURE (message);
+}
+
+/**
+ * gst_message_has_name:
+ * @message: The #GstMessage.
+ * @name: name to check
+ *
+ * Checks if @message has the given @name. This function is usually used to
+ * check the name of a custom message.
+ *
+ * Returns: %TRUE if @name matches the name of the message structure.
+ *
+ * Since: 0.10.20
+ */
+gboolean
+gst_message_has_name (GstMessage * message, const gchar * name)
+{
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
+
+  structure = GST_MESSAGE_STRUCTURE (message);
+  if (structure == NULL)
+    return FALSE;
+
+  return gst_structure_has_name (structure, name);
 }
 
 /**
@@ -1020,49 +1007,7 @@ gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
   g_return_if_fail (tag_list != NULL);
 
-  ret = gst_structure_copy (message->structure);
-  gst_structure_remove_field (ret, "source-pad");
-
-  *tag_list = (GstTagList *) ret;
-}
-
-/**
- * gst_message_parse_tag_full:
- * @message: A valid #GstMessage of type GST_MESSAGE_TAG.
- * @pad: (out callee-allocates): location where the originating pad is stored,
- *     unref after usage
- * @tag_list: (out callee-allocates): return location for the tag-list.
- *
- * Extracts the tag list from the GstMessage. The tag list returned in the
- * output argument is a copy; the caller must free it when done.
- *
- * MT safe.
- *
- * Since: 0.10.24
- */
-void
-gst_message_parse_tag_full (GstMessage * message, GstPad ** pad,
-    GstTagList ** tag_list)
-{
-  GstStructure *ret;
-
-  g_return_if_fail (GST_IS_MESSAGE (message));
-  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
-  g_return_if_fail (tag_list != NULL);
-
-  ret = gst_structure_copy (message->structure);
-
-  if (gst_structure_has_field (ret, "source-pad") && pad) {
-    const GValue *v;
-
-    v = gst_structure_get_value (ret, "source-pad");
-    if (v && G_VALUE_HOLDS (v, GST_TYPE_PAD))
-      *pad = g_value_dup_object (v);
-    else
-      *pad = NULL;
-  } else if (pad) {
-    *pad = NULL;
-  }
+  ret = gst_structure_copy (GST_MESSAGE_STRUCTURE (message));
   gst_structure_remove_field (ret, "source-pad");
 
   *tag_list = (GstTagList *) ret;
@@ -1087,8 +1032,9 @@ gst_message_parse_buffering (GstMessage * message, gint * percent)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
 
   if (percent)
-    *percent = g_value_get_int (gst_structure_id_get_value (message->structure,
-            GST_QUARK (BUFFER_PERCENT)));
+    *percent =
+        g_value_get_int (gst_structure_id_get_value (GST_MESSAGE_STRUCTURE
+            (message), GST_QUARK (BUFFER_PERCENT)));
 }
 
 /**
@@ -1109,7 +1055,7 @@ gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode,
 {
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
 
-  gst_structure_id_set (message->structure,
+  gst_structure_id_set (GST_MESSAGE_STRUCTURE (message),
       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
@@ -1134,21 +1080,24 @@ gst_message_parse_buffering_stats (GstMessage * message,
     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
     gint64 * buffering_left)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (mode)
     *mode = (GstBufferingMode)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (BUFFERING_MODE)));
   if (avg_in)
-    *avg_in = g_value_get_int (gst_structure_id_get_value (message->structure,
+    *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
             GST_QUARK (AVG_IN_RATE)));
   if (avg_out)
-    *avg_out = g_value_get_int (gst_structure_id_get_value (message->structure,
+    *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
             GST_QUARK (AVG_OUT_RATE)));
   if (buffering_left)
     *buffering_left =
-        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+        g_value_get_int64 (gst_structure_id_get_value (structure,
             GST_QUARK (BUFFERING_LEFT)));
 }
 
@@ -1186,20 +1135,23 @@ void
 gst_message_parse_state_changed (GstMessage * message,
     GstState * oldstate, GstState * newstate, GstState * pending)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (oldstate)
     *oldstate = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (OLD_STATE)));
   if (newstate)
     *newstate = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (NEW_STATE)));
   if (pending)
     *pending = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (PENDING_STATE)));
 }
 
@@ -1220,18 +1172,19 @@ gst_message_parse_clock_provide (GstMessage * message, GstClock ** clock,
     gboolean * ready)
 {
   const GValue *clock_gvalue;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);
 
-  clock_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
   if (ready)
     *ready =
-        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+        g_value_get_boolean (gst_structure_id_get_value (structure,
             GST_QUARK (READY)));
   if (clock)
     *clock = (GstClock *) g_value_get_object (clock_gvalue);
@@ -1251,12 +1204,13 @@ void
 gst_message_parse_clock_lost (GstMessage * message, GstClock ** clock)
 {
   const GValue *clock_gvalue;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_LOST);
 
-  clock_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1279,12 +1233,13 @@ void
 gst_message_parse_new_clock (GstMessage * message, GstClock ** clock)
 {
   const GValue *clock_gvalue;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);
 
-  clock_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (CLOCK));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1312,24 +1267,25 @@ gst_message_parse_structure_change (GstMessage * message,
     GstStructureChangeType * type, GstElement ** owner, gboolean * busy)
 {
   const GValue *owner_gvalue;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STRUCTURE_CHANGE);
 
-  owner_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (OWNER));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
   g_return_if_fail (owner_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (owner_gvalue) == GST_TYPE_ELEMENT);
 
   if (type)
     *type = (GstStructureChangeType)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (TYPE)));
   if (owner)
     *owner = (GstElement *) g_value_get_object (owner_gvalue);
   if (busy)
     *busy =
-        g_value_get_boolean (gst_structure_id_get_value (message->structure,
+        g_value_get_boolean (gst_structure_id_get_value (structure,
             GST_QUARK (BUSY)));
 }
 
@@ -1371,14 +1327,15 @@ gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
 {
   const GValue *error_gvalue;
   GError *error_val;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
 
-  error_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1388,7 +1345,7 @@ gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
 
   if (debug)
     *debug =
-        g_value_dup_string (gst_structure_id_get_value (message->structure,
+        g_value_dup_string (gst_structure_id_get_value (structure,
             GST_QUARK (DEBUG)));
 }
 
@@ -1410,14 +1367,15 @@ gst_message_parse_warning (GstMessage * message, GError ** gerror,
 {
   const GValue *error_gvalue;
   GError *error_val;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
 
-  error_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1427,7 +1385,7 @@ gst_message_parse_warning (GstMessage * message, GError ** gerror,
 
   if (debug)
     *debug =
-        g_value_dup_string (gst_structure_id_get_value (message->structure,
+        g_value_dup_string (gst_structure_id_get_value (structure,
             GST_QUARK (DEBUG)));
 }
 
@@ -1450,14 +1408,15 @@ gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug)
 {
   const GValue *error_gvalue;
   GError *error_val;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
 
-  error_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (GERROR));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  error_gvalue = gst_structure_id_get_value (structure, GST_QUARK (GERROR));
   g_return_if_fail (error_gvalue != NULL);
-  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == GST_TYPE_G_ERROR);
+  g_return_if_fail (G_VALUE_TYPE (error_gvalue) == G_TYPE_ERROR);
 
   error_val = (GError *) g_value_get_boxed (error_gvalue);
   if (error_val)
@@ -1467,7 +1426,7 @@ gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug)
 
   if (debug)
     *debug =
-        g_value_dup_string (gst_structure_id_get_value (message->structure,
+        g_value_dup_string (gst_structure_id_get_value (structure,
             GST_QUARK (DEBUG)));
 }
 
@@ -1485,16 +1444,19 @@ void
 gst_message_parse_segment_start (GstMessage * message, GstFormat * format,
     gint64 * position)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (FORMAT)));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+        g_value_get_int64 (gst_structure_id_get_value (structure,
             GST_QUARK (POSITION)));
 }
 
@@ -1512,16 +1474,19 @@ void
 gst_message_parse_segment_done (GstMessage * message, GstFormat * format,
     gint64 * position)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (FORMAT)));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+        g_value_get_int64 (gst_structure_id_get_value (structure,
             GST_QUARK (POSITION)));
 }
 
@@ -1542,40 +1507,44 @@ void
 gst_message_parse_duration (GstMessage * message, GstFormat * format,
     gint64 * duration)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (FORMAT)));
   if (duration)
     *duration =
-        g_value_get_int64 (gst_structure_id_get_value (message->structure,
+        g_value_get_int64 (gst_structure_id_get_value (structure,
             GST_QUARK (DURATION)));
 }
 
 /**
- * gst_message_parse_async_start:
+ * gst_message_parse_async_done:
  * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE.
- * @new_base_time: (out): Result location for the new_base_time or NULL
+ * @reset_time: (out): Result location for the reset_time or NULL
  *
- * Extract the new_base_time from the async_start message. 
+ * Extract the reset_time from the async_done message.
  *
  * MT safe.
- *
- * Since: 0.10.13
  */
 void
-gst_message_parse_async_start (GstMessage * message, gboolean * new_base_time)
+gst_message_parse_async_done (GstMessage * message, gboolean * reset_time)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
-  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_START);
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_DONE);
 
-  if (new_base_time)
-    *new_base_time =
-        g_value_get_boolean (gst_structure_id_get_value (message->structure,
-            GST_QUARK (NEW_BASE_TIME)));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  if (reset_time)
+    *reset_time =
+        g_value_get_boolean (gst_structure_id_get_value (structure,
+            GST_QUARK (RESET_TIME)));
 }
 
 /**
@@ -1592,12 +1561,15 @@ gst_message_parse_async_start (GstMessage * message, gboolean * new_base_time)
 void
 gst_message_parse_request_state (GstMessage * message, GstState * state)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REQUEST_STATE);
 
+  structure = GST_MESSAGE_STRUCTURE (message);
   if (state)
     *state = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (NEW_STATE)));
 }
 
@@ -1623,7 +1595,7 @@ gst_message_new_stream_status (GstObject * src, GstStreamStatusType type,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STREAM_STATUS),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_STATUS),
       GST_QUARK (TYPE), GST_TYPE_STREAM_STATUS_TYPE, (gint) type,
       GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, NULL);
   message = gst_message_new_custom (GST_MESSAGE_STREAM_STATUS, src, structure);
@@ -1650,17 +1622,18 @@ gst_message_parse_stream_status (GstMessage * message,
     GstStreamStatusType * type, GstElement ** owner)
 {
   const GValue *owner_gvalue;
+  GstStructure *structure;
 
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
 
-  owner_gvalue =
-      gst_structure_id_get_value (message->structure, GST_QUARK (OWNER));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
   g_return_if_fail (owner_gvalue != NULL);
 
   if (type)
     *type = (GstStreamStatusType)
-        g_value_get_enum (gst_structure_id_get_value (message->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (TYPE)));
   if (owner)
     *owner = (GstElement *) g_value_get_object (owner_gvalue);
@@ -1680,10 +1653,13 @@ void
 gst_message_set_stream_status_object (GstMessage * message,
     const GValue * object)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
 
-  gst_structure_id_set_value (message->structure, GST_QUARK (OBJECT), object);
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_set_value (structure, GST_QUARK (OBJECT), object);
 }
 
 /**
@@ -1702,12 +1678,14 @@ const GValue *
 gst_message_get_stream_status_object (GstMessage * message)
 {
   const GValue *result;
+  GstStructure *structure;
 
   g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
   g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS,
       NULL);
 
-  result = gst_structure_id_get_value (message->structure, GST_QUARK (OBJECT));
+  structure = GST_MESSAGE_STRUCTURE (message);
+  result = gst_structure_id_get_value (structure, GST_QUARK (OBJECT));
 
   return result;
 }
@@ -1743,7 +1721,7 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_DONE),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_DONE),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
@@ -1778,10 +1756,13 @@ gst_message_parse_step_done (GstMessage * message, GstFormat * format,
     guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate,
     guint64 * duration, gboolean * eos)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
@@ -1825,7 +1806,7 @@ gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_START),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_START),
       GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
@@ -1858,10 +1839,13 @@ gst_message_parse_step_start (GstMessage * message, gboolean * active,
     GstFormat * format, guint64 * amount, gdouble * rate, gboolean * flush,
     gboolean * intermediate)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
@@ -1906,7 +1890,7 @@ gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_QOS),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_QOS),
       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
       GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
@@ -1942,10 +1926,13 @@ void
 gst_message_set_qos_values (GstMessage * message, gint64 jitter,
     gdouble proportion, gint quality)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
-  gst_structure_id_set (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_set (structure,
       GST_QUARK (JITTER), G_TYPE_INT64, jitter,
       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
       GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
@@ -1976,10 +1963,13 @@ void
 gst_message_set_qos_stats (GstMessage * message, GstFormat format,
     guint64 processed, guint64 dropped)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
-  gst_structure_id_set (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_set (structure,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
       GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
@@ -2013,10 +2003,13 @@ gst_message_parse_qos (GstMessage * message, gboolean * live,
     guint64 * running_time, guint64 * stream_time, guint64 * timestamp,
     guint64 * duration)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
       GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
@@ -2045,10 +2038,13 @@ void
 gst_message_parse_qos_values (GstMessage * message, gint64 * jitter,
     gdouble * proportion, gint * quality)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (JITTER), G_TYPE_INT64, jitter,
       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
       GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
@@ -2080,10 +2076,13 @@ void
 gst_message_parse_qos_stats (GstMessage * message, GstFormat * format,
     guint64 * processed, guint64 * dropped)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
       GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
@@ -2120,7 +2119,7 @@ gst_message_new_progress (GstObject * src, GstProgressType type,
   if (type == GST_PROGRESS_TYPE_START || type == GST_PROGRESS_TYPE_CONTINUE)
     percent = 0;
 
-  structure = gst_structure_id_new (GST_QUARK (MESSAGE_PROGRESS),
+  structure = gst_structure_new_id (GST_QUARK (MESSAGE_PROGRESS),
       GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
       GST_QUARK (CODE), G_TYPE_STRING, code,
       GST_QUARK (TEXT), G_TYPE_STRING, text,
@@ -2146,10 +2145,13 @@ void
 gst_message_parse_progress (GstMessage * message, GstProgressType * type,
     gchar ** code, gchar ** text)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROGRESS);
 
-  gst_structure_id_get (message->structure,
+  structure = GST_MESSAGE_STRUCTURE (message);
+  gst_structure_id_get (structure,
       GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
       GST_QUARK (CODE), G_TYPE_STRING, code,
       GST_QUARK (TEXT), G_TYPE_STRING, text, NULL);
index f0fcc7a..0c97a52 100644 (file)
@@ -25,7 +25,6 @@
 G_BEGIN_DECLS
 
 typedef struct _GstMessage GstMessage;
-typedef struct _GstMessageClass GstMessageClass;
 
 /**
  * GstMessageType:
@@ -133,6 +132,7 @@ typedef enum
 #include <gst/gstelement.h>
 #include <gst/gsttaglist.h>
 #include <gst/gststructure.h>
+#include <gst/gstquery.h>
 
 /**
  * GST_MESSAGE_TRACE_NAME:
@@ -142,22 +142,19 @@ typedef enum
 #define GST_MESSAGE_TRACE_NAME  "GstMessage"
 
 #define GST_TYPE_MESSAGE                         (gst_message_get_type())
-#define GST_IS_MESSAGE(obj)                      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MESSAGE))
-#define GST_IS_MESSAGE_CLASS(klass)              (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MESSAGE))
-#define GST_MESSAGE_GET_CLASS(obj)               (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MESSAGE, GstMessageClass))
-#define GST_MESSAGE(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MESSAGE, GstMessage))
-#define GST_MESSAGE_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MESSAGE, GstMessageClass))
+#define GST_IS_MESSAGE(obj)                      (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_MESSAGE))
 #define GST_MESSAGE_CAST(obj)                    ((GstMessage*)(obj))
+#define GST_MESSAGE(obj)                         (GST_MESSAGE_CAST(obj))
 
 /* the lock is used to handle the synchronous handling of messages,
  * the emiting thread is block until the handling thread processed
  * the message using this mutex/cond pair */
-#define GST_MESSAGE_GET_LOCK(message)   (GST_MESSAGE_CAST(message)->lock)
+#define GST_MESSAGE_GET_LOCK(message)   (&GST_MESSAGE_CAST(message)->lock)
 #define GST_MESSAGE_LOCK(message)       g_mutex_lock(GST_MESSAGE_GET_LOCK(message))
 #define GST_MESSAGE_UNLOCK(message)     g_mutex_unlock(GST_MESSAGE_GET_LOCK(message))
-#define GST_MESSAGE_COND(message)       (GST_MESSAGE_CAST(message)->cond)
-#define GST_MESSAGE_WAIT(message)       g_cond_wait(GST_MESSAGE_COND(message),GST_MESSAGE_GET_LOCK(message))
-#define GST_MESSAGE_SIGNAL(message)     g_cond_signal(GST_MESSAGE_COND(message))
+#define GST_MESSAGE_GET_COND(message)   (&GST_MESSAGE_CAST(message)->cond)
+#define GST_MESSAGE_WAIT(message)       g_cond_wait(GST_MESSAGE_GET_COND(message),GST_MESSAGE_GET_LOCK(message))
+#define GST_MESSAGE_SIGNAL(message)     g_cond_signal(GST_MESSAGE_GET_COND(message))
 
 /**
  * GST_MESSAGE_TYPE:
@@ -190,6 +187,15 @@ typedef enum
  * Get the object that posted @message.
  */
 #define GST_MESSAGE_SRC(message)        (GST_MESSAGE_CAST(message)->src)
+
+/**
+ * GST_MESSAGE_SEQNUM:
+ * @message: a #GstMessage
+ *
+ * Get the sequence number of @message.
+ */
+#define GST_MESSAGE_SEQNUM(message)     (GST_MESSAGE_CAST(message)->seqnum)
+
 /**
  * GST_MESSAGE_SRC_NAME:
  * @message: a #GstMessage
@@ -270,40 +276,23 @@ typedef enum {
  * @type: the #GstMessageType of the message
  * @timestamp: the timestamp of the message
  * @src: the src of the message
- * @structure: the #GstStructure containing the message info.
+ * @seqnum: the sequence number of the message
  *
  * A #GstMessage.
  */
 struct _GstMessage
 {
-  GstMiniObject mini_object;
-
-  /*< private >*//* with MESSAGE_LOCK */
-  GMutex *lock;                 /* lock and cond for async delivery */
-  GCond *cond;
+  GstMiniObject   mini_object;
 
   /*< public > *//* with COW */
-  GstMessageType type;
-  guint64 timestamp;
-  GstObject *src;
-
-  GstStructure *structure;
-
-  /*< private >*/
-  union {
-    struct {
-      guint32 seqnum;
-    } ABI;
-    /* + 0 to mark ABI change for future greppage */
-    gpointer _gst_reserved[GST_PADDING + 0];
-  } abidata;
-};
+  GstMessageType  type;
+  guint64         timestamp;
+  GstObject      *src;
+  guint32         seqnum;
 
-struct _GstMessageClass {
-  GstMiniObjectClass mini_object_class;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  /*< private >*//* with MESSAGE_LOCK */
+  GMutex          lock;                 /* lock and cond for async delivery */
+  GCond           cond;
 };
 
 GType           gst_message_get_type            (void);
@@ -369,6 +358,14 @@ gst_message_copy (const GstMessage * msg)
 }
 
 /**
+ * gst_message_is_writable:
+ * @msg: a #GstMessage
+ *
+ * Tests if you can safely write into a message's structure or validly
+ * modify the seqnum and timestamp fields.
+ */
+#define         gst_message_is_writable(msg)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (msg))
+/**
  * gst_message_make_writable:
  * @msg: (transfer full): the message to make writable
  *
@@ -380,6 +377,41 @@ gst_message_copy (const GstMessage * msg)
  * MT safe
  */
 #define         gst_message_make_writable(msg)  GST_MESSAGE_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (msg)))
+/**
+ * gst_message_replace:
+ * @old_message: (inout) (transfer full): pointer to a pointer to a #GstMessage
+ *     to be replaced.
+ * @new_message: (allow-none) (transfer none): pointer to a #GstMessage that will
+ *     replace the message pointed to by @old_message.
+ *
+ * Modifies a pointer to a #GstMessage to point to a different #GstMessage. The
+ * modification is done atomically (so this is useful for ensuring thread safety
+ * in some cases), and the reference counts are updated appropriately (the old
+ * message is unreffed, the new one is reffed).
+ *
+ * Either @new_message or the #GstMessage pointed to by @old_message may be NULL.
+ *
+ * Returns: TRUE if @new_message was different from @old_message
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_message_replace (GstMessage **old_message, GstMessage *new_message);
+#endif
+
+static inline gboolean
+gst_message_replace (GstMessage **old_message, GstMessage *new_message)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_message, (GstMiniObject *) new_message);
+}
+
+
+/* custom messages */
+GstMessage *    gst_message_new_custom          (GstMessageType type,
+                                                 GstObject    * src,
+                                                 GstStructure * structure) G_GNUC_MALLOC;
+const GstStructure *
+                gst_message_get_structure       (GstMessage *message);
+
+gboolean        gst_message_has_name            (GstMessage *message, const gchar *name);
 
 /* identifiers for events and messages */
 guint32         gst_message_get_seqnum          (GstMessage *message);
@@ -403,9 +435,7 @@ void            gst_message_parse_info          (GstMessage *message, GError **g
 
 /* TAG */
 GstMessage *    gst_message_new_tag             (GstObject * src, GstTagList * tag_list) G_GNUC_MALLOC;
-GstMessage *    gst_message_new_tag_full        (GstObject * src, GstPad *pad, GstTagList * tag_list) G_GNUC_MALLOC;
 void            gst_message_parse_tag           (GstMessage *message, GstTagList **tag_list);
-void            gst_message_parse_tag_full      (GstMessage *message, GstPad **pad, GstTagList **tag_list);
 
 /* BUFFERING */
 GstMessage *    gst_message_new_buffering         (GstObject * src, gint percent) G_GNUC_MALLOC;
@@ -471,11 +501,11 @@ void            gst_message_parse_duration      (GstMessage *message, GstFormat
 GstMessage *    gst_message_new_latency         (GstObject * src) G_GNUC_MALLOC;
 
 /* ASYNC_START */
-GstMessage *    gst_message_new_async_start     (GstObject * src, gboolean new_base_time) G_GNUC_MALLOC;
-void            gst_message_parse_async_start   (GstMessage *message, gboolean *new_base_time);
+GstMessage *    gst_message_new_async_start     (GstObject * src) G_GNUC_MALLOC;
 
 /* ASYNC_DONE */
-GstMessage *    gst_message_new_async_done      (GstObject * src) G_GNUC_MALLOC;
+GstMessage *    gst_message_new_async_done      (GstObject * src, gboolean reset_time) G_GNUC_MALLOC;
+void            gst_message_parse_async_done    (GstMessage *message, gboolean *reset_time);
 
 /* STRUCTURE CHANGE */
 GstMessage *    gst_message_new_structure_change   (GstObject * src, GstStructureChangeType type,
@@ -523,12 +553,6 @@ void            gst_message_parse_progress         (GstMessage * message, GstPro
                                                     gchar ** text);
 
 
-/* custom messages */
-GstMessage *    gst_message_new_custom          (GstMessageType type,
-                                                 GstObject    * src,
-                                                 GstStructure * structure) G_GNUC_MALLOC;
-const GstStructure *  gst_message_get_structure (GstMessage *message);
-
 G_END_DECLS
 
 #endif /* __GST_MESSAGE_H__ */
diff --git a/gst/gstmeta.c b/gst/gstmeta.c
new file mode 100644 (file)
index 0000000..5258855
--- /dev/null
@@ -0,0 +1,115 @@
+/* GStreamer
+ * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gstmeta.c: metadata operations
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstmeta
+ * @short_description: Buffer metadata
+ *
+ * Last reviewed on December 17th, 2009 (0.10.26)
+ */
+#include "gst_private.h"
+
+#include "gstbuffer.h"
+#include "gstmeta.h"
+#include "gstinfo.h"
+#include "gstutils.h"
+
+static GHashTable *metainfo = NULL;
+static GRWLock lock;
+
+void
+_priv_gst_meta_initialize (void)
+{
+  g_rw_lock_init (&lock);
+  metainfo = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+/**
+ * gst_meta_register:
+ * @api: the name of the #GstMeta API
+ * @impl: the name of the #GstMeta implementation
+ * @size: the size of the #GstMeta structure
+ * @init_func: a #GstMetaInitFunction
+ * @free_func: a #GstMetaFreeFunction
+ * @copy_func: a #GstMetaCopyFunction
+ * @transform_func: a #GstMetaTransformFunction
+ *
+ * Register a new #GstMeta implementation.
+ *
+ * The same @info can be retrieved later with gst_meta_get_info() by using
+ * @impl as the key.
+ *
+ * Returns: (transfer none): a #GstMetaInfo that can be used to access metadata.
+ */
+
+const GstMetaInfo *
+gst_meta_register (const gchar * api, const gchar * impl, gsize size,
+    GstMetaInitFunction init_func, GstMetaFreeFunction free_func,
+    GstMetaCopyFunction copy_func, GstMetaTransformFunction transform_func)
+{
+  GstMetaInfo *info;
+
+  g_return_val_if_fail (api != NULL, NULL);
+  g_return_val_if_fail (impl != NULL, NULL);
+  g_return_val_if_fail (size != 0, NULL);
+
+  info = g_slice_new (GstMetaInfo);
+  info->api = g_quark_from_string (api);
+  info->type = g_pointer_type_register_static (impl);
+  info->size = size;
+  info->init_func = init_func;
+  info->free_func = free_func;
+  info->copy_func = copy_func;
+  info->transform_func = transform_func;
+
+  GST_DEBUG ("register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT,
+      api, impl, size);
+
+  g_rw_lock_writer_lock (&lock);
+  g_hash_table_insert (metainfo, (gpointer) impl, (gpointer) info);
+  g_rw_lock_writer_unlock (&lock);
+
+  return info;
+}
+
+/**
+ * gst_meta_get_info:
+ * @impl: the name
+ *
+ * Lookup a previously registered meta info structure by its implementation name
+ * @impl.
+ *
+ * Returns: (transfer none): a #GstMetaInfo with @impl, or #NULL when no such
+ * metainfo exists.
+ */
+const GstMetaInfo *
+gst_meta_get_info (const gchar * impl)
+{
+  GstMetaInfo *info;
+
+  g_return_val_if_fail (impl != NULL, NULL);
+
+  g_rw_lock_reader_lock (&lock);
+  info = g_hash_table_lookup (metainfo, impl);
+  g_rw_lock_reader_unlock (&lock);
+
+  return info;
+}
diff --git a/gst/gstmeta.h b/gst/gstmeta.h
new file mode 100644 (file)
index 0000000..7f786b6
--- /dev/null
@@ -0,0 +1,189 @@
+/* GStreamer
+ * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.be>
+ *
+ * gstmeta.h: Header for Metadata structures
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_META_H__
+#define __GST_META_H__
+
+G_BEGIN_DECLS
+
+typedef struct _GstMeta GstMeta;
+typedef struct _GstMetaInfo GstMetaInfo;
+
+#define GST_META_CAST(meta)   ((GstMeta *)(meta))
+
+/**
+ * GstMetaFlags:
+ * @GST_META_FLAG_NONE: no flags
+ * @GST_META_FLAG_READONLY: metadata should not be modified
+ * @GST_META_FLAG_POOLED: metadata is managed by a bufferpool and should not
+ *    be removed
+ * @GST_META_FLAG_LAST: additional flags can be added starting from this flag.
+ *
+ * Extra metadata flags.
+ */
+typedef enum {
+  GST_META_FLAG_NONE        = 0,
+  GST_META_FLAG_READONLY    = (1 << 0),
+  GST_META_FLAG_POOLED      = (1 << 1),
+
+  GST_META_FLAG_LAST        = (1 << 16)
+} GstMetaFlags;
+
+/**
+ * GST_META_FLAGS:
+ * @meta: a #GstMeta.
+ *
+ * A flags word containing #GstMetaFlag flags set on @meta
+ */
+#define GST_META_FLAGS(meta)  (GST_META_CAST (meta)->flags)
+/**
+ * GST_META_FLAG_IS_SET:
+ * @meta: a #GstMeta.
+ * @flag: the #GstMetaFlag to check.
+ *
+ * Gives the status of a specific flag on a metadata.
+ */
+#define GST_META_FLAG_IS_SET(meta,flag)        !!(GST_META_FLAGS (meta) & (flag))
+/**
+ * GST_META_FLAG_SET:
+ * @meta: a #GstMeta.
+ * @flag: the #GstMetaFlag to set.
+ *
+ * Sets a metadata flag on a metadata.
+ */
+#define GST_META_FLAG_SET(meta,flag)           (GST_META_FLAGS (meta) |= (flag))
+/**
+ * GST_META_FLAG_UNSET:
+ * @meta: a #GstMeta.
+ * @flag: the #GstMetaFlag to clear.
+ *
+ * Clears a metadata flag.
+ */
+#define GST_META_FLAG_UNSET(meta,flag)         (GST_META_FLAGS (meta) &= ~(flag))
+
+/**
+ * GstMeta:
+ * @flags: extra flags for the metadata
+ * @info: pointer to the #GstMetaInfo
+ *
+ * Base structure for metadata. Custom metadata will put this structure
+ * as the first member of their structure.
+ */
+struct _GstMeta {
+  GstMetaFlags       flags;
+  const GstMetaInfo *info;
+};
+
+/**
+ * GST_META_TRACE_NAME:
+ *
+ * The name used for tracing memory allocations.
+ */
+#define GST_META_TRACE_NAME           "GstMeta"
+
+/**
+ * GstMetaInitFunction:
+ * @meta: a #GstMeta
+ * @params: parameters passed to the init function
+ * @buffer: a #GstBuffer
+ *
+ * Function called when @meta is initialized in @buffer.
+ */
+typedef gboolean (*GstMetaInitFunction) (GstMeta *meta, gpointer params, GstBuffer *buffer);
+
+/**
+ * GstMetaFreeFunction:
+ * @meta: a #GstMeta
+ * @buffer: a #GstBuffer
+ *
+ * Function called when @meta is freed in @buffer.
+ */
+typedef void (*GstMetaFreeFunction)     (GstMeta *meta, GstBuffer *buffer);
+
+/**
+ * GstMetaCopyFunction:
+ * @dest: a destination #GstBuffer
+ * @meta: a #GstMeta
+ * @buffer: a #GstBuffer
+ * @offset: an offset
+ * @size: a size
+ *
+ * Function called when the region at @offset and @size in @buffer is copied
+ * into @dest. The function should update the metadata on @dest using @meta.
+ */
+typedef void (*GstMetaCopyFunction)     (GstBuffer *dest, GstMeta *meta,
+                                         GstBuffer *buffer, gsize offset, gsize size);
+/**
+ * GstMetaTransformFunction:
+ * @transbuf: a #GstBuffer
+ * @meta: a #GstMeta
+ * @buffer: a #GstBuffer
+ * @data: transform specific data.
+ *
+ * Function called for each @meta in @buffer as a result of performing a
+ * transformation on @transbuf. Additional type specific transform data
+ * is passed to the function.
+ *
+ * Implementations should check the type of the transform @data and parse
+ * additional type specific field that should be used to perform the transform.
+ */
+typedef void (*GstMetaTransformFunction) (GstBuffer *transbuf, GstMeta *meta,
+                                          GstBuffer *buffer, gpointer data);
+
+/**
+ * GstMetaInfo:
+ * @api: tag indentifying the metadata structure and api
+ * @type: type indentifying the implementor of the api
+ * @size: size of the metadata
+ * @init_func: function for initializing the metadata
+ * @free_func: function for freeing the metadata
+ * @copy_func: function for copying the metadata
+ * @transform_func: function for transforming the metadata
+ *
+ * The #GstMetaInfo provides information about a specific metadata
+ * structure.
+ */
+struct _GstMetaInfo {
+  GQuark                     api;
+  GType                      type;
+  gsize                      size;
+
+  GstMetaInitFunction        init_func;
+  GstMetaFreeFunction        free_func;
+  GstMetaCopyFunction        copy_func;
+  GstMetaTransformFunction   transform_func;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+const GstMetaInfo *  gst_meta_register        (const gchar *api, const gchar *impl,
+                                               gsize size,
+                                               GstMetaInitFunction        init_func,
+                                               GstMetaFreeFunction        free_func,
+                                               GstMetaCopyFunction        copy_func,
+                                               GstMetaTransformFunction   transform_func);
+const GstMetaInfo *  gst_meta_get_info        (const gchar * impl);
+
+G_END_DECLS
+
+#endif /* __GST_META_H__ */
index 2454ca8..78749dd 100644 (file)
 #include "gst/gstinfo.h"
 #include <gobject/gvaluecollector.h>
 
+#define GST_DISABLE_TRACE
+
 #ifndef GST_DISABLE_TRACE
 #include "gsttrace.h"
 static GstAllocTrace *_gst_mini_object_trace;
 #endif
 
-#define GST_MINI_OBJECT_GET_CLASS_UNCHECKED(obj) \
-    ((GstMiniObjectClass *) (((GTypeInstance*)(obj))->g_class))
-
-/* Structure used for storing weak references */
-typedef struct
-{
-  GstMiniObject *object;
-  guint n_weak_refs;
-  struct
-  {
-    GstMiniObjectWeakNotify notify;
-    gpointer data;
-  } weak_refs[1];               /* flexible array */
-} WeakRefStack;
-
-/* Structure for storing a mini object's private data */
-struct _GstMiniObjectPrivate
-{
-  WeakRefStack *wstack;
-};
-
-#if 0
-static void gst_mini_object_base_init (gpointer g_class);
-static void gst_mini_object_base_finalize (gpointer g_class);
-#endif
-static void gst_mini_object_class_init (gpointer g_class, gpointer class_data);
-static void gst_mini_object_init (GTypeInstance * instance, gpointer klass);
-
-static void gst_value_mini_object_init (GValue * value);
-static void gst_value_mini_object_free (GValue * value);
-static void weak_refs_notify (WeakRefStack * data);
-static void gst_value_mini_object_copy (const GValue * src_value,
-    GValue * dest_value);
-static gpointer gst_value_mini_object_peek_pointer (const GValue * value);
-static gchar *gst_value_mini_object_collect (GValue * value,
-    guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
-static gchar *gst_value_mini_object_lcopy (const GValue * value,
-    guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
-
-static GstMiniObject *gst_mini_object_copy_default (const GstMiniObject * obj);
-static void gst_mini_object_finalize (GstMiniObject * obj);
-
 /* Mutex used for weak referencing */
 G_LOCK_DEFINE_STATIC (weak_refs_mutex);
 
-GType
-gst_mini_object_get_type (void)
-{
-  static volatile GType _gst_mini_object_type = 0;
-
-  if (g_once_init_enter (&_gst_mini_object_type)) {
-    GType _type;
-    static const GTypeValueTable value_table = {
-      gst_value_mini_object_init,
-      gst_value_mini_object_free,
-      gst_value_mini_object_copy,
-      gst_value_mini_object_peek_pointer,
-      (char *) "p",
-      gst_value_mini_object_collect,
-      (char *) "p",
-      gst_value_mini_object_lcopy
-    };
-    static const GTypeInfo mini_object_info = {
-      sizeof (GstMiniObjectClass),
-#if 0
-      gst_mini_object_base_init,
-      gst_mini_object_base_finalize,
-#else
-      NULL, NULL,
-#endif
-      gst_mini_object_class_init,
-      NULL,
-      NULL,
-      sizeof (GstMiniObject),
-      0,
-      (GInstanceInitFunc) gst_mini_object_init,
-      &value_table
-    };
-    static const GTypeFundamentalInfo mini_object_fundamental_info = {
-      (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE |
-          G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE)
-    };
-
-    _type = g_type_fundamental_next ();
-    g_type_register_fundamental (_type, "GstMiniObject",
-        &mini_object_info, &mini_object_fundamental_info, G_TYPE_FLAG_ABSTRACT);
-
-#ifndef GST_DISABLE_TRACE
-    _gst_mini_object_trace = gst_alloc_trace_register (g_type_name (_type));
-#endif
-    g_once_init_leave (&_gst_mini_object_type, _type);
-  }
-
-  return _gst_mini_object_type;
-}
-
-#if 0
-static void
-gst_mini_object_base_init (gpointer g_class)
-{
-  /* do nothing */
-}
-
-static void
-gst_mini_object_base_finalize (gpointer g_class)
-{
-  /* do nothing */
-}
-#endif
-
-static void
-gst_mini_object_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class);
-
-  mo_class->copy = gst_mini_object_copy_default;
-  mo_class->finalize = gst_mini_object_finalize;
-
-  /* Set the instance data type */
-  g_type_class_add_private (g_class, sizeof (GstMiniObjectPrivate));
-}
-
-static void
-gst_mini_object_init (GTypeInstance * instance, gpointer klass)
-{
-  GstMiniObject *mini_object = GST_MINI_OBJECT_CAST (instance);
-
-  mini_object->refcount = 1;
-
-  /* we delay initialising the mini object's private data until it's actually
-   * needed for now (mini_object->priv automatically inited to NULL) */
-}
-
-static GstMiniObject *
-gst_mini_object_copy_default (const GstMiniObject * obj)
-{
-  g_warning ("GstMiniObject classes must implement GstMiniObject::copy");
-  return NULL;
-}
-
-static void
-gst_mini_object_finalize (GstMiniObject * obj)
-{
-  /* do nothing */
-
-  /* WARNING: if anything is ever put in this method, make sure that the
-   * following sub-classes' finalize method chains up to this one:
-   * gstbuffer
-   * gstevent
-   * gstmessage
-   * gstquery
-   */
-}
-
 /**
- * gst_mini_object_new:
+ * gst_mini_object_init:
+ * @mini_object: a #GstMiniObject 
  * @type: the #GType of the mini-object to create
+ * @size: the size of the data
  *
- * Creates a new mini-object of the desired type.
+ * Initializes a mini-object with the desired type and size.
  *
  * MT safe
  *
  * Returns: (transfer full): the new mini-object.
  */
-GstMiniObject *
-gst_mini_object_new (GType type)
+void
+gst_mini_object_init (GstMiniObject * mini_object, GType type, gsize size)
 {
-  GstMiniObject *mini_object;
-
-  /* we don't support dynamic types because they really aren't useful,
-   * and could cause refcount problems */
-  mini_object = (GstMiniObject *) g_type_create_instance (type);
-
-#ifndef GST_DISABLE_TRACE
-  gst_alloc_trace_new (_gst_mini_object_trace, mini_object);
-#endif
-
-  return mini_object;
+  mini_object->type = type;
+  mini_object->refcount = 1;
+  mini_object->flags = 0;
+  mini_object->size = size;
+  mini_object->n_weak_refs = 0;
+  mini_object->weak_refs = NULL;
 }
 
-/* FIXME 0.11: Current way of doing the copy makes it impossible
- * to currectly chain to the parent classes and do a copy in a
- * subclass without knowing all internals of the parent classes.
- *
- * For 0.11 we should do something like the following:
- *  - The GstMiniObjectClass::copy() implementation of GstMiniObject
- *    should call g_type_create_instance() with the type of the source
- *    object.
- *  - All GstMiniObjectClass::copy() implementations should as first
- *    thing chain up to the parent class and then do whatever they need
- *    to do to copy their type specific data. Note that this way the
- *    instance_init() functions are called!
- */
-
 /**
  * gst_mini_object_copy:
  * @mini_object: the mini-object to copy
@@ -250,13 +84,16 @@ gst_mini_object_new (GType type)
 GstMiniObject *
 gst_mini_object_copy (const GstMiniObject * mini_object)
 {
-  GstMiniObjectClass *mo_class;
+  GstMiniObject *copy;
 
   g_return_val_if_fail (mini_object != NULL, NULL);
 
-  mo_class = GST_MINI_OBJECT_GET_CLASS (mini_object);
+  if (mini_object->copy)
+    copy = mini_object->copy (mini_object);
+  else
+    copy = NULL;
 
-  return mo_class->copy (mini_object);
+  return copy;
 }
 
 /**
@@ -277,8 +114,7 @@ gst_mini_object_is_writable (const GstMiniObject * mini_object)
 {
   g_return_val_if_fail (mini_object != NULL, FALSE);
 
-  return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1) &&
-      ((mini_object->flags & GST_MINI_OBJECT_FLAG_READONLY) == 0);
+  return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
 }
 
 /**
@@ -304,9 +140,9 @@ gst_mini_object_make_writable (GstMiniObject * mini_object)
   if (gst_mini_object_is_writable (mini_object)) {
     ret = mini_object;
   } else {
-    GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy %s miniobject",
-        g_type_name (G_TYPE_FROM_INSTANCE (mini_object)));
     ret = gst_mini_object_copy (mini_object);
+    GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy %s miniobject %p -> %p",
+        g_type_name (GST_MINI_OBJECT_TYPE (mini_object)), mini_object, ret);
     gst_mini_object_unref (mini_object);
   }
 
@@ -337,7 +173,6 @@ gst_mini_object_ref (GstMiniObject * mini_object)
    * the object
    g_return_val_if_fail (mini_object->refcount > 0, NULL);
    */
-  g_return_val_if_fail (GST_IS_MINI_OBJECT (mini_object), NULL);
 
   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object,
       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
@@ -349,44 +184,13 @@ gst_mini_object_ref (GstMiniObject * mini_object)
 }
 
 static void
-weak_refs_notify (WeakRefStack * wstack)
+weak_refs_notify (GstMiniObject * obj)
 {
   guint i;
 
-  for (i = 0; i < wstack->n_weak_refs; i++)
-    wstack->weak_refs[i].notify (wstack->weak_refs[i].data, wstack->object);
-  g_free (wstack);
-}
-
-static void
-gst_mini_object_free (GstMiniObject * mini_object)
-{
-  GstMiniObjectClass *mo_class;
-
-  /* At this point, the refcount of the object is 0. We increase the refcount
-   * here because if a subclass recycles the object and gives out a new
-   * reference we don't want to free the instance anymore. */
-  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object,
-      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
-      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) + 1);
-
-  g_atomic_int_inc (&mini_object->refcount);
-
-  mo_class = GST_MINI_OBJECT_GET_CLASS_UNCHECKED (mini_object);
-  mo_class->finalize (mini_object);
-
-  /* decrement the refcount again, if the subclass recycled the object we don't
-   * want to free the instance anymore */
-  if (G_LIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
-    /* The weak reference stack is freed in the notification function */
-    if (mini_object->priv != NULL && mini_object->priv->wstack != NULL)
-      weak_refs_notify (mini_object->priv->wstack);
-
-#ifndef GST_DISABLE_TRACE
-    gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
-#endif
-    g_type_free_instance ((GTypeInstance *) mini_object);
-  }
+  for (i = 0; i < obj->n_weak_refs; i++)
+    obj->weak_refs[i].notify (obj->weak_refs[i].data, obj);
+  g_free (obj->weak_refs);
 }
 
 /**
@@ -399,7 +203,7 @@ gst_mini_object_free (GstMiniObject * mini_object)
 void
 gst_mini_object_unref (GstMiniObject * mini_object)
 {
-  g_return_if_fail (GST_IS_MINI_OBJECT (mini_object));
+  g_return_if_fail (mini_object != NULL);
   g_return_if_fail (mini_object->refcount > 0);
 
   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p unref %d->%d",
@@ -408,111 +212,27 @@ gst_mini_object_unref (GstMiniObject * mini_object)
       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);
 
   if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
-    gst_mini_object_free (mini_object);
-  }
-}
+    gboolean do_free;
 
-/**
- * gst_mini_object_weak_ref: (skip)
- * @object: #GstMiniObject to reference weakly
- * @notify: callback to invoke before the mini object is freed
- * @data: extra data to pass to notify
- *
- * Adds a weak reference callback to a mini object. Weak references are
- * used for notification when a mini object is finalized. They are called
- * "weak references" because they allow you to safely hold a pointer
- * to the mini object without calling gst_mini_object_ref()
- * (gst_mini_object_ref() adds a strong reference, that is, forces the object
- * to stay alive).
- *
- * Since: 0.10.36
- */
-void
-gst_mini_object_weak_ref (GstMiniObject * object,
-    GstMiniObjectWeakNotify notify, gpointer data)
-{
-  guint i;
+    if (mini_object->dispose)
+      do_free = mini_object->dispose (mini_object);
+    else
+      do_free = TRUE;
 
-  g_return_if_fail (GST_IS_MINI_OBJECT (object));
-  g_return_if_fail (notify != NULL);
-  g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
+    /* if the subclass recycled the object (and returned FALSE) we don't
+     * want to free the instance anymore */
+    if (G_LIKELY (do_free)) {
+      /* The weak reference stack is freed in the notification function */
+      if (mini_object->n_weak_refs)
+        weak_refs_notify (mini_object);
 
-  G_LOCK (weak_refs_mutex);
-
-  if (object->priv == NULL) {
-    object->priv = G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_MINI_OBJECT,
-        GstMiniObjectPrivate);
-
-    /* object->priv->wstack will have been inited to NULL automatically */
-  }
-
-  if (object->priv->wstack) {
-    /* Don't add the weak reference if it already exists. */
-    for (i = 0; i < object->priv->wstack->n_weak_refs; i++) {
-      if (object->priv->wstack->weak_refs[i].notify == notify &&
-          object->priv->wstack->weak_refs[i].data == data) {
-        g_warning ("%s: Attempt to re-add existing weak ref %p(%p) failed.",
-            G_STRFUNC, notify, data);
-        goto found;
-      }
+#ifndef GST_DISABLE_TRACE
+      gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
+#endif
+      if (mini_object->free)
+        mini_object->free (mini_object);
     }
-
-    i = object->priv->wstack->n_weak_refs++;
-    object->priv->wstack =
-        g_realloc (object->priv->wstack, sizeof (*(object->priv->wstack)) +
-        sizeof (object->priv->wstack->weak_refs[0]) * i);
-  } else {
-    object->priv->wstack = g_renew (WeakRefStack, NULL, 1);
-    object->priv->wstack->object = object;
-    object->priv->wstack->n_weak_refs = 1;
-    i = 0;
   }
-  object->priv->wstack->weak_refs[i].notify = notify;
-  object->priv->wstack->weak_refs[i].data = data;
-found:
-  G_UNLOCK (weak_refs_mutex);
-}
-
-/**
- * gst_mini_object_weak_unref: (skip)
- * @object: #GstMiniObject to remove a weak reference from
- * @notify: callback to search for
- * @data: data to search for
- *
- * Removes a weak reference callback to a mini object.
- *
- * Since: 0.10.36
- */
-void
-gst_mini_object_weak_unref (GstMiniObject * object,
-    GstMiniObjectWeakNotify notify, gpointer data)
-{
-  gboolean found_one = FALSE;
-
-  g_return_if_fail (GST_IS_MINI_OBJECT (object));
-  g_return_if_fail (notify != NULL);
-
-  G_LOCK (weak_refs_mutex);
-
-  if (object->priv != NULL && object->priv->wstack != NULL) {
-    guint i;
-
-    for (i = 0; i < object->priv->wstack->n_weak_refs; i++)
-      if (object->priv->wstack->weak_refs[i].notify == notify &&
-          object->priv->wstack->weak_refs[i].data == data) {
-        found_one = TRUE;
-        object->priv->wstack->n_weak_refs -= 1;
-        if (i != object->priv->wstack->n_weak_refs)
-          object->priv->wstack->weak_refs[i] =
-              object->priv->wstack->weak_refs[object->priv->wstack->
-              n_weak_refs];
-
-        break;
-      }
-  }
-  G_UNLOCK (weak_refs_mutex);
-  if (!found_one)
-    g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
 }
 
 /**
@@ -521,16 +241,20 @@ gst_mini_object_weak_unref (GstMiniObject * object,
  *     be replaced
  * @newdata: pointer to new mini-object
  *
- * Modifies a pointer to point to a new mini-object.  The modification
- * is done atomically, and the reference counts are updated correctly.
+ * Atomically modifies a pointer to point to a new mini-object.
+ * The reference count of @olddata is decreased and the reference count of
+ * @newdata is increased.
+ *
  * Either @newdata and the value pointed to by @olddata may be NULL.
+ *
+ * Returns: TRUE if @newdata was different from @olddata
  */
-void
+gboolean
 gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
 {
   GstMiniObject *olddata_val;
 
-  g_return_if_fail (olddata != NULL);
+  g_return_val_if_fail (olddata != NULL, FALSE);
 
   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p (%d) with %p (%d)",
       *olddata, *olddata ? (*olddata)->refcount : 0,
@@ -538,263 +262,182 @@ gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
 
   olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
 
-  if (olddata_val == newdata)
-    return;
+  if (G_UNLIKELY (olddata_val == newdata))
+    return FALSE;
 
   if (newdata)
     gst_mini_object_ref (newdata);
 
-  while (!g_atomic_pointer_compare_and_exchange ((gpointer *) olddata,
-          olddata_val, newdata)) {
+  while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
+              olddata, olddata_val, newdata))) {
     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+    if (G_UNLIKELY (olddata_val == newdata))
+      break;
   }
 
   if (olddata_val)
     gst_mini_object_unref (olddata_val);
-}
-
-static void
-gst_value_mini_object_init (GValue * value)
-{
-  value->data[0].v_pointer = NULL;
-}
-
-static void
-gst_value_mini_object_free (GValue * value)
-{
-  if (value->data[0].v_pointer) {
-    gst_mini_object_unref (GST_MINI_OBJECT_CAST (value->data[0].v_pointer));
-  }
-}
-
-static void
-gst_value_mini_object_copy (const GValue * src_value, GValue * dest_value)
-{
-  if (src_value->data[0].v_pointer) {
-    dest_value->data[0].v_pointer =
-        gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->data[0].
-            v_pointer));
-  } else {
-    dest_value->data[0].v_pointer = NULL;
-  }
-}
-
-static gpointer
-gst_value_mini_object_peek_pointer (const GValue * value)
-{
-  return value->data[0].v_pointer;
-}
-
-static gchar *
-gst_value_mini_object_collect (GValue * value, guint n_collect_values,
-    GTypeCValue * collect_values, guint collect_flags)
-{
-  if (collect_values[0].v_pointer) {
-    value->data[0].v_pointer =
-        gst_mini_object_ref (collect_values[0].v_pointer);
-  } else {
-    value->data[0].v_pointer = NULL;
-  }
-
-  return NULL;
-}
-
-static gchar *
-gst_value_mini_object_lcopy (const GValue * value, guint n_collect_values,
-    GTypeCValue * collect_values, guint collect_flags)
-{
-  gpointer *mini_object_p = collect_values[0].v_pointer;
 
-  if (!mini_object_p) {
-    return g_strdup_printf ("value location for '%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-  }
-
-  if (!value->data[0].v_pointer)
-    *mini_object_p = NULL;
-  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
-    *mini_object_p = value->data[0].v_pointer;
-  else
-    *mini_object_p = gst_mini_object_ref (value->data[0].v_pointer);
-
-  return NULL;
+  return olddata_val != newdata;
 }
 
 /**
- * gst_value_set_mini_object:
- * @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
- * @mini_object: (transfer none): mini object value to set
+ * gst_mini_object_steal:
+ * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
+ *     be stolen
  *
- * Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
- * @mini_object.
- * The caller retains ownership of the reference.
+ * Replace the current #GstMiniObject pointer to by @olddata with NULL and
+ * return the old value.
+ *
+ * Returns: the #GstMiniObject at @oldata
  */
-void
-gst_value_set_mini_object (GValue * value, GstMiniObject * mini_object)
+GstMiniObject *
+gst_mini_object_steal (GstMiniObject ** olddata)
 {
-  gpointer *pointer_p;
-
-  g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
-  g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
+  GstMiniObject *olddata_val;
 
-  pointer_p = &value->data[0].v_pointer;
-  gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
-}
+  g_return_val_if_fail (olddata != NULL, NULL);
 
-/**
- * gst_value_take_mini_object:
- * @value: a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
- * @mini_object: (transfer full): mini object value to take
- *
- * Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
- * @mini_object.
- * Takes over the ownership of the caller's reference to @mini_object;
- * the caller doesn't have to unref it any more.
- */
-void
-gst_value_take_mini_object (GValue * value, GstMiniObject * mini_object)
-{
-  gpointer *pointer_p;
-
-  g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
-  g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
+  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "steal %p (%d)",
+      *olddata, *olddata ? (*olddata)->refcount : 0);
 
-  pointer_p = &value->data[0].v_pointer;
-  /* takes additional refcount */
-  gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
-  /* remove additional refcount */
-  if (mini_object)
-    gst_mini_object_unref (mini_object);
-}
-
-/**
- * gst_value_get_mini_object:
- * @value:   a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
- *
- * Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue.
- * Does not increase the refcount of the returned object.
- *
- * Returns: (transfer none): mini object contents of @value
- */
-GstMiniObject *
-gst_value_get_mini_object (const GValue * value)
-{
-  g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
+  do {
+    olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+    if (olddata_val == NULL)
+      break;
+  } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
+              olddata, olddata_val, NULL)));
 
-  return value->data[0].v_pointer;
+  return olddata_val;
 }
 
 /**
- * gst_value_dup_mini_object:
- * @value:   a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
+ * gst_mini_object_take:
+ * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
+ *     be replaced
+ * @newdata: pointer to new mini-object
  *
- * Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue,
- * increasing its reference count. If the contents of the #GValue
- * are %NULL, %NULL will be returned.
+ * Modifies a pointer to point to a new mini-object. The modification
+ * is done atomically. This version is similar to gst_mini_object_replace()
+ * except that it does not increase the refcount of @newdata and thus
+ * takes ownership of @newdata.
  *
- * Returns: (transfer full): mini object contents of @value
+ * Either @newdata and the value pointed to by @olddata may be NULL.
  *
- * Since: 0.10.20
+ * Returns: TRUE if @newdata was different from @olddata
  */
-GstMiniObject *
-gst_value_dup_mini_object (const GValue * value)
+gboolean
+gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata)
 {
-  g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
+  GstMiniObject *olddata_val;
 
-  return value->data[0].v_pointer ? gst_mini_object_ref (value->
-      data[0].v_pointer) : NULL;
-}
+  g_return_val_if_fail (olddata != NULL, FALSE);
 
+  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "take %p (%d) with %p (%d)",
+      *olddata, *olddata ? (*olddata)->refcount : 0,
+      newdata, newdata ? newdata->refcount : 0);
 
-/* param spec */
+  do {
+    olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+    if (G_UNLIKELY (olddata_val == newdata))
+      break;
+  } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
+              olddata, olddata_val, newdata)));
 
-static void
-param_mini_object_init (GParamSpec * pspec)
-{
-  /* GParamSpecMiniObject *ospec = G_PARAM_SPEC_MINI_OBJECT (pspec); */
-}
+  if (olddata_val)
+    gst_mini_object_unref (olddata_val);
 
-static void
-param_mini_object_set_default (GParamSpec * pspec, GValue * value)
-{
-  value->data[0].v_pointer = NULL;
+  return olddata_val != newdata;
 }
 
-static gboolean
-param_mini_object_validate (GParamSpec * pspec, GValue * value)
+/**
+ * gst_mini_object_weak_ref: (skip)
+ * @object: #GstMiniObject to reference weakly
+ * @notify: callback to invoke before the mini object is freed
+ * @data: extra data to pass to notify
+ *
+ * Adds a weak reference callback to a mini object. Weak references are
+ * used for notification when a mini object is finalized. They are called
+ * "weak references" because they allow you to safely hold a pointer
+ * to the mini object without calling gst_mini_object_ref()
+ * (gst_mini_object_ref() adds a strong reference, that is, forces the object
+ * to stay alive).
+ *
+ * Since: 0.10.35
+ */
+void
+gst_mini_object_weak_ref (GstMiniObject * object,
+    GstMiniObjectWeakNotify notify, gpointer data)
 {
-  GstMiniObject *mini_object = value->data[0].v_pointer;
-  gboolean changed = FALSE;
-
-  if (mini_object
-      && !g_value_type_compatible (G_OBJECT_TYPE (mini_object),
-          pspec->value_type)) {
-    gst_mini_object_unref (mini_object);
-    value->data[0].v_pointer = NULL;
-    changed = TRUE;
-  }
-
-  return changed;
-}
+  guint i;
 
-static gint
-param_mini_object_values_cmp (GParamSpec * pspec,
-    const GValue * value1, const GValue * value2)
-{
-  guint8 *p1 = value1->data[0].v_pointer;
-  guint8 *p2 = value2->data[0].v_pointer;
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (notify != NULL);
+  g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
 
-  /* not much to compare here, try to at least provide stable lesser/greater result */
+  G_LOCK (weak_refs_mutex);
 
-  return p1 < p2 ? -1 : p1 > p2;
-}
+  if (object->n_weak_refs) {
+    /* Don't add the weak reference if it already exists. */
+    for (i = 0; i < object->n_weak_refs; i++) {
+      if (object->weak_refs[i].notify == notify &&
+          object->weak_refs[i].data == data) {
+        g_warning ("%s: Attempt to re-add existing weak ref %p(%p) failed.",
+            G_STRFUNC, notify, data);
+        goto found;
+      }
+    }
 
-GType
-gst_param_spec_mini_object_get_type (void)
-{
-  static GType type;
-
-  if (G_UNLIKELY (type) == 0) {
-    static const GParamSpecTypeInfo pspec_info = {
-      sizeof (GstParamSpecMiniObject),  /* instance_size */
-      16,                       /* n_preallocs */
-      param_mini_object_init,   /* instance_init */
-      G_TYPE_OBJECT,            /* value_type */
-      NULL,                     /* finalize */
-      param_mini_object_set_default,    /* value_set_default */
-      param_mini_object_validate,       /* value_validate */
-      param_mini_object_values_cmp,     /* values_cmp */
-    };
-    /* FIXME 0.11: Should really be GstParamSpecMiniObject */
-    type = g_param_type_register_static ("GParamSpecMiniObject", &pspec_info);
+    i = object->n_weak_refs++;
+    object->weak_refs =
+        g_realloc (object->weak_refs, sizeof (object->weak_refs[0]) * i);
+  } else {
+    object->weak_refs = g_malloc0 (sizeof (object->weak_refs[0]));
+    object->n_weak_refs = 1;
+    i = 0;
   }
-
-  return type;
+  object->weak_refs[i].notify = notify;
+  object->weak_refs[i].data = data;
+found:
+  G_UNLOCK (weak_refs_mutex);
 }
 
 /**
- * gst_param_spec_mini_object:
- * @name: the canonical name of the property
- * @nick: the nickname of the property
- * @blurb: a short description of the property
- * @object_type: the #GstMiniObject #GType for the property
- * @flags: a combination of #GParamFlags
+ * gst_mini_object_weak_unref: (skip)
+ * @object: #GstMiniObject to remove a weak reference from
+ * @notify: callback to search for
+ * @data: data to search for
  *
- * Creates a new #GParamSpec instance that hold #GstMiniObject references.
+ * Removes a weak reference callback to a mini object.
  *
- * Returns: (transfer full): a newly allocated #GParamSpec instance
+ * Since: 0.10.35
  */
-GParamSpec *
-gst_param_spec_mini_object (const char *name, const char *nick,
-    const char *blurb, GType object_type, GParamFlags flags)
+void
+gst_mini_object_weak_unref (GstMiniObject * object,
+    GstMiniObjectWeakNotify notify, gpointer data)
 {
-  GstParamSpecMiniObject *ospec;
+  gboolean found_one = FALSE;
 
-  g_return_val_if_fail (g_type_is_a (object_type, GST_TYPE_MINI_OBJECT), NULL);
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (notify != NULL);
+
+  G_LOCK (weak_refs_mutex);
 
-  ospec = g_param_spec_internal (GST_TYPE_PARAM_MINI_OBJECT,
-      name, nick, blurb, flags);
-  G_PARAM_SPEC (ospec)->value_type = object_type;
+  if (object->n_weak_refs) {
+    guint i;
 
-  return G_PARAM_SPEC (ospec);
+    for (i = 0; i < object->n_weak_refs; i++)
+      if (object->weak_refs[i].notify == notify &&
+          object->weak_refs[i].data == data) {
+        found_one = TRUE;
+        object->n_weak_refs -= 1;
+        if (i != object->n_weak_refs)
+          object->weak_refs[i] = object->weak_refs[object->n_weak_refs];
+
+        break;
+      }
+  }
+  G_UNLOCK (weak_refs_mutex);
+  if (!found_one)
+    g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
 }
index 352066c..f4807a6 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_MINI_OBJECT          (gst_mini_object_get_type())
-#define GST_IS_MINI_OBJECT(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MINI_OBJECT))
-#define GST_IS_MINI_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MINI_OBJECT))
-#define GST_MINI_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MINI_OBJECT, GstMiniObjectClass))
-#define GST_MINI_OBJECT(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MINI_OBJECT, GstMiniObject))
-#define GST_MINI_OBJECT_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MINI_OBJECT, GstMiniObjectClass))
-#define GST_MINI_OBJECT_CAST(obj)     ((GstMiniObject*)(obj))
-#define GST_MINI_OBJECT_CONST_CAST(obj) ((const GstMiniObject*)(obj))
+#define GST_IS_MINI_OBJECT_TYPE(obj,type)  ((obj) && GST_MINI_OBJECT_TYPE(obj) == (type))
+#define GST_MINI_OBJECT_CAST(obj)          ((GstMiniObject*)(obj))
+#define GST_MINI_OBJECT_CONST_CAST(obj)    ((const GstMiniObject*)(obj))
+#define GST_MINI_OBJECT(obj)               (GST_MINI_OBJECT_CAST(obj))
 
 typedef struct _GstMiniObject GstMiniObject;
-typedef struct _GstMiniObjectClass GstMiniObjectClass;
 
 /**
  * GstMiniObjectCopyFunction:
  * @obj: MiniObject to copy
  *
- * Virtual function prototype for methods to create copies of instances.
+ * Function prototype for methods to create copies of instances.
  *
  * Returns: reference to cloned instance.
  */
 typedef GstMiniObject * (*GstMiniObjectCopyFunction) (const GstMiniObject *obj);
 /**
- * GstMiniObjectFinalizeFunction:
- * @obj: MiniObject to finalize
+ * GstMiniObjectDisposeFunction:
+ * @obj: MiniObject to dispose
  *
- * Virtual function prototype for methods to free ressources used by
- * mini-objects. Subclasses of the mini object are allowed to revive the
+ * Function prototype for when a miniobject has lost its last refcount.
+ * Implementation of the mini object are allowed to revive the
  * passed object by doing a gst_mini_object_ref(). If the object is not
- * revived after the finalize function, the memory associated with the
- * object is freed.
+ * revived after the dispose function, the function should return %TRUE
+ * and the memory associated with the object is freed.
+ *
+ * Returns: %TRUE if the object should be cleaned up.
+ */
+typedef gboolean (*GstMiniObjectDisposeFunction) (GstMiniObject *obj);
+/**
+ * GstMiniObjectFreeFunction:
+ * @obj: MiniObject to free
+ *
+ * Virtual function prototype for methods to free ressources used by
+ * mini-objects.
+ */
+typedef void (*GstMiniObjectFreeFunction) (GstMiniObject *obj);
+
+ /**
+ * GstMiniObjectWeakNotify:
+ * @data: data that was provided when the weak reference was established
+ * @where_the_mini_object_was: the mini object being finalized
+ *
+ * A #GstMiniObjectWeakNotify function can be added to a mini object as a
+ * callback that gets triggered when the mini object is finalized. Since the
+ * mini object is already being finalized when the #GstMiniObjectWeakNotify is
+ * called, there's not much you could do with the object, apart from e.g. using
+ * its adress as hash-index or the like.
+ *
+ * Since: 0.10.35
  */
-typedef void (*GstMiniObjectFinalizeFunction) (GstMiniObject *obj);
+typedef void (*GstMiniObjectWeakNotify) (gpointer data,
+    GstMiniObject * where_the_mini_object_was);
 
 /**
  * GST_MINI_OBJECT_FLAGS:
@@ -68,6 +89,13 @@ typedef void (*GstMiniObjectFinalizeFunction) (GstMiniObject *obj);
  *
  * This macro returns the entire set of flags for the mini-object.
  */
+#define GST_MINI_OBJECT_TYPE(obj)  (GST_MINI_OBJECT_CAST(obj)->type)
+/**
+ * GST_MINI_OBJECT_FLAGS:
+ * @obj: MiniObject to return flags for.
+ *
+ * This macro returns the entire set of flags for the mini-object.
+ */
 #define GST_MINI_OBJECT_FLAGS(obj)  (GST_MINI_OBJECT_CAST(obj)->flags)
 /**
  * GST_MINI_OBJECT_FLAG_IS_SET:
@@ -95,27 +123,13 @@ typedef void (*GstMiniObjectFinalizeFunction) (GstMiniObject *obj);
 #define GST_MINI_OBJECT_FLAG_UNSET(obj,flag)         (GST_MINI_OBJECT_FLAGS (obj) &= ~(flag))
 
 /**
- * GST_VALUE_HOLDS_MINI_OBJECT:
- * @value: the #GValue to check
- *
- * Checks if the given #GValue contains a #GST_TYPE_MINI_OBJECT value.
- */
-#define GST_VALUE_HOLDS_MINI_OBJECT(value)  (G_VALUE_HOLDS(value, GST_TYPE_MINI_OBJECT))
-
-/**
  * GstMiniObjectFlags:
- * @GST_MINI_OBJECT_FLAG_READONLY: is the miniobject readonly or writable
- * @GST_MINI_OBJECT_FLAG_RESERVED1: a flag reserved for internal use e.g. as
- *     GST_BUFFER_FLAG_MEDIA4. Since: 0.10.33.
  * @GST_MINI_OBJECT_FLAG_LAST: first flag that can be used by subclasses.
  *
  * Flags for the mini object
  */
-
 typedef enum
 {
-  GST_MINI_OBJECT_FLAG_READONLY = (1<<0),
-  GST_MINI_OBJECT_FLAG_RESERVED1 = (1<<1),
   /* padding */
   GST_MINI_OBJECT_FLAG_LAST = (1<<4)
 } GstMiniObjectFlags;
@@ -136,111 +150,77 @@ typedef enum
 #define GST_MINI_OBJECT_REFCOUNT_VALUE(obj)     (g_atomic_int_get (&(GST_MINI_OBJECT_CAST(obj))->refcount))
 
 /**
- * GstMiniObjectWeakNotify:
- * @data: data that was provided when the weak reference was established
- * @where_the_mini_object_was: the mini object being finalized
- * 
- * A #GstMiniObjectWeakNotify function can be added to a mini object as a
- * callback that gets triggered when the mini object is finalized. Since the
- * mini object is already being finalized when the #GstMiniObjectWeakNotify is
- * called, there's not much you could do with the object, apart from e.g. using
- * its adress as hash-index or the like. 
- *
- * Since: 0.10.35
+ * GST_MINI_OBJECT_SIZE:
+ * @obj: a #GstMiniObject
  *
+ * Get the allocated size of @obj.
  */
-typedef void (*GstMiniObjectWeakNotify) (gpointer data,
-    GstMiniObject * where_the_mini_object_was);
-
-typedef struct _GstMiniObjectPrivate GstMiniObjectPrivate;
+#define GST_MINI_OBJECT_SIZE(obj)              ((GST_MINI_OBJECT_CAST(obj))->size)
 
 /**
  * GstMiniObject:
- * @instance: type instance
+ * @type: the GType of the object
  * @refcount: atomic refcount
  * @flags: extra flags.
- * 
+ * @size: the size of the structure
+ * @copy: a copy function
+ * @dispose: a dispose function
+ * @free: the free function
+ *
  * Base class for refcounted lightweight objects.
  * Ref Func: gst_mini_object_ref
  * Unref Func: gst_mini_object_unref
- * Set Value Func: gst_value_set_mini_object
- * Get Value Func: gst_value_get_mini_object
+ * Set Value Func: g_value_set_boxed
+ * Get Value Func: g_value_get_boxed
  */
 struct _GstMiniObject {
-  GTypeInstance instance;
-  /*< public >*/ /* with COW */
-  gint refcount;
-  guint flags;
-
-  /*< private >*/
-  GstMiniObjectPrivate *priv;
-};
+  GType   type;
 
-struct _GstMiniObjectClass {
-  GTypeClass type_class;
+  /*< public >*/ /* with COW */
+  gint    refcount;
+  guint   flags;
+  gsize   size;
 
   GstMiniObjectCopyFunction copy;
-  GstMiniObjectFinalizeFunction finalize;
-
-  /*< private >*/
-  gpointer _gst_reserved;
+  GstMiniObjectDisposeFunction dispose;
+  GstMiniObjectFreeFunction free;
+
+  /* < private > */
+  /* Used to keep track of weak ref notifies */
+  guint n_weak_refs;
+  struct
+  {
+    GstMiniObjectWeakNotify notify;
+    gpointer data;
+  } *weak_refs;
 };
 
-GType          gst_mini_object_get_type        (void);
+void            gst_mini_object_init            (GstMiniObject *mini_object,
+                                                 GType type, gsize size);
 
-GstMiniObject*         gst_mini_object_new             (GType type) G_GNUC_MALLOC;
-GstMiniObject*         gst_mini_object_copy            (const GstMiniObject *mini_object) G_GNUC_MALLOC;
-gboolean       gst_mini_object_is_writable     (const GstMiniObject *mini_object);
-GstMiniObject*  gst_mini_object_make_writable  (GstMiniObject *mini_object);
+GstMiniObject * gst_mini_object_copy           (const GstMiniObject *mini_object) G_GNUC_MALLOC;
+gboolean        gst_mini_object_is_writable    (const GstMiniObject *mini_object);
+GstMiniObject * gst_mini_object_make_writable  (GstMiniObject *mini_object);
 
 /* refcounting */
-GstMiniObject*         gst_mini_object_ref             (GstMiniObject *mini_object);
-void           gst_mini_object_unref           (GstMiniObject *mini_object);
-void           gst_mini_object_weak_ref        (GstMiniObject *object,
+GstMiniObject * gst_mini_object_ref            (GstMiniObject *mini_object);
+void            gst_mini_object_unref          (GstMiniObject *mini_object);
+
+void            gst_mini_object_weak_ref        (GstMiniObject *object,
                                                 GstMiniObjectWeakNotify notify,
                                                 gpointer data);
-void           gst_mini_object_weak_unref      (GstMiniObject *object,
+void            gst_mini_object_weak_unref     (GstMiniObject *object,
                                                 GstMiniObjectWeakNotify notify,
                                                 gpointer data);
-void           gst_mini_object_replace         (GstMiniObject **olddata, GstMiniObject *newdata);
-
-/* GParamSpec */
-
-#define        GST_TYPE_PARAM_MINI_OBJECT              (gst_param_spec_mini_object_get_type())
-#define GST_IS_PARAM_SPEC_MINI_OBJECT(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), \
-                                                 GST_TYPE_PARAM_MINI_OBJECT))
-#define GST_PARAM_SPEC_MINI_OBJECT(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), \
-                                                 GST_TYPE_PARAM_MINI_OBJECT, \
-                                                GstParamSpecMiniObject))
-
-typedef struct _GstParamSpecMiniObject GstParamSpecMiniObject;
-
-/**
- * GstParamSpecMiniObject:
- * @parent_instance: private %GParamSpec portion
- * 
- * A %GParamSpec derived structure that contains the meta data
- * for %GstMiniObject properties.
- */
-struct _GstParamSpecMiniObject
-{
-  GParamSpec parent_instance;
-};
-
-
-GType gst_param_spec_mini_object_get_type (void);
-
-GParamSpec*    gst_param_spec_mini_object      (const char *name, const char *nick,
-                                                const char *blurb, GType object_type, 
-                                                GParamFlags flags) G_GNUC_MALLOC;
-
-/* GValue stuff */
 
-void           gst_value_set_mini_object       (GValue *value, GstMiniObject *mini_object);
-void           gst_value_take_mini_object      (GValue *value, GstMiniObject *mini_object);
-GstMiniObject*         gst_value_get_mini_object       (const GValue *value);
-GstMiniObject*  gst_value_dup_mini_object       (const GValue *value);
+gboolean        gst_mini_object_replace         (GstMiniObject **olddata, GstMiniObject *newdata);
+gboolean        gst_mini_object_take            (GstMiniObject **olddata, GstMiniObject *newdata);
+GstMiniObject * gst_mini_object_steal           (GstMiniObject **olddata);
 
+#define GST_DEFINE_MINI_OBJECT_TYPE(TypeName,type_name) \
+   G_DEFINE_BOXED_TYPE(TypeName,type_name,              \
+       (GBoxedCopyFunc) gst_mini_object_ref,            \
+       (GBoxedFreeFunc)gst_mini_object_unref)
 
 G_END_DECLS
 
index 5f3aa78..7863256 100644 (file)
  * gst_object_set_name() and gst_object_get_name() are used to set/get the name
  * of the object.
  *
+ * <refsect2>
+ * <title>controlled properties</title>
+ * <para>
+ * Controlled properties offers a lightweight way to adjust gobject
+ * properties over stream-time. It works by using time-stamped value pairs that
+ * are queued for element-properties. At run-time the elements continously pull
+ * values changes for the current stream-time.
+ *
+ * What needs to be changed in a #GstElement?
+ * Very little - it is just two steps to make a plugin controllable!
+ * <orderedlist>
+ *   <listitem><para>
+ *     mark gobject-properties paramspecs that make sense to be controlled,
+ *     by GST_PARAM_CONTROLLABLE.
+ *   </para></listitem>
+ *   <listitem><para>
+ *     when processing data (get, chain, loop function) at the beginning call
+ *     gst_object_sync_values(element,timestamp).
+ *     This will made the controller to update all gobject properties that are under
+ *     control with the current values based on timestamp.
+ *   </para></listitem>
+ * </orderedlist>
+ *
+ * What needs to be done in applications?
+ * Again its not a lot to change.
+ * <orderedlist>
+ *   <listitem><para>
+ *     first put some properties under control, by calling
+ *     gst_object_control_properties (object, "prop1", "prop2",...);
+ *   </para></listitem>
+ *   <listitem><para>
+ *     create a #GstControlSource.
+ *     csource = gst_interpolation_control_source_new ();
+ *     g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+ *   </para></listitem>
+ *   <listitem><para>
+ *     Attach the #GstControlSource on the controller to a property.
+ *     gst_object_add_control_binding (object, gst_control_binding_direct_new (objetct, "prop1", csource));
+ *   </para></listitem>
+ *   <listitem><para>
+ *     Set the control values
+ *     gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1);
+ *     gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);
+ *   </para></listitem>
+ *   <listitem><para>
+ *     start your pipeline
+ *   </para></listitem>
+ * </orderedlist>
+ * </para>
+ * </refsect2>
+ *
  * Last reviewed on 2005-11-09 (0.9.4)
  */
 
 
 #include "gstobject.h"
 #include "gstmarshal.h"
+#include "gstclock.h"
+#include "gstcontrolbinding.h"
+#include "gstcontrolsource.h"
 #include "gstinfo.h"
+#include "gstparamspecs.h"
 #include "gstutils.h"
 
 #ifndef GST_DISABLE_TRACE
@@ -99,24 +154,18 @@ static GstAllocTrace *_gst_object_trace;
 #define DEBUG_REFCOUNT
 
 /* Object signals and args */
-/* FIXME-0.11: have a read-only parent property instead of the two signals
- * then we get notify::parent for free */
 enum
 {
-  PARENT_SET,
-  PARENT_UNSET,
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  OBJECT_SAVED,
-#endif
   DEEP_NOTIFY,
   LAST_SIGNAL
 };
 
 enum
 {
-  ARG_0,
-  ARG_NAME
-      /* FILL ME */
+  PROP_0,
+  PROP_NAME,
+  PROP_PARENT,
+  PROP_LAST
 };
 
 enum
@@ -130,19 +179,11 @@ static GData *object_name_counts = NULL;
 
 G_LOCK_DEFINE_STATIC (object_name_mutex);
 
-typedef struct _GstSignalObject GstSignalObject;
-typedef struct _GstSignalObjectClass GstSignalObjectClass;
-
-static GType gst_signal_object_get_type (void);
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
-#endif
-
 static void gst_object_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_object_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
+
 static void gst_object_dispatch_properties_changed (GObject * object,
     guint n_pspecs, GParamSpec ** pspecs);
 
@@ -151,36 +192,17 @@ static void gst_object_finalize (GObject * object);
 
 static gboolean gst_object_set_name_default (GstObject * object);
 
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#undef GstXmlNodePtr
-#define GstXmlNodePtr xmlNodePtr
-#include <libxml/parser.h>
-GstXmlNodePtr gst_object_save_thyself (GstObject * object,
-    GstXmlNodePtr parent);
-void gst_object_restore_thyself (GstObject * object, GstXmlNodePtr parent);
-void gst_class_signal_emit_by_name (GstObject * object, const gchar * name,
-    GstXmlNodePtr self);
-#endif
-#endif
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static void gst_object_real_restore_thyself (GstObject * object,
-    GstXmlNodePtr self);
-#endif
-
-static GObjectClass *parent_class = NULL;
 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_OBJECT);
+static GParamSpec *properties[PROP_LAST];
+
+G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_INITIALLY_UNOWNED);
 
 static void
 gst_object_class_init (GstObjectClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
 #ifndef GST_DISABLE_TRACE
   _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT));
 #endif
@@ -188,56 +210,15 @@ gst_object_class_init (GstObjectClass * klass)
   gobject_class->set_property = gst_object_set_property;
   gobject_class->get_property = gst_object_get_property;
 
-  g_object_class_install_property (gobject_class, ARG_NAME,
-      g_param_spec_string ("name", "Name", "The name of the object",
-          NULL,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  properties[PROP_NAME] =
+      g_param_spec_string ("name", "Name", "The name of the object", NULL,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
 
-  /**
-   * GstObject::parent-set:
-   * @gstobject: a #GstObject
-   * @parent: the new parent
-   *
-   * Emitted when the parent of an object is set.
-   */
-  gst_object_signals[PARENT_SET] =
-      g_signal_new ("parent-set", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
-      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT);
+  properties[PROP_PARENT] =
+      g_param_spec_object ("parent", "Parent", "The parent of the object",
+      GST_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
-  /**
-   * GstObject::parent-unset:
-   * @gstobject: a #GstObject
-   * @parent: the old parent
-   *
-   * Emitted when the parent of an object is unset.
-   */
-  gst_object_signals[PARENT_UNSET] =
-      g_signal_new ("parent-unset", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, parent_unset), NULL,
-      NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT);
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  /**
-   * GstObject::object-saved:
-   * @gstobject: a #GstObject
-   * @xml_node: the xmlNodePtr of the parent node
-   *
-   * Trigered whenever a new object is saved to XML. You can connect to this
-   * signal to insert custom XML tags into the core XML.
-   */
-  /* FIXME This should be the GType of xmlNodePtr instead of G_TYPE_POINTER
-   *       (if libxml would use GObject)
-   */
-  gst_object_signals[OBJECT_SAVED] =
-      g_signal_new ("object-saved", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL,
-      NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
-
-  klass->restore_thyself =
-      ((void (*)(GstObject * object,
-              gpointer self)) *gst_object_real_restore_thyself);
-#endif
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
 
   /**
    * GstObject::deep-notify:
@@ -257,11 +238,6 @@ gst_object_class_init (GstObjectClass * klass)
       G_TYPE_PARAM);
 
   klass->path_string_separator = "/";
-  /* FIXME 0.11: Store this directly in the class struct */
-  klass->lock = g_slice_new (GStaticRecMutex);
-  g_static_rec_mutex_init (klass->lock);
-
-  klass->signal_object = g_object_newv (gst_signal_object_get_type (), 0, NULL);
 
   /* see the comments at gst_object_dispatch_properties_changed */
   gobject_class->dispatch_properties_changed
@@ -274,7 +250,7 @@ gst_object_class_init (GstObjectClass * klass)
 static void
 gst_object_init (GstObject * object)
 {
-  object->lock = g_mutex_new ();
+  g_mutex_init (&object->lock);
   object->parent = NULL;
   object->name = NULL;
   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object);
@@ -284,7 +260,9 @@ gst_object_init (GstObject * object)
 #endif
 
   object->flags = 0;
-  GST_OBJECT_FLAG_SET (object, GST_OBJECT_FLOATING);
+
+  object->control_rate = 100 * GST_MSECOND;
+  object->last_sync = GST_CLOCK_TIME_NONE;
 }
 
 /**
@@ -340,7 +318,7 @@ gst_object_unref (gpointer object)
 }
 
 /**
- * gst_object_ref_sink:
+ * gst_object_ref_sink: (skip)
  * @object: a #GstObject to sink
  *
  * Increase the reference count of @object, and possibly remove the floating
@@ -351,61 +329,18 @@ gst_object_unref (gpointer object)
  * the floating flag while leaving the reference count unchanged. If the object
  * is not floating, then this call adds a new normal reference increasing the
  * reference count by one.
- *
- * MT safe. This function grabs and releases @object lock.
- *
- * Since: 0.10.24
  */
-void
+gpointer
 gst_object_ref_sink (gpointer object)
 {
-  g_return_if_fail (GST_IS_OBJECT (object));
-
-  GST_OBJECT_LOCK (object);
-  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
-    GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object,
-        "unsetting floating flag");
-    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
-    GST_OBJECT_UNLOCK (object);
-  } else {
-    GST_OBJECT_UNLOCK (object);
-    gst_object_ref (object);
-  }
-}
-
-/**
- * gst_object_sink:
- * @object: a #GstObject to sink
- *
- * If @object was floating, the #GST_OBJECT_FLOATING flag is removed
- * and @object is unreffed. When @object was not floating,
- * this function does nothing.
- *
- * Any newly created object has a refcount of 1 and is floating.
- * This function should be used when creating a new object to
- * symbolically 'take ownership' of @object. This done by first doing a
- * gst_object_ref() to keep a reference to @object and then gst_object_sink()
- * to remove and unref any floating references to @object.
- * Use gst_object_set_parent() to have this done for you.
- *
- * MT safe. This function grabs and releases @object lock.
- */
-void
-gst_object_sink (gpointer object)
-{
-  g_return_if_fail (GST_IS_OBJECT (object));
-
-  GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "sink");
+  g_return_val_if_fail (object != NULL, NULL);
 
-  GST_OBJECT_LOCK (object);
-  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
-    GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "clear floating flag");
-    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
-    GST_OBJECT_UNLOCK (object);
-    gst_object_unref (object);
-  } else {
-    GST_OBJECT_UNLOCK (object);
-  }
+#ifdef DEBUG_REFCOUNT
+  GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref_sink %d->%d",
+      object, ((GObject *) object)->ref_count,
+      ((GObject *) object)->ref_count + 1);
+#endif
+  return g_object_ref_sink (object);
 }
 
 /**
@@ -414,25 +349,20 @@ gst_object_sink (gpointer object)
  *     replace
  * @newobj: (transfer none): a new #GstObject
  *
- * Unrefs the #GstObject pointed to by @oldobj, refs @newobj and
- * puts @newobj in *@oldobj. Be carefull when calling this
- * function, it does not take any locks. You might want to lock
- * the object owning @oldobj pointer before calling this
- * function.
+ * Atomically modifies a pointer to point to a new object.
+ * The reference count of @oldobj is decreased and the reference count of
+ * @newobj is increased.
  *
- * Make sure not to LOCK @oldobj because it might be unreffed
- * which could cause a deadlock when it is disposed.
+ * Either @newobj and the value pointed to by @oldobj may be NULL.
  *
- * Since 0.10.36, this function operates atomically.
+ * Returns: TRUE if @newobj was different from @oldobj
  */
-void
+gboolean
 gst_object_replace (GstObject ** oldobj, GstObject * newobj)
 {
   GstObject *oldptr;
 
-  g_return_if_fail (oldobj != NULL);
-  g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
-  g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
+  g_return_val_if_fail (oldobj != NULL, FALSE);
 
 #ifdef DEBUG_REFCOUNT
   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)",
@@ -442,13 +372,25 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
       newobj ? G_OBJECT (newobj)->ref_count : 0);
 #endif
 
+  oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
+
+  if (G_UNLIKELY (oldptr == newobj))
+    return FALSE;
+
   if (newobj)
     g_object_ref (newobj);
-  do {
-    oldptr = *oldobj;
-  } while (!G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE (oldobj, oldptr, newobj));
+
+  while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
+              oldobj, oldptr, newobj))) {
+    oldptr = g_atomic_pointer_get ((gpointer *) oldobj);
+    if (G_UNLIKELY (oldptr == newobj))
+      break;
+  }
+
   if (oldptr)
     g_object_unref (oldptr);
+
+  return oldptr != newobj;
 }
 
 /* dispose is called when the object has to release all links
@@ -456,6 +398,7 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
 static void
 gst_object_dispose (GObject * object)
 {
+  GstObject *self = (GstObject *) object;
   GstObject *parent;
 
   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
@@ -466,7 +409,17 @@ gst_object_dispose (GObject * object)
   GST_OBJECT_PARENT (object) = NULL;
   GST_OBJECT_UNLOCK (object);
 
-  parent_class->dispose (object);
+  if (self->control_bindings) {
+    GList *node;
+
+    for (node = self->control_bindings; node; node = g_list_next (node)) {
+      g_object_unref (node->data);
+    }
+    g_list_free (self->control_bindings);
+    self->control_bindings = NULL;
+  }
+
+  ((GObjectClass *) gst_object_parent_class)->dispose (object);
 
   return;
 
@@ -495,13 +448,13 @@ gst_object_finalize (GObject * object)
   g_signal_handlers_destroy (object);
 
   g_free (gstobject->name);
-  g_mutex_free (gstobject->lock);
+  g_mutex_clear (&gstobject->lock);
 
 #ifndef GST_DISABLE_TRACE
   gst_alloc_trace_free (_gst_object_trace, object);
 #endif
 
-  parent_class->finalize (object);
+  ((GObjectClass *) gst_object_parent_class)->finalize (object);
 }
 
 /* Changing a GObject property of a GstObject will result in "deep-notify"
@@ -510,9 +463,6 @@ gst_object_finalize (GObject * object)
  * top-level bin to catch property-change notifications for all contained
  * elements.
  *
- * This function is not MT safe in glib < 2.8 so we need to lock it with a
- * classwide mutex in that case.
- *
  * MT safe.
  */
 static void
@@ -527,11 +477,13 @@ gst_object_dispatch_properties_changed (GObject * object,
 #endif
 
   /* do the standard dispatching */
-  parent_class->dispatch_properties_changed (object, n_pspecs, pspecs);
+  ((GObjectClass *)
+      gst_object_parent_class)->dispatch_properties_changed (object, n_pspecs,
+      pspecs);
 
   gst_object = GST_OBJECT_CAST (object);
 #ifndef GST_DISABLE_GST_DEBUG
-  if (G_UNLIKELY (__gst_debug_min >= GST_LEVEL_LOG)) {
+  if (G_UNLIKELY (_gst_debug_min >= GST_LEVEL_LOG)) {
     name = gst_object_get_name (gst_object);
     debug_name = GST_STR_NULL (name);
   } else
@@ -753,80 +705,12 @@ gst_object_get_name (GstObject * object)
 }
 
 /**
- * gst_object_set_name_prefix:
- * @object:      a #GstObject
- * @name_prefix: new name prefix of @object
- *
- * Sets the name prefix of @object to @name_prefix.
- * This function makes a copy of the provided name prefix, so the caller
- * retains ownership of the name prefix it sent.
- *
- * MT safe.  This function grabs and releases @object's LOCK.
- *
- * Deprecated: deprecated because the name prefix has never actually been used
- *     for anything.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void gst_object_set_name_prefix (GstObject * object, const gchar * name_prefix);
-#endif
-void
-gst_object_set_name_prefix (GstObject * object, const gchar * name_prefix)
-{
-  g_return_if_fail (GST_IS_OBJECT (object));
-
-  GST_OBJECT_LOCK (object);
-  g_free (object->name_prefix);
-  object->name_prefix = g_strdup (name_prefix); /* NULL gives NULL */
-  GST_OBJECT_UNLOCK (object);
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
- * gst_object_get_name_prefix:
- * @object: a #GstObject
- *
- * Returns a copy of the name prefix of @object.
- * Caller should g_free() the return value after usage.
- * For a prefixless object, this returns NULL, which you can safely g_free()
- * as well.
- *
- * Returns: the name prefix of @object. g_free() after usage.
- *
- * MT safe. This function grabs and releases @object's LOCK.
- *
- * Deprecated: deprecated because the name prefix has never actually been used
- *     for anything.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gchar *gst_object_get_name_prefix (GstObject * object);
-#endif
-gchar *
-gst_object_get_name_prefix (GstObject * object)
-{
-  gchar *result = NULL;
-
-  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
-
-  GST_OBJECT_LOCK (object);
-  result = g_strdup (object->name_prefix);
-  GST_OBJECT_UNLOCK (object);
-
-  return result;
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
  * gst_object_set_parent:
  * @object: a #GstObject
  * @parent: new parent of object
  *
  * Sets the parent of @object to @parent. The object's reference count will
- * be incremented, and any floating reference will be removed (see gst_object_sink()).
- *
- * This function causes the parent-set signal to be emitted when the parent
- * was successfully set.
+ * be incremented, and any floating reference will be removed (see gst_object_ref_sink()).
  *
  * Returns: TRUE if @parent could be set or FALSE when @object
  * already had a parent or @object and @parent are the same.
@@ -847,21 +731,14 @@ gst_object_set_parent (GstObject * object, GstObject * parent)
   if (G_UNLIKELY (object->parent != NULL))
     goto had_parent;
 
-  /* sink object, we don't call our own function because we don't
-   * need to release/acquire the lock needlessly or touch the refcount
-   * in the floating case. */
   object->parent = parent;
-  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
-    GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object,
-        "unsetting floating flag");
-    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
-    GST_OBJECT_UNLOCK (object);
-  } else {
-    GST_OBJECT_UNLOCK (object);
-    gst_object_ref (object);
-  }
+  gst_object_ref_sink (object);
+  GST_OBJECT_UNLOCK (object);
 
-  g_signal_emit (object, gst_object_signals[PARENT_SET], 0, parent);
+  /* FIXME, this does not work, the deep notify takes the lock from the parent
+   * object and deadlocks when the parent holds its lock when calling this
+   * function (like _element_add_pad()) */
+  /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */
 
   return TRUE;
 
@@ -927,7 +804,7 @@ gst_object_unparent (GstObject * object)
     object->parent = NULL;
     GST_OBJECT_UNLOCK (object);
 
-    g_signal_emit (object, gst_object_signals[PARENT_UNSET], 0, parent);
+    /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */
 
     gst_object_unref (object);
   } else {
@@ -1013,65 +890,6 @@ gst_object_check_uniqueness (GList * list, const gchar * name)
 }
 
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-/**
- * gst_object_save_thyself:
- * @object: a #GstObject to save
- * @parent: The parent XML node to save @object into
- *
- * Saves @object into the parent XML node.
- *
- * Returns: the new xmlNodePtr with the saved object
- */
-GstXmlNodePtr
-gst_object_save_thyself (GstObject * object, GstXmlNodePtr parent)
-{
-  GstObjectClass *oclass;
-
-  g_return_val_if_fail (GST_IS_OBJECT (object), parent);
-  g_return_val_if_fail (parent != NULL, parent);
-
-  oclass = GST_OBJECT_GET_CLASS (object);
-
-  if (oclass->save_thyself)
-    oclass->save_thyself (object, parent);
-
-  g_signal_emit (object, gst_object_signals[OBJECT_SAVED], 0, parent);
-
-  return parent;
-}
-
-/**
- * gst_object_restore_thyself:
- * @object: a #GstObject to load into
- * @self: The XML node to load @object from
- *
- * Restores @object with the data from the parent XML node.
- */
-void
-gst_object_restore_thyself (GstObject * object, GstXmlNodePtr self)
-{
-  GstObjectClass *oclass;
-
-  g_return_if_fail (GST_IS_OBJECT (object));
-  g_return_if_fail (self != NULL);
-
-  oclass = GST_OBJECT_GET_CLASS (object);
-
-  if (oclass->restore_thyself)
-    oclass->restore_thyself (object, self);
-}
-
-static void
-gst_object_real_restore_thyself (GstObject * object, GstXmlNodePtr self)
-{
-  g_return_if_fail (GST_IS_OBJECT (object));
-  g_return_if_fail (self != NULL);
-
-  gst_class_signal_emit_by_name (object, "object_loaded", self);
-}
-#endif /* GST_DISABLE_LOADSAVE */
-
 static void
 gst_object_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -1081,9 +899,12 @@ gst_object_set_property (GObject * object, guint prop_id,
   gstobject = GST_OBJECT_CAST (object);
 
   switch (prop_id) {
-    case ARG_NAME:
+    case PROP_NAME:
       gst_object_set_name (gstobject, g_value_get_string (value));
       break;
+    case PROP_PARENT:
+      gst_object_set_parent (gstobject, g_value_get_object (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1099,9 +920,12 @@ gst_object_get_property (GObject * object, guint prop_id,
   gstobject = GST_OBJECT_CAST (object);
 
   switch (prop_id) {
-    case ARG_NAME:
+    case PROP_NAME:
       g_value_take_string (value, gst_object_get_name (gstobject));
       break;
+    case PROP_PARENT:
+      g_value_take_object (value, gst_object_get_parent (gstobject));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1194,83 +1018,401 @@ gst_object_get_path_string (GstObject * object)
   return path;
 }
 
+/* controller helper functions */
 
-struct _GstSignalObject
+/*
+ * gst_object_find_control_binding:
+ * @self: the gobject to search for a property in
+ * @name: the gobject property name to look for
+ *
+ * Searches the list of properties under control.
+ *
+ * Returns: a #GstControlBinding or %NULL if the property is not being
+ * controlled.
+ */
+static GstControlBinding *
+gst_object_find_control_binding (GstObject * self, const gchar * name)
 {
-  GObject object;
-};
+  GstControlBinding *binding;
+  GList *node;
+
+  for (node = self->control_bindings; node; node = g_list_next (node)) {
+    binding = node->data;
+    /* FIXME: eventually use GQuark to speed it up */
+    if (!strcmp (binding->name, name)) {
+      GST_DEBUG_OBJECT (self, "found control binding for property '%s'", name);
+      return binding;
+    }
+  }
+  GST_DEBUG_OBJECT (self, "controller does not manage property '%s'", name);
+
+  return NULL;
+}
 
-struct _GstSignalObjectClass
+/* controller functions */
+
+/**
+ * gst_object_suggest_next_sync:
+ * @object: the object that has controlled properties
+ *
+ * Returns a suggestion for timestamps where buffers should be split
+ * to get best controller results.
+ *
+ * Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE
+ * if no control-rate was set.
+ */
+GstClockTime
+gst_object_suggest_next_sync (GstObject * object)
 {
-  GObjectClass parent_class;
+  GstClockTime ret;
 
-  /* signals */
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  void (*object_loaded) (GstSignalObject * object, GstObject * new,
-      GstXmlNodePtr self);
-#endif
-};
+  g_return_val_if_fail (GST_IS_OBJECT (object), GST_CLOCK_TIME_NONE);
+  g_return_val_if_fail (object->control_rate != GST_CLOCK_TIME_NONE,
+      GST_CLOCK_TIME_NONE);
 
-G_DEFINE_TYPE (GstSignalObject, gst_signal_object, G_TYPE_OBJECT);
+  GST_OBJECT_LOCK (object);
 
-static void
-gst_signal_object_class_init (GstSignalObjectClass * klass)
-{
-  parent_class = g_type_class_peek_parent (klass);
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  gst_signal_object_signals[SO_OBJECT_LOADED] =
-      g_signal_new ("object-loaded", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSignalObjectClass, object_loaded),
-      NULL, NULL, gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2,
-      G_TYPE_OBJECT, G_TYPE_POINTER);
-#endif
+  /* TODO: Implement more logic, depending on interpolation mode and control
+   * points
+   * FIXME: we need playback direction
+   */
+  ret = object->last_sync + object->control_rate;
+
+  GST_OBJECT_UNLOCK (object);
+
+  return ret;
 }
 
-static void
-gst_signal_object_init (GstSignalObject * object)
+/**
+ * gst_object_sync_values:
+ * @object: the object that has controlled properties
+ * @timestamp: the time that should be processed
+ *
+ * Sets the properties of the object, according to the #GstControlSources that
+ * (maybe) handle them and for the given timestamp.
+ *
+ * If this function fails, it is most likely the application developers fault.
+ * Most probably the control sources are not setup correctly.
+ *
+ * Returns: %TRUE if the controller values could be applied to the object
+ * properties, %FALSE otherwise
+ */
+gboolean
+gst_object_sync_values (GstObject * object, GstClockTime timestamp)
 {
+  GList *node;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+
+  GST_LOG_OBJECT (object, "sync_values");
+  if (!object->control_bindings)
+    return TRUE;
+
+  /* FIXME: this deadlocks */
+  /* GST_OBJECT_LOCK (object); */
+  g_object_freeze_notify ((GObject *) object);
+  for (node = object->control_bindings; node; node = g_list_next (node)) {
+    ret &= gst_control_binding_sync_values ((GstControlBinding *) node->data,
+        object, timestamp, object->last_sync);
+  }
+  object->last_sync = timestamp;
+  g_object_thaw_notify ((GObject *) object);
+  /* GST_OBJECT_UNLOCK (object); */
+
+  return ret;
 }
 
+
 /**
- * gst_class_signal_connect
- * @klass: a #GstObjectClass to attach the signal to
- * @name: the name of the signal to attach to
- * @func: the signal function
- * @func_data: a pointer to user data
+ * gst_object_has_active_control_bindings:
+ * @object: the object that has controlled properties
  *
- * Connect to a class signal.
+ * Check if the @object has an active controlled properties.
  *
- * Returns: the signal id.
+ * Returns: %TRUE if the object has active controlled properties
  */
-guint
-gst_class_signal_connect (GstObjectClass * klass,
-    const gchar * name, gpointer func, gpointer func_data)
+gboolean
+gst_object_has_active_control_bindings (GstObject * object)
 {
-  /* [0.11] func parameter needs to be changed to a GCallback *
-   * doing so now would be an API break. */
-  return g_signal_connect (klass->signal_object, name, G_CALLBACK (func),
-      func_data);
+  gboolean res = FALSE;
+  GList *node;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+
+  GST_OBJECT_LOCK (object);
+  for (node = object->control_bindings; node; node = g_list_next (node)) {
+    res |= !gst_control_binding_is_disabled ((GstControlBinding *) node->data);
+  }
+  GST_OBJECT_UNLOCK (object);
+  return res;
 }
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
 /**
- * gst_class_signal_emit_by_name:
- * @object: a #GstObject that emits the signal
- * @name: the name of the signal to emit
- * @self: data for the signal
+ * gst_object_set_control_bindings_disabled:
+ * @object: the object that has controlled properties
+ * @disabled: boolean that specifies whether to disable the controller
+ * or not.
  *
- * emits the named class signal.
+ * This function is used to disable all controlled properties of the @object for
+ * some time, i.e. gst_object_sync_values() will do nothing.
  */
 void
-gst_class_signal_emit_by_name (GstObject * object,
-    const gchar * name, GstXmlNodePtr self)
+gst_object_set_control_bindings_disabled (GstObject * object, gboolean disabled)
+{
+  GList *node;
+
+  g_return_if_fail (GST_IS_OBJECT (object));
+
+  GST_OBJECT_LOCK (object);
+  for (node = object->control_bindings; node; node = g_list_next (node)) {
+    gst_control_binding_set_disabled ((GstControlBinding *) node->data,
+        disabled);
+  }
+  GST_OBJECT_UNLOCK (object);
+}
+
+/**
+ * gst_object_set_control_binding_disabled:
+ * @object: the object that has controlled properties
+ * @property_name: property to disable
+ * @disabled: boolean that specifies whether to disable the controller
+ * or not.
+ *
+ * This function is used to disable the #GstController on a property for
+ * some time, i.e. gst_controller_sync_values() will do nothing for the
+ * property.
+ */
+void
+gst_object_set_control_binding_disabled (GstObject * object,
+    const gchar * property_name, gboolean disabled)
+{
+  GstControlBinding *binding;
+
+  g_return_if_fail (GST_IS_OBJECT (object));
+  g_return_if_fail (property_name);
+
+  GST_OBJECT_LOCK (object);
+  if ((binding = gst_object_find_control_binding (object, property_name))) {
+    gst_control_binding_set_disabled (binding, disabled);
+  }
+  GST_OBJECT_UNLOCK (object);
+}
+
+
+/**
+ * gst_object_add_control_binding:
+ * @object: the controller object
+ * @binding: (transfer full): the #GstControlBinding that should be used
+ *
+ * Sets the #GstControlBinding. If there already was a #GstControlBinding
+ * for this property it will be replaced.
+ * The @object will take ownership of the @binding.
+ *
+ * Returns: %FALSE if the given @binding has not been setup for this object  or
+ * %TRUE otherwise.
+ */
+gboolean
+gst_object_add_control_binding (GstObject * object, GstControlBinding * binding)
 {
-  GstObjectClass *oclass;
+  GstControlBinding *old;
 
-  oclass = GST_OBJECT_GET_CLASS (object);
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);
+  //g_return_val_if_fail (g_type_is_a (binding->pspec->owner_type,
+  //        G_OBJECT_TYPE (object)), FALSE);
 
-  g_signal_emit_by_name (oclass->signal_object, name, object, self);
+  GST_OBJECT_LOCK (object);
+  if ((old = gst_object_find_control_binding (object, binding->name))) {
+    GST_DEBUG_OBJECT (object, "controlled property %s removed", old->name);
+    object->control_bindings = g_list_remove (object->control_bindings, old);
+    gst_object_unparent (GST_OBJECT_CAST (old));
+  }
+  object->control_bindings = g_list_prepend (object->control_bindings, binding);
+  gst_object_set_parent (GST_OBJECT_CAST (binding), object);
+  GST_DEBUG_OBJECT (object, "controlled property %s added", binding->name);
+  GST_OBJECT_UNLOCK (object);
+
+  return TRUE;
 }
 
-#endif /* GST_DISABLE_LOADSAVE */
+/**
+ * gst_object_get_control_binding:
+ * @object: the object
+ * @property_name: name of the property
+ *
+ * Gets the corresponding #GstControlBinding for the property. This should be
+ * unreferenced again after use.
+ *
+ * Returns: (transfer full): the #GstControlBinding for @property_name or %NULL if
+ * the property is not controlled.
+ */
+GstControlBinding *
+gst_object_get_control_binding (GstObject * object, const gchar * property_name)
+{
+  GstControlBinding *binding;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
+  g_return_val_if_fail (property_name, NULL);
+
+  GST_OBJECT_LOCK (object);
+  if ((binding = gst_object_find_control_binding (object, property_name))) {
+    g_object_ref (binding);
+  }
+  GST_OBJECT_UNLOCK (object);
+
+  return binding;
+}
+
+/**
+ * gst_object_remove_control_binding:
+ * @object: the object
+ * @binding: the binding
+ *
+ * Removes the corresponding #GstControlBinding. If it was the
+ * last ref of the binding, it will be disposed.  
+ *
+ * Returns: %TRUE if the binding could be removed.
+ */
+gboolean
+gst_object_remove_control_binding (GstObject * object,
+    GstControlBinding * binding)
+{
+  GList *node;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);
+
+  GST_OBJECT_LOCK (object);
+  if ((node = g_list_find (object->control_bindings, binding))) {
+    GST_DEBUG_OBJECT (object, "controlled property %s removed", binding->name);
+    object->control_bindings =
+        g_list_delete_link (object->control_bindings, node);
+    gst_object_unparent (GST_OBJECT_CAST (binding));
+    ret = TRUE;
+  }
+  GST_OBJECT_UNLOCK (object);
+
+  return ret;
+}
+
+/**
+ * gst_object_get_value:
+ * @object: the object that has controlled properties
+ * @property_name: the name of the property to get
+ * @timestamp: the time the control-change should be read from
+ *
+ * Gets the value for the given controlled property at the requested time.
+ *
+ * Returns: the GValue of the property at the given time, or %NULL if the
+ * property isn't controlled.
+ */
+GValue *
+gst_object_get_value (GstObject * object, const gchar * property_name,
+    GstClockTime timestamp)
+{
+  GstControlBinding *binding;
+  GValue *val = NULL;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
+  g_return_val_if_fail (property_name, NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
+
+  GST_OBJECT_LOCK (object);
+  if ((binding = gst_object_find_control_binding (object, property_name))) {
+    val = gst_control_binding_get_value (binding, timestamp);
+  }
+  GST_OBJECT_UNLOCK (object);
+
+  return val;
+}
+
+/**
+ * gst_object_get_value_array:
+ * @object: the object that has controlled properties
+ * @property_name: the name of the property to get
+ * @timestamp: the time that should be processed
+ * @interval: the time spacing between subsequent values
+ * @n_values: the number of values
+ * @values: array to put control-values in
+ *
+ * Gets a number of values for the given controllered property starting at the
+ * requested time. The array @values need to hold enough space for @n_values of
+ * the same type as the objects property's type.
+ *
+ * This function is useful if one wants to e.g. draw a graph of the control
+ * curve or apply a control curve sample by sample.
+ *
+ * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+ */
+gboolean
+gst_object_get_value_array (GstObject * object, const gchar * property_name,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  gboolean res = FALSE;
+  GstControlBinding *binding;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (property_name, FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+
+  GST_OBJECT_LOCK (object);
+  if ((binding = gst_object_find_control_binding (object, property_name))) {
+    res = gst_control_binding_get_value_array (binding, timestamp, interval,
+        n_values, values);
+  }
+  GST_OBJECT_UNLOCK (object);
+  return res;
+}
+
+
+/**
+ * gst_object_get_control_rate:
+ * @object: the object that has controlled properties
+ *
+ * Obtain the control-rate for this @object. Audio processing #GstElement
+ * objects will use this rate to sub-divide their processing loop and call
+ * gst_object_sync_values() inbetween. The length of the processing segment
+ * should be up to @control-rate nanoseconds.
+ *
+ * If the @object is not under property control, this will return
+ * %GST_CLOCK_TIME_NONE. This allows the element to avoid the sub-dividing.
+ *
+ * The control-rate is not expected to change if the element is in
+ * %GST_STATE_PAUSED or %GST_STATE_PLAYING.
+ *
+ * Returns: the control rate in nanoseconds
+ */
+GstClockTime
+gst_object_get_control_rate (GstObject * object)
+{
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+
+  return object->control_rate;
+}
+
+/**
+ * gst_object_set_control_rate:
+ * @object: the object that has controlled properties
+ * @control_rate: the new control-rate in nanoseconds.
+ *
+ * Change the control-rate for this @object. Audio processing #GstElement
+ * objects will use this rate to sub-divide their processing loop and call
+ * gst_object_sync_values() inbetween. The length of the processing segment
+ * should be up to @control-rate nanoseconds.
+ *
+ * The control-rate should not change if the element is in %GST_STATE_PAUSED or
+ * %GST_STATE_PLAYING.
+ */
+void
+gst_object_set_control_rate (GstObject * object, GstClockTime control_rate)
+{
+  g_return_if_fail (GST_IS_OBJECT (object));
+
+  object->control_rate = control_rate;
+}
index a522aee..e753516 100644 (file)
@@ -39,27 +39,14 @@ G_BEGIN_DECLS
 #define GST_OBJECT_CAST(obj)            ((GstObject*)(obj))
 #define GST_OBJECT_CLASS_CAST(klass)    ((GstObjectClass*)(klass))
 
-/* make sure we don't change the object size but still make it compile
- * without libxml */
-#if defined(GST_DISABLE_LOADSAVE) || defined(GST_DISABLE_DEPRECATED)
-#define GstXmlNodePtr  gpointer
-#else
-#define GstXmlNodePtr  xmlNodePtr
-#endif
-
 /**
  * GstObjectFlags:
- * @GST_OBJECT_DISPOSING: the object is been destroyed, don't use it anymore
- * @GST_OBJECT_FLOATING:  the object has a floating reference count (e.g. its
- *  not assigned to a bin)
  * @GST_OBJECT_FLAG_LAST: subclasses can add additional flags starting from this flag
  *
  * The standard flags that an gstobject may have.
  */
 typedef enum
 {
-  GST_OBJECT_DISPOSING = (1<<0),
-  GST_OBJECT_FLOATING = (1<<1),
   /* padding */
   GST_OBJECT_FLAG_LAST = (1<<4)
 } GstObjectFlags;
@@ -88,7 +75,7 @@ typedef enum
  *
  * Acquire a reference to the mutex of this object.
  */
-#define GST_OBJECT_GET_LOCK(obj)               (GST_OBJECT_CAST(obj)->lock)
+#define GST_OBJECT_GET_LOCK(obj)               (&GST_OBJECT_CAST(obj)->lock)
 /**
  * GST_OBJECT_LOCK:
  * @obj: a #GstObject to lock
@@ -162,139 +149,53 @@ typedef enum
  */
 #define GST_OBJECT_FLAG_UNSET(obj,flag)        (GST_OBJECT_FLAGS (obj) &= ~(flag))
 
-
-/**
- * GST_OBJECT_IS_DISPOSING:
- * @obj: a #GstObject
- *
- * Check if the given object is beeing destroyed.
- */
-#define GST_OBJECT_IS_DISPOSING(obj)    (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_DISPOSING))
-/**
- * GST_OBJECT_IS_FLOATING:
- * @obj: a #GstObject
- *
- * Check if the given object is floating (has no owner).
- */
-#define GST_OBJECT_IS_FLOATING(obj)     (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLOATING))
-
 typedef struct _GstObject GstObject;
 typedef struct _GstObjectClass GstObjectClass;
 
 /**
  * GstObject:
- * @refcount: unused
  * @lock: object LOCK
  * @name: The name of the object
- * @name_prefix: unused
  * @parent: this object's parent, weak ref
- * @flags: use GST_OBJECT_IS_XXX macros to access the flags
+ * @flags: flags for this object
  *
  * GStreamer base object class.
  */
 struct _GstObject {
-  GObject       object;
-
-  /*< public >*/
-  gint           refcount;    /* unused (FIXME 0.11: remove) */
+  GInitiallyUnowned object;
 
   /*< public >*/ /* with LOCK */
-  GMutex        *lock;        /* object LOCK */
+  GMutex         lock;        /* object LOCK */
   gchar         *name;        /* object name */
-  gchar         *name_prefix; /* (un)used for debugging (FIXME 0.11: remove) */
   GstObject     *parent;      /* this object's parent, weak ref */
   guint32        flags;
 
   /*< private >*/
+  GList         *control_bindings;  /* List of GstControlBinding */
+  guint64        control_rate;
+  guint64        last_sync;
+
   gpointer _gst_reserved;
 };
 
 /**
- * GST_CLASS_GET_LOCK:
- * @obj: a #GstObjectClass
- *
- * This macro will return the class lock used to protect deep_notify signal
- * emission on thread-unsafe glib versions (glib < 2.8).
- *
- * Deprecated: 0.10.36: Don't use this, it's not needed any longer.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_CLASS_GET_LOCK(obj)         (GST_OBJECT_CLASS_CAST(obj)->lock)
-#endif
-
-/**
- * GST_CLASS_LOCK:
- * @obj: a #GstObjectClass
- *
- * Lock the class.
- *
- * Deprecated: 0.10.36: Don't use this, it's not needed any longer.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_CLASS_LOCK(obj)             (g_static_rec_mutex_lock(GST_CLASS_GET_LOCK(obj)))
-#endif
-
-/**
- * GST_CLASS_TRYLOCK:
- * @obj: a #GstObjectClass
- *
- * Try to lock the class, returns TRUE if class could be locked.
- *
- * Deprecated: 0.10.36: Don't use this, it's not needed any longer.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_CLASS_TRYLOCK(obj)          (g_static_rec_mutex_trylock(GST_CLASS_GET_LOCK(obj)))
-#endif
-
-/**
- * GST_CLASS_UNLOCK:
- * @obj: a #GstObjectClass
- *
- * Unlock the class.
- *
- * Deprecated: 0.10.36: Don't use this, it's not needed any longer.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_CLASS_UNLOCK(obj)           (g_static_rec_mutex_unlock(GST_CLASS_GET_LOCK(obj)))
-#endif
-
-/**
  * GstObjectClass:
  * @parent_class: parent
  * @path_string_separator: separator used by gst_object_get_path_string()
- * @signal_object: is used to signal to the whole class
- * @lock: class lock to be used with GST_CLASS_GET_LOCK(), GST_CLASS_LOCK(), GST_CLASS_UNLOCK() and others.
- * @parent_set: default signal handler
- * @parent_unset: default signal handler
- * @object_saved: default signal handler
  * @deep_notify: default signal handler
- * @save_thyself: xml serialisation
- * @restore_thyself: xml de-serialisation
  *
  * GStreamer base object class.
  */
 struct _GstObjectClass {
-  GObjectClass parent_class;
+  GInitiallyUnownedClass parent_class;
 
   const gchar  *path_string_separator;
-  GObject      *signal_object;
-
-  /* FIXME-0.11: remove this, plus the above GST_CLASS_*_LOCK macros */
-  GStaticRecMutex *lock;
 
   /* signals */
-  /* FIXME-0.11: remove, and pass NULL in g_signal_new(), we never used them */
-  void          (*parent_set)       (GstObject * object, GstObject * parent);
-  void          (*parent_unset)     (GstObject * object, GstObject * parent);
-  /* FIXME 0.11: Remove this, it's deprecated */
-  void          (*object_saved)     (GstObject * object, GstXmlNodePtr parent);
   void          (*deep_notify)      (GstObject * object, GstObject * orig, GParamSpec * pspec);
 
   /*< public >*/
   /* virtual methods for subclasses */
-  /* FIXME 0.11: Remove this, it's deprecated */
-  GstXmlNodePtr (*save_thyself)     (GstObject * object, GstXmlNodePtr parent);
-  void          (*restore_thyself)  (GstObject * object, GstXmlNodePtr self);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -307,28 +208,22 @@ GType             gst_object_get_type             (void);
 gboolean       gst_object_set_name             (GstObject *object, const gchar *name);
 gchar*         gst_object_get_name             (GstObject *object);
 
-#ifndef GST_DISABLE_DEPRECATED
-void           gst_object_set_name_prefix      (GstObject *object, const gchar *name_prefix);
-gchar*         gst_object_get_name_prefix      (GstObject *object);
-#endif
-
 /* parentage routines */
 gboolean       gst_object_set_parent           (GstObject *object, GstObject *parent);
 GstObject*     gst_object_get_parent           (GstObject *object);
 void           gst_object_unparent             (GstObject *object);
 gboolean       gst_object_has_ancestor         (GstObject *object, GstObject *ancestor);
 
-void            gst_object_default_deep_notify         (GObject *object, GstObject *orig,
+void            gst_object_default_deep_notify  (GObject *object, GstObject *orig,
                                                  GParamSpec *pspec, gchar **excluded_props);
 
 /* refcounting + life cycle */
 gpointer       gst_object_ref                  (gpointer object);
 void           gst_object_unref                (gpointer object);
-void           gst_object_ref_sink             (gpointer object);
-void           gst_object_sink                 (gpointer object);
+gpointer        gst_object_ref_sink            (gpointer object);
 
 /* replace object pointer */
-void           gst_object_replace              (GstObject **oldobj, GstObject *newobj);
+gboolean        gst_object_replace             (GstObject **oldobj, GstObject *newobj);
 
 /* printing out the 'path' of the object */
 gchar *                gst_object_get_path_string      (GstObject *object);
@@ -336,36 +231,32 @@ gchar *           gst_object_get_path_string      (GstObject *object);
 /* misc utils */
 gboolean       gst_object_check_uniqueness     (GList *list, const gchar *name);
 
-/* load/save */
-#ifndef GST_DISABLE_DEPRECATED
-#ifndef GST_DISABLE_LOADSAVE
-GstXmlNodePtr   gst_object_save_thyself    (GstObject *object, GstXmlNodePtr parent);
-void            gst_object_restore_thyself (GstObject *object, GstXmlNodePtr self);
-#else
-#if defined __GNUC__ && __GNUC__ >= 3
-#pragma GCC poison gst_object_save_thyself
-#pragma GCC poison gst_object_restore_thyself
-#endif
-#endif
-#endif
-
-/* class signal stuff */
-guint          gst_class_signal_connect        (GstObjectClass *klass,
-                                                const gchar    *name,
-                                                gpointer        func,
-                                                gpointer        func_data);
-
-#ifndef GST_DISABLE_DEPRECATED
-#ifndef GST_DISABLE_LOADSAVE
-void        gst_class_signal_emit_by_name   (GstObject     * object,
-                                             const gchar   * name,
-                                             GstXmlNodePtr   self);
-#else
-#if defined __GNUC__ && __GNUC__ >= 3
-#pragma GCC poison gst_class_signal_emit_by_name
-#endif
-#endif
-#endif
+/* controller functions */
+#include <gst/gstcontrolbinding.h>
+#include <gst/gstcontrolsource.h>
+
+GstClockTime    gst_object_suggest_next_sync      (GstObject * object);
+gboolean        gst_object_sync_values            (GstObject * object, GstClockTime timestamp);
+
+gboolean        gst_object_has_active_control_bindings   (GstObject *object);
+void            gst_object_set_control_bindings_disabled (GstObject *object, gboolean disabled);
+void            gst_object_set_control_binding_disabled  (GstObject *object,
+                                                          const gchar * property_name,
+                                                          gboolean disabled);
+
+gboolean        gst_object_add_control_binding    (GstObject * object, GstControlBinding * binding);
+GstControlBinding *
+                gst_object_get_control_binding    (GstObject *object, const gchar * property_name);
+gboolean        gst_object_remove_control_binding (GstObject * object, GstControlBinding * binding);
+
+GValue *        gst_object_get_value              (GstObject * object, const gchar * property_name,
+                                                   GstClockTime timestamp);
+gboolean        gst_object_get_value_array        (GstObject * object, const gchar * property_name,
+                                                   GstClockTime timestamp, GstClockTime interval,
+                                                   guint n_values, GValue *values);
+
+GstClockTime    gst_object_get_control_rate       (GstObject * object);
+void            gst_object_set_control_rate       (GstObject * object, GstClockTime control_rate);
 
 G_END_DECLS
 
index ef28bf5..8aec51c 100644 (file)
@@ -36,7 +36,7 @@
  * gst_pad_new_from_template().
  *
  * Pads have #GstCaps attached to it to describe the media type they are
- * capable of dealing with.  gst_pad_get_caps() and gst_pad_set_caps() are
+ * capable of dealing with.  gst_pad_query_caps() and gst_pad_set_caps() are
  * used to manipulate the caps of the pads.
  * Pads created from a pad template cannot set capabilities that are
  * incompatible with the pad template capabilities.
@@ -60,9 +60,6 @@
  * Last reviewed on 2006-07-06 (0.10.9)
  */
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "gst_private.h"
 
 #include "gstpad.h"
@@ -83,8 +80,6 @@ enum
 {
   PAD_LINKED,
   PAD_UNLINKED,
-  PAD_REQUEST_LINK,
-  PAD_HAVE_DATA,
   /* FILL ME */
   LAST_SIGNAL
 };
@@ -98,30 +93,46 @@ enum
   /* FILL ME */
 };
 
-typedef struct _GstPadPushCache GstPadPushCache;
-
-struct _GstPadPushCache
-{
-  GstPad *peer;                 /* reffed peer pad */
-  GstCaps *caps;                /* caps for this link */
-};
-
-static GstPadPushCache _pad_cache_invalid = { NULL, };
-
-#define PAD_CACHE_INVALID (&_pad_cache_invalid)
-
 #define GST_PAD_GET_PRIVATE(obj)  \
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
 
-#define GST_PAD_CHAINLISTFUNC(pad) ((pad)->abidata.ABI.priv->chainlistfunc)
+/* we have a pending and an active event on the pad. On source pads only the
+ * active event is used. On sinkpads, events are copied to the pending entry and
+ * moved to the active event when the eventfunc returned TRUE. */
+typedef struct
+{
+  gboolean received;
+  GstEvent *event;
+} PadEvent;
 
 struct _GstPadPrivate
 {
-  GstPadChainListFunction chainlistfunc;
+  guint events_cookie;
+  GArray *events;
 
-  GstPadPushCache *cache_ptr;
+  gint using;
+  guint probe_list_cookie;
+  guint probe_cookie;
 };
 
+typedef struct
+{
+  GHook hook;
+  guint cookie;
+} GstProbe;
+
+#define PROBE_COOKIE(h) (((GstProbe *)(h))->cookie)
+
+typedef struct
+{
+  GstPad *pad;
+  GstPadProbeInfo *info;
+  gboolean dropped;
+  gboolean pass;
+  gboolean marshalled;
+  guint cookie;
+} ProbeMarshall;
+
 static void gst_pad_dispose (GObject * object);
 static void gst_pad_finalize (GObject * object);
 static void gst_pad_set_property (GObject * object, guint prop_id,
@@ -129,36 +140,23 @@ static void gst_pad_set_property (GObject * object, guint prop_id,
 static void gst_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static GstFlowReturn handle_pad_block (GstPad * pad);
-static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad);
 static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
-static gboolean gst_pad_activate_default (GstPad * pad);
-static gboolean gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps);
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#ifdef GST_DISABLE_DEPRECATED
-#include <libxml/parser.h>
-#endif
-static xmlNodePtr gst_pad_save_thyself (GstObject * object, xmlNodePtr parent);
-void gst_pad_load_and_link (xmlNodePtr self, GstObject * parent);
-#endif
-
-/* Some deprecated stuff that we need inside here for
- * backwards compatibility */
-#ifdef GST_DISABLE_DEPRECATED
-#ifndef GST_REMOVE_DEPRECATED
-#define GST_PAD_INTLINKFUNC(pad)       (GST_PAD_CAST(pad)->intlinkfunc)
-GList *gst_pad_get_internal_links_default (GstPad * pad);
-#endif
-#endif
-
-static GstObjectClass *parent_class = NULL;
+static gboolean gst_pad_activate_default (GstPad * pad, GstObject * parent);
+static GstFlowReturn gst_pad_chain_list_default (GstPad * pad,
+    GstObject * parent, GstBufferList * list);
+
+static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad,
+    GstEvent * event, GstPadProbeType type);
+static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad,
+    GstEvent * event, GstPadProbeType type, gboolean * stored);
+
 static guint gst_pad_signals[LAST_SIGNAL] = { 0 };
 
 static GParamSpec *pspec_caps = NULL;
 
 /* quarks for probe signals */
 static GQuark buffer_quark;
+static GQuark buffer_list_quark;
 static GQuark event_quark;
 
 typedef struct
@@ -170,11 +168,10 @@ typedef struct
 
 static GstFlowQuarks flow_quarks[] = {
   {GST_FLOW_CUSTOM_SUCCESS, "custom-success", 0},
-  {GST_FLOW_RESEND, "resend", 0},
   {GST_FLOW_OK, "ok", 0},
   {GST_FLOW_NOT_LINKED, "not-linked", 0},
   {GST_FLOW_WRONG_STATE, "wrong-state", 0},
-  {GST_FLOW_UNEXPECTED, "unexpected", 0},
+  {GST_FLOW_EOS, "eos", 0},
   {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0},
   {GST_FLOW_ERROR, "error", 0},
   {GST_FLOW_NOT_SUPPORTED, "not-supported", 0},
@@ -231,6 +228,7 @@ gst_flow_to_quark (GstFlowReturn ret)
   gint i; \
   \
   buffer_quark = g_quark_from_static_string ("buffer"); \
+  buffer_list_quark = g_quark_from_static_string ("bufferlist"); \
   event_quark = g_quark_from_static_string ("event"); \
   \
   for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {                   \
@@ -241,26 +239,9 @@ gst_flow_to_quark (GstFlowReturn ret)
       GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \
 }
 
+#define gst_pad_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT, _do_init);
 
-static gboolean
-_gst_do_pass_data_accumulator (GSignalInvocationHint * ihint,
-    GValue * return_accu, const GValue * handler_return, gpointer dummy)
-{
-  gboolean ret = g_value_get_boolean (handler_return);
-
-  GST_DEBUG ("accumulated %d", ret);
-  g_value_set_boolean (return_accu, ret);
-
-  return ret;
-}
-
-static gboolean
-default_have_data (GstPad * pad, GstMiniObject * o)
-{
-  return TRUE;
-}
-
 static void
 gst_pad_class_init (GstPadClass * klass)
 {
@@ -272,8 +253,6 @@ gst_pad_class_init (GstPadClass * klass)
 
   g_type_class_add_private (klass, sizeof (GstPadPrivate));
 
-  parent_class = g_type_class_peek_parent (klass);
-
   gobject_class->dispose = gst_pad_dispose;
   gobject_class->finalize = gst_pad_finalize;
   gobject_class->set_property = gst_pad_set_property;
@@ -301,36 +280,6 @@ gst_pad_class_init (GstPadClass * klass)
       g_signal_new ("unlinked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstPadClass, unlinked), NULL, NULL,
       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
-  /**
-   * GstPad::request-link:
-   * @pad: the pad that emitted the signal
-   * @peer: the peer pad for which a connection is requested
-   *
-   * Signals that a pad connection has been requested.
-   */
-  gst_pad_signals[PAD_REQUEST_LINK] =
-      g_signal_new ("request-link", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPadClass, request_link), NULL,
-      NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 0);
-
-  /**
-   * GstPad::have-data:
-   * @pad: the pad that emitted the signal
-   * @mini_obj: new data
-   *
-   * Signals that new data is available on the pad. This signal is used
-   * internally for implementing pad probes.
-   * See gst_pad_add_*_probe functions.
-   *
-   * Returns: %TRUE to keep the data, %FALSE to drop it
-   */
-  gst_pad_signals[PAD_HAVE_DATA] =
-      g_signal_new ("have-data", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-      G_STRUCT_OFFSET (GstPadClass, have_data),
-      _gst_do_pass_data_accumulator,
-      NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1,
-      GST_TYPE_MINI_OBJECT);
 
   pspec_caps = g_param_spec_boxed ("caps", "Caps",
       "The capabilities of the pad", GST_TYPE_CAPS,
@@ -341,75 +290,261 @@ gst_pad_class_init (GstPadClass * klass)
       g_param_spec_enum ("direction", "Direction", "The direction of the pad",
           GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
   /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */
   g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE,
       g_param_spec_object ("template", "Template",
           "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  gstobject_class->save_thyself =
-      ((gpointer (*)(GstObject * object,
-              gpointer self)) * GST_DEBUG_FUNCPTR (gst_pad_save_thyself));
-#endif
   gstobject_class->path_string_separator = ".";
 
   /* Register common function pointer descriptions */
   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_activate_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_event_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_pad_get_query_types_default);
   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_query_default);
-#ifndef GST_REMOVE_DEPRECATED
-  GST_DEBUG_REGISTER_FUNCPTR (gst_pad_get_internal_links_default);
-#endif
   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_iterate_internal_links_default);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_pad_acceptcaps_default);
-
-  /* from gstutils.c */
-  GST_DEBUG_REGISTER_FUNCPTR (gst_pad_get_fixed_caps_func);
-
-  klass->have_data = default_have_data;
+  GST_DEBUG_REGISTER_FUNCPTR (gst_pad_chain_list_default);
 }
 
 static void
 gst_pad_init (GstPad * pad)
 {
-  pad->abidata.ABI.priv = GST_PAD_GET_PRIVATE (pad);
+  pad->priv = GST_PAD_GET_PRIVATE (pad);
 
   GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN;
-  GST_PAD_PEER (pad) = NULL;
-
-  GST_PAD_CHAINFUNC (pad) = NULL;
-
-  GST_PAD_LINKFUNC (pad) = NULL;
-
-  GST_PAD_CAPS (pad) = NULL;
-  GST_PAD_GETCAPSFUNC (pad) = NULL;
 
   GST_PAD_ACTIVATEFUNC (pad) = gst_pad_activate_default;
   GST_PAD_EVENTFUNC (pad) = gst_pad_event_default;
-  GST_PAD_QUERYTYPEFUNC (pad) = gst_pad_get_query_types_default;
   GST_PAD_QUERYFUNC (pad) = gst_pad_query_default;
-#ifndef GST_REMOVE_DEPRECATED
-  GST_PAD_INTLINKFUNC (pad) = gst_pad_get_internal_links_default;
-#endif
   GST_PAD_ITERINTLINKFUNC (pad) = gst_pad_iterate_internal_links_default;
+  GST_PAD_CHAINLISTFUNC (pad) = gst_pad_chain_list_default;
+
+  GST_PAD_SET_FLUSHING (pad);
 
-  GST_PAD_ACCEPTCAPSFUNC (pad) = gst_pad_acceptcaps_default;
+  g_rec_mutex_init (&pad->stream_rec_lock);
 
-  pad->do_buffer_signals = 0;
-  pad->do_event_signals = 0;
+  g_cond_init (&pad->block_cond);
 
-  GST_PAD_SET_FLUSHING (pad);
+  g_hook_list_init (&pad->probes, sizeof (GstProbe));
+
+  pad->priv->events = g_array_sized_new (FALSE, TRUE,
+      sizeof (PadEvent), GST_EVENT_MAX_STICKY);
+}
+
+/* called when setting the pad inactive. It removes all sticky events from
+ * the pad */
+static void
+remove_events (GstPad * pad)
+{
+  guint i, len;
+  GArray *events;
+
+  events = pad->priv->events;
+
+  len = events->len;
+  for (i = 0; i < len; i++) {
+    PadEvent *ev = &g_array_index (events, PadEvent, i);
+    gst_event_unref (ev->event);
+  }
+  GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+  g_array_set_size (events, 0);
+  pad->priv->events_cookie++;
+}
+
+static PadEvent *
+find_event_by_type (GstPad * pad, GstEventType type, guint idx)
+{
+  guint i, len;
+  GArray *events;
+  PadEvent *ev;
+
+  events = pad->priv->events;
+  len = events->len;
+
+  for (i = 0; i < len; i++) {
+    ev = &g_array_index (events, PadEvent, i);
+    if (ev->event == NULL)
+      continue;
+
+    if (GST_EVENT_TYPE (ev->event) == type) {
+      if (idx == 0)
+        goto found;
+      idx--;
+    }
+  }
+  ev = NULL;
+found:
+  return ev;
+}
+
+static PadEvent *
+find_event (GstPad * pad, GstEvent * event)
+{
+  guint i, len;
+  GArray *events;
+  PadEvent *ev;
+
+  events = pad->priv->events;
+  len = events->len;
+
+  for (i = 0; i < len; i++) {
+    ev = &g_array_index (events, PadEvent, i);
+    if (event == ev->event)
+      goto found;
+  }
+  ev = NULL;
+found:
+  return ev;
+}
+
+static void
+remove_event_by_type (GstPad * pad, GstEventType type)
+{
+  guint i, len;
+  GArray *events;
+  PadEvent *ev;
+
+  events = pad->priv->events;
+  len = events->len;
+
+  i = 0;
+  while (i < len) {
+    ev = &g_array_index (events, PadEvent, i);
+    if (ev->event == NULL)
+      goto next;
+
+    if (GST_EVENT_TYPE (ev->event) != type)
+      goto next;
+
+    gst_event_unref (ev->event);
+    g_array_remove_index (events, i);
+    len--;
+    pad->priv->events_cookie++;
+    continue;
+
+  next:
+    i++;
+  }
+}
+
+static void
+schedule_events (GstPad * srcpad, GstPad * sinkpad)
+{
+  gint i, len;
+  GArray *events;
+  PadEvent *ev;
+  gboolean pending = FALSE;
+
+  events = srcpad->priv->events;
+  len = events->len;
+
+  for (i = 0; i < len; i++) {
+    ev = &g_array_index (events, PadEvent, i);
+    if (ev->event == NULL)
+      continue;
+
+    if (sinkpad == NULL || !find_event (sinkpad, ev->event)) {
+      ev->received = FALSE;
+      pending = TRUE;
+    }
+  }
+  if (pending)
+    GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PENDING_EVENTS);
+}
+
+typedef gboolean (*PadEventFunction) (GstPad * pad, PadEvent * ev,
+    gpointer user_data);
+
+static void
+events_foreach (GstPad * pad, PadEventFunction func, gpointer user_data)
+{
+  guint i, len;
+  GArray *events;
+  gboolean ret;
+  guint cookie;
+
+  events = pad->priv->events;
+
+restart:
+  cookie = pad->priv->events_cookie;
+  i = 0;
+  len = events->len;
+  while (i < len) {
+    PadEvent *ev, ev_ret;
+
+    ev = &g_array_index (events, PadEvent, i);
+    if (G_UNLIKELY (ev->event == NULL))
+      goto next;
+
+    /* take aditional ref, func might release the lock */
+    ev_ret.event = gst_event_ref (ev->event);
+    ev_ret.received = ev->received;
+
+    ret = func (pad, &ev_ret, user_data);
+
+    /* recheck the cookie, lock might have been released and the list could have
+     * changed */
+    if (G_UNLIKELY (cookie != pad->priv->events_cookie)) {
+      if (G_LIKELY (ev_ret.event))
+        gst_event_unref (ev_ret.event);
+      goto restart;
+    }
+
+    /* if the event changed, we need to do something */
+    if (G_UNLIKELY (ev->event != ev_ret.event)) {
+      if (G_UNLIKELY (ev_ret.event == NULL)) {
+        /* function unreffed and set the event to NULL, remove it */
+        g_array_remove_index (events, i);
+        len--;
+        cookie = ++pad->priv->events_cookie;
+        continue;
+      } else {
+        /* function gave a new event for us */
+        gst_event_take (&ev->event, ev_ret.event);
+      }
+    } else {
+      /* just unref, nothing changed */
+      gst_event_unref (ev_ret.event);
+    }
+    if (!ret)
+      break;
+  next:
+    i++;
+  }
+}
 
-  pad->preroll_lock = g_mutex_new ();
-  pad->preroll_cond = g_cond_new ();
+/* should be called with LOCK */
+static GstEvent *
+apply_pad_offset (GstPad * pad, GstEvent * event)
+{
+  /* check if we need to adjust the segment */
+  if (pad->offset != 0) {
+    GstSegment segment;
+
+    /* copy segment values */
+    gst_event_copy_segment (event, &segment);
+    gst_event_unref (event);
+
+    /* adjust and make a new event with the offset applied */
+    segment.base += pad->offset;
+    event = gst_event_new_segment (&segment);
+  }
+  return event;
+}
+
+/* should be called with the OBJECT_LOCK */
+static GstCaps *
+get_pad_caps (GstPad * pad)
+{
+  GstCaps *caps = NULL;
+  PadEvent *ev;
 
-  /* FIXME 0.11: Store this directly in the instance struct */
-  pad->stream_rec_lock = g_slice_new (GStaticRecMutex);
-  g_static_rec_mutex_init (pad->stream_rec_lock);
+  ev = find_event_by_type (pad, GST_EVENT_CAPS, 0);
+  if (ev && ev->event)
+    gst_event_parse_caps (ev->event, &caps);
 
-  pad->block_cond = g_cond_new ();
+  return caps;
 }
 
 static void
@@ -433,15 +568,11 @@ gst_pad_dispose (GObject * object)
     gst_object_unref (peer);
   }
 
-  /* clear the caps */
-  gst_caps_replace (&GST_PAD_CAPS (pad), NULL);
-
   gst_pad_set_pad_template (pad, NULL);
 
-  if (pad->block_destroy_data && pad->block_data) {
-    pad->block_destroy_data (pad->block_data);
-    pad->block_data = NULL;
-  }
+  remove_events (pad);
+
+  g_hook_list_clear (&pad->probes);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -459,21 +590,30 @@ gst_pad_finalize (GObject * object)
     gst_object_unref (task);
   }
 
-  if (pad->stream_rec_lock) {
-    g_static_rec_mutex_free (pad->stream_rec_lock);
-    g_slice_free (GStaticRecMutex, pad->stream_rec_lock);
-    pad->stream_rec_lock = NULL;
-  }
-  if (pad->preroll_lock) {
-    g_mutex_free (pad->preroll_lock);
-    g_cond_free (pad->preroll_cond);
-    pad->preroll_lock = NULL;
-    pad->preroll_cond = NULL;
-  }
-  if (pad->block_cond) {
-    g_cond_free (pad->block_cond);
-    pad->block_cond = NULL;
-  }
+  if (pad->activatenotify)
+    pad->activatenotify (pad);
+  if (pad->activatemodenotify)
+    pad->activatemodenotify (pad);
+  if (pad->linknotify)
+    pad->linknotify (pad);
+  if (pad->unlinknotify)
+    pad->unlinknotify (pad);
+  if (pad->chainnotify)
+    pad->chainnotify (pad);
+  if (pad->chainlistnotify)
+    pad->chainlistnotify (pad);
+  if (pad->getrangenotify)
+    pad->getrangenotify (pad);
+  if (pad->eventnotify)
+    pad->eventnotify (pad);
+  if (pad->querynotify)
+    pad->querynotify (pad);
+  if (pad->iterintlinknotify)
+    pad->iterintlinknotify (pad);
+
+  g_rec_mutex_clear (&pad->stream_rec_lock);
+  g_cond_clear (&pad->block_cond);
+  g_array_free (pad->priv->events, TRUE);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -507,7 +647,7 @@ gst_pad_get_property (GObject * object, guint prop_id,
   switch (prop_id) {
     case PAD_PROP_CAPS:
       GST_OBJECT_LOCK (object);
-      g_value_set_boxed (value, GST_PAD_CAPS (object));
+      g_value_set_boxed (value, get_pad_caps (GST_PAD_CAST (object)));
       GST_OBJECT_UNLOCK (object);
       break;
     case PAD_PROP_DIRECTION:
@@ -589,6 +729,20 @@ gst_pad_new_from_static_template (GstStaticPadTemplate * templ,
   return pad;
 }
 
+#define ACQUIRE_PARENT(pad, parent, label)                      \
+  G_STMT_START {                                                \
+    if (G_LIKELY ((parent = GST_OBJECT_PARENT (pad))))          \
+      gst_object_ref (parent);                                  \
+    else if (G_LIKELY (GST_PAD_NEEDS_PARENT (pad)))             \
+      goto label;                                               \
+  } G_STMT_END
+
+#define RELEASE_PARENT(parent)                                  \
+  G_STMT_START {                                                \
+    if (G_LIKELY (parent))                                      \
+      gst_object_unref (parent);                                \
+  } G_STMT_END
+
 /**
  * gst_pad_get_direction:
  * @pad: a #GstPad to get the direction of.
@@ -616,51 +770,72 @@ gst_pad_get_direction (GstPad * pad)
 }
 
 static gboolean
-gst_pad_activate_default (GstPad * pad)
+gst_pad_activate_default (GstPad * pad, GstObject * parent)
 {
-  return gst_pad_activate_push (pad, TRUE);
+  return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
 }
 
 static void
-pre_activate (GstPad * pad, GstActivateMode new_mode)
+pre_activate (GstPad * pad, GstPadMode new_mode)
 {
   switch (new_mode) {
-    case GST_ACTIVATE_PUSH:
-    case GST_ACTIVATE_PULL:
-      GST_OBJECT_LOCK (pad);
-      GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE %d, unset flushing",
-          new_mode);
-      GST_PAD_UNSET_FLUSHING (pad);
-      GST_PAD_ACTIVATE_MODE (pad) = new_mode;
-      GST_OBJECT_UNLOCK (pad);
-      break;
-    case GST_ACTIVATE_NONE:
+    case GST_PAD_MODE_NONE:
       GST_OBJECT_LOCK (pad);
-      GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE NONE, set flushing");
-      _priv_gst_pad_invalidate_cache (pad);
+      GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing");
       GST_PAD_SET_FLUSHING (pad);
-      GST_PAD_ACTIVATE_MODE (pad) = new_mode;
+      GST_PAD_MODE (pad) = new_mode;
       /* unlock blocked pads so element can resume and stop */
       GST_PAD_BLOCK_BROADCAST (pad);
       GST_OBJECT_UNLOCK (pad);
       break;
+    case GST_PAD_MODE_PUSH:
+    case GST_PAD_MODE_PULL:
+      GST_OBJECT_LOCK (pad);
+      GST_DEBUG_OBJECT (pad, "setting PAD_MODE %d, unset flushing", new_mode);
+      GST_PAD_UNSET_FLUSHING (pad);
+      GST_PAD_MODE (pad) = new_mode;
+      if (GST_PAD_IS_SINK (pad)) {
+        GstPad *peer;
+        /* make sure the peer src pad sends us all events */
+        if ((peer = GST_PAD_PEER (pad))) {
+          gst_object_ref (peer);
+          GST_OBJECT_UNLOCK (pad);
+
+          GST_DEBUG_OBJECT (pad, "reschedule events on peer %s:%s",
+              GST_DEBUG_PAD_NAME (peer));
+
+          GST_OBJECT_LOCK (peer);
+          schedule_events (peer, NULL);
+          GST_OBJECT_UNLOCK (peer);
+
+          gst_object_unref (peer);
+        } else {
+          GST_OBJECT_UNLOCK (pad);
+        }
+      } else {
+        GST_OBJECT_UNLOCK (pad);
+      }
+      break;
   }
 }
 
 static void
-post_activate (GstPad * pad, GstActivateMode new_mode)
+post_activate (GstPad * pad, GstPadMode new_mode)
 {
   switch (new_mode) {
-    case GST_ACTIVATE_PUSH:
-    case GST_ACTIVATE_PULL:
-      /* nop */
-      break;
-    case GST_ACTIVATE_NONE:
+    case GST_PAD_MODE_NONE:
       /* ensures that streaming stops */
       GST_PAD_STREAM_LOCK (pad);
       GST_DEBUG_OBJECT (pad, "stopped streaming");
+      GST_OBJECT_LOCK (pad);
+      remove_events (pad);
+      GST_OBJECT_UNLOCK (pad);
       GST_PAD_STREAM_UNLOCK (pad);
       break;
+    case GST_PAD_MODE_PUSH:
+    case GST_PAD_MODE_PULL:
+      /* NOP */
+      break;
   }
 }
 
@@ -687,48 +862,56 @@ post_activate (GstPad * pad, GstActivateMode new_mode)
 gboolean
 gst_pad_set_active (GstPad * pad, gboolean active)
 {
-  GstActivateMode old;
+  GstObject *parent;
+  GstPadMode old;
   gboolean ret = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
   GST_OBJECT_LOCK (pad);
-  old = GST_PAD_ACTIVATE_MODE (pad);
+  old = GST_PAD_MODE (pad);
+  ACQUIRE_PARENT (pad, parent, no_parent);
   GST_OBJECT_UNLOCK (pad);
 
   if (active) {
-    switch (old) {
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad, "activating pad from push");
-        ret = TRUE;
-        break;
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad, "activating pad from pull");
-        ret = TRUE;
-        break;
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "activating pad from none");
-        ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad);
-        break;
+    if (old == GST_PAD_MODE_NONE) {
+      GST_DEBUG_OBJECT (pad, "activating pad from none");
+      ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent);
+    } else {
+      GST_DEBUG_OBJECT (pad, "pad was active in mode %d", old);
+      ret = TRUE;
     }
   } else {
-    switch (old) {
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from push");
-        ret = gst_pad_activate_push (pad, FALSE);
-        break;
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from pull");
-        ret = gst_pad_activate_pull (pad, FALSE);
-        break;
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from none");
-        ret = TRUE;
-        break;
+    if (old == GST_PAD_MODE_NONE) {
+      GST_DEBUG_OBJECT (pad, "pad was inactive");
+      ret = TRUE;
+    } else {
+      GST_DEBUG_OBJECT (pad, "deactivating pad from mode %d", old);
+      ret = gst_pad_activate_mode (pad, old, FALSE);
     }
   }
 
-  if (!ret) {
+  RELEASE_PARENT (parent);
+
+  if (G_UNLIKELY (!ret))
+    goto failed;
+
+  if (!active) {
+    GST_OBJECT_LOCK (pad);
+    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+    GST_OBJECT_UNLOCK (pad);
+  }
+  return ret;
+
+  /* ERRORS */
+no_parent:
+  {
+    GST_DEBUG_OBJECT (pad, "no parent");
+    GST_OBJECT_UNLOCK (pad);
+    return FALSE;
+  }
+failed:
+  {
     GST_OBJECT_LOCK (pad);
     if (!active) {
       g_critical ("Failed to deactivate pad %s:%s, very bad",
@@ -737,21 +920,18 @@ gst_pad_set_active (GstPad * pad, gboolean active)
       GST_WARNING_OBJECT (pad, "Failed to activate pad");
     }
     GST_OBJECT_UNLOCK (pad);
+    return FALSE;
   }
-
-  return ret;
 }
 
 /**
- * gst_pad_activate_pull:
+ * gst_pad_activate_mode:
  * @pad: the #GstPad to activate or deactivate.
+ * @mode: the requested activation mode
  * @active: whether or not the pad should be active.
  *
- * Activates or deactivates the given pad in pull mode via dispatching to the
- * pad's activatepullfunc. For use from within pad activation functions only.
- * When called on sink pads, will first proxy the call to the peer pad, which
- * is expected to activate its internally linked pads from within its
- * activate_pull function.
+ * Activates or deactivates the given pad in @mode via dispatching to the
+ * pad's activatemodefunc. For use from within pad activation functions only.
  *
  * If you don't know what this is, you probably don't want to call it.
  *
@@ -760,79 +940,69 @@ gst_pad_set_active (GstPad * pad, gboolean active)
  * MT safe.
  */
 gboolean
-gst_pad_activate_pull (GstPad * pad, gboolean active)
+gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active)
 {
-  GstActivateMode old, new;
+  gboolean res = FALSE;
+  GstObject *parent;
+  GstPadMode old, new;
+  GstPadDirection dir;
   GstPad *peer;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
   GST_OBJECT_LOCK (pad);
-  old = GST_PAD_ACTIVATE_MODE (pad);
+  old = GST_PAD_MODE (pad);
+  dir = GST_PAD_DIRECTION (pad);
+  ACQUIRE_PARENT (pad, parent, no_parent);
   GST_OBJECT_UNLOCK (pad);
 
-  if (active) {
-    switch (old) {
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad, "activating pad from pull, was ok");
-        goto was_ok;
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad,
-            "activating pad from push, deactivate push first");
-        /* pad was activate in the wrong direction, deactivate it
-         * and reactivate it in pull mode */
-        if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE)))
-          goto deactivate_failed;
-        /* fallthrough, pad is deactivated now. */
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "activating pad from none");
-        break;
-    }
-  } else {
-    switch (old) {
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from none, was ok");
-        goto was_ok;
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from push, weird");
-        /* pad was activated in the other direction, deactivate it
-         * in push mode, this should not happen... */
-        if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE)))
-          goto deactivate_failed;
-        /* everything is fine now */
-        goto was_ok;
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from pull");
-        break;
-    }
+  new = active ? mode : GST_PAD_MODE_NONE;
+
+  if (old == new)
+    goto was_ok;
+
+  if (active && old != mode) {
+    /* pad was activate in the wrong direction, deactivate it
+     * and reactivate it in the requested mode */
+    GST_DEBUG_OBJECT (pad, "deactivating pad from mode %d", old);
+    if (G_UNLIKELY (!gst_pad_activate_mode (pad, old, FALSE)))
+      goto deactivate_failed;
   }
 
-  if (gst_pad_get_direction (pad) == GST_PAD_SINK) {
-    if ((peer = gst_pad_get_peer (pad))) {
-      GST_DEBUG_OBJECT (pad, "calling peer");
-      if (G_UNLIKELY (!gst_pad_activate_pull (peer, active)))
-        goto peer_failed;
-      gst_object_unref (peer);
-    } else {
-      /* there is no peer, this is only fatal when we activate. When we
-       * deactivate, we must assume the application has unlinked the peer and
-       * will deactivate it eventually. */
-      if (active)
-        goto not_linked;
-      else
-        GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
-    }
-  } else {
-    if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
-      goto failure;             /* Can't activate pull on a src without a
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+    {
+      if (dir == GST_PAD_SINK) {
+        if ((peer = gst_pad_get_peer (pad))) {
+          GST_DEBUG_OBJECT (pad, "calling peer");
+          if (G_UNLIKELY (!gst_pad_activate_mode (peer, mode, active)))
+            goto peer_failed;
+          gst_object_unref (peer);
+        } else {
+          /* there is no peer, this is only fatal when we activate. When we
+           * deactivate, we must assume the application has unlinked the peer and
+           * will deactivate it eventually. */
+          if (active)
+            goto not_linked;
+          else
+            GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
+        }
+      } else {
+        if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
+          goto failure;         /* Can't activate pull on a src without a
                                    getrange function */
+      }
+      break;
+    }
+    default:
+      break;
   }
 
-  new = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
   pre_activate (pad, new);
 
-  if (GST_PAD_ACTIVATEPULLFUNC (pad)) {
-    if (G_UNLIKELY (!GST_PAD_ACTIVATEPULLFUNC (pad) (pad, active)))
+  if (GST_PAD_ACTIVATEMODEFUNC (pad)) {
+    if (G_UNLIKELY (!GST_PAD_ACTIVATEMODEFUNC (pad) (pad, parent, mode,
+                active)))
       goto failure;
   } else {
     /* can happen for sinks of passthrough elements */
@@ -840,365 +1010,241 @@ gst_pad_activate_pull (GstPad * pad, gboolean active)
 
   post_activate (pad, new);
 
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in pull mode",
-      active ? "activated" : "deactivated");
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in mode %d",
+      active ? "activated" : "deactivated", mode);
 
-  return TRUE;
+exit_success:
+  res = TRUE;
+exit:
+  RELEASE_PARENT (parent);
+
+  return res;
 
+no_parent:
+  {
+    GST_DEBUG_OBJECT (pad, "no parent");
+    GST_OBJECT_UNLOCK (pad);
+    return FALSE;
+  }
 was_ok:
   {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in pull mode",
-        active ? "activated" : "deactivated");
-    return TRUE;
+    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in mode %d",
+        active ? "activated" : "deactivated", mode);
+    goto exit_success;
   }
 deactivate_failed:
   {
     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "failed to %s in switch to pull from mode %d",
-        (active ? "activate" : "deactivate"), old);
-    return FALSE;
+        "failed to %s in switch to mode %d from mode %d",
+        (active ? "activate" : "deactivate"), mode, old);
+    goto exit;
   }
 peer_failed:
   {
     GST_OBJECT_LOCK (peer);
     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "activate_pull on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
+        "activate_mode on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
     GST_OBJECT_UNLOCK (peer);
     gst_object_unref (peer);
-    return FALSE;
+    goto exit;
   }
 not_linked:
   {
     GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "can't activate unlinked sink "
         "pad in pull mode");
-    return FALSE;
+    goto exit;
   }
 failure:
   {
     GST_OBJECT_LOCK (pad);
-    GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in pull mode",
-        active ? "activate" : "deactivate");
-    _priv_gst_pad_invalidate_cache (pad);
+    GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in mode %d",
+        active ? "activate" : "deactivate", mode);
     GST_PAD_SET_FLUSHING (pad);
-    GST_PAD_ACTIVATE_MODE (pad) = old;
+    GST_PAD_MODE (pad) = old;
     GST_OBJECT_UNLOCK (pad);
-    return FALSE;
+    goto exit;
   }
 }
 
 /**
- * gst_pad_activate_push:
- * @pad: the #GstPad to activate or deactivate.
- * @active: whether the pad should be active or not.
- *
- * Activates or deactivates the given pad in push mode via dispatching to the
- * pad's activatepushfunc. For use from within pad activation functions only.
+ * gst_pad_is_active:
+ * @pad: the #GstPad to query
  *
- * If you don't know what this is, you probably don't want to call it.
+ * Query if a pad is active
  *
- * Returns: %TRUE if the operation was successful.
+ * Returns: TRUE if the pad is active.
  *
  * MT safe.
  */
 gboolean
-gst_pad_activate_push (GstPad * pad, gboolean active)
+gst_pad_is_active (GstPad * pad)
 {
-  GstActivateMode old, new;
+  gboolean result = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "trying to set %s in push mode",
-      active ? "activated" : "deactivated");
 
   GST_OBJECT_LOCK (pad);
-  old = GST_PAD_ACTIVATE_MODE (pad);
+  result = GST_PAD_IS_ACTIVE (pad);
   GST_OBJECT_UNLOCK (pad);
 
-  if (active) {
-    switch (old) {
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad, "activating pad from push, was ok");
-        goto was_ok;
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad,
-            "activating pad from push, deactivating pull first");
-        /* pad was activate in the wrong direction, deactivate it
-         * an reactivate it in push mode */
-        if (G_UNLIKELY (!gst_pad_activate_pull (pad, FALSE)))
-          goto deactivate_failed;
-        /* fallthrough, pad is deactivated now. */
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "activating pad from none");
-        break;
-    }
-  } else {
-    switch (old) {
-      case GST_ACTIVATE_NONE:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from none, was ok");
-        goto was_ok;
-      case GST_ACTIVATE_PULL:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from pull, weird");
-        /* pad was activated in the other direction, deactivate it
-         * in pull mode, this should not happen... */
-        if (G_UNLIKELY (!gst_pad_activate_pull (pad, FALSE)))
-          goto deactivate_failed;
-        /* everything is fine now */
-        goto was_ok;
-      case GST_ACTIVATE_PUSH:
-        GST_DEBUG_OBJECT (pad, "deactivating pad from push");
-        break;
-    }
-  }
+  return result;
+}
 
-  new = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
-  pre_activate (pad, new);
+/**
+ * gst_pad_add_probe:
+ * @pad: the #GstPad to add the probe to
+ * @mask: the probe mask
+ * @callback: #GstPadProbeCallback that will be called with notifications of
+ *           the pad state
+ * @user_data: (closure): user data passed to the callback
+ * @destroy_data: #GDestroyNotify for user_data
+ *
+ * Be notified of different states of pads. The provided callback is called for
+ * every state that matches @mask.
+ *
+ * Returns: an id or 0 on error. The id can be used to remove the probe with
+ * gst_pad_remove_probe().
+ *
+ * MT safe.
+ */
+gulong
+gst_pad_add_probe (GstPad * pad, GstPadProbeType mask,
+    GstPadProbeCallback callback, gpointer user_data,
+    GDestroyNotify destroy_data)
+{
+  GHook *hook;
+  gulong res;
 
-  if (GST_PAD_ACTIVATEPUSHFUNC (pad)) {
-    if (G_UNLIKELY (!GST_PAD_ACTIVATEPUSHFUNC (pad) (pad, active))) {
-      goto failure;
+  g_return_val_if_fail (GST_IS_PAD (pad), 0);
+  g_return_val_if_fail (mask != 0, 0);
+
+  GST_OBJECT_LOCK (pad);
+
+  /* make a new probe */
+  hook = g_hook_alloc (&pad->probes);
+
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "adding probe for mask 0x%08x",
+      mask);
+
+  /* when no contraints are given for the types, assume all types are
+   * acceptable */
+  if ((mask & GST_PAD_PROBE_TYPE_ALL_BOTH) == 0)
+    mask |= GST_PAD_PROBE_TYPE_ALL_BOTH;
+  if ((mask & GST_PAD_PROBE_TYPE_SCHEDULING) == 0)
+    mask |= GST_PAD_PROBE_TYPE_SCHEDULING;
+
+  /* store our flags and other fields */
+  hook->flags |= (mask << G_HOOK_FLAG_USER_SHIFT);
+  hook->func = callback;
+  hook->data = user_data;
+  hook->destroy = destroy_data;
+  PROBE_COOKIE (hook) = (pad->priv->probe_cookie - 1);
+
+  /* add the probe */
+  g_hook_prepend (&pad->probes, hook);
+  pad->num_probes++;
+  /* incremenent cookie so that the new hook get's called */
+  pad->priv->probe_list_cookie++;
+
+  /* get the id of the hook, we return this and it can be used to remove the
+   * probe later */
+  res = hook->hook_id;
+
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got probe id %lu", res);
+
+  if (mask & GST_PAD_PROBE_TYPE_BLOCKING) {
+    /* we have a block probe */
+    pad->num_blocked++;
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKED);
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "added blocking probe, "
+        "now %d blocking probes", pad->num_blocked);
+  }
+
+  /* call the callback if we need to be called for idle callbacks */
+  if ((mask & GST_PAD_PROBE_TYPE_IDLE) && (callback != NULL)) {
+    if (pad->priv->using > 0) {
+      /* the pad is in use, we can't signal the idle callback yet. Since we set the
+       * flag above, the last thread to leave the push will do the callback. New
+       * threads going into the push will block. */
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+          "pad is in use, delay idle callback");
+      GST_OBJECT_UNLOCK (pad);
+    } else {
+      GstPadProbeInfo info = { GST_PAD_PROBE_TYPE_IDLE, };
+
+      /* the pad is idle now, we can signal the idle callback now */
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+          "pad is idle, trigger idle callback");
+      GST_OBJECT_UNLOCK (pad);
+
+      callback (pad, &info, user_data);
     }
   } else {
-    /* quite ok, element relies on state change func to prepare itself */
+    GST_OBJECT_UNLOCK (pad);
   }
+  return res;
+}
 
-  post_activate (pad, new);
+static void
+cleanup_hook (GstPad * pad, GHook * hook)
+{
+  GstPadProbeType type;
 
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in push mode",
-      active ? "activated" : "deactivated");
-  return TRUE;
+  type = (hook->flags) >> G_HOOK_FLAG_USER_SHIFT;
 
-was_ok:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in push mode",
-        active ? "activated" : "deactivated");
-    return TRUE;
-  }
-deactivate_failed:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "failed to %s in switch to push from mode %d",
-        (active ? "activate" : "deactivate"), old);
-    return FALSE;
-  }
-failure:
-  {
-    GST_OBJECT_LOCK (pad);
-    GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in push mode",
-        active ? "activate" : "deactivate");
-    _priv_gst_pad_invalidate_cache (pad);
-    GST_PAD_SET_FLUSHING (pad);
-    GST_PAD_ACTIVATE_MODE (pad) = old;
-    GST_OBJECT_UNLOCK (pad);
-    return FALSE;
+  if (type & GST_PAD_PROBE_TYPE_BLOCKING) {
+    /* unblock when we remove the last blocking probe */
+    pad->num_blocked--;
+    GST_DEBUG_OBJECT (pad, "remove blocking probe, now %d left",
+        pad->num_blocked);
+    if (pad->num_blocked == 0) {
+      GST_DEBUG_OBJECT (pad, "last blocking probe removed, unblocking");
+      GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKED);
+      GST_PAD_BLOCK_BROADCAST (pad);
+    }
   }
+  g_hook_destroy_link (&pad->probes, hook);
+  pad->num_probes--;
 }
 
 /**
- * gst_pad_is_active:
- * @pad: the #GstPad to query
- *
- * Query if a pad is active
- *
- * Returns: TRUE if the pad is active.
- *
- * MT safe.
- */
-gboolean
-gst_pad_is_active (GstPad * pad)
-{
-  gboolean result = FALSE;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-
-  GST_OBJECT_LOCK (pad);
-  result = GST_PAD_MODE_ACTIVATE (GST_PAD_ACTIVATE_MODE (pad));
-  GST_OBJECT_UNLOCK (pad);
-
-  return result;
-}
-
-/**
- * gst_pad_set_blocked_async_full:
- * @pad: the #GstPad to block or unblock
- * @blocked: boolean indicating whether the pad should be blocked or unblocked
- * @callback: #GstPadBlockCallback that will be called when the
- *            operation succeeds
- * @user_data: (closure): user data passed to the callback
- * @destroy_data: #GDestroyNotify for user_data
- *
- * Blocks or unblocks the dataflow on a pad. The provided callback
- * is called when the operation succeeds; this happens right before the next
- * attempt at pushing a buffer on the pad.
+ * gst_pad_remove_probe:
+ * @pad: the #GstPad with the probe
+ * @id: the probe id to remove
  *
- * This can take a while as the pad can only become blocked when real dataflow
- * is happening.
- * When the pipeline is stalled, for example in PAUSED, this can
- * take an indeterminate amount of time.
- * You can pass NULL as the callback to make this call block. Be careful with
- * this blocking call as it might not return for reasons stated above.
- *
- * <note>
- *  Pad block handlers are only called for source pads in push mode
- *  and sink pads in pull mode.
- * </note>
- *
- * Returns: %TRUE if the pad could be blocked. This function can fail if the
- * wrong parameters were passed or the pad was already in the requested state.
+ * Remove the probe with @id from @pad.
  *
  * MT safe.
- *
- * Since: 0.10.23
  */
-gboolean
-gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
-    GstPadBlockCallback callback, gpointer user_data,
-    GDestroyNotify destroy_data)
+void
+gst_pad_remove_probe (GstPad * pad, gulong id)
 {
-  gboolean was_blocked = FALSE;
+  GHook *hook;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_if_fail (GST_IS_PAD (pad));
 
   GST_OBJECT_LOCK (pad);
 
-  was_blocked = GST_PAD_IS_BLOCKED (pad);
+  hook = g_hook_get (&pad->probes, id);
+  if (hook == NULL)
+    goto not_found;
 
-  if (G_UNLIKELY (was_blocked == blocked))
-    goto had_right_state;
-
-  if (G_UNLIKELY (
-          (GST_PAD_ACTIVATE_MODE (pad) == GST_ACTIVATE_PUSH) &&
-          (GST_PAD_DIRECTION (pad) != GST_PAD_SRC)))
-    goto wrong_direction;
-  if (G_UNLIKELY (
-          (GST_PAD_ACTIVATE_MODE (pad) == GST_ACTIVATE_PULL) &&
-          (GST_PAD_DIRECTION (pad) != GST_PAD_SINK)))
-    goto wrong_direction;
-
-  if (blocked) {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad");
-
-    _priv_gst_pad_invalidate_cache (pad);
-    GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
-
-    if (pad->block_destroy_data && pad->block_data)
-      pad->block_destroy_data (pad->block_data);
-
-    pad->block_callback = callback;
-    pad->block_data = user_data;
-    pad->block_destroy_data = destroy_data;
-    pad->abidata.ABI.block_callback_called = FALSE;
-    if (!callback) {
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
-      GST_PAD_BLOCK_WAIT (pad);
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked");
-    }
-  } else {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
-
-    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
-
-    if (pad->block_destroy_data && pad->block_data)
-      pad->block_destroy_data (pad->block_data);
-
-    pad->block_callback = callback;
-    pad->block_data = user_data;
-    pad->block_destroy_data = destroy_data;
-    pad->abidata.ABI.block_callback_called = FALSE;
-
-    GST_PAD_BLOCK_BROADCAST (pad);
-    if (!callback) {
-      /* no callback, wait for the unblock to happen */
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock");
-      GST_PAD_BLOCK_WAIT (pad);
-      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked");
-    }
-  }
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "removing hook %ld",
+      hook->hook_id);
+  cleanup_hook (pad, hook);
   GST_OBJECT_UNLOCK (pad);
 
-  return TRUE;
-
-/* Errors */
-
-had_right_state:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pad was in right state (%d)", was_blocked);
-    GST_OBJECT_UNLOCK (pad);
+  return;
 
-    return FALSE;
-  }
-wrong_direction:
+not_found:
   {
-    GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pad block on the wrong pad, "
-        "block src pads in push mode and sink pads in pull mode.");
     GST_OBJECT_UNLOCK (pad);
-
-    return FALSE;
+    g_warning ("%s: pad `%p' has no probe with id `%lu'", G_STRLOC, pad, id);
+    return;
   }
 }
 
 /**
- * gst_pad_set_blocked_async:
- * @pad: the #GstPad to block or unblock
- * @blocked: boolean indicating whether the pad should be blocked or unblocked
- * @callback: #GstPadBlockCallback that will be called when the
- *            operation succeeds
- * @user_data: (closure): user data passed to the callback
- *
- * Blocks or unblocks the dataflow on a pad. The provided callback
- * is called when the operation succeeds; this happens right before the next
- * attempt at pushing a buffer on the pad.
- *
- * This can take a while as the pad can only become blocked when real dataflow
- * is happening.
- * When the pipeline is stalled, for example in PAUSED, this can
- * take an indeterminate amount of time.
- * You can pass NULL as the callback to make this call block. Be careful with
- * this blocking call as it might not return for reasons stated above.
- *
- * <note>
- *  Pad block handlers are only called for source pads in push mode
- *  and sink pads in pull mode.
- * </note>
- *
- * Returns: TRUE if the pad could be blocked. This function can fail if the
- * wrong parameters were passed or the pad was already in the requested state.
- *
- * MT safe.
- */
-gboolean
-gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
-    GstPadBlockCallback callback, gpointer user_data)
-{
-  return gst_pad_set_blocked_async_full (pad, blocked,
-      callback, user_data, NULL);
-}
-
-/**
- * gst_pad_set_blocked:
- * @pad: the #GstPad to block or unblock
- * @blocked: boolean indicating we should block or unblock
- *
- * Blocks or unblocks the dataflow on a pad. This function is
- * a shortcut for gst_pad_set_blocked_async() with a NULL
- * callback.
- *
- * <note>
- *  Pad blocks are only possible for source pads in push mode
- *  and sink pads in pull mode.
- * </note>
- *
- * Returns: TRUE if the pad could be blocked. This function can fail if the
- * wrong parameters were passed or the pad was already in the requested state.
- *
- * MT safe.
- */
-gboolean
-gst_pad_set_blocked (GstPad * pad, gboolean blocked)
-{
-  return gst_pad_set_blocked_async (pad, blocked, NULL, NULL);
-}
-
-/**
  * gst_pad_is_blocked:
  * @pad: the #GstPad to query
  *
@@ -1218,7 +1264,7 @@ gst_pad_is_blocked (GstPad * pad)
   g_return_val_if_fail (GST_IS_PAD (pad), result);
 
   GST_OBJECT_LOCK (pad);
-  result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED);
+  result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED);
   GST_OBJECT_UNLOCK (pad);
 
   return result;
@@ -1246,96 +1292,134 @@ gst_pad_is_blocking (GstPad * pad)
 
   GST_OBJECT_LOCK (pad);
   /* the blocking flag is only valid if the pad is not flushing */
-  result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) &&
-      !GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING);
+  result = GST_PAD_IS_BLOCKING (pad) && !GST_PAD_IS_FLUSHING (pad);
   GST_OBJECT_UNLOCK (pad);
 
   return result;
 }
 
 /**
- * gst_pad_set_activate_function:
- * @pad: a #GstPad.
- * @activate: the #GstPadActivateFunction to set.
+ * gst_pad_check_reconfigure:
+ * @pad: the #GstPad to check
  *
- * Sets the given activate function for @pad. The activate function will
- * dispatch to gst_pad_activate_push() or gst_pad_activate_pull() to perform
- * the actual activation. Only makes sense to set on sink pads.
+ * Check and clear the #GST_PAD_FLAG_NEED_RECONFIGURE flag on @pad and return %TRUE
+ * if the flag was set.
  *
- * Call this function if your sink pad can start a pull-based task.
+ * Returns: %TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag was set on @pad.
+ */
+gboolean
+gst_pad_check_reconfigure (GstPad * pad)
+{
+  gboolean reconfigure;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+
+  GST_OBJECT_LOCK (pad);
+  reconfigure = GST_PAD_NEEDS_RECONFIGURE (pad);
+  GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+  GST_OBJECT_UNLOCK (pad);
+
+  return reconfigure;
+}
+
+/**
+ * gst_pad_mark_reconfigure:
+ * @pad: the #GstPad to mark
+ *
+ * Mark a pad for needing reconfiguration. The next call to
+ * gst_pad_check_reconfigure() will return %TRUE after this call.
  */
 void
-gst_pad_set_activate_function (GstPad * pad, GstPadActivateFunction activate)
+gst_pad_mark_reconfigure (GstPad * pad)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
-  GST_PAD_ACTIVATEFUNC (pad) = activate;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (activate));
+  GST_OBJECT_LOCK (pad);
+  GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+  GST_OBJECT_UNLOCK (pad);
 }
 
 /**
- * gst_pad_set_activatepull_function:
+ * gst_pad_set_activate_function_full:
  * @pad: a #GstPad.
- * @activatepull: the #GstPadActivateModeFunction to set.
+ * @activate: the #GstPadActivateFunction to set.
+ * @notify: notify called when @activate will not be used anymore.
+ *
+ * Sets the given activate function for @pad. The activate function will
+ * dispatch to gst_pad_activate_push() or gst_pad_activate_pull() to perform
+ * the actual activation. Only makes sense to set on sink pads.
  *
- * Sets the given activate_pull function for the pad. An activate_pull function
- * prepares the element and any upstream connections for pulling. See XXX
- * part-activation.txt for details.
+ * Call this function if your sink pad can start a pull-based task.
  */
 void
-gst_pad_set_activatepull_function (GstPad * pad,
-    GstPadActivateModeFunction activatepull)
+gst_pad_set_activate_function_full (GstPad * pad,
+    GstPadActivateFunction activate, GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
-  GST_PAD_ACTIVATEPULLFUNC (pad) = activatepull;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatepullfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (activatepull));
+  if (pad->activatenotify)
+    pad->activatenotify (pad);
+  GST_PAD_ACTIVATEFUNC (pad) = activate;
+  pad->activatenotify = notify;
+
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s",
+      GST_DEBUG_FUNCPTR_NAME (activate));
 }
 
 /**
- * gst_pad_set_activatepush_function:
+ * gst_pad_set_activatemode_function_full:
  * @pad: a #GstPad.
- * @activatepush: the #GstPadActivateModeFunction to set.
+ * @activatemode: the #GstPadActivateModeFunction to set.
+ * @notify: notify called when @activatemode will not be used anymore.
  *
- * Sets the given activate_push function for the pad. An activate_push function
- * prepares the element for pushing. See XXX part-activation.txt for details.
+ * Sets the given activate_mode function for the pad. An activate_mode function
+ * prepares the element for data passing.
  */
 void
-gst_pad_set_activatepush_function (GstPad * pad,
-    GstPadActivateModeFunction activatepush)
+gst_pad_set_activatemode_function_full (GstPad * pad,
+    GstPadActivateModeFunction activatemode, GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
-  GST_PAD_ACTIVATEPUSHFUNC (pad) = activatepush;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatepushfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (activatepush));
+  if (pad->activatemodenotify)
+    pad->activatemodenotify (pad);
+  GST_PAD_ACTIVATEMODEFUNC (pad) = activatemode;
+  pad->activatemodenotify = notify;
+
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatemodefunc set to %s",
+      GST_DEBUG_FUNCPTR_NAME (activatemode));
 }
 
 /**
- * gst_pad_set_chain_function:
+ * gst_pad_set_chain_function_full:
  * @pad: a sink #GstPad.
  * @chain: the #GstPadChainFunction to set.
+ * @notify: notify called when @chain will not be used anymore.
  *
  * Sets the given chain function for the pad. The chain function is called to
  * process a #GstBuffer input buffer. see #GstPadChainFunction for more details.
  */
 void
-gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
+gst_pad_set_chain_function_full (GstPad * pad, GstPadChainFunction chain,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (GST_PAD_IS_SINK (pad));
 
+  if (pad->chainnotify)
+    pad->chainnotify (pad);
   GST_PAD_CHAINFUNC (pad) = chain;
+  pad->chainnotify = notify;
+
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (chain));
 }
 
 /**
- * gst_pad_set_chain_list_function:
+ * gst_pad_set_chain_list_function_full:
  * @pad: a sink #GstPad.
  * @chainlist: the #GstPadChainListFunction to set.
+ * @notify: notify called when @chainlist will not be used anymore.
  *
  * Sets the given chain list function for the pad. The chainlist function is
  * called to process a #GstBufferList input buffer list. See
@@ -1344,224 +1428,123 @@ gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
  * Since: 0.10.24
  */
 void
-gst_pad_set_chain_list_function (GstPad * pad,
-    GstPadChainListFunction chainlist)
+gst_pad_set_chain_list_function_full (GstPad * pad,
+    GstPadChainListFunction chainlist, GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (GST_PAD_IS_SINK (pad));
 
+  if (pad->chainlistnotify)
+    pad->chainlistnotify (pad);
   GST_PAD_CHAINLISTFUNC (pad) = chainlist;
+  pad->chainlistnotify = notify;
+
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (chainlist));
 }
 
 /**
- * gst_pad_set_getrange_function:
+ * gst_pad_set_getrange_function_full:
  * @pad: a source #GstPad.
  * @get: the #GstPadGetRangeFunction to set.
+ * @notify: notify called when @get will not be used anymore.
  *
  * Sets the given getrange function for the pad. The getrange function is
  * called to produce a new #GstBuffer to start the processing pipeline. see
  * #GstPadGetRangeFunction for a description of the getrange function.
  */
 void
-gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get)
+gst_pad_set_getrange_function_full (GstPad * pad, GstPadGetRangeFunction get,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (GST_PAD_IS_SRC (pad));
 
+  if (pad->getrangenotify)
+    pad->getrangenotify (pad);
   GST_PAD_GETRANGEFUNC (pad) = get;
+  pad->getrangenotify = notify;
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (get));
 }
 
 /**
- * gst_pad_set_checkgetrange_function:
- * @pad: a source #GstPad.
- * @check: the #GstPadCheckGetRangeFunction to set.
- *
- * Sets the given checkgetrange function for the pad. Implement this function
- * on a pad if you dynamically support getrange based scheduling on the pad.
- */
-void
-gst_pad_set_checkgetrange_function (GstPad * pad,
-    GstPadCheckGetRangeFunction check)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (GST_PAD_IS_SRC (pad));
-
-  GST_PAD_CHECKGETRANGEFUNC (pad) = check;
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "checkgetrangefunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (check));
-}
-
-/**
- * gst_pad_set_event_function:
+ * gst_pad_set_event_function_full:
  * @pad: a #GstPad of either direction.
  * @event: the #GstPadEventFunction to set.
+ * @notify: notify called when @event will not be used anymore.
  *
  * Sets the given event handler for the pad.
  */
 void
-gst_pad_set_event_function (GstPad * pad, GstPadEventFunction event)
+gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  if (pad->eventnotify)
+    pad->eventnotify (pad);
   GST_PAD_EVENTFUNC (pad) = event;
+  pad->eventnotify = notify;
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfunc for set to %s",
       GST_DEBUG_FUNCPTR_NAME (event));
 }
 
 /**
- * gst_pad_set_query_function:
+ * gst_pad_set_query_function_full:
  * @pad: a #GstPad of either direction.
  * @query: the #GstPadQueryFunction to set.
+ * @notify: notify called when @query will not be used anymore.
  *
  * Set the given query function for the pad.
  */
 void
-gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query)
+gst_pad_set_query_function_full (GstPad * pad, GstPadQueryFunction query,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  if (pad->querynotify)
+    pad->querynotify (pad);
   GST_PAD_QUERYFUNC (pad) = query;
+  pad->querynotify = notify;
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "queryfunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (query));
 }
 
 /**
- * gst_pad_set_query_type_function:
- * @pad: a #GstPad of either direction.
- * @type_func: the #GstPadQueryTypeFunction to set.
- *
- * Set the given query type function for the pad.
- */
-void
-gst_pad_set_query_type_function (GstPad * pad,
-    GstPadQueryTypeFunction type_func)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_QUERYTYPEFUNC (pad) = type_func;
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "querytypefunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (type_func));
-}
-
-/**
- * gst_pad_get_query_types:
- * @pad: a #GstPad.
- *
- * Get an array of supported queries that can be performed
- * on this pad.
- *
- * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
- *     of #GstQueryType.
- */
-const GstQueryType *
-gst_pad_get_query_types (GstPad * pad)
-{
-  GstPadQueryTypeFunction func;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  if (G_UNLIKELY ((func = GST_PAD_QUERYTYPEFUNC (pad)) == NULL))
-    goto no_func;
-
-  return func (pad);
-
-no_func:
-  {
-    return NULL;
-  }
-}
-
-static gboolean
-gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data)
-{
-  *data = gst_pad_get_query_types (pad);
-
-  return TRUE;
-}
-
-/**
- * gst_pad_get_query_types_default:
- * @pad: a #GstPad.
- *
- * Invoke the default dispatcher for the query types on
- * the pad.
- *
- * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
- *     of #GstQueryType, or NULL if none of the internally-linked pads has a
- *     query types function.
- */
-const GstQueryType *
-gst_pad_get_query_types_default (GstPad * pad)
-{
-  GstQueryType *result = NULL;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
-      gst_pad_get_query_types_dispatcher, &result);
-
-  return result;
-}
-
-/**
- * gst_pad_set_iterate_internal_links_function:
+ * gst_pad_set_iterate_internal_links_function_full:
  * @pad: a #GstPad of either direction.
  * @iterintlink: the #GstPadIterIntLinkFunction to set.
+ * @notify: notify called when @iterintlink will not be used anymore.
  *
  * Sets the given internal link iterator function for the pad.
  *
  * Since: 0.10.21
  */
 void
-gst_pad_set_iterate_internal_links_function (GstPad * pad,
-    GstPadIterIntLinkFunction iterintlink)
+gst_pad_set_iterate_internal_links_function_full (GstPad * pad,
+    GstPadIterIntLinkFunction iterintlink, GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  if (pad->iterintlinknotify)
+    pad->iterintlinknotify (pad);
   GST_PAD_ITERINTLINKFUNC (pad) = iterintlink;
+  pad->iterintlinknotify = notify;
+
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s",
       GST_DEBUG_FUNCPTR_NAME (iterintlink));
 }
 
 /**
- * gst_pad_set_internal_link_function:
- * @pad: a #GstPad of either direction.
- * @intlink: the #GstPadIntLinkFunction to set.
- *
- * Sets the given internal link function for the pad.
- *
- * Deprecated: Use the thread-safe gst_pad_set_iterate_internal_links_function()
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void
-gst_pad_set_internal_link_function (GstPad * pad,
-    GstPadIntLinkFunction intlink);
-#endif
-void
-gst_pad_set_internal_link_function (GstPad * pad, GstPadIntLinkFunction intlink)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_INTLINKFUNC (pad) = intlink;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s",
-      GST_DEBUG_FUNCPTR_NAME (intlink));
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
- * gst_pad_set_link_function:
+ * gst_pad_set_link_function_full:
  * @pad: a #GstPad.
  * @link: the #GstPadLinkFunction to set.
+ * @notify: notify called when @link will not be used anymore.
  *
  * Sets the given link function for the pad. It will be called when
  * the pad is linked with another pad.
@@ -1576,169 +1559,62 @@ gst_pad_set_internal_link_function (GstPad * pad, GstPadIntLinkFunction intlink)
  * of the peer sink pad, if present.
  */
 void
-gst_pad_set_link_function (GstPad * pad, GstPadLinkFunction link)
+gst_pad_set_link_function_full (GstPad * pad, GstPadLinkFunction link,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  if (pad->linknotify)
+    pad->linknotify (pad);
   GST_PAD_LINKFUNC (pad) = link;
+  pad->linknotify = notify;
+
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "linkfunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (link));
 }
 
 /**
- * gst_pad_set_unlink_function:
+ * gst_pad_set_unlink_function_full:
  * @pad: a #GstPad.
  * @unlink: the #GstPadUnlinkFunction to set.
+ * @notify: notify called when @unlink will not be used anymore.
  *
  * Sets the given unlink function for the pad. It will be called
  * when the pad is unlinked.
  */
 void
-gst_pad_set_unlink_function (GstPad * pad, GstPadUnlinkFunction unlink)
+gst_pad_set_unlink_function_full (GstPad * pad, GstPadUnlinkFunction unlink,
+    GDestroyNotify notify)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  if (pad->unlinknotify)
+    pad->unlinknotify (pad);
   GST_PAD_UNLINKFUNC (pad) = unlink;
+  pad->unlinknotify = notify;
+
   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "unlinkfunc set to %s",
       GST_DEBUG_FUNCPTR_NAME (unlink));
 }
 
 /**
- * gst_pad_set_getcaps_function:
- * @pad: a #GstPad.
- * @getcaps: the #GstPadGetCapsFunction to set.
- *
- * Sets the given getcaps function for the pad. @getcaps should return the
- * allowable caps for a pad in the context of the element's state, its link to
- * other elements, and the devices or files it has opened. These caps must be a
- * subset of the pad template caps. In the NULL state with no links, @getcaps
- * should ideally return the same caps as the pad template. In rare
- * circumstances, an object property can affect the caps returned by @getcaps,
- * but this is discouraged.
- *
- * You do not need to call this function if @pad's allowed caps are always the
- * same as the pad template caps. This can only be true if the padtemplate
- * has fixed simple caps.
- *
- * For most filters, the caps returned by @getcaps is directly affected by the
- * allowed caps on other pads. For demuxers and decoders, the caps returned by
- * the srcpad's getcaps function is directly related to the stream data. Again,
- * @getcaps should return the most specific caps it reasonably can, since this
- * helps with autoplugging.
- *
- * Note that the return value from @getcaps is owned by the caller, so the
- * caller should unref the caps after usage.
- */
-void
-gst_pad_set_getcaps_function (GstPad * pad, GstPadGetCapsFunction getcaps)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_GETCAPSFUNC (pad) = getcaps;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getcapsfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (getcaps));
-}
-
-/**
- * gst_pad_set_acceptcaps_function:
- * @pad: a #GstPad.
- * @acceptcaps: the #GstPadAcceptCapsFunction to set.
+ * gst_pad_unlink:
+ * @srcpad: the source #GstPad to unlink.
+ * @sinkpad: the sink #GstPad to unlink.
  *
- * Sets the given acceptcaps function for the pad.  The acceptcaps function
- * will be called to check if the pad can accept the given caps. Setting the
- * acceptcaps function to NULL restores the default behaviour of allowing
- * any caps that matches the caps from gst_pad_get_caps().
- */
-void
-gst_pad_set_acceptcaps_function (GstPad * pad,
-    GstPadAcceptCapsFunction acceptcaps)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_ACCEPTCAPSFUNC (pad) = acceptcaps;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "acceptcapsfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (acceptcaps));
-}
-
-/**
- * gst_pad_set_fixatecaps_function:
- * @pad: a #GstPad.
- * @fixatecaps: the #GstPadFixateCapsFunction to set.
+ * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked
+ * signal on both pads.
  *
- * Sets the given fixatecaps function for the pad.  The fixatecaps function
- * will be called whenever the default values for a GstCaps needs to be
- * filled in.
- */
-void
-gst_pad_set_fixatecaps_function (GstPad * pad,
-    GstPadFixateCapsFunction fixatecaps)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_FIXATECAPSFUNC (pad) = fixatecaps;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fixatecapsfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (fixatecaps));
-}
-
-/**
- * gst_pad_set_setcaps_function:
- * @pad: a #GstPad.
- * @setcaps: the #GstPadSetCapsFunction to set.
+ * Returns: TRUE if the pads were unlinked. This function returns FALSE if
+ * the pads were not linked together.
  *
- * Sets the given setcaps function for the pad.  The setcaps function
- * will be called whenever a buffer with a new media type is pushed or
- * pulled from the pad. The pad/element needs to update its internal
- * structures to process the new media type. If this new type is not
- * acceptable, the setcaps function should return FALSE.
+ * MT safe.
  */
-void
-gst_pad_set_setcaps_function (GstPad * pad, GstPadSetCapsFunction setcaps)
+gboolean
+gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
 {
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  GST_PAD_SETCAPSFUNC (pad) = setcaps;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "setcapsfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (setcaps));
-}
-
-/**
- * gst_pad_set_bufferalloc_function:
- * @pad: a sink #GstPad.
- * @bufalloc: the #GstPadBufferAllocFunction to set.
- *
- * Sets the given bufferalloc function for the pad. Note that the
- * bufferalloc function can only be set on sinkpads.
- */
-void
-gst_pad_set_bufferalloc_function (GstPad * pad,
-    GstPadBufferAllocFunction bufalloc)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (GST_PAD_IS_SINK (pad));
-
-  GST_PAD_BUFFERALLOCFUNC (pad) = bufalloc;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "bufferallocfunc set to %s",
-      GST_DEBUG_FUNCPTR_NAME (bufalloc));
-}
-
-/**
- * gst_pad_unlink:
- * @srcpad: the source #GstPad to unlink.
- * @sinkpad: the sink #GstPad to unlink.
- *
- * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked
- * signal on both pads.
- *
- * Returns: TRUE if the pads were unlinked. This function returns FALSE if
- * the pads were not linked together.
- *
- * MT safe.
- */
-gboolean
-gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
-{
-  gboolean result = FALSE;
-  GstElement *parent = NULL;
+  gboolean result = FALSE;
+  GstElement *parent = NULL;
 
   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
   g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE);
@@ -1764,7 +1640,6 @@ gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
   }
 
   GST_OBJECT_LOCK (srcpad);
-
   GST_OBJECT_LOCK (sinkpad);
 
   if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad))
@@ -1777,8 +1652,6 @@ gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
     GST_PAD_UNLINKFUNC (sinkpad) (sinkpad);
   }
 
-  _priv_gst_pad_invalidate_cache (srcpad);
-
   /* first clear peers */
   GST_PAD_PEER (srcpad) = NULL;
   GST_PAD_PEER (sinkpad) = NULL;
@@ -1859,8 +1732,14 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink,
 
   /* Doing the expensive caps checking takes priority over only checking the template caps */
   if (flags & GST_PAD_LINK_CHECK_CAPS) {
-    srccaps = gst_pad_get_caps_unlocked (src);
-    sinkcaps = gst_pad_get_caps_unlocked (sink);
+    GST_OBJECT_UNLOCK (sink);
+    GST_OBJECT_UNLOCK (src);
+
+    srccaps = gst_pad_query_caps (src, NULL);
+    sinkcaps = gst_pad_query_caps (sink, NULL);
+
+    GST_OBJECT_LOCK (src);
+    GST_OBJECT_LOCK (sink);
   } else {
     /* If one of the two pads doesn't have a template, consider the intersection
      * as valid.*/
@@ -2100,6 +1979,7 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
 {
   GstPadLinkReturn result;
   GstElement *parent;
+  GstPadLinkFunction srcfunc, sinkfunc;
 
   g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
   g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
@@ -2108,8 +1988,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
       GST_PAD_LINK_WRONG_DIRECTION);
 
   /* Notify the parent early. See gst_pad_unlink for details. */
-  if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
-    if (GST_IS_ELEMENT (parent)) {
+  if (G_LIKELY ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad))))) {
+    if (G_LIKELY (GST_IS_ELEMENT (parent))) {
       gst_element_post_message (parent,
           gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
               GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
@@ -2122,44 +2002,81 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
   /* prepare will also lock the two pads */
   result = gst_pad_link_prepare (srcpad, sinkpad, flags);
 
-  if (result != GST_PAD_LINK_OK)
+  if (G_UNLIKELY (result != GST_PAD_LINK_OK))
     goto done;
 
   /* must set peers before calling the link function */
   GST_PAD_PEER (srcpad) = sinkpad;
   GST_PAD_PEER (sinkpad) = srcpad;
 
+  /* check events, when something is different, mark pending */
+  schedule_events (srcpad, sinkpad);
+
+  /* get the link functions */
+  srcfunc = GST_PAD_LINKFUNC (srcpad);
+  sinkfunc = GST_PAD_LINKFUNC (sinkpad);
+
+  if (G_UNLIKELY (srcfunc || sinkfunc)) {
+    /* custom link functions, execute them */
+    GST_OBJECT_UNLOCK (sinkpad);
+    GST_OBJECT_UNLOCK (srcpad);
+
+    if (srcfunc) {
+      /* this one will call the peer link function */
+      result = srcfunc (srcpad, sinkpad);
+    } else if (sinkfunc) {
+      /* if no source link function, we need to call the sink link
+       * function ourselves. */
+      result = sinkfunc (sinkpad, srcpad);
+    }
+
+    GST_OBJECT_LOCK (srcpad);
+    GST_OBJECT_LOCK (sinkpad);
+
+    /* we released the lock, check if the same pads are linked still */
+    if (GST_PAD_PEER (srcpad) != sinkpad || GST_PAD_PEER (sinkpad) != srcpad)
+      goto concurrent_link;
+
+    if (G_UNLIKELY (result != GST_PAD_LINK_OK))
+      goto link_failed;
+  }
   GST_OBJECT_UNLOCK (sinkpad);
   GST_OBJECT_UNLOCK (srcpad);
 
-  /* FIXME released the locks here, concurrent thread might link
-   * something else. */
-  if (GST_PAD_LINKFUNC (srcpad)) {
-    /* this one will call the peer link function */
-    result = GST_PAD_LINKFUNC (srcpad) (srcpad, sinkpad);
-  } else if (GST_PAD_LINKFUNC (sinkpad)) {
-    /* if no source link function, we need to call the sink link
-     * function ourselves. */
-    result = GST_PAD_LINKFUNC (sinkpad) (sinkpad, srcpad);
-  } else {
-    result = GST_PAD_LINK_OK;
+  /* fire off a signal to each of the pads telling them
+   * that they've been linked */
+  g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
+  g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad);
+
+  GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
+      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
+  gst_pad_send_event (srcpad, gst_event_new_reconfigure ());
+
+done:
+  if (G_LIKELY (parent)) {
+    gst_element_post_message (parent,
+        gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
+            GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
+    gst_object_unref (parent);
   }
 
-  GST_OBJECT_LOCK (srcpad);
-  GST_OBJECT_LOCK (sinkpad);
+  return result;
 
-  if (result == GST_PAD_LINK_OK) {
+  /* ERRORS */
+concurrent_link:
+  {
+    GST_CAT_INFO (GST_CAT_PADS, "concurrent link between %s:%s and %s:%s",
+        GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
     GST_OBJECT_UNLOCK (sinkpad);
     GST_OBJECT_UNLOCK (srcpad);
 
-    /* fire off a signal to each of the pads telling them
-     * that they've been linked */
-    g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
-    g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad);
-
-    GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
-        GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-  } else {
+    /* The other link operation succeeded first */
+    result = GST_PAD_LINK_WAS_LINKED;
+    goto done;
+  }
+link_failed:
+  {
     GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed",
         GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
 
@@ -2168,17 +2085,9 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
 
     GST_OBJECT_UNLOCK (sinkpad);
     GST_OBJECT_UNLOCK (srcpad);
-  }
 
-done:
-  if (parent) {
-    gst_element_post_message (parent,
-        gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
-            GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
-    gst_object_unref (parent);
+    goto done;
   }
-
-  return result;
 }
 
 /**
@@ -2221,1517 +2130,945 @@ gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ)
  *
  * Gets the template for @pad.
  *
- * Returns: (transfer none): the #GstPadTemplate from which this pad was
- *     instantiated, or %NULL if this pad has no template.
- *
- * FIXME: currently returns an unrefcounted padtemplate.
+ * Returns: (transfer full): the #GstPadTemplate from which this pad was
+ *     instantiated, or %NULL if this pad has no template. Unref after
+ *     usage.
  */
 GstPadTemplate *
 gst_pad_get_pad_template (GstPad * pad)
 {
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  return GST_PAD_PAD_TEMPLATE (pad);
-}
-
-
-/* should be called with the pad LOCK held */
-/* refs the caps, so caller is responsible for getting it unreffed */
-static GstCaps *
-gst_pad_get_caps_unlocked (GstPad * pad)
-{
-  GstCaps *result = NULL;
   GstPadTemplate *templ;
 
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
-
-  if (GST_PAD_GETCAPSFUNC (pad)) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "dispatching to pad getcaps function");
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-    GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_GETCAPS);
-    GST_OBJECT_UNLOCK (pad);
-    result = GST_PAD_GETCAPSFUNC (pad) (pad);
-    GST_OBJECT_LOCK (pad);
-    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS);
+  templ = GST_PAD_PAD_TEMPLATE (pad);
 
-    if (result == NULL) {
-      g_critical ("pad %s:%s returned NULL caps from getcaps function",
-          GST_DEBUG_PAD_NAME (pad));
-    } else {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-          "pad getcaps returned %" GST_PTR_FORMAT, result);
-#ifndef G_DISABLE_ASSERT
-      /* check that the returned caps are a real subset of the template caps */
-      if (GST_PAD_PAD_TEMPLATE (pad)) {
-        const GstCaps *templ_caps =
-            GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
-        if (!gst_caps_is_subset (result, templ_caps)) {
-          GstCaps *temp;
-
-          GST_CAT_ERROR_OBJECT (GST_CAT_CAPS, pad,
-              "pad returned caps %" GST_PTR_FORMAT
-              " which are not a real subset of its template caps %"
-              GST_PTR_FORMAT, result, templ_caps);
-          g_warning
-              ("pad %s:%s returned caps which are not a real "
-              "subset of its template caps", GST_DEBUG_PAD_NAME (pad));
-          temp = gst_caps_intersect (templ_caps, result);
-          gst_caps_unref (result);
-          result = temp;
-        }
-      }
-#endif
-      goto done;
-    }
-  }
-  if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
-    result = GST_PAD_TEMPLATE_CAPS (templ);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
-        result);
+  return (templ ? gst_object_ref (templ) : NULL);
+}
 
-    result = gst_caps_ref (result);
-    goto done;
-  }
-  if ((result = GST_PAD_CAPS (pad))) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "using pad caps %p %" GST_PTR_FORMAT, result, result);
+/**
+ * gst_pad_has_current_caps:
+ * @pad: a  #GstPad to check
+ *
+ * Check if @pad has caps set on it with a #GST_EVENT_CAPS event.
+ *
+ * Returns: TRUE when @pad has caps associated with it.
+ */
+gboolean
+gst_pad_has_current_caps (GstPad * pad)
+{
+  gboolean result;
+  GstCaps *caps;
 
-    result = gst_caps_ref (result);
-    goto done;
-  }
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
-  /* this almost never happens */
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps");
-  result = gst_caps_new_empty ();
+  GST_OBJECT_LOCK (pad);
+  caps = get_pad_caps (pad);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+      "check current pad caps %" GST_PTR_FORMAT, caps);
+  result = (caps != NULL);
+  GST_OBJECT_UNLOCK (pad);
 
-done:
   return result;
 }
 
-/* FIXME-0.11: what about making this the default and using
- * gst_caps_make_writable() explicitly where needed
- */
 /**
- * gst_pad_get_caps_reffed:
- * @pad: a  #GstPad to get the capabilities of.
- *
- * Gets the capabilities this pad can produce or consume. Preferred function if
- * one only wants to read or intersect the caps.
+ * gst_pad_get_current_caps:
+ * @pad: a  #GstPad to get the current capabilities of.
  *
- * Returns: (transfer full): the caps of the pad with incremented ref-count.
+ * Gets the capabilities currently configured on @pad with the last
+ * #GST_EVENT_CAPS event.
  *
- * Since: 0.10.26
+ * Returns: the current caps of the pad with incremented ref-count.
  */
 GstCaps *
-gst_pad_get_caps_reffed (GstPad * pad)
+gst_pad_get_current_caps (GstPad * pad)
 {
-  GstCaps *result = NULL;
+  GstCaps *result;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
   GST_OBJECT_LOCK (pad);
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
-
-  result = gst_pad_get_caps_unlocked (pad);
-
+  if ((result = get_pad_caps (pad)))
+    gst_caps_ref (result);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+      "get current pad caps %" GST_PTR_FORMAT, result);
   GST_OBJECT_UNLOCK (pad);
 
   return result;
 }
 
 /**
- * gst_pad_get_caps:
- * @pad: a  #GstPad to get the capabilities of.
+ * gst_pad_set_caps:
+ * @pad: a  #GstPad to set the capabilities of.
+ * @caps: (transfer none): a #GstCaps to set.
  *
- * Gets the capabilities this pad can produce or consume.
- * Note that this method doesn't necessarily return the caps set by
- * gst_pad_set_caps() - use GST_PAD_CAPS() for that instead.
- * gst_pad_get_caps returns all possible caps a pad can operate with, using
- * the pad's get_caps function;
- * this returns the pad template caps if not explicitly set.
+ * Sets the capabilities of this pad. The caps must be fixed. Any previous
+ * caps on the pad will be unreffed. This function refs the caps so you should
+ * unref if as soon as you don't need it anymore.
+ * It is possible to set NULL caps, which will make the pad unnegotiated
+ * again.
  *
- * Returns: (transfer full): a newly allocated copy of the #GstCaps of this pad
+ * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
+ * or bad parameters were provided to this function.
  *
  * MT safe.
  */
-GstCaps *
-gst_pad_get_caps (GstPad * pad)
+gboolean
+gst_pad_set_caps (GstPad * pad, GstCaps * caps)
 {
-  GstCaps *result = gst_pad_get_caps_reffed (pad);
+  GstEvent *event;
+  gboolean res = TRUE;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (caps != NULL && gst_caps_is_fixed (caps), FALSE);
 
-  /* be sure that we have a copy */
-  if (G_LIKELY (result))
-    result = gst_caps_make_writable (result);
+  event = gst_event_new_caps (caps);
 
-  return result;
+  if (GST_PAD_IS_SRC (pad))
+    res = gst_pad_push_event (pad, event);
+  else
+    res = gst_pad_send_event (pad, event);
+
+  return res;
 }
 
-/* FIXME-0.11: what about making this the default and using
- * gst_caps_make_writable() explicitly where needed
- */
 /**
- * gst_pad_peer_get_caps_reffed:
- * @pad: a  #GstPad to get the capabilities of.
- *
- * Gets the capabilities of the peer connected to this pad. Preferred function
- * if one only wants to read or intersect the caps.
+ * gst_pad_get_pad_template_caps:
+ * @pad: a #GstPad to get the template capabilities from.
  *
- * Returns: (transfer full): the caps of the pad with incremented ref-count
+ * Gets the capabilities for @pad's template.
  *
- * Since: 0.10.26
+ * Returns: (transfer full): the #GstCaps of this pad template.
+ * Unref after usage.
  */
 GstCaps *
-gst_pad_peer_get_caps_reffed (GstPad * pad)
+gst_pad_get_pad_template_caps (GstPad * pad)
 {
-  GstPad *peerpad;
-  GstCaps *result = NULL;
+  static GstStaticCaps anycaps = GST_STATIC_CAPS ("ANY");
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  GST_OBJECT_LOCK (pad);
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get peer caps");
+  if (GST_PAD_PAD_TEMPLATE (pad))
+    return gst_pad_template_get_caps (GST_PAD_PAD_TEMPLATE (pad));
 
-  peerpad = GST_PAD_PEER (pad);
-  if (G_UNLIKELY (peerpad == NULL))
-    goto no_peer;
+  return gst_static_caps_get (&anycaps);
+}
 
-  gst_object_ref (peerpad);
-  GST_OBJECT_UNLOCK (pad);
+/**
+ * gst_pad_get_peer:
+ * @pad: a #GstPad to get the peer of.
+ *
+ * Gets the peer of @pad. This function refs the peer pad so
+ * you need to unref it after use.
+ *
+ * Returns: (transfer full): the peer #GstPad. Unref after usage.
+ *
+ * MT safe.
+ */
+GstPad *
+gst_pad_get_peer (GstPad * pad)
+{
+  GstPad *result;
 
-  result = gst_pad_get_caps_reffed (peerpad);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  gst_object_unref (peerpad);
+  GST_OBJECT_LOCK (pad);
+  result = GST_PAD_PEER (pad);
+  if (result)
+    gst_object_ref (result);
+  GST_OBJECT_UNLOCK (pad);
 
   return result;
-
-no_peer:
-  {
-    GST_OBJECT_UNLOCK (pad);
-    return NULL;
-  }
 }
 
 /**
- * gst_pad_peer_get_caps:
- * @pad: a  #GstPad to get the peer capabilities of.
+ * gst_pad_get_allowed_caps:
+ * @pad: a #GstPad.
+ *
+ * Gets the capabilities of the allowed media types that can flow through
+ * @pad and its peer.
  *
- * Gets the capabilities of the peer connected to this pad. Similar to
- * gst_pad_get_caps().
+ * The allowed capabilities is calculated as the intersection of the results of
+ * calling gst_pad_query_caps() on @pad and its peer. The caller owns a reference
+ * on the resulting caps.
+ *
+ * Returns: (transfer full): the allowed #GstCaps of the pad link. Unref the
+ *     caps when you no longer need it. This function returns NULL when @pad
+ *     has no peer.
  *
- * Returns: (transfer full): a newly allocated copy of the #GstCaps of the
- *     peer pad. Use gst_caps_unref() to get rid of it. This function
- *     returns %NULL if there is no peer pad.
+ * MT safe.
  */
 GstCaps *
-gst_pad_peer_get_caps (GstPad * pad)
+gst_pad_get_allowed_caps (GstPad * pad)
 {
-  GstPad *peerpad;
-  GstCaps *result = NULL;
+  GstCaps *mycaps;
+  GstCaps *caps;
+  GstCaps *peercaps;
+  GstPad *peer;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
   GST_OBJECT_LOCK (pad);
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get peer caps");
-
-  peerpad = GST_PAD_PEER (pad);
-  if (G_UNLIKELY (peerpad == NULL))
+  peer = GST_PAD_PEER (pad);
+  if (G_UNLIKELY (peer == NULL))
     goto no_peer;
 
-  gst_object_ref (peerpad);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting allowed caps");
+
+  gst_object_ref (peer);
   GST_OBJECT_UNLOCK (pad);
+  mycaps = gst_pad_query_caps (pad, NULL);
+
+  peercaps = gst_pad_query_caps (peer, NULL);
+  gst_object_unref (peer);
 
-  result = gst_pad_get_caps (peerpad);
+  caps = gst_caps_intersect (mycaps, peercaps);
+  gst_caps_unref (peercaps);
+  gst_caps_unref (mycaps);
 
-  gst_object_unref (peerpad);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT,
+      caps);
 
-  return result;
+  return caps;
 
 no_peer:
   {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer");
     GST_OBJECT_UNLOCK (pad);
-    return NULL;
-  }
-}
-
-static gboolean
-fixate_value (GValue * dest, const GValue * src)
-{
-  if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
-    g_value_init (dest, G_TYPE_INT);
-    g_value_set_int (dest, gst_value_get_int_range_min (src));
-  } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
-    g_value_init (dest, G_TYPE_DOUBLE);
-    g_value_set_double (dest, gst_value_get_double_range_min (src));
-  } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
-    gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
-  } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
-    GValue temp = { 0 };
-
-    /* list could be empty */
-    if (gst_value_list_get_size (src) <= 0)
-      return FALSE;
-
-    gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
-
-    if (!fixate_value (dest, &temp))
-      gst_value_init_and_copy (dest, &temp);
-    g_value_unset (&temp);
-  } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
-    gboolean res = FALSE;
-    guint n, len;
-
-    len = gst_value_array_get_size (src);
-    g_value_init (dest, GST_TYPE_ARRAY);
-    for (n = 0; n < len; n++) {
-      GValue kid = { 0 };
-      const GValue *orig_kid = gst_value_array_get_value (src, n);
-
-      if (!fixate_value (&kid, orig_kid))
-        gst_value_init_and_copy (&kid, orig_kid);
-      else
-        res = TRUE;
-      gst_value_array_append_value (dest, &kid);
-      g_value_unset (&kid);
-    }
-
-    if (!res)
-      g_value_unset (dest);
-
-    return res;
-  } else {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-gst_pad_default_fixate (GQuark field_id, const GValue * value, gpointer data)
-{
-  GstStructure *s = data;
-  GValue v = { 0 };
 
-  if (fixate_value (&v, value)) {
-    gst_structure_id_set_value (s, field_id, &v);
-    g_value_unset (&v);
+    return NULL;
   }
-
-  return TRUE;
 }
 
 /**
- * gst_pad_fixate_caps:
- * @pad: a  #GstPad to fixate
- * @caps: the  #GstCaps to fixate
- *
- * Fixate a caps on the given pad. Modifies the caps in place, so you should
- * make sure that the caps are actually writable (see gst_caps_make_writable()).
+ * gst_pad_iterate_internal_links_default:
+ * @pad: the #GstPad to get the internal links of.
+ * @parent: the parent of @pad or NULL
+ *
+ * Iterate the list of pads to which the given pad is linked to inside of
+ * the parent element.
+ * This is the default handler, and thus returns an iterator of all of the
+ * pads inside the parent element with opposite direction.
+ *
+ * The caller must free this iterator after use with gst_iterator_free().
+ *
+ * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
+ * returned pad with gst_object_unref().
+ *
+ * Since: 0.10.21
  */
-void
-gst_pad_fixate_caps (GstPad * pad, GstCaps * caps)
+GstIterator *
+gst_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
 {
-  GstPadFixateCapsFunction fixatefunc;
-  GstStructure *s;
+  GstIterator *res;
+  GList **padlist;
+  guint32 *cookie;
+  GMutex *lock;
+  gpointer owner;
+  GstElement *eparent;
 
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (caps != NULL);
-  g_return_if_fail (!gst_caps_is_empty (caps));
-  /* FIXME-0.11: do not allow fixating any-caps
-   * g_return_if_fail (!gst_caps_is_any (caps));
-   */
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  if (gst_caps_is_fixed (caps) || gst_caps_is_any (caps))
-    return;
+  if (parent != NULL && GST_IS_ELEMENT (parent)) {
+    eparent = GST_ELEMENT_CAST (gst_object_ref (parent));
+  } else {
+    GST_OBJECT_LOCK (pad);
+    eparent = GST_PAD_PARENT (pad);
+    if (!eparent || !GST_IS_ELEMENT (eparent))
+      goto no_parent;
 
-  fixatefunc = GST_PAD_FIXATECAPSFUNC (pad);
-  if (fixatefunc) {
-    fixatefunc (pad, caps);
+    gst_object_ref (eparent);
+    GST_OBJECT_UNLOCK (pad);
   }
 
-  /* default fixation */
-  gst_caps_truncate (caps);
-  s = gst_caps_get_structure (caps, 0);
-  gst_structure_foreach (s, gst_pad_default_fixate, s);
-}
-
-/* Default accept caps implementation just checks against
- * against the allowed caps for the pad */
-static gboolean
-gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
-{
-  /* get the caps and see if it intersects to something not empty */
-  GstCaps *allowed;
-  gboolean result = FALSE;
-
-  GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps);
+  if (pad->direction == GST_PAD_SRC)
+    padlist = &eparent->sinkpads;
+  else
+    padlist = &eparent->srcpads;
 
-  allowed = gst_pad_get_caps_reffed (pad);
-  if (!allowed)
-    goto nothing_allowed;
+  GST_DEBUG_OBJECT (pad, "Making iterator");
 
-  GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed);
+  cookie = &eparent->pads_cookie;
+  owner = eparent;
+  lock = GST_OBJECT_GET_LOCK (eparent);
 
-  result = gst_caps_can_intersect (allowed, caps);
+  res = gst_iterator_new_list (GST_TYPE_PAD,
+      lock, cookie, padlist, (GObject *) owner, NULL);
 
-  gst_caps_unref (allowed);
+  gst_object_unref (owner);
 
-  return result;
+  return res;
 
   /* ERRORS */
-nothing_allowed:
+no_parent:
   {
-    GST_DEBUG_OBJECT (pad, "no caps allowed on the pad");
-    return FALSE;
+    GST_OBJECT_UNLOCK (pad);
+    GST_DEBUG_OBJECT (pad, "no parent element");
+    return NULL;
   }
 }
 
 /**
- * gst_pad_accept_caps:
- * @pad: a #GstPad to check
- * @caps: a #GstCaps to check on the pad
+ * gst_pad_iterate_internal_links:
+ * @pad: the GstPad to get the internal links of.
+ *
+ * Gets an iterator for the pads to which the given pad is linked to inside
+ * of the parent element.
+ *
+ * Each #GstPad element yielded by the iterator will have its refcount increased,
+ * so unref after use.
+ *
+ * Free-function: gst_iterator_free
  *
- * Check if the given pad accepts the caps.
+ * Returns: (transfer full): a new #GstIterator of #GstPad or %NULL when the
+ *     pad does not have an iterator function configured. Use
+ *     gst_iterator_free() after usage.
  *
- * Returns: TRUE if the pad can accept the caps.
+ * Since: 0.10.21
  */
-gboolean
-gst_pad_accept_caps (GstPad * pad, GstCaps * caps)
+GstIterator *
+gst_pad_iterate_internal_links (GstPad * pad)
 {
-  gboolean result;
-  GstPadAcceptCapsFunction acceptfunc;
-  GstCaps *existing = NULL;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  GstIterator *res = NULL;
+  GstObject *parent;
 
-  /* any pad can be unnegotiated */
-  if (caps == NULL)
-    return TRUE;
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  /* lock for checking the existing caps */
   GST_OBJECT_LOCK (pad);
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps);
-  /* The current caps on a pad are trivially acceptable */
-  if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) {
-    if (caps == existing || gst_caps_is_equal (caps, existing))
-      goto is_same_caps;
-  }
-  acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad);
+  ACQUIRE_PARENT (pad, parent, no_parent);
   GST_OBJECT_UNLOCK (pad);
 
-  if (G_LIKELY (acceptfunc)) {
-    /* we can call the function */
-    result = acceptfunc (pad, caps);
-    GST_DEBUG_OBJECT (pad, "acceptfunc returned %d", result);
-  } else {
-    /* Only null if the element explicitly unset it */
-    result = gst_pad_acceptcaps_default (pad, caps);
-    GST_DEBUG_OBJECT (pad, "default acceptcaps returned %d", result);
-  }
+  if (GST_PAD_ITERINTLINKFUNC (pad))
+    res = GST_PAD_ITERINTLINKFUNC (pad) (pad, parent);
 
-  return result;
+  RELEASE_PARENT (parent);
+
+  return res;
 
-is_same_caps:
+  /* ERRORS */
+no_parent:
   {
-    GST_DEBUG_OBJECT (pad, "pad had same caps");
+    GST_DEBUG_OBJECT (pad, "no parent");
     GST_OBJECT_UNLOCK (pad);
-    return TRUE;
+    return FALSE;
   }
 }
 
 /**
- * gst_pad_peer_accept_caps:
- * @pad: a  #GstPad to check the peer of
- * @caps: a #GstCaps to check on the pad
+ * gst_pad_forward:
+ * @pad: a #GstPad
+ * @forward: a #GstPadForwardFunction
+ * @user_data: user data passed to @forward
  *
- * Check if the peer of @pad accepts @caps. If @pad has no peer, this function
- * returns TRUE.
+ * Calls @forward for all internally linked pads of @pad. This function deals with
+ * dynamically changing internal pads and will make sure that the @forward
+ * function is only called once for each pad.
  *
- * Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer.
+ * When @forward returns TRUE, no further pads will be processed.
+ *
+ * Returns: TRUE if one of the dispatcher functions returned TRUE.
  */
 gboolean
-gst_pad_peer_accept_caps (GstPad * pad, GstCaps * caps)
+gst_pad_forward (GstPad * pad, GstPadForwardFunction forward,
+    gpointer user_data)
 {
-  GstPad *peerpad;
-  gboolean result;
+  gboolean result = FALSE;
+  GstIterator *iter;
+  gboolean done = FALSE;
+  GValue item = { 0, };
+  GList *pushed_pads = NULL;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  iter = gst_pad_iterate_internal_links (pad);
 
-  GST_OBJECT_LOCK (pad);
+  if (!iter)
+    goto no_iter;
+
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+      {
+        GstPad *intpad;
 
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "peer accept caps of (%p)", pad);
+        intpad = g_value_get_object (&item);
 
-  peerpad = GST_PAD_PEER (pad);
-  if (G_UNLIKELY (peerpad == NULL))
-    goto no_peer;
+        /* if already pushed, skip. FIXME, find something faster to tag pads */
+        if (intpad == NULL || g_list_find (pushed_pads, intpad)) {
+          g_value_reset (&item);
+          break;
+        }
 
-  gst_object_ref (peerpad);
-  /* release lock before calling external methods but keep ref to pad */
-  GST_OBJECT_UNLOCK (pad);
+        GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s",
+            GST_DEBUG_PAD_NAME (intpad));
+        done = result = forward (intpad, user_data);
 
-  result = gst_pad_accept_caps (peerpad, caps);
+        pushed_pads = g_list_prepend (pushed_pads, intpad);
 
-  gst_object_unref (peerpad);
+        g_value_reset (&item);
+        break;
+      }
+      case GST_ITERATOR_RESYNC:
+        /* We don't reset the result here because we don't push the event
+         * again on pads that got the event already and because we need
+         * to consider the result of the previous pushes */
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+    }
+  }
+  g_value_unset (&item);
+  gst_iterator_free (iter);
+
+  g_list_free (pushed_pads);
 
+no_iter:
   return result;
+}
 
-no_peer:
-  {
-    GST_OBJECT_UNLOCK (pad);
-    return TRUE;
-  }
+typedef struct
+{
+  GstEvent *event;
+  gboolean result;
+  gboolean dispatched;
+} EventData;
+
+static gboolean
+event_forward_func (GstPad * pad, EventData * data)
+{
+  /* for each pad we send to, we should ref the event; it's up
+   * to downstream to unref again when handled. */
+  GST_LOG_OBJECT (pad, "Reffing and pushing event %p (%s) to %s:%s",
+      data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad));
+
+  data->result |= gst_pad_push_event (pad, gst_event_ref (data->event));
+
+  data->dispatched = TRUE;
+
+  /* don't stop */
+  return FALSE;
 }
 
 /**
- * gst_pad_set_caps:
- * @pad: a  #GstPad to set the capabilities of.
- * @caps: (transfer none): a #GstCaps to set.
+ * gst_pad_event_default:
+ * @pad: a #GstPad to call the default event handler on.
+ * @parent: the parent of @pad or NULL
+ * @event: (transfer full): the #GstEvent to handle.
  *
- * Sets the capabilities of this pad. The caps must be fixed. Any previous
- * caps on the pad will be unreffed. This function refs the caps so you should
- * unref if as soon as you don't need it anymore.
- * It is possible to set NULL caps, which will make the pad unnegotiated
- * again.
+ * Invokes the default event handler for the given pad.
  *
- * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
- * or bad parameters were provided to this function.
+ * The EOS event will pause the task associated with @pad before it is forwarded
+ * to all internally linked pads,
  *
- * MT safe.
+ * The the event is sent to all pads internally linked to @pad. This function
+ * takes ownership of @event.
+ *
+ * Returns: TRUE if the event was sent successfully.
  */
 gboolean
-gst_pad_set_caps (GstPad * pad, GstCaps * caps)
+gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstPadSetCapsFunction setcaps;
-  GstCaps *existing;
+  gboolean result, forward = TRUE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (caps == NULL || gst_caps_is_fixed (caps), FALSE);
-
-  GST_OBJECT_LOCK (pad);
-  existing = GST_PAD_CAPS (pad);
-  if (existing == caps)
-    goto was_ok;
-
-  if (gst_caps_is_equal (caps, existing))
-    goto setting_same_caps;
+  g_return_val_if_fail (event != NULL, FALSE);
 
-  setcaps = GST_PAD_SETCAPSFUNC (pad);
+  GST_LOG_OBJECT (pad, "default event handler");
 
-  /* call setcaps function to configure the pad only if the
-   * caps is not NULL */
-  if (setcaps != NULL && caps) {
-    if (!GST_PAD_IS_IN_SETCAPS (pad)) {
-      GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_SETCAPS);
-      GST_OBJECT_UNLOCK (pad);
-      if (!setcaps (pad, caps))
-        goto could_not_set;
-      GST_OBJECT_LOCK (pad);
-      GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS);
-    } else {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad was dispatching");
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+    {
+      GST_DEBUG_OBJECT (pad, "pausing task because of eos");
+      gst_pad_pause_task (pad);
+      break;
     }
+    case GST_EVENT_CAPS:
+      forward = GST_PAD_IS_PROXY_CAPS (pad);
+      result = TRUE;
+      break;
+    default:
+      break;
   }
 
-  gst_caps_replace (&GST_PAD_CAPS (pad), caps);
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "caps %p %" GST_PTR_FORMAT, caps,
-      caps);
-  GST_OBJECT_UNLOCK (pad);
+  if (forward) {
+    EventData data;
 
-#if GLIB_CHECK_VERSION(2,26,0)
-  g_object_notify_by_pspec ((GObject *) pad, pspec_caps);
-#else
-  g_object_notify ((GObject *) pad, "caps");
-#endif
+    data.event = event;
+    data.dispatched = FALSE;
+    data.result = FALSE;
 
-  return TRUE;
+    gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);
 
-was_ok:
-  {
-    GST_OBJECT_UNLOCK (pad);
-    return TRUE;
-  }
-setting_same_caps:
-  {
-    gst_caps_replace (&GST_PAD_CAPS (pad), caps);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "caps %p %" GST_PTR_FORMAT " same as existing, updating ptr only", caps,
-        caps);
-    GST_OBJECT_UNLOCK (pad);
-    return TRUE;
+    /* for sinkpads without a parent element or without internal links, nothing
+     * will be dispatched but we still want to return TRUE. */
+    if (data.dispatched)
+      result = data.result;
+    else
+      result = TRUE;
   }
 
-  /* ERRORS */
-could_not_set:
-  {
-    GST_OBJECT_LOCK (pad);
-    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "caps %" GST_PTR_FORMAT " could not be set", caps);
-    GST_OBJECT_UNLOCK (pad);
+  gst_event_unref (event);
 
-    return FALSE;
-  }
+  return result;
 }
 
+/* Default accept caps implementation just checks against
+ * the allowed caps for the pad */
 static gboolean
-gst_pad_configure_sink (GstPad * pad, GstCaps * caps)
+gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query)
 {
-  gboolean res;
+  /* get the caps and see if it intersects to something not empty */
+  GstCaps *caps, *allowed;
+  gboolean result;
 
-  /* See if pad accepts the caps */
-  if (!gst_caps_can_intersect (caps, gst_pad_get_pad_template_caps (pad)))
-    goto not_accepted;
+  GST_DEBUG_OBJECT (pad, "query accept-caps %" GST_PTR_FORMAT, query);
 
-  /* set caps on pad if call succeeds */
-  res = gst_pad_set_caps (pad, caps);
-  /* no need to unref the caps here, set_caps takes a ref and
-   * our ref goes away when we leave this function. */
+  /* first forward the query to internally linked pads when we are dealing with
+   * a PROXY CAPS */
+  if (GST_PAD_IS_PROXY_CAPS (pad)) {
+    if ((result = gst_pad_proxy_query_accept_caps (pad, query))) {
+      goto done;
+    }
+  }
 
-  return res;
+  allowed = gst_pad_query_caps (pad, NULL);
+  gst_query_parse_accept_caps (query, &caps);
 
-not_accepted:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "caps %" GST_PTR_FORMAT " not accepted", caps);
-    return FALSE;
+  if (allowed) {
+    GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed);
+    result = gst_caps_is_subset (caps, allowed);
+    gst_caps_unref (allowed);
+  } else {
+    GST_DEBUG_OBJECT (pad, "no caps allowed on the pad");
+    result = FALSE;
   }
+  gst_query_set_accept_caps_result (query, result);
+
+done:
+  return TRUE;
 }
 
-/* returns TRUE if the src pad could be configured to accept the given caps */
+/* Default caps implementation */
 static gboolean
-gst_pad_configure_src (GstPad * pad, GstCaps * caps, gboolean dosetcaps)
+gst_pad_query_caps_default (GstPad * pad, GstQuery * query)
 {
-  gboolean res;
+  GstCaps *result = NULL, *filter;
+  GstPadTemplate *templ;
+  gboolean fixed_caps;
 
-  if (dosetcaps) {
-    /* See if pad accepts the caps */
-    if (!gst_pad_accept_caps (pad, caps))
-      goto not_accepted;
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
 
-    res = gst_pad_set_caps (pad, caps);
-  } else {
-    res = TRUE;
+  gst_query_parse_caps (query, &filter);
+
+  /* first try to proxy if we must */
+  if (GST_PAD_IS_PROXY_CAPS (pad)) {
+    if ((gst_pad_proxy_query_caps (pad, query))) {
+      gst_query_parse_caps_result (query, &result);
+      goto filter_done;
+    }
   }
-  return res;
 
-not_accepted:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
-        "caps %" GST_PTR_FORMAT " not accepted", caps);
-    return FALSE;
+  /* no proxy or it failed, do default handling */
+  fixed_caps = GST_PAD_IS_FIXED_CAPS (pad);
+
+  GST_OBJECT_LOCK (pad);
+  if (fixed_caps) {
+    /* fixed caps, try the negotiated caps first */
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "fixed pad caps: trying pad caps");
+    if ((result = get_pad_caps (pad)))
+      goto filter_done_unlock;
   }
-}
 
-/**
- * gst_pad_get_pad_template_caps:
- * @pad: a #GstPad to get the template capabilities from.
- *
- * Gets the capabilities for @pad's template.
- *
- * Returns: (transfer none): the #GstCaps of this pad template. If you intend
- *     to keep a reference on the caps, make a copy (see gst_caps_copy ()).
- */
-const GstCaps *
-gst_pad_get_pad_template_caps (GstPad * pad)
-{
-  static GstStaticCaps anycaps = GST_STATIC_CAPS ("ANY");
+  if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps");
+    if ((result = GST_PAD_TEMPLATE_CAPS (templ)))
+      goto filter_done_unlock;
+  }
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  if (!fixed_caps) {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+        "non-fixed pad caps: trying pad caps");
+    /* non fixed caps, try the negotiated caps */
+    if ((result = get_pad_caps (pad)))
+      goto filter_done_unlock;
+  }
+  GST_OBJECT_UNLOCK (pad);
 
-  if (GST_PAD_PAD_TEMPLATE (pad))
-    return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
+  /* this almost never happens */
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps");
+  result = gst_caps_new_empty ();
 
-  return gst_static_caps_get (&anycaps);
-}
+  goto done;
 
-/**
- * gst_pad_get_peer:
- * @pad: a #GstPad to get the peer of.
- *
- * Gets the peer of @pad. This function refs the peer pad so
- * you need to unref it after use.
- *
- * Returns: (transfer full): the peer #GstPad. Unref after usage.
- *
- * MT safe.
- */
-GstPad *
-gst_pad_get_peer (GstPad * pad)
-{
-  GstPad *result;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  GST_OBJECT_LOCK (pad);
-  result = GST_PAD_PEER (pad);
-  if (result)
-    gst_object_ref (result);
-  GST_OBJECT_UNLOCK (pad);
-
-  return result;
-}
-
-/**
- * gst_pad_get_allowed_caps:
- * @pad: a #GstPad.
- *
- * Gets the capabilities of the allowed media types that can flow through
- * @pad and its peer.
- *
- * The allowed capabilities is calculated as the intersection of the results of
- * calling gst_pad_get_caps() on @pad and its peer. The caller owns a reference
- * on the resulting caps.
- *
- * Returns: (transfer full): the allowed #GstCaps of the pad link. Unref the
- *     caps when you no longer need it. This function returns NULL when @pad
- *     has no peer.
- *
- * MT safe.
- */
-GstCaps *
-gst_pad_get_allowed_caps (GstPad * pad)
-{
-  GstCaps *mycaps;
-  GstCaps *caps;
-  GstCaps *peercaps;
-  GstPad *peer;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  GST_OBJECT_LOCK (pad);
-
-  peer = GST_PAD_PEER (pad);
-  if (G_UNLIKELY (peer == NULL))
-    goto no_peer;
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting allowed caps");
-
-  gst_object_ref (peer);
+filter_done_unlock:
   GST_OBJECT_UNLOCK (pad);
-  mycaps = gst_pad_get_caps_reffed (pad);
-
-  peercaps = gst_pad_get_caps_reffed (peer);
-  gst_object_unref (peer);
-
-  caps = gst_caps_intersect (mycaps, peercaps);
-  gst_caps_unref (peercaps);
-  gst_caps_unref (mycaps);
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT,
-      caps);
 
-  return caps;
+filter_done:
+  /* run the filter on the result */
+  if (filter) {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+        "using caps %p %" GST_PTR_FORMAT " with filter %p %"
+        GST_PTR_FORMAT, result, result, filter, filter);
+    result = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
+        result, result);
+  } else {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+        "using caps %p %" GST_PTR_FORMAT, result, result);
+    result = gst_caps_ref (result);
+  }
 
-no_peer:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer");
-    GST_OBJECT_UNLOCK (pad);
+done:
+  gst_query_set_caps_result (query, result);
+  gst_caps_unref (result);
 
-    return NULL;
-  }
+  return TRUE;
 }
 
 /**
- * gst_pad_get_negotiated_caps:
- * @pad: a #GstPad.
- *
- * Gets the capabilities of the media type that currently flows through @pad
- * and its peer.
- *
- * This function can be used on both src and sinkpads. Note that srcpads are
- * always negotiated before sinkpads so it is possible that the negotiated caps
- * on the srcpad do not match the negotiated caps of the peer.
+ * gst_pad_query_default:
+ * @pad: a #GstPad to call the default query handler on.
+ * @parent: the parent of @pad or NULL
+ * @query: (transfer none): the #GstQuery to handle.
  *
- * Returns: (transfer full): the negotiated #GstCaps of the pad link. Unref
- *     the caps when you no longer need it. This function returns NULL when
- *     the @pad has no peer or is not negotiated yet.
+ * Invokes the default query handler for the given pad.
+ * The query is sent to all pads internally linked to @pad. Note that
+ * if there are many possible sink pads that are internally linked to
+ * @pad, only one will be sent the query.
+ * Multi-sinkpad elements should implement custom query handlers.
  *
- * MT safe.
+ * Returns: TRUE if the query was performed successfully.
  */
-GstCaps *
-gst_pad_get_negotiated_caps (GstPad * pad)
-{
-  GstCaps *caps;
-  GstPad *peer;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  GST_OBJECT_LOCK (pad);
-
-  if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
-    goto no_peer;
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting negotiated caps");
-
-  caps = GST_PAD_CAPS (pad);
-  if (caps)
-    gst_caps_ref (caps);
-  GST_OBJECT_UNLOCK (pad);
-
-  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "negotiated caps %" GST_PTR_FORMAT,
-      caps);
-
-  return caps;
-
-no_peer:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer");
-    GST_OBJECT_UNLOCK (pad);
-
-    return NULL;
-  }
-}
-
-/* calls the buffer_alloc function on the given pad */
-static GstFlowReturn
-gst_pad_buffer_alloc_unchecked (GstPad * pad, guint64 offset, gint size,
-    GstCaps * caps, GstBuffer ** buf)
+gboolean
+gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstFlowReturn ret;
-  GstPadBufferAllocFunction bufferallocfunc;
-
-  GST_OBJECT_LOCK (pad);
-  /* when the pad is flushing we cannot give a buffer */
-  if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
-    goto flushing;
-
-  bufferallocfunc = pad->bufferallocfunc;
-
-  if (offset == GST_BUFFER_OFFSET_NONE) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "calling bufferallocfunc &%s (@%p) for size %d offset NONE",
-        GST_DEBUG_FUNCPTR_NAME (bufferallocfunc), bufferallocfunc, size);
-  } else {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "calling bufferallocfunc &%s (@%p) of for size %d offset %"
-        G_GUINT64_FORMAT, GST_DEBUG_FUNCPTR_NAME (bufferallocfunc),
-        bufferallocfunc, size, offset);
-  }
-  GST_OBJECT_UNLOCK (pad);
-
-  /* G_LIKELY for now since most elements don't implement a buffer alloc
-   * function and there is no default alloc proxy function as this is usually
-   * not possible. */
-  if (G_LIKELY (bufferallocfunc == NULL))
-    goto fallback;
+  gboolean forward = TRUE, ret = FALSE;
 
-  ret = bufferallocfunc (pad, offset, size, caps, buf);
-
-  if (G_UNLIKELY (ret != GST_FLOW_OK))
-    goto error;
-
-  /* no error, but NULL buffer means fallback to the default */
-  if (G_UNLIKELY (*buf == NULL))
-    goto fallback;
-
-  /* If the buffer alloc function didn't set up the caps like it should,
-   * do it for it */
-  if (G_UNLIKELY (caps && (GST_BUFFER_CAPS (*buf) == NULL))) {
-    GST_WARNING_OBJECT (pad,
-        "Buffer allocation function did not set caps. Setting");
-    gst_buffer_set_caps (*buf, caps);
-  }
-  return ret;
-
-flushing:
-  {
-    /* pad was flushing */
-    GST_OBJECT_UNLOCK (pad);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad was flushing");
-    return GST_FLOW_WRONG_STATE;
-  }
-error:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "alloc function returned error (%d) %s", ret, gst_flow_get_name (ret));
-    return ret;
-  }
-fallback:
-  {
-    /* fallback case, allocate a buffer of our own, add pad caps. */
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc");
-
-    if ((*buf = gst_buffer_try_new_and_alloc (size))) {
-      GST_BUFFER_OFFSET (*buf) = offset;
-      gst_buffer_set_caps (*buf, caps);
-      return GST_FLOW_OK;
-    } else {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-          "out of memory allocating %d bytes", size);
-      return GST_FLOW_ERROR;
-    }
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_SCHEDULING:
+    case GST_QUERY_ALLOCATION:
+      forward = FALSE;
+      break;
+    case GST_QUERY_ACCEPT_CAPS:
+      ret = gst_pad_query_accept_caps_default (pad, query);
+      forward = FALSE;
+      break;
+    case GST_QUERY_CAPS:
+      ret = gst_pad_query_caps_default (pad, query);
+      forward = FALSE;
+      break;
+    case GST_QUERY_POSITION:
+    case GST_QUERY_SEEKING:
+    case GST_QUERY_FORMATS:
+    case GST_QUERY_LATENCY:
+    case GST_QUERY_JITTER:
+    case GST_QUERY_RATE:
+    case GST_QUERY_CONVERT:
+    default:
+      break;
   }
-}
-
-/* FIXME 0.11: size should be unsigned */
-static GstFlowReturn
-gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size,
-    GstCaps * caps, GstBuffer ** buf, gboolean setcaps)
-{
-  GstPad *peer;
-  GstFlowReturn ret;
-  GstCaps *newcaps;
-  gboolean caps_changed;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-  g_return_val_if_fail (size >= 0, GST_FLOW_ERROR);
-
-  GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d, caps %"
-      GST_PTR_FORMAT, offset, size, caps);
-
-  GST_OBJECT_LOCK (pad);
-  while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
-    if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
-      goto flushed;
-
-  if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
-    goto no_peer;
-
-  gst_object_ref (peer);
-  GST_OBJECT_UNLOCK (pad);
-
-  ret = gst_pad_buffer_alloc_unchecked (peer, offset, size, caps, buf);
-  gst_object_unref (peer);
-
-  if (G_UNLIKELY (ret != GST_FLOW_OK))
-    goto peer_error;
-
-  /* FIXME, move capnego this into a base class? */
-  newcaps = GST_BUFFER_CAPS (*buf);
-
-  /* Lock for checking caps, pretty pointless as the _pad_push() function might
-   * change it concurrently, one of the problems with automatic caps setting in
-   * pad_alloc_and_set_caps. Worst case, if does a check too much, but only
-   * when there is heavy renegotiation going on in both directions. */
-  GST_OBJECT_LOCK (pad);
-  caps_changed = newcaps && newcaps != GST_PAD_CAPS (pad);
-  GST_OBJECT_UNLOCK (pad);
 
-  /* we got a new datatype on the pad, see if it can handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    GST_DEBUG_OBJECT (pad,
-        "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (pad), newcaps, newcaps);
-    if (G_UNLIKELY (!gst_pad_configure_src (pad, newcaps, setcaps)))
-      goto not_negotiated;
+  if (forward) {
+    ret = gst_pad_forward
+        (pad, (GstPadForwardFunction) gst_pad_peer_query, query);
   }
-
-  /* sanity check (only if caps are the same) */
-  if (G_LIKELY (newcaps == caps) && G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size))
-    goto wrong_size_fallback;
-
   return ret;
-
-flushed:
-  {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad block stopped by flush");
-    GST_OBJECT_UNLOCK (pad);
-    return ret;
-  }
-no_peer:
-  {
-    /* pad has no peer */
-    GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-        "called bufferallocfunc but had no peer");
-    GST_OBJECT_UNLOCK (pad);
-    return GST_FLOW_NOT_LINKED;
-  }
-peer_error:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "alloc function returned error %s", gst_flow_get_name (ret));
-    return ret;
-  }
-not_negotiated:
-  {
-    gst_buffer_unref (*buf);
-    *buf = NULL;
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "alloc function returned unacceptable buffer");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-wrong_size_fallback:
-  {
-    GST_CAT_ERROR_OBJECT (GST_CAT_PADS, pad, "buffer returned by alloc "
-        "function is too small (%u < %d), doing fallback buffer alloc",
-        GST_BUFFER_SIZE (*buf), size);
-
-    gst_buffer_unref (*buf);
-
-    if ((*buf = gst_buffer_try_new_and_alloc (size))) {
-      GST_BUFFER_OFFSET (*buf) = offset;
-      gst_buffer_set_caps (*buf, caps);
-      return GST_FLOW_OK;
-    } else {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-          "out of memory allocating %d bytes", size);
-      return GST_FLOW_ERROR;
-    }
-  }
-}
-
-/**
- * gst_pad_alloc_buffer:
- * @pad: a source #GstPad
- * @offset: the offset of the new buffer in the stream
- * @size: the size of the new buffer
- * @caps: the caps of the new buffer
- * @buf: a newly allocated buffer
- *
- * Allocates a new, empty buffer optimized to push to pad @pad.  This
- * function only works if @pad is a source pad and has a peer.
- *
- * A new, empty #GstBuffer will be put in the @buf argument.
- * You need to check the caps of the buffer after performing this
- * function and renegotiate to the format if needed. If the caps changed, it is
- * possible that the buffer returned in @buf is not of the right size for the
- * new format, @buf needs to be unreffed and reallocated if this is the case.
- *
- * Returns: a result code indicating success of the operation. Any
- * result code other than #GST_FLOW_OK is an error and @buf should
- * not be used.
- * An error can occur if the pad is not connected or when the downstream
- * peer elements cannot provide an acceptable buffer.
- *
- * MT safe.
- */
-
-/* FIXME 0.11: size should be unsigned */
-GstFlowReturn
-gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size, GstCaps * caps,
-    GstBuffer ** buf)
-{
-  return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, FALSE);
-}
-
-/**
- * gst_pad_alloc_buffer_and_set_caps:
- * @pad: a source #GstPad
- * @offset: the offset of the new buffer in the stream
- * @size: the size of the new buffer
- * @caps: (transfer none): the caps of the new buffer
- * @buf: (out callee-allocates): a newly allocated buffer
- *
- * In addition to the function gst_pad_alloc_buffer(), this function
- * automatically calls gst_pad_set_caps() when the caps of the
- * newly allocated buffer are different from the @pad caps.
- *
- * After a renegotiation, the size of the new buffer returned in @buf could
- * be of the wrong size for the new format and must be unreffed an reallocated
- * in that case.
- *
- * Returns: a result code indicating success of the operation. Any
- * result code other than #GST_FLOW_OK is an error and @buf should
- * not be used.
- * An error can occur if the pad is not connected or when the downstream
- * peer elements cannot provide an acceptable buffer.
- *
- * MT safe.
- */
-
-/* FIXME 0.11: size should be unsigned */
-GstFlowReturn
-gst_pad_alloc_buffer_and_set_caps (GstPad * pad, guint64 offset, gint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE);
 }
 
-
-#ifndef GST_REMOVE_DEPRECATED
-typedef struct
-{
-  GList *list;
-  guint32 cookie;
-} IntLinkIterData;
-
 static void
-int_link_iter_data_free (IntLinkIterData * data)
-{
-  g_list_free (data->list);
-  g_slice_free (IntLinkIterData, data);
-}
-#endif
-
-static GstIteratorItem
-iterate_pad (GstIterator * it, GstPad * pad)
+probe_hook_marshal (GHook * hook, ProbeMarshall * data)
 {
-  gst_object_ref (pad);
-  return GST_ITERATOR_ITEM_PASS;
-}
-
-/**
- * gst_pad_iterate_internal_links_default:
- * @pad: the #GstPad to get the internal links of.
- *
- * Iterate the list of pads to which the given pad is linked to inside of
- * the parent element.
- * This is the default handler, and thus returns an iterator of all of the
- * pads inside the parent element with opposite direction.
- *
- * The caller must free this iterator after use with gst_iterator_free().
- *
- * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
- * returned pad with gst_object_unref().
- *
- * Since: 0.10.21
- */
-GstIterator *
-gst_pad_iterate_internal_links_default (GstPad * pad)
-{
-  GstIterator *res;
-  GList **padlist;
-  guint32 *cookie;
-  GMutex *lock;
-  gpointer owner;
-  GstIteratorDisposeFunction dispose;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-#ifndef GST_REMOVE_DEPRECATED
-  /* when we get here, the default handler for the iterate links is called,
-   * which means that the user has not installed a custom one. We first check if
-   * there is maybe a custom legacy function we can call. */
-  if (GST_PAD_INTLINKFUNC (pad) &&
-      GST_PAD_INTLINKFUNC (pad) != gst_pad_get_internal_links_default) {
-    IntLinkIterData *data;
-
-    /* make an iterator for the list. We can't protect the list with a
-     * cookie. If we would take the cookie of the parent element, we need to
-     * have a parent, which is not required for GST_PAD_INTLINKFUNC(). We could
-     * cache the per-pad list and invalidate the list when a new call to
-     * INTLINKFUNC() returned a different list but then this would only work if
-     * two concurrent iterators were used and the last iterator would still be
-     * thread-unsafe. Just don't use this method anymore. */
-    data = g_slice_new (IntLinkIterData);
-    data->list = ((GstPadIntLinkFunction) GST_PAD_INTLINKFUNC (pad)) (pad);
-    data->cookie = 0;
-
-    GST_WARNING_OBJECT (pad, "Making unsafe iterator");
-
-    cookie = &data->cookie;
-    padlist = &data->list;
-    owner = data;
-    dispose = (GstIteratorDisposeFunction) int_link_iter_data_free;
-    /* reuse the pad lock, it's all we have here */
-    lock = GST_OBJECT_GET_LOCK (pad);
-  } else
-#endif
-  {
-    GstElement *parent;
-
-    GST_OBJECT_LOCK (pad);
-    parent = GST_PAD_PARENT (pad);
-    if (!parent || !GST_IS_ELEMENT (parent))
-      goto no_parent;
-
-    gst_object_ref (parent);
-    GST_OBJECT_UNLOCK (pad);
-
-    if (pad->direction == GST_PAD_SRC)
-      padlist = &parent->sinkpads;
-    else
-      padlist = &parent->srcpads;
-
-    GST_DEBUG_OBJECT (pad, "Making iterator");
-
-    cookie = &parent->pads_cookie;
-    owner = parent;
-    dispose = (GstIteratorDisposeFunction) gst_object_unref;
-    lock = GST_OBJECT_GET_LOCK (parent);
-  }
-
-  res = gst_iterator_new_list (GST_TYPE_PAD,
-      lock, cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad,
-      dispose);
+  GstPad *pad = data->pad;
+  GstPadProbeInfo *info = data->info;
+  GstPadProbeType type, flags;
+  GstPadProbeCallback callback;
+  GstPadProbeReturn ret;
 
-  return res;
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "hook %lu, cookie %u checking", hook->hook_id, PROBE_COOKIE (hook));
 
-  /* ERRORS */
-no_parent:
-  {
-    GST_OBJECT_UNLOCK (pad);
-    GST_DEBUG_OBJECT (pad, "no parent element");
-    return NULL;
+  /* if we have called this callback, do nothing */
+  if (PROBE_COOKIE (hook) == data->cookie) {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "hook %lu, cookie %u already called", hook->hook_id,
+        PROBE_COOKIE (hook));
+    return;
   }
-}
-
-/**
- * gst_pad_iterate_internal_links:
- * @pad: the GstPad to get the internal links of.
- *
- * Gets an iterator for the pads to which the given pad is linked to inside
- * of the parent element.
- *
- * Each #GstPad element yielded by the iterator will have its refcount increased,
- * so unref after use.
- *
- * Free-function: gst_iterator_free
- *
- * Returns: (transfer full): a new #GstIterator of #GstPad or %NULL when the
- *     pad does not have an iterator function configured. Use
- *     gst_iterator_free() after usage.
- *
- * Since: 0.10.21
- */
-GstIterator *
-gst_pad_iterate_internal_links (GstPad * pad)
-{
-  GstIterator *res = NULL;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  if (GST_PAD_ITERINTLINKFUNC (pad))
-    res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
-
-  return res;
-}
+  PROBE_COOKIE (hook) = data->cookie;
 
-#ifndef GST_REMOVE_DEPRECATED
-static void
-add_unref_pad_to_list (GstPad * pad, GList ** list)
-{
-  *list = g_list_prepend (*list, pad);
-  gst_object_unref (pad);
-}
-#endif
+  flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT;
+  type = info->type;
 
-/**
- * gst_pad_get_internal_links_default:
- * @pad: the #GstPad to get the internal links of.
- *
- * Gets a list of pads to which the given pad is linked to
- * inside of the parent element.
- * This is the default handler, and thus returns a list of all of the
- * pads inside the parent element with opposite direction.
- *
- * The caller must free this list after use with g_list_free().
- *
- * Returns: (transfer full) (element-type Gst.Pad): a newly allocated #GList
- *     of pads, or NULL if the pad has no parent.
- *
- * Not MT safe.
- *
- * Deprecated: This function does not ref the pads in the list so that they
- * could become invalid by the time the application accesses them. It's also
- * possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
- * gst_pad_iterate_internal_links_default() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-GList *
-gst_pad_get_internal_links_default (GstPad * pad)
-{
-  GList *res = NULL;
-  GstElement *parent;
+  /* one of the data types */
+  if ((flags & GST_PAD_PROBE_TYPE_ALL_BOTH & type) == 0)
+    goto no_match;
+  /* one of the scheduling types */
+  if ((flags & GST_PAD_PROBE_TYPE_SCHEDULING & type) == 0)
+    goto no_match;
+  /* one of the blocking types must match */
+  if ((type & GST_PAD_PROBE_TYPE_BLOCKING) &&
+      (flags & GST_PAD_PROBE_TYPE_BLOCKING & type) == 0)
+    goto no_match;
+  /* only probes that have GST_PAD_PROBE_TYPE_EVENT_FLUSH set */
+  if ((type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) &&
+      (flags & GST_PAD_PROBE_TYPE_EVENT_FLUSH & type) == 0)
+    goto no_match;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "hook %lu with flags 0x%08x matches", hook->hook_id, flags);
 
-  GST_WARNING_OBJECT (pad, "Unsafe internal links used");
-
-  /* when we get here, the default handler for get_internal_links is called,
-   * which means that the user has not installed a custom one. We first check if
-   * there is maybe a custom iterate function we can call. */
-  if (GST_PAD_ITERINTLINKFUNC (pad) &&
-      GST_PAD_ITERINTLINKFUNC (pad) != gst_pad_iterate_internal_links_default) {
-    GstIterator *it;
-    GstIteratorResult ires;
-    gboolean done = FALSE;
-
-    it = gst_pad_iterate_internal_links (pad);
-    /* loop over the iterator and put all elements into a list, we also
-     * immediately unref them, which is bad. */
-    do {
-      ires = gst_iterator_foreach (it, (GFunc) add_unref_pad_to_list, &res);
-      switch (ires) {
-        case GST_ITERATOR_OK:
-        case GST_ITERATOR_DONE:
-        case GST_ITERATOR_ERROR:
-          done = TRUE;
-          break;
-        case GST_ITERATOR_RESYNC:
-          /* restart, discard previous list */
-          gst_iterator_resync (it);
-          g_list_free (res);
-          res = NULL;
-          break;
-      }
-    } while (!done);
+  callback = (GstPadProbeCallback) hook->func;
+  if (callback == NULL)
+    return;
 
-    gst_iterator_free (it);
-  } else {
-    /* lock pad, check and ref parent */
-    GST_OBJECT_LOCK (pad);
-    parent = GST_PAD_PARENT (pad);
-    if (!parent || !GST_IS_ELEMENT (parent))
-      goto no_parent;
+  GST_OBJECT_UNLOCK (pad);
 
-    parent = gst_object_ref (parent);
-    GST_OBJECT_UNLOCK (pad);
+  ret = callback (pad, info, hook->data);
 
-    /* now lock the parent while we copy the pads */
-    GST_OBJECT_LOCK (parent);
-    if (pad->direction == GST_PAD_SRC)
-      res = g_list_copy (parent->sinkpads);
-    else
-      res = g_list_copy (parent->srcpads);
-    GST_OBJECT_UNLOCK (parent);
+  GST_OBJECT_LOCK (pad);
+  data->marshalled = TRUE;
 
-    gst_object_unref (parent);
+  switch (ret) {
+    case GST_PAD_PROBE_REMOVE:
+      /* remove the probe */
+      GST_DEBUG_OBJECT (pad, "asked to remove hook");
+      cleanup_hook (pad, hook);
+      break;
+    case GST_PAD_PROBE_DROP:
+      /* need to drop the data, make sure other probes don't get called
+       * anymore */
+      GST_DEBUG_OBJECT (pad, "asked to drop item");
+      info->type = GST_PAD_PROBE_TYPE_INVALID;
+      data->dropped = TRUE;
+      break;
+    case GST_PAD_PROBE_PASS:
+      /* inform the pad block to let things pass */
+      GST_DEBUG_OBJECT (pad, "asked to pass item");
+      data->pass = TRUE;
+      break;
+    default:
+      GST_DEBUG_OBJECT (pad, "probe returned %d", ret);
+      break;
   }
+  return;
 
-  /* At this point pads can be changed and unreffed. Nothing we can do about it
-   * because for compatibility reasons this function cannot ref the pads or
-   * notify the app that the list changed. */
-
-  return res;
-
-no_parent:
+no_match:
   {
-    GST_DEBUG_OBJECT (pad, "no parent");
-    GST_OBJECT_UNLOCK (pad);
-    return NULL;
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "hook %lu with flags 0x%08x does not match %08x", hook->hook_id,
+        flags, info->type);
+    return;
   }
 }
-#endif /* GST_REMOVE_DEPRECATED */
 
-/**
- * gst_pad_get_internal_links:
- * @pad: the #GstPad to get the internal links of.
- *
- * Gets a list of pads to which the given pad is linked to
- * inside of the parent element.
- * The caller must free this list after use.
- *
- * Not MT safe.
- *
- * Returns: (transfer full) (element-type Gst.Pad): a newly allocated #GList
- *     of pads, free with g_list_free().
- *
- * Deprecated: This function does not ref the pads in the list so that they
- * could become invalid by the time the application accesses them. It's also
- * possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
- * gst_pad_iterate_internal_links() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-GList *gst_pad_get_internal_links (GstPad * pad);
-#endif
-GList *
-gst_pad_get_internal_links (GstPad * pad)
-{
-  GList *res = NULL;
+#define PROBE_PRE_PULL(pad,mask,data,offs,size,label,probed,defaultval)    \
+  G_STMT_START {                                               \
+    if (G_UNLIKELY (pad->num_probes)) {                                \
+      /* we start with passing NULL as the data item */         \
+      GstPadProbeInfo info = { mask, NULL, offs, size };        \
+      ret = do_probe_callbacks (pad, &info, defaultval);       \
+      /* store the possibly updated data item */                \
+      data = GST_PAD_PROBE_INFO_DATA (&info);                   \
+      /* if something went wrong, exit */                       \
+      if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK))        \
+        goto label;                                            \
+      /* otherwise check if the probe retured data */           \
+      if (G_UNLIKELY (data != NULL))                            \
+        goto probed;                                           \
+    }                                                          \
+  } G_STMT_END
+
+
+/* a probe that does not take or return any data */
+#define PROBE_NO_DATA(pad,mask,label,defaultval)                \
+  G_STMT_START {                                               \
+    if (G_UNLIKELY (pad->num_probes)) {                                \
+      /* pass NULL as the data item */                          \
+      GstPadProbeInfo info = { mask, NULL, 0, 0 };              \
+      ret = do_probe_callbacks (pad, &info, defaultval);       \
+      if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK))        \
+        goto label;                                            \
+    }                                                          \
+  } G_STMT_END
+
+#define PROBE_FULL(pad,mask,data,offs,size,label,defaultval)    \
+  G_STMT_START {                                               \
+    if (G_UNLIKELY (pad->num_probes)) {                                \
+      GstPadProbeInfo info = { mask, data, offs, size };        \
+      ret = do_probe_callbacks (pad, &info, defaultval);       \
+      data = GST_PAD_PROBE_INFO_DATA (&info);                   \
+      if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK))        \
+        goto label;                                            \
+    }                                                          \
+  } G_STMT_END
+
+#define PROBE_PUSH(pad,mask,data,label)                                \
+  PROBE_FULL(pad, mask, data, -1, -1, label, GST_FLOW_OK);
+#define PROBE_PULL(pad,mask,data,offs,size,label)              \
+  PROBE_FULL(pad, mask, data, offs, size, label, GST_FLOW_OK);
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+static GstFlowReturn
+do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info,
+    GstFlowReturn defaultval)
+{
+  ProbeMarshall data;
+  guint cookie;
+  gboolean is_block;
 
-  GST_WARNING_OBJECT (pad, "Calling unsafe internal links");
+  data.pad = pad;
+  data.info = info;
+  data.pass = FALSE;
+  data.marshalled = FALSE;
+  data.dropped = FALSE;
+  data.cookie = ++pad->priv->probe_cookie;
 
-  if (GST_PAD_INTLINKFUNC (pad))
-    res = ((GstPadIntLinkFunction) GST_PAD_INTLINKFUNC (pad)) (pad);
+  is_block =
+      (info->type & GST_PAD_PROBE_TYPE_BLOCK) == GST_PAD_PROBE_TYPE_BLOCK;
 
-  return res;
-}
-#endif /* GST_REMOVE_DEPRECATED */
+again:
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "do probes cookie %u", data.cookie);
+  cookie = pad->priv->probe_list_cookie;
 
-static gboolean
-gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
-{
-  gboolean result = FALSE;
-  GstIterator *iter;
-  gboolean done = FALSE;
-  gpointer item;
-  GstPad *eventpad;
-  GList *pushed_pads = NULL;
+  g_hook_list_marshal (&pad->probes, TRUE,
+      (GHookMarshaller) probe_hook_marshal, &data);
 
-  GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
-      event, GST_EVENT_TYPE_NAME (event));
+  /* if the list changed, call the new callbacks (they will not have their
+   * cookie set to data.cookie */
+  if (cookie != pad->priv->probe_list_cookie) {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "probe list changed, restarting");
+    goto again;
+  }
 
-  iter = gst_pad_iterate_internal_links (pad);
+  /* the first item that dropped will stop the hooks and then we drop here */
+  if (data.dropped)
+    goto dropped;
 
-  if (!iter)
-    goto no_iter;
+  /* if no handler matched and we are blocking, let the item pass */
+  if (!data.marshalled && is_block)
+    goto passed;
 
-  while (!done) {
-    switch (gst_iterator_next (iter, &item)) {
-      case GST_ITERATOR_OK:
-        eventpad = GST_PAD_CAST (item);
+  /* At this point, all handlers returned either OK or PASS. If one handler
+   * returned PASS, let the item pass */
+  if (data.pass)
+    goto passed;
 
-        /* if already pushed,  skip */
-        if (g_list_find (pushed_pads, eventpad)) {
-          gst_object_unref (item);
-          break;
-        }
+  if (is_block) {
+    while (GST_PAD_IS_BLOCKED (pad)) {
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+          "we are blocked %d times", pad->num_blocked);
 
-        if (GST_PAD_IS_SRC (eventpad)) {
-          /* for each pad we send to, we should ref the event; it's up
-           * to downstream to unref again when handled. */
-          GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
-              event, GST_EVENT_TYPE_NAME (event),
-              GST_DEBUG_PAD_NAME (eventpad));
-          gst_event_ref (event);
-          result |= gst_pad_push_event (eventpad, event);
-        } else {
-          /* we only send the event on one pad, multi-sinkpad elements
-           * should implement a handler */
-          GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
-              event, GST_EVENT_TYPE_NAME (event),
-              GST_DEBUG_PAD_NAME (eventpad));
-          result = gst_pad_push_event (eventpad, event);
-          done = TRUE;
-          event = NULL;
-        }
+      /* we might have released the lock */
+      if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+        goto flushing;
 
-        pushed_pads = g_list_prepend (pushed_pads, eventpad);
+      /* now we block the streaming thread. It can be unlocked when we
+       * deactivate the pad (which will also set the FLUSHING flag) or
+       * when the pad is unblocked. A flushing event will also unblock
+       * the pad after setting the FLUSHING flag. */
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+          "Waiting to be unblocked or set flushing");
+      GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING);
+      GST_PAD_BLOCK_WAIT (pad);
+      GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING);
+      GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked");
 
-        gst_object_unref (item);
-        break;
-      case GST_ITERATOR_RESYNC:
-        /* We don't reset the result here because we don't push the event
-         * again on pads that got the event already and because we need
-         * to consider the result of the previous pushes */
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_ERROR:
-        GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
-        done = TRUE;
-        break;
-      case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
+      if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+        goto flushing;
     }
   }
-  gst_iterator_free (iter);
-
-no_iter:
-
-  /* If this is a sinkpad and we don't have pads to send the event to, we
-   * return TRUE. This is so that when using the default handler on a sink
-   * element, we don't fail to push it. */
-  if (!pushed_pads)
-    result = GST_PAD_IS_SINK (pad);
 
-  g_list_free (pushed_pads);
+  return defaultval;
 
-  /* we handled the incoming event so we unref once */
-  if (event) {
-    GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
-    gst_event_unref (event);
+  /* ERRORS */
+flushing:
+  {
+    GST_DEBUG_OBJECT (pad, "pad is flushing");
+    return GST_FLOW_WRONG_STATE;
+  }
+dropped:
+  {
+    GST_DEBUG_OBJECT (pad, "data is dropped");
+    return GST_FLOW_CUSTOM_SUCCESS;
+  }
+passed:
+  {
+    /* FIXME : Should we return FLOW_OK or the defaultval ?? */
+    GST_DEBUG_OBJECT (pad, "data is passed");
+    return GST_FLOW_OK;
   }
-
-  return result;
 }
 
+/* pad offsets */
+
 /**
- * gst_pad_event_default:
- * @pad: a #GstPad to call the default event handler on.
- * @event: (transfer full): the #GstEvent to handle.
+ * gst_pad_get_offset:
+ * @pad: a #GstPad
  *
- * Invokes the default event handler for the given pad. End-of-stream and
- * discontinuity events are handled specially, and then the event is sent to all
- * pads internally linked to @pad. Note that if there are many possible sink
- * pads that are internally linked to @pad, only one will be sent an event.
- * Multi-sinkpad elements should implement custom event handlers.
+ * Get the offset applied to the running time of @pad. @pad has to be a source
+ * pad.
  *
- * Returns: TRUE if the event was sent successfully.
+ * Returns: the offset.
  */
-gboolean
-gst_pad_event_default (GstPad * pad, GstEvent * event)
+gint64
+gst_pad_get_offset (GstPad * pad)
 {
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
+  gint64 result;
 
-  GST_LOG_OBJECT (pad, "default event handler");
+  g_return_val_if_fail (GST_IS_PAD (pad), 0);
 
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-    {
-      GST_DEBUG_OBJECT (pad, "pausing task because of eos");
-      gst_pad_pause_task (pad);
-    }
-      /* fall thru */
-    default:
-      break;
-  }
+  GST_OBJECT_LOCK (pad);
+  result = pad->offset;
+  GST_OBJECT_UNLOCK (pad);
 
-  return gst_pad_event_default_dispatch (pad, event);
+  return result;
 }
 
 /**
- * gst_pad_dispatcher:
- * @pad: a #GstPad to dispatch.
- * @dispatch: the #GstPadDispatcherFunction to call.
- * @data: (closure): gpointer user data passed to the dispatcher function.
- *
- * Invokes the given dispatcher function on each respective peer of
- * all pads that are internally linked to the given pad.
- * The GstPadDispatcherFunction should return TRUE when no further pads
- * need to be processed.
+ * gst_pad_set_offset:
+ * @pad: a #GstPad
+ * @offset: the offset
  *
- * Returns: TRUE if one of the dispatcher functions returned TRUE.
+ * Set the offset that will be applied to the running time of @pad.
  */
-gboolean
-gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch,
-    gpointer data)
+void
+gst_pad_set_offset (GstPad * pad, gint64 offset)
 {
-  gboolean res = FALSE;
-  GstIterator *iter = NULL;
-  gboolean done = FALSE;
-  gpointer item;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dispatch != NULL, FALSE);
+  PadEvent *ev;
 
-  iter = gst_pad_iterate_internal_links (pad);
+  g_return_if_fail (GST_IS_PAD (pad));
 
-  if (!iter)
-    goto no_iter;
+  GST_OBJECT_LOCK (pad);
+  /* if nothing changed, do nothing */
+  if (pad->offset == offset)
+    goto done;
 
-  while (!done) {
-    switch (gst_iterator_next (iter, &item)) {
-      case GST_ITERATOR_OK:
-      {
-        GstPad *int_pad = GST_PAD_CAST (item);
-        GstPad *int_peer = gst_pad_get_peer (int_pad);
-
-        if (int_peer) {
-          GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
-              GST_DEBUG_PAD_NAME (int_peer));
-          done = res = dispatch (int_peer, data);
-          gst_object_unref (int_peer);
-        } else {
-          GST_DEBUG_OBJECT (int_pad, "no peer");
-        }
-      }
-        gst_object_unref (item);
-        break;
-      case GST_ITERATOR_RESYNC:
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_ERROR:
-        done = TRUE;
-        GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
-        break;
-      case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
-    }
-  }
-  gst_iterator_free (iter);
+  pad->offset = offset;
+  GST_DEBUG_OBJECT (pad, "changed offset to %" G_GINT64_FORMAT, offset);
 
-  GST_DEBUG_OBJECT (pad, "done, result %d", res);
+  /* sinkpads will apply their offset the next time a segment
+   * event is received. */
+  if (GST_PAD_IS_SINK (pad))
+    goto done;
 
-no_iter:
+  /* resend the last segment event on next buffer push */
+  if ((ev = find_event_by_type (pad, GST_EVENT_SEGMENT, 0))) {
+    ev->received = FALSE;
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+  }
 
-  return res;
+done:
+  GST_OBJECT_UNLOCK (pad);
 }
 
+
 /**
  * gst_pad_query:
  * @pad: a #GstPad to invoke the default query on.
@@ -3753,388 +3090,152 @@ no_iter:
 gboolean
 gst_pad_query (GstPad * pad, GstQuery * query)
 {
+  GstObject *parent;
+  gboolean res;
   GstPadQueryFunction func;
+  GstPadProbeType type;
+  GstFlowReturn ret;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
 
-  GST_DEBUG_OBJECT (pad, "sending query %p", query);
+  GST_DEBUG_OBJECT (pad, "sending query %p (%s)", query,
+      GST_QUERY_TYPE_NAME (query));
 
-  if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
-    goto no_func;
+  if (GST_PAD_IS_SRC (pad))
+    type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM;
+  else
+    type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM;
 
-  return func (pad, query);
+  GST_OBJECT_LOCK (pad);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
+      GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
 
-no_func:
-  {
-    GST_DEBUG_OBJECT (pad, "had no query function");
-    return FALSE;
-  }
-}
+  ACQUIRE_PARENT (pad, parent, no_parent);
+  GST_OBJECT_UNLOCK (pad);
 
-/**
- * gst_pad_peer_query:
- * @pad: a #GstPad to invoke the peer query on.
- * @query: (transfer none): the #GstQuery to perform.
- *
- * Performs gst_pad_query() on the peer of @pad.
- *
- * The caller is responsible for both the allocation and deallocation of
- * the query structure.
- *
- * Returns: TRUE if the query could be performed. This function returns %FALSE
- * if @pad has no peer.
- *
- * Since: 0.10.15
- */
-gboolean
-gst_pad_peer_query (GstPad * pad, GstQuery * query)
-{
-  GstPad *peerpad;
-  gboolean result;
+  if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
+    goto no_func;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
+  res = func (pad, parent, query);
 
-  GST_OBJECT_LOCK (pad);
+  RELEASE_PARENT (parent);
 
-  GST_DEBUG_OBJECT (pad, "peer query");
+  GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
+      GST_QUERY_TYPE_NAME (query), res);
 
-  peerpad = GST_PAD_PEER (pad);
-  if (G_UNLIKELY (peerpad == NULL))
-    goto no_peer;
+  if (res != TRUE)
+    goto query_failed;
 
-  gst_object_ref (peerpad);
+  GST_OBJECT_LOCK (pad);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped);
   GST_OBJECT_UNLOCK (pad);
 
-  result = gst_pad_query (peerpad, query);
-
-  gst_object_unref (peerpad);
-
-  return result;
+  return res;
 
   /* ERRORS */
-no_peer:
+no_parent:
   {
-    GST_WARNING_OBJECT (pad, "pad has no peer");
+    GST_DEBUG_OBJECT (pad, "had no parent");
     GST_OBJECT_UNLOCK (pad);
     return FALSE;
   }
-}
-
-/**
- * gst_pad_query_default:
- * @pad: a #GstPad to call the default query handler on.
- * @query: (transfer none): the #GstQuery to handle.
- *
- * Invokes the default query handler for the given pad.
- * The query is sent to all pads internally linked to @pad. Note that
- * if there are many possible sink pads that are internally linked to
- * @pad, only one will be sent the query.
- * Multi-sinkpad elements should implement custom query handlers.
- *
- * Returns: TRUE if the query was performed successfully.
- */
-gboolean
-gst_pad_query_default (GstPad * pad, GstQuery * query)
-{
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    case GST_QUERY_SEEKING:
-    case GST_QUERY_FORMATS:
-    case GST_QUERY_LATENCY:
-    case GST_QUERY_JITTER:
-    case GST_QUERY_RATE:
-    case GST_QUERY_CONVERT:
-    default:
-      return gst_pad_dispatcher
-          (pad, (GstPadDispatcherFunction) gst_pad_query, query);
-  }
-}
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-/* FIXME: why isn't this on a GstElement ? */
-/**
- * gst_pad_load_and_link:
- * @self: an #xmlNodePtr to read the description from.
- * @parent: the #GstObject element that owns the pad.
- *
- * Reads the pad definition from the XML node and links the given pad
- * in the element to a pad of an element up in the hierarchy.
- */
-void
-gst_pad_load_and_link (xmlNodePtr self, GstObject * parent)
-{
-  xmlNodePtr field = self->xmlChildrenNode;
-  GstPad *pad = NULL, *targetpad;
-  GstPadTemplate *tmpl;
-  gchar *peer = NULL;
-  gchar **split;
-  GstElement *target;
-  GstObject *grandparent;
-  gchar *name = NULL;
-
-  while (field) {
-    if (!strcmp ((char *) field->name, "name")) {
-      name = (gchar *) xmlNodeGetContent (field);
-      pad = gst_element_get_static_pad (GST_ELEMENT (parent), name);
-      if ((!pad) || ((tmpl = gst_pad_get_pad_template (pad))
-              && (GST_PAD_REQUEST == GST_PAD_TEMPLATE_PRESENCE (tmpl))))
-        pad = gst_element_get_request_pad (GST_ELEMENT (parent), name);
-      g_free (name);
-    } else if (!strcmp ((char *) field->name, "peer")) {
-      peer = (gchar *) xmlNodeGetContent (field);
-    }
-    field = field->next;
-  }
-  g_return_if_fail (pad != NULL);
-
-  if (peer == NULL)
-    return;
-
-  split = g_strsplit (peer, ".", 2);
-
-  if (split[0] == NULL || split[1] == NULL) {
-    GST_CAT_DEBUG_OBJECT (GST_CAT_XML, pad,
-        "Could not parse peer '%s', leaving unlinked", peer);
-
-    g_free (peer);
-    return;
-  }
-  g_free (peer);
-
-  g_return_if_fail (split[0] != NULL);
-  g_return_if_fail (split[1] != NULL);
-
-  grandparent = gst_object_get_parent (parent);
-
-  if (grandparent && GST_IS_BIN (grandparent)) {
-    target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
-  } else
-    goto cleanup;
-
-  if (target == NULL)
-    goto cleanup;
-
-  targetpad = gst_element_get_static_pad (target, split[1]);
-  if (!targetpad)
-    targetpad = gst_element_get_request_pad (target, split[1]);
-
-  if (targetpad == NULL)
-    goto cleanup;
-
-  if (gst_pad_get_direction (pad) == GST_PAD_SRC)
-    gst_pad_link (pad, targetpad);
-  else
-    gst_pad_link (targetpad, pad);
-
-cleanup:
-  g_strfreev (split);
-}
-
-/**
- * gst_pad_save_thyself:
- * @pad: a #GstPad to save.
- * @parent: the parent #xmlNodePtr to save the description in.
- *
- * Saves the pad into an xml representation.
- *
- * Returns: the #xmlNodePtr representation of the pad.
- */
-static xmlNodePtr
-gst_pad_save_thyself (GstObject * object, xmlNodePtr parent)
-{
-  GstPad *pad;
-  GstPad *peer;
-
-  g_return_val_if_fail (GST_IS_PAD (object), NULL);
-
-  pad = GST_PAD_CAST (object);
-
-  xmlNewChild (parent, NULL, (xmlChar *) "name",
-      (xmlChar *) GST_PAD_NAME (pad));
-
-  if (GST_PAD_IS_SRC (pad)) {
-    xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "source");
-  } else if (GST_PAD_IS_SINK (pad)) {
-    xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "sink");
-  } else {
-    xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
+no_func:
+  {
+    GST_DEBUG_OBJECT (pad, "had no query function");
+    RELEASE_PARENT (parent);
+    return FALSE;
+  }
+query_failed:
+  {
+    GST_DEBUG_OBJECT (pad, "query failed");
+    return FALSE;
+  }
+probe_stopped:
+  {
+    GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
+    return FALSE;
   }
-
-  if (GST_PAD_PEER (pad) != NULL) {
-    gchar *content;
-
-    peer = GST_PAD_PEER (pad);
-    /* first check to see if the peer's parent's parent is the same */
-    /* we just save it off */
-    content = g_strdup_printf ("%s.%s",
-        GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));
-    xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content);
-    g_free (content);
-  } else
-    xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL);
-
-  return parent;
 }
 
-#if 0
 /**
- * gst_ghost_pad_save_thyself:
- * @pad: a ghost #GstPad to save.
- * @parent: the parent #xmlNodePtr to save the description in.
+ * gst_pad_peer_query:
+ * @pad: a #GstPad to invoke the peer query on.
+ * @query: (transfer none): the #GstQuery to perform.
+ *
+ * Performs gst_pad_query() on the peer of @pad.
  *
- * Saves the ghost pad into an xml representation.
+ * The caller is responsible for both the allocation and deallocation of
+ * the query structure.
+ *
+ * Returns: TRUE if the query could be performed. This function returns %FALSE
+ * if @pad has no peer.
  *
- * Returns: the #xmlNodePtr representation of the pad.
+ * Since: 0.10.15
  */
-xmlNodePtr
-gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent)
+gboolean
+gst_pad_peer_query (GstPad * pad, GstQuery * query)
 {
-  xmlNodePtr self;
-
-  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
+  GstPad *peerpad;
+  GstPadProbeType type;
+  gboolean res;
+  GstFlowReturn ret;
 
-  self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
-  xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad));
-  xmlNewChild (self, NULL, (xmlChar *) "parent",
-      (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
 
-  /* FIXME FIXME FIXME! */
+  if (GST_PAD_IS_SRC (pad))
+    type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM;
+  else
+    type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM;
 
-  return self;
-}
-#endif /* 0 */
-#endif /* GST_DISABLE_LOADSAVE */
-
-/*
- * should be called with pad OBJECT_LOCK and STREAM_LOCK held.
- * GST_PAD_IS_BLOCKED (pad) == TRUE when this function is
- * called.
- *
- * This function performs the pad blocking when an event, buffer push
- * or buffer_alloc is performed on a _SRC_ pad. It blocks the
- * streaming thread after informing the pad has been blocked.
- *
- * An application can with this method wait and block any streaming
- * thread and perform operations such as seeking or linking.
- *
- * Two methods are available for notifying the application of the
- * block:
- * - the callback method, which happens in the STREAMING thread with
- *   the STREAM_LOCK held. With this method, the most useful way of
- *   dealing with the callback is to post a message to the main thread
- *   where the pad block can then be handled outside of the streaming
- *   thread. With the last method one can perform all operations such
- *   as doing a state change, linking, unblocking, seeking etc on the
- *   pad.
- * - the GCond signal method, which makes any thread unblock when
- *   the pad block happens.
- *
- * During the actual blocking state, the GST_PAD_BLOCKING flag is set.
- * The GST_PAD_BLOCKING flag is unset when the pad was unblocked.
- *
- * MT safe.
- */
-static GstFlowReturn
-handle_pad_block (GstPad * pad)
-{
-  GstPadBlockCallback callback;
-  gpointer user_data;
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "signal block taken");
-
-  /* flushing, don't bother trying to block and return WRONG_STATE
-   * right away */
-  if (GST_PAD_IS_FLUSHING (pad))
-    goto flushingnonref;
-
-  /* we grab an extra ref for the callbacks, this is probably not
-   * needed (callback code does not have a ref and cannot unref). I
-   * think this was done to make it possible to unref the element in
-   * the callback, which is in the end totally impossible as it
-   * requires grabbing the STREAM_LOCK and OBJECT_LOCK which are
-   * all taken when calling this function. */
-  gst_object_ref (pad);
-
-  while (GST_PAD_IS_BLOCKED (pad)) {
-    do {
-      /* we either have a callback installed to notify the block or
-       * some other thread is doing a GCond wait. */
-      callback = pad->block_callback;
-      pad->abidata.ABI.block_callback_called = TRUE;
-      if (callback) {
-        /* there is a callback installed, call it. We release the
-         * lock so that the callback can do something useful with the
-         * pad */
-        user_data = pad->block_data;
-        GST_OBJECT_UNLOCK (pad);
-        callback (pad, TRUE, user_data);
-        GST_OBJECT_LOCK (pad);
+  GST_DEBUG_OBJECT (pad, "peer query %p (%s)", query,
+      GST_QUERY_TYPE_NAME (query));
 
-        /* we released the lock, recheck flushing */
-        if (GST_PAD_IS_FLUSHING (pad))
-          goto flushing;
-      } else {
-        /* no callback, signal the thread that is doing a GCond wait
-         * if any. */
-        GST_PAD_BLOCK_BROADCAST (pad);
-      }
-    } while (pad->abidata.ABI.block_callback_called == FALSE
-        && GST_PAD_IS_BLOCKED (pad));
+  GST_OBJECT_LOCK (pad);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
+      GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
 
-    /* OBJECT_LOCK could have been released when we did the callback, which
-     * then could have made the pad unblock so we need to check the blocking
-     * condition again.   */
-    if (!GST_PAD_IS_BLOCKED (pad))
-      break;
+  peerpad = GST_PAD_PEER (pad);
+  if (G_UNLIKELY (peerpad == NULL))
+    goto no_peer;
 
-    /* now we block the streaming thread. It can be unlocked when we
-     * deactivate the pad (which will also set the FLUSHING flag) or
-     * when the pad is unblocked. A flushing event will also unblock
-     * the pad after setting the FLUSHING flag. */
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "Waiting to be unblocked or set flushing");
-    GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKING);
-    GST_PAD_BLOCK_WAIT (pad);
-    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING);
+  gst_object_ref (peerpad);
+  GST_OBJECT_UNLOCK (pad);
 
-    /* see if we got unblocked by a flush or not */
-    if (GST_PAD_IS_FLUSHING (pad))
-      goto flushing;
-  }
+  res = gst_pad_query (peerpad, query);
 
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
+  gst_object_unref (peerpad);
 
-  /* when we get here, the pad is unblocked again and we perform
-   * the needed unblock code. */
-  callback = pad->block_callback;
-  if (callback) {
-    /* we need to call the callback */
-    user_data = pad->block_data;
-    GST_OBJECT_UNLOCK (pad);
-    callback (pad, FALSE, user_data);
-    GST_OBJECT_LOCK (pad);
-  } else {
-    /* we need to signal the thread waiting on the GCond */
-    GST_PAD_BLOCK_BROADCAST (pad);
-  }
+  if (res != TRUE)
+    goto query_failed;
 
-  gst_object_unref (pad);
+  GST_OBJECT_LOCK (pad);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped);
+  GST_OBJECT_UNLOCK (pad);
 
-  return ret;
+  return res;
 
-flushingnonref:
+  /* ERRORS */
+no_peer:
   {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pad was flushing");
-    return GST_FLOW_WRONG_STATE;
+    GST_WARNING_OBJECT (pad, "pad has no peer");
+    GST_OBJECT_UNLOCK (pad);
+    return FALSE;
   }
-flushing:
+query_failed:
   {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pad became flushing");
-    gst_object_unref (pad);
-    return GST_FLOW_WRONG_STATE;
+    GST_DEBUG_OBJECT (pad, "query failed");
+    return FALSE;
+  }
+probe_stopped:
+  {
+    GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
+    return FALSE;
   }
 }
 
@@ -4143,77 +3244,33 @@ flushing:
  */
 
 static gboolean
-gst_pad_emit_have_data_signal (GstPad * pad, GstMiniObject * obj)
+push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
 {
-  GValue ret = { 0 };
-  GValue args[2] = { {0}, {0} };
-  gboolean res;
-  GQuark detail;
-
-  /* init */
-  g_value_init (&ret, G_TYPE_BOOLEAN);
-  g_value_set_boolean (&ret, TRUE);
-  g_value_init (&args[0], GST_TYPE_PAD);
-  g_value_set_object (&args[0], pad);
-  g_value_init (&args[1], GST_TYPE_MINI_OBJECT);
-  gst_value_set_mini_object (&args[1], obj);
-
-  if (GST_IS_EVENT (obj))
-    detail = event_quark;
-  else
-    detail = buffer_quark;
-
-  /* actually emit */
-  g_signal_emitv (args, gst_pad_signals[PAD_HAVE_DATA], detail, &ret);
-  res = g_value_get_boolean (&ret);
-
-  /* clean up */
-  g_value_unset (&ret);
-  g_value_unset (&args[0]);
-  g_value_unset (&args[1]);
-
-  return res;
-}
+  GstFlowReturn *data = user_data;
+  gboolean stored;
 
-static void
-gst_pad_data_unref (gboolean is_buffer, void *data)
-{
-  if (G_LIKELY (is_buffer)) {
-    gst_buffer_unref (data);
-  } else {
-    gst_buffer_list_unref (data);
+  if (ev->received) {
+    GST_DEBUG_OBJECT (pad, "event %s was already received",
+        GST_EVENT_TYPE_NAME (ev->event));
+    return TRUE;
   }
-}
-
-static GstCaps *
-gst_pad_data_get_caps (gboolean is_buffer, void *data)
-{
-  GstCaps *caps;
+  GST_OBJECT_UNLOCK (pad);
 
-  if (G_LIKELY (is_buffer)) {
-    caps = GST_BUFFER_CAPS (data);
-  } else {
-    GstBuffer *buf;
+  *data = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event),
+      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, &stored);
 
-    if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0, 0)))
-      caps = GST_BUFFER_CAPS (buf);
-    else
-      caps = NULL;
-  }
-  return caps;
+  GST_OBJECT_LOCK (pad);
+  return *data == GST_FLOW_OK;
 }
 
 /* this is the chain function that does not perform the additional argument
  * checking for that little extra speed.
  */
 static inline GstFlowReturn
-gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
-    GstPadPushCache * cache)
+gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data)
 {
-  GstCaps *caps;
-  gboolean caps_changed;
   GstFlowReturn ret;
-  gboolean emit_signal;
+  GstObject *parent;
 
   GST_PAD_STREAM_LOCK (pad);
 
@@ -4221,39 +3278,19 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
     goto flushing;
 
-  caps = gst_pad_data_get_caps (is_buffer, data);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
-
-  emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
-  GST_OBJECT_UNLOCK (pad);
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
 
-  /* see if the signal should be emited, we emit before caps nego as
-   * we might drop the buffer and do capsnego for nothing. */
-  if (G_UNLIKELY (emit_signal)) {
-    cache = NULL;
-    if (G_LIKELY (is_buffer)) {
-      if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
-        goto dropping;
-    } else {
-      /* chain all groups in the buffer list one by one to avoid problems with
-       * buffer probes that push buffers or events */
-      goto chain_groups;
-    }
-  }
+  PROBE_PUSH (pad, type, data, probe_stopped);
 
-  /* we got a new datatype on the pad, see if it can handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
-    if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
-      goto not_negotiated;
-  }
+  parent = GST_OBJECT_PARENT (pad);
+  GST_OBJECT_UNLOCK (pad);
 
   /* NOTE: we read the chainfunc unlocked.
    * we cannot hold the lock for the pad so we might send
    * the data to the wrong function. This is not really a
    * problem since functions are assigned at creation time
    * and don't change that often... */
-  if (G_LIKELY (is_buffer)) {
+  if (G_LIKELY (type & GST_PAD_PROBE_TYPE_BUFFER)) {
     GstPadChainFunction chainfunc;
 
     if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
@@ -4263,12 +3300,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
         "calling chainfunction &%s with buffer %" GST_PTR_FORMAT,
         GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_BUFFER (data));
 
-    if (cache) {
-      cache->peer = gst_object_ref (pad);
-      cache->caps = caps ? gst_caps_ref (caps) : NULL;
-    }
-
-    ret = chainfunc (pad, GST_BUFFER_CAST (data));
+    ret = chainfunc (pad, parent, GST_BUFFER_CAST (data));
 
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "called chainfunction &%s with buffer %p, returned %s",
@@ -4277,13 +3309,13 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
     GstPadChainListFunction chainlistfunc;
 
     if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL))
-      goto chain_groups;
+      goto no_function;
 
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "calling chainlistfunction &%s",
         GST_DEBUG_FUNCPTR_NAME (chainlistfunc));
 
-    ret = chainlistfunc (pad, GST_BUFFER_LIST_CAST (data));
+    ret = chainlistfunc (pad, parent, GST_BUFFER_LIST_CAST (data));
 
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "called chainlistfunction &%s, returned %s",
@@ -4294,72 +3326,39 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
 
   return ret;
 
-chain_groups:
-  {
-    GstBufferList *list;
-    GstBufferListIterator *it;
-    GstBuffer *group;
-
-    GST_PAD_STREAM_UNLOCK (pad);
-
-    GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
-
-    list = GST_BUFFER_LIST_CAST (data);
-    it = gst_buffer_list_iterate (list);
-
-    if (gst_buffer_list_iterator_next_group (it)) {
-      do {
-        group = gst_buffer_list_iterator_merge_group (it);
-        if (group == NULL) {
-          group = gst_buffer_new ();
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
-        } else {
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
-        }
-        ret = gst_pad_chain_data_unchecked (pad, TRUE, group, NULL);
-      } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
-    } else {
-      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
-      ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_new (), NULL);
-    }
-
-    gst_buffer_list_iterator_free (it);
-    gst_buffer_list_unref (list);
-
-    return ret;
-  }
-
   /* ERRORS */
 flushing:
   {
-    gst_pad_data_unref (is_buffer, data);
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but pad was flushing");
+        "chaining, but pad was flushing");
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     return GST_FLOW_WRONG_STATE;
   }
-dropping:
-  {
-    gst_pad_data_unref (is_buffer, data);
-    GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
-    GST_PAD_STREAM_UNLOCK (pad);
-    return GST_FLOW_OK;
-  }
-not_negotiated:
+probe_stopped:
   {
-    gst_pad_data_unref (is_buffer, data);
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing data but pad did not accept");
+    GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
-    return GST_FLOW_NOT_NEGOTIATED;
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+
+    switch (ret) {
+      case GST_FLOW_CUSTOM_SUCCESS:
+        GST_DEBUG_OBJECT (pad, "dropped buffer");
+        ret = GST_FLOW_OK;
+        break;
+      default:
+        GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+        break;
+    }
+    return ret;
   }
 no_function:
   {
-    gst_pad_data_unref (is_buffer, data);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "pushing, but not chainhandler");
-    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+    GST_ELEMENT_ERROR (parent, CORE, PAD, (NULL),
         ("push on pad %s:%s but it has no chainfunction",
             GST_DEBUG_PAD_NAME (pad)));
     GST_PAD_STREAM_UNLOCK (pad);
@@ -4377,10 +3376,9 @@ no_function:
  *
  * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
  *
- * If the caps on @buffer are different from the current caps on @pad, this
- * function will call any setcaps function (see gst_pad_set_setcaps_function())
- * installed on @pad. If the new caps are not acceptable for @pad, this
- * function returns #GST_FLOW_NOT_NEGOTIATED.
+ * If the buffer type is not acceptable for @pad (as negotiated with a
+ * preceeding GST_EVENT_CAPS event), this function returns
+ * #GST_FLOW_NOT_NEGOTIATED.
  *
  * The function proceeds calling the chain function installed on @pad (see
  * gst_pad_set_chain_function()) and the return value of that function is
@@ -4401,7 +3399,35 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
 
-  return gst_pad_chain_data_unchecked (pad, TRUE, buffer, NULL);
+  return gst_pad_chain_data_unchecked (pad,
+      GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
+}
+
+static GstFlowReturn
+gst_pad_chain_list_default (GstPad * pad, GstObject * parent,
+    GstBufferList * list)
+{
+  guint i, len;
+  GstBuffer *buffer;
+  GstFlowReturn ret;
+
+  GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+
+  len = gst_buffer_list_length (list);
+
+  ret = GST_FLOW_OK;
+  for (i = 0; i < len; i++) {
+    buffer = gst_buffer_list_get (list, i);
+    ret =
+        gst_pad_chain_data_unchecked (pad,
+        GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH,
+        gst_buffer_ref (buffer));
+    if (ret != GST_FLOW_OK)
+      break;
+  }
+  gst_buffer_list_unref (list);
+
+  return ret;
 }
 
 /**
@@ -4414,10 +3440,8 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
  *
  * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
  *
- * If the caps on the first buffer of @list are different from the current
- * caps on @pad, this function will call any setcaps function
- * (see gst_pad_set_setcaps_function()) installed on @pad. If the new caps
- * are not acceptable for @pad, this function returns #GST_FLOW_NOT_NEGOTIATED.
+ * If @pad was not negotiated properly with a CAPS event, this function
+ * returns #GST_FLOW_NOT_NEGOTIATED.
  *
  * The function proceeds calling the chainlist function installed on @pad (see
  * gst_pad_set_chain_list_function()) and the return value of that function is
@@ -4440,207 +3464,102 @@ gst_pad_chain_list (GstPad * pad, GstBufferList * list)
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
 
-  return gst_pad_chain_data_unchecked (pad, FALSE, list, NULL);
+  return gst_pad_chain_data_unchecked (pad,
+      GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list);
 }
 
 static GstFlowReturn
-gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
-    GstPadPushCache * cache)
+gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data)
 {
   GstPad *peer;
   GstFlowReturn ret;
-  GstCaps *caps;
-  gboolean caps_changed;
 
   GST_OBJECT_LOCK (pad);
+  if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+    goto flushing;
 
-  /* FIXME: this check can go away; pad_set_blocked could be implemented with
-   * probes completely or probes with an extended pad block. */
-  while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
-    if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
-      goto flushed;
-
-  /* we emit signals on the pad arg, the peer will have a chance to
-   * emit in the _chain() function */
-  if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) {
-    cache = NULL;
-    /* unlock before emitting */
-    GST_OBJECT_UNLOCK (pad);
+  if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
+    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
 
-    if (G_LIKELY (is_buffer)) {
-      /* if the signal handler returned FALSE, it means we should just drop the
-       * buffer */
-      if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
-        goto dropped;
-    } else {
-      /* push all buffers in the list */
-      goto push_groups;
-    }
-    GST_OBJECT_LOCK (pad);
+    GST_DEBUG_OBJECT (pad, "pushing all sticky events");
+
+    ret = GST_FLOW_OK;
+    events_foreach (pad, push_sticky, &ret);
+    if (ret != GST_FLOW_OK)
+      goto events_error;
   }
 
-  /* Before pushing the buffer to the peer pad, ensure that caps
-   * are set on this pad */
-  caps = gst_pad_data_get_caps (is_buffer, data);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+  /* do block probes */
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
 
-  /* we got a new datatype from the pad, it had better handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    /* unlock before setting */
-    GST_OBJECT_UNLOCK (pad);
-    GST_DEBUG_OBJECT (pad,
-        "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
-        GST_PAD_CAPS (pad), caps, caps);
-    if (G_UNLIKELY (!gst_pad_set_caps (pad, caps)))
-      goto not_negotiated;
-    GST_OBJECT_LOCK (pad);
-  }
+  /* do post-blocking probes */
+  PROBE_PUSH (pad, type, data, probe_stopped);
 
   if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
     goto not_linked;
 
   /* take ref to peer pad before releasing the lock */
   gst_object_ref (peer);
+  pad->priv->using++;
   GST_OBJECT_UNLOCK (pad);
 
-  ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, cache);
+  ret = gst_pad_chain_data_unchecked (peer, type, data);
 
   gst_object_unref (peer);
 
+  GST_OBJECT_LOCK (pad);
+  pad->priv->using--;
+  if (pad->priv->using == 0) {
+    /* pad is not active anymore, trigger idle callbacks */
+    PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
+        probe_stopped, ret);
+  }
+  GST_OBJECT_UNLOCK (pad);
+
   return ret;
 
-push_groups:
+  /* ERROR recovery here */
+  /* ERRORS */
+flushing:
   {
-    GstBufferList *list;
-    GstBufferListIterator *it;
-    GstBuffer *group;
-
-    GST_INFO_OBJECT (pad, "pushing each group in list as a merged buffer");
-
-    list = GST_BUFFER_LIST_CAST (data);
-    it = gst_buffer_list_iterate (list);
-
-    if (gst_buffer_list_iterator_next_group (it)) {
-      do {
-        group = gst_buffer_list_iterator_merge_group (it);
-        if (group == NULL) {
-          group = gst_buffer_new ();
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
-        } else {
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing group");
-        }
-        ret = gst_pad_push_data (pad, TRUE, group, NULL);
-      } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
-    } else {
-      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
-      ret = gst_pad_push_data (pad, TRUE, gst_buffer_new (), NULL);
-    }
-
-    gst_buffer_list_iterator_free (it);
-    gst_buffer_list_unref (list);
-
-    return ret;
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but pad was flushing");
+    GST_OBJECT_UNLOCK (pad);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+    return GST_FLOW_WRONG_STATE;
   }
-
-  /* ERROR recovery here */
-flushed:
+events_error:
   {
-    gst_pad_data_unref (is_buffer, data);
-    GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "error pushing events, return %s", gst_flow_get_name (ret));
     GST_OBJECT_UNLOCK (pad);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     return ret;
   }
-dropped:
+probe_stopped:
   {
-    gst_pad_data_unref (is_buffer, data);
-    GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
-    return GST_FLOW_OK;
+    GST_OBJECT_UNLOCK (pad);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+
+    switch (ret) {
+      case GST_FLOW_CUSTOM_SUCCESS:
+        GST_DEBUG_OBJECT (pad, "dropped buffer");
+        ret = GST_FLOW_OK;
+        break;
+      default:
+        GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+        break;
+    }
+    return ret;
   }
 not_linked:
   {
-    gst_pad_data_unref (is_buffer, data);
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "pushing, but it was not linked");
     GST_OBJECT_UNLOCK (pad);
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
     return GST_FLOW_NOT_LINKED;
   }
-not_negotiated:
-  {
-    gst_pad_data_unref (is_buffer, data);
-    GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "element pushed data then refused to accept the caps");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-}
-
-static inline GstPadPushCache *
-pad_take_cache (GstPad * pad, gpointer * cache_ptr)
-{
-  GstPadPushCache *cache;
-
-  /* try to get the cached data */
-  do {
-    cache = g_atomic_pointer_get (cache_ptr);
-    /* now try to replace the pointer with NULL to mark that we are busy
-     * with it */
-  } while (!g_atomic_pointer_compare_and_exchange (cache_ptr, cache, NULL));
-
-  /* we could have a leftover invalid entry */
-  if (G_UNLIKELY (cache == PAD_CACHE_INVALID))
-    cache = NULL;
-
-  return cache;
-}
-
-static inline void
-pad_free_cache (GstPadPushCache * cache)
-{
-  gst_object_unref (cache->peer);
-  if (cache->caps)
-    gst_caps_unref (cache->caps);
-  g_slice_free (GstPadPushCache, cache);
-}
-
-static inline void
-pad_put_cache (GstPad * pad, GstPadPushCache * cache, gpointer * cache_ptr)
-{
-  /* put it back */
-  if (!g_atomic_pointer_compare_and_exchange (cache_ptr, NULL, cache)) {
-    /* something changed, clean up our cache */
-    pad_free_cache (cache);
-  }
-}
-
-/* must be called with the pad lock */
-void
-_priv_gst_pad_invalidate_cache (GstPad * pad)
-{
-  GstPadPushCache *cache;
-  gpointer *cache_ptr;
-
-  GST_LOG_OBJECT (pad, "Invalidating pad cache");
-
-  /* we hold the pad lock here so we can get the peer and it stays
-   * alive during this call */
-  if (GST_PAD_IS_SINK (pad)) {
-    if (!(pad = GST_PAD_PEER (pad)))
-      return;
-  }
-
-  cache_ptr = (gpointer *) & pad->abidata.ABI.priv->cache_ptr;
-
-  /* try to get the cached data */
-  do {
-    cache = g_atomic_pointer_get (cache_ptr);
-    /* now try to replace the pointer with INVALID. If nothing is busy with this
-     * caps, we get the cache and clean it up. If something is busy, we replace
-     * with INVALID so that when the function finishes and tries to put the
-     * cache back, it'll fail and cleanup */
-  } while (!g_atomic_pointer_compare_and_exchange (cache_ptr, cache,
-          PAD_CACHE_INVALID));
-
-  if (G_LIKELY (cache && cache != PAD_CACHE_INVALID))
-    pad_free_cache (cache);
 }
 
 /**
@@ -4651,13 +3570,8 @@ _priv_gst_pad_invalidate_cache (GstPad * pad)
  *
  * Pushes a buffer to the peer of @pad.
  *
- * This function will call an installed pad block before triggering any
- * installed pad probes.
- *
- * If the caps on @buffer are different from the currently configured caps on
- * @pad, this function will call any installed setcaps function on @pad (see
- * gst_pad_set_setcaps_function()). In case of failure to renegotiate the new
- * format, this function returns #GST_FLOW_NOT_NEGOTIATED.
+ * This function will call installed block probes before triggering any
+ * installed data probes.
  *
  * The function proceeds calling gst_pad_chain() on the peer pad and returns
  * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
@@ -4673,81 +3587,12 @@ _priv_gst_pad_invalidate_cache (GstPad * pad)
 GstFlowReturn
 gst_pad_push (GstPad * pad, GstBuffer * buffer)
 {
-  GstPadPushCache *cache;
-  GstFlowReturn ret;
-  gpointer *cache_ptr;
-  GstPad *peer;
-  GstCaps *caps;
-
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
-
-  cache_ptr = (gpointer *) & pad->abidata.ABI.priv->cache_ptr;
-
-  cache = pad_take_cache (pad, cache_ptr);
-
-  if (G_UNLIKELY (cache == NULL))
-    goto slow_path;
-
-  /* check caps */
-  caps = GST_BUFFER_CAPS (buffer);
-  if (G_UNLIKELY (caps && caps != cache->caps)) {
-    pad_free_cache (cache);
-    goto slow_path;
-  }
-
-  peer = cache->peer;
-
-  GST_PAD_STREAM_LOCK (peer);
-  if (G_UNLIKELY (g_atomic_pointer_get (cache_ptr) == PAD_CACHE_INVALID))
-    goto invalid;
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "calling chainfunction &%s with buffer %" GST_PTR_FORMAT,
-      GST_DEBUG_FUNCPTR_NAME (GST_PAD_CHAINFUNC (peer)), buffer);
-
-  ret = GST_PAD_CHAINFUNC (peer) (peer, buffer);
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "called chainfunction &%s with buffer %p, returned %s",
-      GST_DEBUG_FUNCPTR_NAME (GST_PAD_CHAINFUNC (peer)), buffer,
-      gst_flow_get_name (ret));
-
-  GST_PAD_STREAM_UNLOCK (peer);
-
-  pad_put_cache (pad, cache, cache_ptr);
-
-  return ret;
-
-  /* slow path */
-slow_path:
-  {
-    GstPadPushCache scache = { NULL, };
-
-    GST_LOG_OBJECT (pad, "Taking slow path");
-
-    ret = gst_pad_push_data (pad, TRUE, buffer, &scache);
-
-    if (scache.peer) {
-      GstPadPushCache *ncache;
-
-      GST_LOG_OBJECT (pad, "Caching push data");
-
-      /* make cache structure */
-      ncache = g_slice_new (GstPadPushCache);
-      *ncache = scache;
-
-      pad_put_cache (pad, ncache, cache_ptr);
-    }
-    return ret;
-  }
-invalid:
-  {
-    GST_PAD_STREAM_UNLOCK (peer);
-    pad_free_cache (cache);
-    goto slow_path;
-  }
+  g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
+
+  return gst_pad_push_data (pad,
+      GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
 }
 
 /**
@@ -4758,18 +3603,8 @@ invalid:
  *
  * Pushes a buffer list to the peer of @pad.
  *
- * This function will call an installed pad block before triggering any
- * installed pad probes.
- *
- * If the caps on the first buffer in the first group of @list are different
- * from the currently configured caps on @pad, this function will call any
- * installed setcaps function on @pad (see gst_pad_set_setcaps_function()). In
- * case of failure to renegotiate the new format, this function returns
- * #GST_FLOW_NOT_NEGOTIATED.
- *
- * If there are any probes installed on @pad every group of the buffer list
- * will be merged into a normal #GstBuffer and pushed via gst_pad_push and the
- * buffer list will be unreffed.
+ * This function will call installed block probes before triggering any
+ * installed data probes.
  *
  * The function proceeds calling the chain function on the peer pad and returns
  * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
@@ -4789,147 +3624,12 @@ invalid:
 GstFlowReturn
 gst_pad_push_list (GstPad * pad, GstBufferList * list)
 {
-  GstBuffer *buf;
-  GstPadPushCache *cache;
-  GstFlowReturn ret;
-  gpointer *cache_ptr;
-  GstPad *peer;
-  GstCaps *caps;
-
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
 
-  cache_ptr = (gpointer *) & pad->abidata.ABI.priv->cache_ptr;
-
-  cache = pad_take_cache (pad, cache_ptr);
-
-  if (G_UNLIKELY (cache == NULL))
-    goto slow_path;
-
-  /* check caps */
-  if ((buf = gst_buffer_list_get (list, 0, 0)))
-    caps = GST_BUFFER_CAPS (buf);
-  else
-    caps = NULL;
-
-  if (G_UNLIKELY (caps && caps != cache->caps)) {
-    pad_free_cache (cache);
-    goto slow_path;
-  }
-
-  peer = cache->peer;
-
-  GST_PAD_STREAM_LOCK (peer);
-  if (G_UNLIKELY (g_atomic_pointer_get (cache_ptr) == PAD_CACHE_INVALID))
-    goto invalid;
-
-  ret = GST_PAD_CHAINLISTFUNC (peer) (peer, list);
-
-  GST_PAD_STREAM_UNLOCK (peer);
-
-  pad_put_cache (pad, cache, cache_ptr);
-
-  return ret;
-
-  /* slow path */
-slow_path:
-  {
-    GstPadPushCache scache = { NULL, };
-
-    GST_LOG_OBJECT (pad, "Taking slow path");
-
-    ret = gst_pad_push_data (pad, FALSE, list, &scache);
-
-    if (scache.peer) {
-      GstPadPushCache *ncache;
-
-      GST_LOG_OBJECT (pad, "Caching push data");
-
-      /* make cache structure */
-      ncache = g_slice_new (GstPadPushCache);
-      *ncache = scache;
-
-      pad_put_cache (pad, ncache, cache_ptr);
-    }
-    return ret;
-  }
-invalid:
-  {
-    GST_PAD_STREAM_UNLOCK (peer);
-    pad_free_cache (cache);
-    goto slow_path;
-  }
-}
-
-/**
- * gst_pad_check_pull_range:
- * @pad: a sink #GstPad.
- *
- * Checks if a gst_pad_pull_range() can be performed on the peer
- * source pad. This function is used by plugins that want to check
- * if they can use random access on the peer source pad.
- *
- * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction
- * if it needs to perform some logic to determine if pull_range is
- * possible.
- *
- * Returns: a gboolean with the result.
- *
- * MT safe.
- */
-gboolean
-gst_pad_check_pull_range (GstPad * pad)
-{
-  GstPad *peer;
-  gboolean ret;
-  GstPadCheckGetRangeFunction checkgetrangefunc;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-
-  GST_OBJECT_LOCK (pad);
-  if (!GST_PAD_IS_SINK (pad))
-    goto wrong_direction;
-
-  if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
-    goto not_connected;
-
-  gst_object_ref (peer);
-  GST_OBJECT_UNLOCK (pad);
-
-  /* see note in above function */
-  if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) {
-    /* FIXME, kindoff ghetto */
-    ret = GST_PAD_GETRANGEFUNC (peer) != NULL;
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "no checkgetrangefunc, assuming %d", ret);
-  } else {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "calling checkgetrangefunc %s of peer pad %s:%s",
-        GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer));
-
-    ret = checkgetrangefunc (peer);
-  }
-
-  gst_object_unref (peer);
-
-  return ret;
-
-  /* ERROR recovery here */
-wrong_direction:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "checking pull range, but pad must be a sinkpad");
-    GST_OBJECT_UNLOCK (pad);
-    return FALSE;
-  }
-not_connected:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "checking pull range, but it was not linked");
-    GST_OBJECT_UNLOCK (pad);
-    return FALSE;
-  }
+  return gst_pad_push_data (pad,
+      GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list);
 }
 
 static GstFlowReturn
@@ -4938,9 +3638,7 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
 {
   GstFlowReturn ret;
   GstPadGetRangeFunction getrangefunc;
-  gboolean emit_signal;
-  GstCaps *caps;
-  gboolean caps_changed;
+  GstObject *parent;
 
   GST_PAD_STREAM_LOCK (pad);
 
@@ -4948,7 +3646,23 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
     goto flushing;
 
-  emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
+  if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
+    GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+
+    GST_DEBUG_OBJECT (pad, "pushing all sticky events");
+
+    ret = GST_FLOW_OK;
+    events_foreach (pad, push_sticky, &ret);
+    if (ret != GST_FLOW_OK)
+      goto events_error;
+  }
+
+  /* when one of the probes returns a buffer, probed_data will be called and we
+   * skip calling the getrange function */
+  PROBE_PRE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
+      *buffer, offset, size, probe_stopped, probed_data, GST_FLOW_OK);
+
+  ACQUIRE_PARENT (pad, parent, no_parent);
   GST_OBJECT_UNLOCK (pad);
 
   if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL))
@@ -4959,76 +3673,83 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
       G_GUINT64_FORMAT ", size %u",
       GST_DEBUG_FUNCPTR_NAME (getrangefunc), offset, size);
 
-  ret = getrangefunc (pad, offset, size, buffer);
+  ret = getrangefunc (pad, parent, offset, size, buffer);
 
-  /* can only fire the signal if we have a valid buffer */
-  if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) {
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
-      goto dropping;
-  }
-
-  GST_PAD_STREAM_UNLOCK (pad);
+  RELEASE_PARENT (parent);
 
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto get_range_failed;
 
+  /* can only fire the signal if we have a valid buffer */
   GST_OBJECT_LOCK (pad);
-  /* Before pushing the buffer to the peer pad, ensure that caps
-   * are set on this pad */
-  caps = GST_BUFFER_CAPS (*buffer);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
+probed_data:
+  PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
+      *buffer, offset, size, probe_stopped_unref);
   GST_OBJECT_UNLOCK (pad);
 
-  if (G_UNLIKELY (caps_changed)) {
-    GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
-    /* this should usually work because the element produced the buffer */
-    if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
-      goto not_negotiated;
-  }
+  GST_PAD_STREAM_UNLOCK (pad);
+
   return ret;
 
   /* ERRORS */
 flushing:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pulling range, but pad was flushing");
+        "getrange, but pad was flushing");
+    GST_OBJECT_UNLOCK (pad);
+    GST_PAD_STREAM_UNLOCK (pad);
+    return GST_FLOW_WRONG_STATE;
+  }
+events_error:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events");
+    GST_OBJECT_UNLOCK (pad);
+    GST_PAD_STREAM_UNLOCK (pad);
+    return ret;
+  }
+no_parent:
+  {
+    GST_DEBUG_OBJECT (pad, "no parent");
     GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
     return GST_FLOW_WRONG_STATE;
   }
 no_function:
   {
-    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
-        ("pullrange on pad %s:%s but it has no getrangefunction",
+    GST_ELEMENT_ERROR (parent, CORE, PAD, (NULL),
+        ("getrange on pad %s:%s but it has no getrangefunction",
             GST_DEBUG_PAD_NAME (pad)));
+    RELEASE_PARENT (parent);
     GST_PAD_STREAM_UNLOCK (pad);
     return GST_FLOW_NOT_SUPPORTED;
   }
-dropping:
+probe_stopped:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "probe returned %s", gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
+    GST_PAD_STREAM_UNLOCK (pad);
+    return ret;
+  }
+probe_stopped_unref:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "Dropping data after FALSE probe return");
+        "probe returned %s", gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
     GST_PAD_STREAM_UNLOCK (pad);
     gst_buffer_unref (*buffer);
     *buffer = NULL;
-    return GST_FLOW_UNEXPECTED;
+    return ret;
   }
 get_range_failed:
   {
+    GST_PAD_STREAM_UNLOCK (pad);
     *buffer = NULL;
     GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
-        (ret >= GST_FLOW_UNEXPECTED) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
+        (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
         pad, "getrange failed, flow: %s", gst_flow_get_name (ret));
     return ret;
   }
-not_negotiated:
-  {
-    gst_buffer_unref (*buffer);
-    *buffer = NULL;
-    GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
-        "getrange returned buffer of unaccaptable caps");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
 }
 
 /**
@@ -5082,10 +3803,6 @@ gst_pad_get_range (GstPad * pad, guint64 offset, guint size,
  * See gst_pad_get_range() for a list of return values and for the
  * semantics of the arguments of this function.
  *
- * @buffer's caps must either be unset or the same as what is already
- * configured on @pad. Renegotiation within a running pull-mode pipeline is not
- * supported.
- *
  * Returns: a #GstFlowReturn from the peer pad.
  * When this function returns #GST_FLOW_OK, @buffer will contain a valid
  * #GstBuffer that should be freed with gst_buffer_unref() after usage.
@@ -5100,59 +3817,66 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
 {
   GstPad *peer;
   GstFlowReturn ret;
-  gboolean emit_signal;
-  GstCaps *caps;
-  gboolean caps_changed;
 
   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
   GST_OBJECT_LOCK (pad);
+  if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+    goto flushing;
 
-  while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
-    handle_pad_block (pad);
+  /* when one of the probes returns a buffer, probed_data will be called and we
+   * skip calling the peer getrange function */
+  PROBE_PRE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
+      *buffer, offset, size, pre_probe_stopped, probed_data, GST_FLOW_OK);
 
   if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
-    goto not_connected;
-
-  /* signal emision for the pad, peer has chance to emit when
-   * we call _get_range() */
-  emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
+    goto not_linked;
 
   gst_object_ref (peer);
+  pad->priv->using++;
   GST_OBJECT_UNLOCK (pad);
 
   ret = gst_pad_get_range_unchecked (peer, offset, size, buffer);
 
   gst_object_unref (peer);
 
+  GST_OBJECT_LOCK (pad);
+  pad->priv->using--;
+  if (pad->priv->using == 0) {
+    /* pad is not active anymore, trigger idle callbacks */
+    PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE,
+        post_probe_stopped, ret);
+  }
+
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto pull_range_failed;
 
-  /* can only fire the signal if we have a valid buffer */
-  if (G_UNLIKELY (emit_signal)) {
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
-      goto dropping;
-  }
+probed_data:
+  PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
+      *buffer, offset, size, post_probe_stopped);
 
-  GST_OBJECT_LOCK (pad);
-  /* Before pushing the buffer to the peer pad, ensure that caps
-   * are set on this pad */
-  caps = GST_BUFFER_CAPS (*buffer);
-  caps_changed = caps && caps != GST_PAD_CAPS (pad);
   GST_OBJECT_UNLOCK (pad);
 
-  /* we got a new datatype on the pad, see if it can handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
-    if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
-      goto not_negotiated;
-  }
   return ret;
 
   /* ERROR recovery here */
-not_connected:
+flushing:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pullrange, but pad was flushing");
+    GST_OBJECT_UNLOCK (pad);
+    return GST_FLOW_WRONG_STATE;
+  }
+pre_probe_stopped:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pre probe returned %s",
+        gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
+    return ret;
+  }
+not_linked:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
         "pulling range, but it was not linked");
@@ -5162,218 +3886,365 @@ not_connected:
 pull_range_failed:
   {
     *buffer = NULL;
+    GST_OBJECT_UNLOCK (pad);
     GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
-        (ret >= GST_FLOW_UNEXPECTED) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
+        (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
         pad, "pullrange failed, flow: %s", gst_flow_get_name (ret));
     return ret;
   }
-dropping:
+post_probe_stopped:
   {
     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "Dropping data after FALSE probe return");
-    gst_buffer_unref (*buffer);
+        "post probe returned %s", gst_flow_get_name (ret));
+    GST_OBJECT_UNLOCK (pad);
+    if (ret == GST_FLOW_OK)
+      gst_buffer_unref (*buffer);
     *buffer = NULL;
-    return GST_FLOW_UNEXPECTED;
+    return ret;
   }
-not_negotiated:
-  {
-    gst_buffer_unref (*buffer);
-    *buffer = NULL;
-    GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pullrange returned buffer of different caps");
-    return GST_FLOW_NOT_NEGOTIATED;
+}
+
+static gboolean
+gst_pad_store_sticky_event (GstPad * pad, GstEvent * event, gboolean locked)
+{
+  guint i, len;
+  GstEventType type;
+  GArray *events;
+  gboolean res = FALSE;
+  const gchar *name = NULL;
+
+  type = GST_EVENT_TYPE (event);
+  if (type & GST_EVENT_TYPE_STICKY_MULTI)
+    name = gst_structure_get_name (gst_event_get_structure (event));
+
+  events = pad->priv->events;
+  len = events->len;
+
+  for (i = 0; i < len; i++) {
+    PadEvent *ev = &g_array_index (events, PadEvent, i);
+
+    if (ev->event == NULL)
+      continue;
+
+    if (type == GST_EVENT_TYPE (ev->event)) {
+      /* matching types, check matching name if needed */
+      if (name && !gst_event_has_name (ev->event, name))
+        continue;
+
+      /* overwrite */
+      if ((res = gst_event_replace (&ev->event, event)))
+        ev->received = FALSE;
+      break;
+    }
+  }
+  if (i == len) {
+    PadEvent ev;
+    ev.event = gst_event_ref (event);
+    ev.received = FALSE;
+    g_array_append_val (events, ev);
+    res = TRUE;
+  }
+
+  if (res) {
+    pad->priv->events_cookie++;
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+
+    GST_LOG_OBJECT (pad, "stored sticky event %s", GST_EVENT_TYPE_NAME (event));
+
+    switch (GST_EVENT_TYPE (event)) {
+      case GST_EVENT_CAPS:
+        if (locked)
+          GST_OBJECT_UNLOCK (pad);
+
+        GST_DEBUG_OBJECT (pad, "notify caps");
+        g_object_notify_by_pspec ((GObject *) pad, pspec_caps);
+
+        if (locked)
+          GST_OBJECT_LOCK (pad);
+        break;
+      default:
+        break;
+    }
   }
+  return res;
 }
 
-/**
- * gst_pad_push_event:
- * @pad: a #GstPad to push the event to.
- * @event: (transfer full): the #GstEvent to send to the pad.
- *
- * Sends the event to the peer of the given pad. This function is
- * mainly used by elements to send events to their peer
- * elements.
- *
- * This function takes owership of the provided event so you should
- * gst_event_ref() it if you want to reuse the event after this call.
- *
- * Returns: TRUE if the event was handled.
- *
- * MT safe.
- */
-gboolean
-gst_pad_push_event (GstPad * pad, GstEvent * event)
+static GstFlowReturn
+gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
+    GstPadProbeType type, gboolean * stored)
 {
+  GstFlowReturn ret;
   GstPad *peerpad;
-  gboolean result;
+  GstEventType event_type;
+  gboolean sticky;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
-
-  GST_LOG_OBJECT (pad, "event: %s", GST_EVENT_TYPE_NAME (event));
+  sticky = GST_EVENT_IS_STICKY (event);
 
   GST_OBJECT_LOCK (pad);
 
   /* Two checks to be made:
    * . (un)set the FLUSHING flag for flushing events,
    * . handle pad blocking */
-  switch (GST_EVENT_TYPE (event)) {
+  event_type = GST_EVENT_TYPE (event);
+  *stored = FALSE;
+  switch (event_type) {
     case GST_EVENT_FLUSH_START:
-      _priv_gst_pad_invalidate_cache (pad);
       GST_PAD_SET_FLUSHING (pad);
 
-      if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
-        /* flush start will have set the FLUSHING flag and will then
-         * unlock all threads doing a GCond wait on the blocking pad. This
-         * will typically unblock the STREAMING thread blocked on a pad. */
-        GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-start, "
-            "doing block signal.");
-        GST_PAD_BLOCK_BROADCAST (pad);
-        goto flushed;
-      }
+      GST_PAD_BLOCK_BROADCAST (pad);
+      type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
       break;
     case GST_EVENT_FLUSH_STOP:
       GST_PAD_UNSET_FLUSHING (pad);
 
-      /* if we are blocked, flush away the FLUSH_STOP event */
-      if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
-        GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-stop");
-        goto flushed;
-      }
+      /* Remove sticky EOS events */
+      GST_LOG_OBJECT (pad, "Removing pending EOS events");
+      remove_event_by_type (pad, GST_EVENT_EOS);
+
+      type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
       break;
     default:
-      while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) {
-        /* block the event as long as the pad is blocked */
-        if (handle_pad_block (pad) != GST_FLOW_OK)
-          goto flushed;
+    {
+      if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+        goto flushed;
+
+      /* store the event on the pad, but only on srcpads. We always store the
+       * event exactly how it was sent */
+      if (sticky) {
+        /* srcpad sticky events are store immediately, the received flag is set
+         * to FALSE and will be set to TRUE when we can successfully push the
+         * event to the peer pad */
+        if (gst_pad_store_sticky_event (pad, event, TRUE)) {
+          GST_DEBUG_OBJECT (pad, "event %s updated",
+              GST_EVENT_TYPE_NAME (event));
+        }
+        *stored = TRUE;
       }
-      break;
-  }
 
-  if (G_UNLIKELY (GST_EVENT_SRC (event) == NULL)) {
-    GST_LOG_OBJECT (pad, "event had no source, setting pad as event source");
-    GST_EVENT_SRC (event) = gst_object_ref (pad);
+      switch (GST_EVENT_TYPE (event)) {
+        case GST_EVENT_SEGMENT:
+          /* pass the adjusted segment event on. We need to do this even if
+           * there is no peer pad because of the probes. */
+          event = apply_pad_offset (pad, event);
+          break;
+        case GST_EVENT_RECONFIGURE:
+          if (GST_PAD_IS_SINK (pad))
+            GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+          break;
+        default:
+          break;
+      }
+      PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
+          GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
+      break;
+    }
   }
 
-  if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) {
-    GST_OBJECT_UNLOCK (pad);
-
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event)))
-      goto dropping;
+  /* send probes after modifying the events above */
+  PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
 
-    GST_OBJECT_LOCK (pad);
-  }
+  /* now check the peer pad */
   peerpad = GST_PAD_PEER (pad);
   if (peerpad == NULL)
     goto not_linked;
 
-  GST_LOG_OBJECT (pad,
-      "sending event %s (%" GST_PTR_FORMAT ") to peerpad %" GST_PTR_FORMAT,
-      GST_EVENT_TYPE_NAME (event), event, peerpad);
   gst_object_ref (peerpad);
+  pad->priv->using++;
   GST_OBJECT_UNLOCK (pad);
 
-  result = gst_pad_send_event (peerpad, event);
+  GST_LOG_OBJECT (pad, "sending event %p (%s) to peerpad %" GST_PTR_FORMAT,
+      event, GST_EVENT_TYPE_NAME (event), peerpad);
+
+  ret = gst_pad_send_event_unchecked (peerpad, event, type);
+
+  /* Note: we gave away ownership of the event at this point but we can still
+   * print the old pointer */
+  GST_LOG_OBJECT (pad,
+      "sent event %p to peerpad %" GST_PTR_FORMAT ", ret %s", event, peerpad,
+      gst_flow_get_name (ret));
 
-  /* Note: we gave away ownership of the event at this point */
-  GST_LOG_OBJECT (pad, "sent event to peerpad %" GST_PTR_FORMAT ", result %d",
-      peerpad, result);
   gst_object_unref (peerpad);
 
-  return result;
+  GST_OBJECT_LOCK (pad);
+  if (sticky) {
+    if (ret == GST_FLOW_OK) {
+      PadEvent *ev;
+
+      if ((ev = find_event (pad, event)))
+        ev->received = TRUE;
+
+      GST_DEBUG_OBJECT (pad, "event marked received");
+    } else {
+      GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+      GST_DEBUG_OBJECT (pad, "mark pending events");
+    }
+  }
+  pad->priv->using--;
+  if (pad->priv->using == 0) {
+    /* pad is not active anymore, trigger idle callbacks */
+    PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
+        idle_probe_stopped, ret);
+  }
+  GST_OBJECT_UNLOCK (pad);
+
+  return ret;
 
   /* ERROR handling */
-dropping:
+flushed:
   {
-    GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return");
+    GST_DEBUG_OBJECT (pad, "We're flushing");
+    GST_OBJECT_UNLOCK (pad);
     gst_event_unref (event);
-    return FALSE;
+    return GST_FLOW_WRONG_STATE;
+  }
+probe_stopped:
+  {
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
+    GST_OBJECT_UNLOCK (pad);
+    gst_event_unref (event);
+
+    switch (ret) {
+      case GST_FLOW_CUSTOM_SUCCESS:
+        GST_DEBUG_OBJECT (pad, "dropped event");
+        ret = GST_FLOW_OK;
+        break;
+      default:
+        GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+        break;
+    }
+    return ret;
   }
 not_linked:
   {
     GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
-    gst_event_unref (event);
+    GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
     GST_OBJECT_UNLOCK (pad);
-    return FALSE;
+    gst_event_unref (event);
+    return sticky ? GST_FLOW_OK : GST_FLOW_NOT_LINKED;
   }
-flushed:
+idle_probe_stopped:
   {
-    GST_DEBUG_OBJECT (pad,
-        "Not forwarding event since we're flushing and blocking");
-    gst_event_unref (event);
+    GST_DEBUG_OBJECT (pad, "Idle probe returned %s", gst_flow_get_name (ret));
     GST_OBJECT_UNLOCK (pad);
-    return TRUE;
+    return ret;
   }
 }
 
 /**
- * gst_pad_send_event:
- * @pad: a #GstPad to send the event to.
+ * gst_pad_push_event:
+ * @pad: a #GstPad to push the event to.
  * @event: (transfer full): the #GstEvent to send to the pad.
  *
- * Sends the event to the pad. This function can be used
- * by applications to send events in the pipeline.
- *
- * If @pad is a source pad, @event should be an upstream event. If @pad is a
- * sink pad, @event should be a downstream event. For example, you would not
- * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream.
- * Furthermore, some downstream events have to be serialized with data flow,
- * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If
- * the event needs to be serialized with data flow, this function will take the
- * pad's stream lock while calling its event function.
- *
- * To find out whether an event type is upstream, downstream, or downstream and
- * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(),
- * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and
- * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or
- * plugin doesn't need to bother itself with this information; the core handles
- * all necessary locks and checks.
+ * Sends the event to the peer of the given pad. This function is
+ * mainly used by elements to send events to their peer
+ * elements.
  *
  * This function takes owership of the provided event so you should
  * gst_event_ref() it if you want to reuse the event after this call.
  *
  * Returns: TRUE if the event was handled.
+ *
+ * MT safe.
  */
 gboolean
-gst_pad_send_event (GstPad * pad, GstEvent * event)
+gst_pad_push_event (GstPad * pad, GstEvent * event)
 {
-  gboolean result = FALSE;
-  GstPadEventFunction eventfunc;
-  gboolean serialized, need_unlock = FALSE;
+  gboolean res;
+  GstPadProbeType type;
+  gboolean stored;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
 
-  GST_OBJECT_LOCK (pad);
-  if (GST_PAD_IS_SINK (pad)) {
+  if (GST_PAD_IS_SRC (pad)) {
     if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
       goto wrong_direction;
-    serialized = GST_EVENT_IS_SERIALIZED (event);
-  } else if (GST_PAD_IS_SRC (pad)) {
+    type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
+  } else if (GST_PAD_IS_SINK (pad)) {
     if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
       goto wrong_direction;
-    /* events on srcpad never are serialized */
-    serialized = FALSE;
+    /* events pushed on sinkpad never are sticky */
+    type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
   } else
     goto unknown_direction;
 
-  if (G_UNLIKELY (GST_EVENT_SRC (event) == NULL)) {
-    GST_LOG_OBJECT (pad, "event had no source, setting pad as event source");
-    GST_EVENT_SRC (event) = gst_object_ref (pad);
+  if (gst_pad_push_event_unchecked (pad, event, type, &stored) != GST_FLOW_OK)
+    res = stored ? TRUE : FALSE;
+  else
+    res = TRUE;
+
+  return res;
+
+  /* ERROR handling */
+wrong_direction:
+  {
+    g_warning ("pad %s:%s pushing %s event in wrong direction",
+        GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
+    gst_event_unref (event);
+    return FALSE;
+  }
+unknown_direction:
+  {
+    g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
+    gst_event_unref (event);
+    return FALSE;
   }
+}
 
-  /* pad signals */
-  if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) {
-    GST_OBJECT_UNLOCK (pad);
+/* Check if we can call the event function with the given event */
+static GstFlowReturn
+pre_eventfunc_check (GstPad * pad, GstEvent * event)
+{
+  GstCaps *caps, *templ;
 
-    if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (event)))
-      goto dropping;
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      /* backwards compatibility mode for caps */
+      gst_event_parse_caps (event, &caps);
 
-    GST_OBJECT_LOCK (pad);
+      /* See if pad accepts the caps */
+      templ = gst_pad_get_pad_template_caps (pad);
+      if (!gst_caps_is_subset (caps, templ))
+        goto not_accepted;
+
+      gst_caps_unref (templ);
+      break;
+    }
+    default:
+      break;
   }
+  return GST_FLOW_OK;
 
-  switch (GST_EVENT_TYPE (event)) {
+  /* ERRORS */
+not_accepted:
+  {
+    gst_caps_unref (templ);
+    GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+        "caps %" GST_PTR_FORMAT " not accepted", caps);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+}
+
+static GstFlowReturn
+gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
+    GstPadProbeType type)
+{
+  GstFlowReturn ret;
+  GstEventType event_type;
+  gboolean serialized, need_unlock = FALSE, sticky;
+  GstPadEventFunction eventfunc;
+  GstObject *parent;
+
+  GST_OBJECT_LOCK (pad);
+  if (GST_PAD_IS_SINK (pad))
+    serialized = GST_EVENT_IS_SERIALIZED (event);
+  else
+    serialized = FALSE;
+  sticky = GST_EVENT_IS_STICKY (event);
+  event_type = GST_EVENT_TYPE (event);
+  switch (event_type) {
     case GST_EVENT_FLUSH_START:
       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
           "have event type %d (FLUSH_START)", GST_EVENT_TYPE (event));
@@ -5382,27 +4253,33 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
       if (GST_PAD_IS_FLUSHING (pad))
         goto flushing;
 
-      _priv_gst_pad_invalidate_cache (pad);
       GST_PAD_SET_FLUSHING (pad);
       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "set flush flag");
       break;
     case GST_EVENT_FLUSH_STOP:
-      if (G_LIKELY (GST_PAD_ACTIVATE_MODE (pad) != GST_ACTIVATE_NONE)) {
+      if (G_LIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_NONE)) {
         GST_PAD_UNSET_FLUSHING (pad);
         GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "cleared flush flag");
       }
+      /* Remove pending EOS events */
+      GST_LOG_OBJECT (pad, "Removing pending EOS events");
+      remove_event_by_type (pad, GST_EVENT_EOS);
+
       GST_OBJECT_UNLOCK (pad);
       /* grab stream lock */
       GST_PAD_STREAM_LOCK (pad);
       need_unlock = TRUE;
       GST_OBJECT_LOCK (pad);
+      if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
+        goto flushing;
       break;
+    case GST_EVENT_RECONFIGURE:
+      if (GST_PAD_IS_SRC (pad))
+        GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
     default:
       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "have event type %s",
           GST_EVENT_TYPE_NAME (event));
 
-      /* make this a little faster, no point in grabbing the lock
-       * if the pad is already flushing. */
       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
         goto flushing;
 
@@ -5415,37 +4292,96 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
         if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
           goto flushing;
       }
+
+      switch (GST_EVENT_TYPE (event)) {
+        case GST_EVENT_SEGMENT:
+          event = apply_pad_offset (pad, event);
+          break;
+        default:
+          break;
+      }
+
+      /* now do the probe */
+      PROBE_PUSH (pad,
+          type | GST_PAD_PROBE_TYPE_PUSH |
+          GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
+
+      PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
       break;
   }
+
   if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
     goto no_function;
 
+  ACQUIRE_PARENT (pad, parent, no_parent);
   GST_OBJECT_UNLOCK (pad);
 
-  result = eventfunc (pad, event);
+  ret = pre_eventfunc_check (pad, event);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto precheck_failed;
+
+  if (sticky)
+    gst_event_ref (event);
+
+  if (eventfunc (pad, parent, event)) {
+    ret = GST_FLOW_OK;
+  } else {
+    /* something went wrong */
+    switch (event_type) {
+      case GST_EVENT_CAPS:
+        ret = GST_FLOW_NOT_NEGOTIATED;
+        break;
+      default:
+        ret = GST_FLOW_ERROR;
+        break;
+    }
+  }
+  RELEASE_PARENT (parent);
+
+  GST_DEBUG_OBJECT (pad, "sent event, ret %s", gst_flow_get_name (ret));
+
+  if (sticky) {
+    if (ret == GST_FLOW_OK) {
+      /* after the event function accepted the event, we can store the sticky
+       * event on the pad */
+      gst_pad_store_sticky_event (pad, event, FALSE);
+    }
+    gst_event_unref (event);
+  }
 
   if (need_unlock)
     GST_PAD_STREAM_UNLOCK (pad);
 
-  GST_DEBUG_OBJECT (pad, "sent event, result %d", result);
-
-  return result;
+  return ret;
 
   /* ERROR handling */
-wrong_direction:
+flushing:
   {
-    g_warning ("pad %s:%s sending %s event in wrong direction",
-        GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
     GST_OBJECT_UNLOCK (pad);
+    if (need_unlock)
+      GST_PAD_STREAM_UNLOCK (pad);
+    GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
+        "Received event on flushing pad. Discarding");
     gst_event_unref (event);
-    return FALSE;
+    return GST_FLOW_WRONG_STATE;
   }
-unknown_direction:
+probe_stopped:
   {
-    g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
     GST_OBJECT_UNLOCK (pad);
+    if (need_unlock)
+      GST_PAD_STREAM_UNLOCK (pad);
     gst_event_unref (event);
-    return FALSE;
+
+    switch (ret) {
+      case GST_FLOW_CUSTOM_SUCCESS:
+        GST_DEBUG_OBJECT (pad, "dropped event");
+        ret = GST_FLOW_OK;
+        break;
+      default:
+        GST_DEBUG_OBJECT (pad, "en error occured %s", gst_flow_get_name (ret));
+        break;
+    }
+    return ret;
   }
 no_function:
   {
@@ -5455,21 +4391,94 @@ no_function:
     if (need_unlock)
       GST_PAD_STREAM_UNLOCK (pad);
     gst_event_unref (event);
-    return FALSE;
+    return GST_FLOW_NOT_SUPPORTED;
   }
-flushing:
+no_parent:
   {
+    GST_DEBUG_OBJECT (pad, "no parent");
     GST_OBJECT_UNLOCK (pad);
     if (need_unlock)
       GST_PAD_STREAM_UNLOCK (pad);
-    GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
-        "Received event on flushing pad. Discarding");
+    gst_event_unref (event);
+    return GST_FLOW_WRONG_STATE;
+  }
+precheck_failed:
+  {
+    GST_DEBUG_OBJECT (pad, "pre event check failed");
+    RELEASE_PARENT (parent);
+    if (need_unlock)
+      GST_PAD_STREAM_UNLOCK (pad);
+    gst_event_unref (event);
+    return ret;
+  }
+}
+
+/**
+ * gst_pad_send_event:
+ * @pad: a #GstPad to send the event to.
+ * @event: (transfer full): the #GstEvent to send to the pad.
+ *
+ * Sends the event to the pad. This function can be used
+ * by applications to send events in the pipeline.
+ *
+ * If @pad is a source pad, @event should be an upstream event. If @pad is a
+ * sink pad, @event should be a downstream event. For example, you would not
+ * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream.
+ * Furthermore, some downstream events have to be serialized with data flow,
+ * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If
+ * the event needs to be serialized with data flow, this function will take the
+ * pad's stream lock while calling its event function.
+ *
+ * To find out whether an event type is upstream, downstream, or downstream and
+ * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(),
+ * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and
+ * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or
+ * plugin doesn't need to bother itself with this information; the core handles
+ * all necessary locks and checks.
+ *
+ * This function takes owership of the provided event so you should
+ * gst_event_ref() it if you want to reuse the event after this call.
+ *
+ * Returns: TRUE if the event was handled.
+ */
+gboolean
+gst_pad_send_event (GstPad * pad, GstEvent * event)
+{
+  gboolean result;
+  GstPadProbeType type;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (GST_PAD_IS_SINK (pad)) {
+    if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
+      goto wrong_direction;
+    type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
+  } else if (GST_PAD_IS_SRC (pad)) {
+    if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
+      goto wrong_direction;
+    type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
+  } else
+    goto unknown_direction;
+
+  if (gst_pad_send_event_unchecked (pad, event, type) != GST_FLOW_OK)
+    result = FALSE;
+  else
+    result = TRUE;
+
+  return result;
+
+  /* ERROR handling */
+wrong_direction:
+  {
+    g_warning ("pad %s:%s sending %s event in wrong direction",
+        GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
     gst_event_unref (event);
     return FALSE;
   }
-dropping:
+unknown_direction:
   {
-    GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return");
+    g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
     gst_event_unref (event);
     return FALSE;
   }
@@ -5505,6 +4514,84 @@ gst_pad_get_element_private (GstPad * pad)
   return pad->element_private;
 }
 
+/**
+ * gst_pad_get_sticky_event:
+ * @pad: the #GstPad to get the event from.
+ * @event_type: the #GstEventType that should be retrieved.
+ * @idx: the index of the event
+ *
+ * Returns a new reference of the sticky event of type @event_type
+ * from the event.
+ *
+ * Returns: (transfer full): a #GstEvent of type @event_type or NULL when no
+ * event of @event_type was on @pad. Unref after usage.
+ */
+GstEvent *
+gst_pad_get_sticky_event (GstPad * pad, GstEventType event_type, guint idx)
+{
+  GstEvent *event = NULL;
+  PadEvent *ev;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail ((event_type & GST_EVENT_TYPE_STICKY) != 0, NULL);
+
+  GST_OBJECT_LOCK (pad);
+  ev = find_event_by_type (pad, event_type, idx);
+  if (ev && (event = ev->event))
+    gst_event_ref (event);
+  GST_OBJECT_UNLOCK (pad);
+
+  return event;
+}
+
+typedef struct
+{
+  GstPadStickyEventsForeachFunction func;
+  gpointer user_data;
+} ForeachDispatch;
+
+static gboolean
+foreach_dispatch_function (GstPad * pad, PadEvent * ev, gpointer user_data)
+{
+  ForeachDispatch *data = user_data;
+  gboolean ret;
+
+  GST_OBJECT_UNLOCK (pad);
+
+  ret = data->func (pad, &ev->event, data->user_data);
+
+  GST_OBJECT_LOCK (pad);
+
+  return ret;
+}
+
+/**
+ * gst_pad_sticky_events_foreach:
+ * @pad: the #GstPad that should be used for iteration.
+ * @foreach_func: (scope call): the #GstPadStickyEventsForeachFunction that
+ *                should be called for every event.
+ * @user_data: (closure): the optional user data.
+ *
+ * Iterates all sticky events on @pad and calls @foreach_func for every
+ * event. If @foreach_func returns %FALSE the iteration is immediately stopped.
+ */
+void
+gst_pad_sticky_events_foreach (GstPad * pad,
+    GstPadStickyEventsForeachFunction foreach_func, gpointer user_data)
+{
+  ForeachDispatch data;
+
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (foreach_func != NULL);
+
+  data.func = foreach_func;
+  data.user_data = user_data;
+
+  GST_OBJECT_LOCK (pad);
+  events_foreach (pad, foreach_dispatch_function, &data);
+  GST_OBJECT_UNLOCK (pad);
+}
+
 static void
 do_stream_status (GstPad * pad, GstStreamStatusType type,
     GThread * thread, GstTask * task)
@@ -5593,7 +4680,7 @@ gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data)
   GST_OBJECT_LOCK (pad);
   task = GST_PAD_TASK (pad);
   if (task == NULL) {
-    task = gst_task_create (func, data);
+    task = gst_task_new (func, data);
     gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad));
     gst_task_set_thread_callbacks (task, &thr_callbacks, pad, NULL);
     GST_DEBUG_OBJECT (pad, "created task");
index 8990fdc..93c4970 100644 (file)
 
 #include <gst/gstconfig.h>
 
+typedef struct _GstPad GstPad;
+typedef struct _GstPadPrivate GstPadPrivate;
+typedef struct _GstPadClass GstPadClass;
+
+/**
+ * GstPadDirection:
+ * @GST_PAD_UNKNOWN: direction is unknown.
+ * @GST_PAD_SRC: the pad is a source pad.
+ * @GST_PAD_SINK: the pad is a sink pad.
+ *
+ * The direction of a pad.
+ */
+typedef enum {
+  GST_PAD_UNKNOWN,
+  GST_PAD_SRC,
+  GST_PAD_SINK
+} GstPadDirection;
+
+/**
+ * GstPadMode:
+ * @GST_PAD_MODE_NONE: Pad will not handle dataflow
+ * @GST_PAD_MODE_PUSH: Pad handles dataflow in downstream push mode
+ * @GST_PAD_MODE_PULL: Pad handles dataflow in upstream pull mode
+ *
+ * The status of a GstPad. After activating a pad, which usually happens when the
+ * parent element goes from READY to PAUSED, the GstPadMode defines if the
+ * pad operates in push or pull mode.
+ */
+typedef enum {
+  GST_PAD_MODE_NONE,
+  GST_PAD_MODE_PUSH,
+  GST_PAD_MODE_PULL
+} GstPadMode;
+
 #include <gst/gstobject.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstbufferlist.h>
 #include <gst/gstcaps.h>
+#include <gst/gstpadtemplate.h>
 #include <gst/gstevent.h>
 #include <gst/gstquery.h>
 #include <gst/gsttask.h>
@@ -47,9 +82,6 @@ G_BEGIN_DECLS
 #define GST_PAD_CAST(obj)              ((GstPad*)(obj))
 
 
-typedef struct _GstPad GstPad;
-typedef struct _GstPadPrivate GstPadPrivate;
-typedef struct _GstPadClass GstPadClass;
 
 /**
  * GstPadLinkReturn:
@@ -93,12 +125,10 @@ typedef enum {
 
 /**
  * GstFlowReturn:
- * @GST_FLOW_RESEND:            Resend buffer, possibly with new caps (not
- *                                 sent yet) (unused/unimplemented).
  * @GST_FLOW_OK:                Data passing was ok.
  * @GST_FLOW_NOT_LINKED:        Pad is not linked.
  * @GST_FLOW_WRONG_STATE:       Pad is in wrong state.
- * @GST_FLOW_UNEXPECTED:        Did not expect anything, like after EOS.
+ * @GST_FLOW_EOS:                Pad is EOS.
  * @GST_FLOW_NOT_NEGOTIATED:    Pad is not negotiated.
  * @GST_FLOW_ERROR:             Some (fatal) error occured. Element generating
  *                               this error should post an error message with more
@@ -132,13 +162,12 @@ typedef enum {
   GST_FLOW_CUSTOM_SUCCESS = 100,
 
   /* core predefined */
-  GST_FLOW_RESEND        =  1,
   GST_FLOW_OK            =  0,
   /* expected failures */
   GST_FLOW_NOT_LINKED     = -1,
   GST_FLOW_WRONG_STATE    = -2,
   /* error cases */
-  GST_FLOW_UNEXPECTED     = -3,
+  GST_FLOW_EOS            = -3,
   GST_FLOW_NOT_NEGOTIATED = -4,
   GST_FLOW_ERROR         = -5,
   GST_FLOW_NOT_SUPPORTED  = -6,
@@ -149,41 +178,6 @@ typedef enum {
   GST_FLOW_CUSTOM_ERROR_2 = -102
 } GstFlowReturn;
 
-/**
- * GST_FLOW_IS_FATAL:
- * @ret: a #GstFlowReturn value
- *
- * Macro to test if the given #GstFlowReturn value indicates a fatal
- * error. This macro is mainly used in elements driving the pipeline to decide
- * whether an error message should be posted on the bus. Note that such
- * elements may also need to post an error message in the #GST_FLOW_NOT_LINKED
- * case which is not caught by this macro.
- *
- * Deprecated: This macro is badly named and can't be used in any real
- * scenarios without additional checks.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_FLOW_IS_FATAL(ret) ((ret) <= GST_FLOW_UNEXPECTED)
-#endif
-
-/**
- * GST_FLOW_IS_SUCCESS:
- * @ret: a #GstFlowReturn value
- *
- * Macro to test if the given #GstFlowReturn value indicates a
- * successful result
- * This macro is mainly used in elements to decide if the processing
- * of a buffer was successful.
- *
- * Since: 0.10.7
- *
- * Deprecated: This macro is badly named and can't be used in any real
- * scenarios without additional checks.
- */
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_FLOW_IS_SUCCESS(ret) ((ret) >= GST_FLOW_OK)
-#endif
-
 const gchar*           gst_flow_get_name       (GstFlowReturn ret);
 GQuark                 gst_flow_to_quark       (GstFlowReturn ret);
 
@@ -197,7 +191,7 @@ GQuark                      gst_flow_to_quark       (GstFlowReturn ret);
  *   their template caps. This is much faster than @GST_PAD_LINK_CHECK_CAPS, but
  *   would be unsafe e.g. if one pad has %GST_CAPS_ANY.
  * @GST_PAD_LINK_CHECK_CAPS: Check if the pads are compatible by comparing the
- *   caps returned by gst_pad_get_caps().
+ *   caps returned by gst_pad_query_caps().
  *
  * The amount of checking to be done when linking pads. @GST_PAD_LINK_CHECK_CAPS
  * and @GST_PAD_LINK_CHECK_TEMPLATE_CAPS are mutually exclusive. If both are
@@ -230,35 +224,11 @@ typedef enum {
  */
 #define GST_PAD_LINK_CHECK_DEFAULT ((GstPadLinkCheck) (GST_PAD_LINK_CHECK_HIERARCHY | GST_PAD_LINK_CHECK_CAPS))
 
-/**
- * GstActivateMode:
- * @GST_ACTIVATE_NONE:          Pad will not handle dataflow
- * @GST_ACTIVATE_PUSH:          Pad handles dataflow in downstream push mode
- * @GST_ACTIVATE_PULL:          Pad handles dataflow in upstream pull mode
- *
- * The status of a GstPad. After activating a pad, which usually happens when the
- * parent element goes from READY to PAUSED, the GstActivateMode defines if the
- * pad operates in push or pull mode.
- */
-typedef enum {
-  GST_ACTIVATE_NONE,
-  GST_ACTIVATE_PUSH,
-  GST_ACTIVATE_PULL
-} GstActivateMode;
-
-/**
- * GST_PAD_MODE_ACTIVATE:
- * @mode: a #GstActivateMode
- *
- * Macro to test if the given #GstActivateMode value indicates that datapassing
- * is possible or not.
- */
-#define GST_PAD_MODE_ACTIVATE(mode) ((mode) != GST_ACTIVATE_NONE)
-
 /* pad states */
 /**
  * GstPadActivateFunction:
  * @pad: a #GstPad
+ * @parent: the parent of @pad
  *
  * This function is called when the pad is activated during the element
  * READY to PAUSED state change. By default this function will call the
@@ -267,23 +237,29 @@ typedef enum {
  *
  * Returns: TRUE if the pad could be activated.
  */
-typedef gboolean               (*GstPadActivateFunction)       (GstPad *pad);
+typedef gboolean               (*GstPadActivateFunction)       (GstPad *pad, GstObject *parent);
 /**
  * GstPadActivateModeFunction:
  * @pad: a #GstPad
+ * @parent: the parent of @pad
+ * @mode: the requested activation mode of @pad
  * @active: activate or deactivate the pad.
  *
  * The prototype of the push and pull activate functions.
  *
  * Returns: TRUE if the pad could be activated or deactivated.
  */
-typedef gboolean               (*GstPadActivateModeFunction)   (GstPad *pad, gboolean active);
+typedef gboolean               (*GstPadActivateModeFunction)   (GstPad *pad, GstObject *parent,
+                                                                 GstPadMode mode, gboolean active);
 
 
 /* data passing */
 /**
  * GstPadChainFunction:
  * @pad: the sink #GstPad that performed the chain.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  * @buffer: the #GstBuffer that is chained, not %NULL.
  *
  * A function that will be called on sinkpads when chaining buffers.
@@ -298,11 +274,15 @@ typedef gboolean          (*GstPadActivateModeFunction)   (GstPad *pad, gboolean active);
  *
  * Returns: #GST_FLOW_OK for success
  */
-typedef GstFlowReturn          (*GstPadChainFunction)          (GstPad *pad, GstBuffer *buffer);
+typedef GstFlowReturn          (*GstPadChainFunction)          (GstPad *pad, GstObject *parent,
+                                                                 GstBuffer *buffer);
 
 /**
  * GstPadChainListFunction:
  * @pad: the sink #GstPad that performed the chain.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  * @list: the #GstBufferList that is chained, not %NULL.
  *
  * A function that will be called on sinkpads when chaining buffer lists.
@@ -317,11 +297,15 @@ typedef GstFlowReturn             (*GstPadChainFunction)          (GstPad *pad, GstBuffer *buffer);
  *
  * Returns: #GST_FLOW_OK for success
  */
-typedef GstFlowReturn          (*GstPadChainListFunction)      (GstPad *pad, GstBufferList *list);
+typedef GstFlowReturn          (*GstPadChainListFunction)      (GstPad *pad, GstObject *parent,
+                                                                 GstBufferList *list);
 
 /**
  * GstPadGetRangeFunction:
  * @pad: the src #GstPad to perform the getrange on.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  * @offset: the offset of the range
  * @length: the length of the range
  * @buffer: a memory location to hold the result buffer, cannot be NULL.
@@ -362,57 +346,33 @@ typedef GstFlowReturn             (*GstPadChainListFunction)      (GstPad *pad, GstBufferList *l
  * Returns: #GST_FLOW_OK for success and a valid buffer in @buffer. Any other
  * return value leaves @buffer undefined.
  */
-typedef GstFlowReturn          (*GstPadGetRangeFunction)       (GstPad *pad, guint64 offset,
-                                                                guint length, GstBuffer **buffer);
+typedef GstFlowReturn          (*GstPadGetRangeFunction)       (GstPad *pad, GstObject *parent,
+                                                                 guint64 offset, guint length,
+                                                                 GstBuffer **buffer);
 
 /**
  * GstPadEventFunction:
  * @pad: the #GstPad to handle the event.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  * @event: the #GstEvent to handle.
  *
  * Function signature to handle an event for the pad.
  *
  * Returns: TRUE if the pad could handle the event.
  */
-typedef gboolean               (*GstPadEventFunction)          (GstPad *pad, GstEvent *event);
-
+typedef gboolean               (*GstPadEventFunction)          (GstPad *pad, GstObject *parent,
+                                                                 GstEvent *event);
 
-/* FIXME: 0.11: deprecate me, check range should use seeking query */
-/**
- * GstPadCheckGetRangeFunction:
- * @pad: a #GstPad
- *
- * Check if @pad can be activated in pull mode.
- *
- * This function will be deprecated after 0.10; use the seeking query to check
- * if a pad can support random access.
- *
- * Returns: TRUE if the pad can operate in pull mode.
- */
-typedef gboolean               (*GstPadCheckGetRangeFunction)  (GstPad *pad);
 
 /* internal links */
 /**
- * GstPadIntLinkFunction:
- * @pad: The #GstPad to query.
- *
- * The signature of the internal pad link function.
- *
- * Returns: (element-type Gst.Pad) (transfer container): a newly allocated #GList of pads that are linked to the given pad on
- * the inside of the parent element.
- *
- * The caller must call g_list_free() on it after use.
- *
- * Deprecated: use the threadsafe #GstPadIterIntLinkFunction instead.
- */
-#ifndef GST_DISABLE_DEPRECATED
-typedef GList*                 (*GstPadIntLinkFunction)        (GstPad *pad);
-#endif
-
-
-/**
  * GstPadIterIntLinkFunction:
  * @pad: The #GstPad to query.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  *
  * The signature of the internal pad link iterator function.
  *
@@ -423,29 +383,23 @@ typedef GList*                    (*GstPadIntLinkFunction)        (GstPad *pad);
  *
  * Since 0.10.21
  */
-typedef GstIterator*           (*GstPadIterIntLinkFunction)    (GstPad *pad);
+typedef GstIterator*           (*GstPadIterIntLinkFunction)    (GstPad *pad, GstObject *parent);
 
 /* generic query function */
 /**
- * GstPadQueryTypeFunction:
- * @pad: a #GstPad to query
- *
- * The signature of the query types function.
- *
- * Returns: a constant array of query types
- */
-typedef const GstQueryType*    (*GstPadQueryTypeFunction)      (GstPad *pad);
-
-/**
  * GstPadQueryFunction:
  * @pad: the #GstPad to query.
+ * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set,
+ *          @parent is guaranteed to be not-NULL and remain valid during the
+ *          execution of this function.
  * @query: the #GstQuery object to execute
  *
  * The signature of the query function.
  *
  * Returns: TRUE if the query could be performed.
  */
-typedef gboolean               (*GstPadQueryFunction)          (GstPad *pad, GstQuery *query);
+typedef gboolean               (*GstPadQueryFunction)          (GstPad *pad, GstObject *parent,
+                                                                 GstQuery *query);
 
 
 /* linking */
@@ -468,279 +422,267 @@ typedef GstPadLinkReturn        (*GstPadLinkFunction)           (GstPad *pad, GstPad *peer);
 typedef void                   (*GstPadUnlinkFunction)         (GstPad *pad);
 
 
-/* caps nego */
+/* misc */
 /**
- * GstPadGetCapsFunction:
- * @pad: the #GstPad to get the capabilities of.
+ * GstPadForwardFunction:
+ * @pad: the #GstPad that is forwarded.
+ * @user_data: the gpointer to optional user data.
  *
- * Returns a copy of the capabilities of the specified pad. By default this
- * function will return the pad template capabilities, but can optionally
- * be overridden by elements.
+ * A forward function is called for all internally linked pads, see
+ * gst_pad_forward().
  *
- * Returns: a newly allocated copy #GstCaps of the pad.
+ * Returns: TRUE if the dispatching procedure has to be stopped.
  */
-typedef GstCaps*               (*GstPadGetCapsFunction)        (GstPad *pad);
+typedef gboolean               (*GstPadForwardFunction)        (GstPad *pad, gpointer user_data);
+
+/**
+ * GstPadProbeType:
+ * @GST_PAD_PROBE_TYPE_INVALID: invalid probe type
+ * @GST_PAD_PROBE_TYPE_IDLE: probe idle pads and block
+ * @GST_PAD_PROBE_TYPE_BLOCK: probe and block pads
+ * @GST_PAD_PROBE_TYPE_BUFFER: probe buffers
+ * @GST_PAD_PROBE_TYPE_BUFFER_LIST: probe buffer lists
+ * @GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM: probe downstream events
+ * @GST_PAD_PROBE_TYPE_EVENT_UPSTREAM: probe upstream events
+ * @GST_PAD_PROBE_TYPE_EVENT_FLUSH: probe flush events. This probe has to be
+ *     explicitly enabled and is not included in the
+ *     @@GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM or
+ *     @@GST_PAD_PROBE_TYPE_EVENT_UPSTREAM probe types.
+ * @GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM: probe downstream queries
+ * @GST_PAD_PROBE_TYPE_QUERY_UPSTREAM: probe upstream queries
+ * @GST_PAD_PROBE_TYPE_PUSH: probe push
+ * @GST_PAD_PROBE_TYPE_PULL: probe pull
+ *
+ * The different probing types that can occur. When either one of
+ * @GST_PAD_PROBE_TYPE_IDLE or @GST_PAD_PROBE_TYPE_BLOCK is used, the probe will be a
+ * blocking probe.
+ */
+typedef enum
+{
+  GST_PAD_PROBE_TYPE_INVALID          = 0,
+  /* flags to control blocking */
+  GST_PAD_PROBE_TYPE_IDLE             = (1 << 0),
+  GST_PAD_PROBE_TYPE_BLOCK            = (1 << 1),
+  /* flags to select datatypes */
+  GST_PAD_PROBE_TYPE_BUFFER           = (1 << 4),
+  GST_PAD_PROBE_TYPE_BUFFER_LIST      = (1 << 5),
+  GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM = (1 << 6),
+  GST_PAD_PROBE_TYPE_EVENT_UPSTREAM   = (1 << 7),
+  GST_PAD_PROBE_TYPE_EVENT_FLUSH      = (1 << 8),
+  GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM = (1 << 9),
+  GST_PAD_PROBE_TYPE_QUERY_UPSTREAM   = (1 << 10),
+  /* flags to select scheduling mode */
+  GST_PAD_PROBE_TYPE_PUSH             = (1 << 12),
+  GST_PAD_PROBE_TYPE_PULL             = (1 << 13)
+} GstPadProbeType;
+
+#define GST_PAD_PROBE_TYPE_BLOCKING         (GST_PAD_PROBE_TYPE_IDLE | GST_PAD_PROBE_TYPE_BLOCK)
+#define GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM (GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM)
+#define GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM   (GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_DATA_UPSTREAM)
+#define GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM  (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST | \
+                                             GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)
+#define GST_PAD_PROBE_TYPE_DATA_UPSTREAM    (GST_PAD_PROBE_TYPE_EVENT_UPSTREAM)
+#define GST_PAD_PROBE_TYPE_DATA_BOTH        (GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM | \
+                                             GST_PAD_PROBE_TYPE_DATA_UPSTREAM)
+#define GST_PAD_PROBE_TYPE_EVENT_BOTH       (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | \
+                                             GST_PAD_PROBE_TYPE_EVENT_UPSTREAM)
+#define GST_PAD_PROBE_TYPE_QUERY_BOTH       (GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM | \
+                                             GST_PAD_PROBE_TYPE_QUERY_UPSTREAM)
+#define GST_PAD_PROBE_TYPE_ALL_BOTH         (GST_PAD_PROBE_TYPE_DATA_BOTH | \
+                                             GST_PAD_PROBE_TYPE_QUERY_BOTH)
+#define GST_PAD_PROBE_TYPE_SCHEDULING       (GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_PULL)
+
+/**
+ * GstPadProbeReturn:
+ * @GST_PAD_PROBE_OK: normal probe return value
+ * @GST_PAD_PROBE_DROP: drop data in data probes
+ * @GST_PAD_PROBE_REMOVE: remove probe
+ * @GST_PAD_PROBE_PASS: pass the data item in the block probe and block on
+ *                         the next item
+ *
+ * Different return values for the #GstPadProbeCallback.
+ */
+typedef enum
+{
+  GST_PAD_PROBE_DROP,
+  GST_PAD_PROBE_OK,
+  GST_PAD_PROBE_REMOVE,
+  GST_PAD_PROBE_PASS,
+} GstPadProbeReturn;
+
+
+/**
+ * GstPadProbeInfo:
+ * @type: the current probe type
+ * @data: type specific data, check the @type field to know the datatype.
+ *    This field can be NULL.
+ * @offset: offset of pull probe, this field is valid when @type contains
+ *    #GST_PAD_PROBE_TYPE_PULL
+ * @size: size of pull probe, this field is valid when @type contains
+ *    #GST_PAD_PROBE_TYPE_PULL
+ *
+ * Info passed in the #GstPadProbeCallback.
+ */
+typedef struct
+{
+  GstPadProbeType type;
+  gpointer data;
+  guint64 offset;
+  guint size;
+
+  gpointer _gst_reserved[GST_PADDING];
+} GstPadProbeInfo;
+
+#define GST_PAD_PROBE_INFO_TYPE(d)         ((d)->type)
+#define GST_PAD_PROBE_INFO_DATA(d)         ((d)->data)
+
+#define GST_PAD_PROBE_INFO_BUFFER(d)       GST_BUFFER_CAST(GST_PAD_PROBE_INFO_DATA(d))
+#define GST_PAD_PROBE_INFO_BUFFER_LIST(d)  GST_BUFFER_LIST_CAST(GST_PAD_PROBE_INFO_DATA(d))
+#define GST_PAD_PROBE_INFO_EVENT(d)        GST_EVENT_CAST(GST_PAD_PROBE_INFO_DATA(d))
+#define GST_PAD_PROBE_INFO_QUERY(d)        GST_QUERY_CAST(GST_PAD_PROBE_INFO_DATA(d))
+
+#define GST_PAD_PROBE_INFO_OFFSET(d)       ((d)->offset)
+#define GST_PAD_PROBE_INFO_SIZE(d)         ((d)->size)
 
 /**
- * GstPadSetCapsFunction:
- * @pad: the #GstPad to set the capabilities of.
- * @caps: the #GstCaps to set
- *
- * Set @caps on @pad. By default this function updates the caps of the
- * pad but the function can be overriden by elements to perform extra
- * actions or verifications.
- *
- * Returns: TRUE if the caps could be set on the pad.
- */
-typedef gboolean               (*GstPadSetCapsFunction)        (GstPad *pad, GstCaps *caps);
-/**
- * GstPadAcceptCapsFunction:
- * @pad: the #GstPad to check
- * @caps: the #GstCaps to check
+ * GstPadProbeCallback
+ * @pad: the #GstPad that is blocked
+ * @info: #GstPadProbeInfo
+ * @user_data: the gpointer to optional user data.
  *
- * Check if @pad can accept @caps. By default this function will see if @caps
- * intersect with the result from gst_pad_get_caps() by can be overridden to
- * perform extra checks.
+ * Callback used by gst_pad_add_probe(). Gets called to notify about the current
+ * blocking type.
  *
- * Returns: TRUE if the caps can be accepted by the pad.
+ * The callback is allowed to modify the data pointer in @info.
  */
-typedef gboolean               (*GstPadAcceptCapsFunction)     (GstPad *pad, GstCaps *caps);
-/**
- * GstPadFixateCapsFunction:
- * @pad: a #GstPad
- * @caps: the #GstCaps to fixate
- *
- * Given possibly unfixed caps @caps, let @pad use its default preferred
- * format to make a fixed caps. @caps should be writable. By default this
- * function will pick the first value of any ranges or lists in the caps but
- * elements can override this function to perform other behaviour.
- */
-typedef void                   (*GstPadFixateCapsFunction)     (GstPad *pad, GstCaps *caps);
-/**
- * GstPadBufferAllocFunction:
- * @pad: a sink #GstPad
- * @offset: the desired offset of the buffer
- * @size: the desired size of the buffer
- * @caps: the desired caps of the buffer
- * @buf: pointer to hold the allocated buffer.
- *
- * Ask the sinkpad @pad to allocate a buffer with @offset, @size and @caps.
- * The result will be stored in @buf.
- *
- * The purpose of this function is to allocate a buffer that is optimal to
- * be processed by @pad. The function is mostly overridden by elements that can
- * provide a hardware buffer in order to avoid additional memcpy operations.
- *
- * The function can return a buffer that has caps different from the requested
- * @caps, in which case the upstream element requests a format change to this
- * new caps.
- * If a format change was requested, the returned buffer will be one to hold
- * the data of said new caps, so its size might be different from the requested
- * @size.
- *
- * When this function returns anything else than #GST_FLOW_OK, the buffer allocation
- * failed and @buf does not contain valid data. If the function returns #GST_FLOW_OK and
- * the @buf is NULL, a #GstBuffer will be created with @caps, @offset and @size.
- *
- * By default this function returns a new buffer of @size and with @caps containing
- * purely malloced data. The buffer should be freed with gst_buffer_unref()
- * after usage.
- *
- * Returns: #GST_FLOW_OK if @buf contains a valid buffer, any other return
- *  value means @buf does not hold a valid buffer.
- */
-typedef GstFlowReturn          (*GstPadBufferAllocFunction)    (GstPad *pad, guint64 offset, guint size,
-                                                                GstCaps *caps, GstBuffer **buf);
+typedef GstPadProbeReturn   (*GstPadProbeCallback)   (GstPad *pad, GstPadProbeInfo *info,
+                                                      gpointer user_data);
 
-/* misc */
 /**
- * GstPadDispatcherFunction:
- * @pad: the #GstPad that is dispatched.
- * @data: the gpointer to optional user data.
+ * GstPadStickyEventsForeachFunction:
+ * @pad: the #GstPad.
+ * @event: a sticky #GstEvent.
+ * @user_data: the #gpointer to optional user data.
  *
- * A dispatcher function is called for all internally linked pads, see
- * gst_pad_dispatcher().
+ * Callback used by gst_pad_sticky_events_foreach().
  *
- * Returns: TRUE if the dispatching procedure has to be stopped.
- */
-typedef gboolean               (*GstPadDispatcherFunction)     (GstPad *pad, gpointer data);
-
-/**
- * GstPadBlockCallback:
- * @pad: the #GstPad that is blockend or unblocked.
- * @blocked: blocking state for the pad
- * @user_data: the gpointer to optional user data.
+ * When this function returns %TRUE, the next event will be
+ * returned. When %FALSE is returned, gst_pad_sticky_events_foreach() will return.
  *
- * Callback used by gst_pad_set_blocked_async(). Gets called when the blocking
- * operation succeeds.
- */
-typedef void                   (*GstPadBlockCallback)          (GstPad *pad, gboolean blocked, gpointer user_data);
-
-/**
- * GstPadDirection:
- * @GST_PAD_UNKNOWN: direction is unknown.
- * @GST_PAD_SRC: the pad is a source pad.
- * @GST_PAD_SINK: the pad is a sink pad.
+ * When @event is set to NULL, the item will be removed from the list of sticky events.
+ * When @event has been made writable, the new buffer reference can be assigned
+ * to @event. This function is responsible for unreffing the old event when
+ * removing or modifying.
  *
- * The direction of a pad.
+ * Returns: %TRUE if the iteration should continue
  */
-typedef enum {
-  GST_PAD_UNKNOWN,
-  GST_PAD_SRC,
-  GST_PAD_SINK
-} GstPadDirection;
+typedef gboolean  (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent **event,
+                                                        gpointer user_data);
 
 /**
  * GstPadFlags:
- * @GST_PAD_BLOCKED: is dataflow on a pad blocked
- * @GST_PAD_FLUSHING: is pad refusing buffers
- * @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now
- * @GST_PAD_IN_SETCAPS: GstPadSetCapsFunction() is running now
- * @GST_PAD_BLOCKING: is pad currently blocking on a buffer or event
+ * @GST_PAD_FLAG_BLOCKED: is dataflow on a pad blocked
+ * @GST_PAD_FLAG_FLUSHING: is pad refusing buffers
+ * @GST_PAD_FLAG_BLOCKING: is pad currently blocking on a buffer or event
+ * @GST_PAD_FLAG_NEED_RECONFIGURE: the pad should be reconfigured/renegotiated.
+ *                            The flag has to be unset manually after
+ *                            reconfiguration happened.
+ *                            Since: 0.10.34.
+ * @GST_PAD_FLAG_PENDING_EVENTS: the pad has pending events
+ * @GST_PAD_FLAG_FIXED_CAPS: the pad is using fixed caps this means that once the
+ *                      caps are set on the pad, the caps query function only
+ *                      returns those caps.
+ * @GST_PAD_FLAG_PROXY_CAPS: the default event and query handler will forward
+ *                      all events and queries to the internally linked pads
+ *                      instead of discarding them.
+ * @GST_PAD_FLAG_NEED_PARENT: ensure that there is a parent object before calling
+ *                       into the pad callbacks.
  * @GST_PAD_FLAG_LAST: offset to define more flags
  *
  * Pad state flags
  */
 typedef enum {
-  GST_PAD_BLOCKED       = (GST_OBJECT_FLAG_LAST << 0),
-  GST_PAD_FLUSHING      = (GST_OBJECT_FLAG_LAST << 1),
-  GST_PAD_IN_GETCAPS    = (GST_OBJECT_FLAG_LAST << 2),
-  GST_PAD_IN_SETCAPS    = (GST_OBJECT_FLAG_LAST << 3),
-  GST_PAD_BLOCKING     = (GST_OBJECT_FLAG_LAST << 4),
+  GST_PAD_FLAG_BLOCKED          = (GST_OBJECT_FLAG_LAST << 0),
+  GST_PAD_FLAG_FLUSHING         = (GST_OBJECT_FLAG_LAST << 1),
+  GST_PAD_FLAG_BLOCKING         = (GST_OBJECT_FLAG_LAST << 2),
+  GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 3),
+  GST_PAD_FLAG_PENDING_EVENTS   = (GST_OBJECT_FLAG_LAST << 4),
+  GST_PAD_FLAG_FIXED_CAPS       = (GST_OBJECT_FLAG_LAST << 5),
+  GST_PAD_FLAG_PROXY_CAPS       = (GST_OBJECT_FLAG_LAST << 6),
+  GST_PAD_FLAG_NEED_PARENT      = (GST_OBJECT_FLAG_LAST << 7),
   /* padding */
-  GST_PAD_FLAG_LAST     = (GST_OBJECT_FLAG_LAST << 8)
+  GST_PAD_FLAG_LAST        = (GST_OBJECT_FLAG_LAST << 16)
 } GstPadFlags;
 
-/* FIXME: this awful circular dependency need to be resolved properly (see padtemplate.h) */
-typedef struct _GstPadTemplate GstPadTemplate;
-
 /**
  * GstPad:
  * @element_private: private data owned by the parent element
  * @padtemplate: padtemplate for this pad
  * @direction: the direction of the pad, cannot change after creating
  *             the pad.
- * @stream_rec_lock: recursive stream lock of the pad, used to protect
- *                   the data used in streaming.
- * @task: task for this pad if the pad is actively driving dataflow.
- * @preroll_lock: lock used when prerolling
- * @preroll_cond: conf to signal preroll
- * @block_cond: conditional to signal pad block
- * @block_callback: callback for the pad block if any
- * @block_data: user data for @block_callback
- * @caps: the current caps of the pad
- * @getcapsfunc: function to get caps of the pad
- * @setcapsfunc: function to set caps on the pad
- * @acceptcapsfunc: function to check if pad can accept caps
- * @fixatecapsfunc: function to fixate caps
- * @activatefunc: pad activation function
- * @activatepushfunc: function to activate/deactivate pad in push mode
- * @activatepullfunc: function to activate/deactivate pad in pull mode
- * @linkfunc: function called when pad is linked
- * @unlinkfunc: function called when pad is unlinked
- * @peer: the pad this pad is linked to
- * @sched_private: private storage for the scheduler
- * @chainfunc: function to chain buffer to pad
- * @checkgetrangefunc: function to check if pad can operate in pull mode
- * @getrangefunc: function to get a range of data from a pad
- * @eventfunc: function to send an event to a pad
- * @mode: current activation mode of the pad
- * @querytypefunc: get list of supported queries
- * @queryfunc: perform a query on the pad
- * @intlinkfunc: get the internal links of this pad
- * @bufferallocfunc: function to allocate a buffer for this pad
- * @do_buffer_signals: counter counting installed buffer signals
- * @do_event_signals: counter counting installed event signals
- * @iterintlinkfunc: get the internal links iterator of this pad
- * @block_destroy_data: notify function for gst_pad_set_blocked_async_full()
  *
  * The #GstPad structure. Use the functions to update the variables.
  */
 struct _GstPad {
-  GstObject                    object;
+  GstObject                      object;
 
   /*< public >*/
-  gpointer                     element_private;
+  gpointer                       element_private;
 
-  GstPadTemplate               *padtemplate;
+  GstPadTemplate                *padtemplate;
 
-  GstPadDirection               direction;
+  GstPadDirection                direction;
 
-  /*< public >*/ /* with STREAM_LOCK */
+  /*< private >*/
   /* streaming rec_lock */
-  GStaticRecMutex              *stream_rec_lock;
+  GRecMutex                     stream_rec_lock;
   GstTask                      *task;
-  /*< public >*/ /* with PREROLL_LOCK */
-  GMutex                       *preroll_lock;
-  GCond                                *preroll_cond;
 
-  /*< public >*/ /* with LOCK */
   /* block cond, mutex is from the object */
-  GCond                                *block_cond;
-  GstPadBlockCallback           block_callback;
-  gpointer                      block_data;
-
-  /* the pad capabilities */
-  GstCaps                      *caps;
-  GstPadGetCapsFunction                getcapsfunc;
-  GstPadSetCapsFunction                setcapsfunc;
-  GstPadAcceptCapsFunction      acceptcapsfunc;
-  GstPadFixateCapsFunction      fixatecapsfunc;
+  GCond                                 block_cond;
+  GHookList                      probes;
 
+  GstPadMode                    mode;
   GstPadActivateFunction        activatefunc;
-  GstPadActivateModeFunction    activatepushfunc;
-  GstPadActivateModeFunction    activatepullfunc;
+  GDestroyNotify                 activatenotify;
+  GstPadActivateModeFunction    activatemodefunc;
+  GDestroyNotify                 activatemodenotify;
 
   /* pad link */
+  GstPad                       *peer;
   GstPadLinkFunction            linkfunc;
+  GDestroyNotify                 linknotify;
   GstPadUnlinkFunction          unlinkfunc;
-  GstPad                       *peer;
-
-  gpointer                      sched_private;
+  GDestroyNotify                 unlinknotify;
 
   /* data transport functions */
   GstPadChainFunction           chainfunc;
-  GstPadCheckGetRangeFunction   checkgetrangefunc;
+  GDestroyNotify                 chainnotify;
+  GstPadChainListFunction        chainlistfunc;
+  GDestroyNotify                 chainlistnotify;
   GstPadGetRangeFunction        getrangefunc;
+  GDestroyNotify                 getrangenotify;
   GstPadEventFunction           eventfunc;
+  GDestroyNotify                 eventnotify;
 
-  GstActivateMode               mode;
+  /* pad offset */
+  gint64                         offset;
 
   /* generic query method */
-  GstPadQueryTypeFunction       querytypefunc;
   GstPadQueryFunction           queryfunc;
+  GDestroyNotify                 querynotify;
 
   /* internal links */
-#ifndef GST_DISABLE_DEPRECATED
-  GstPadIntLinkFunction                 intlinkfunc;
-#else
-#ifndef __GTK_DOC_IGNORE__
-  gpointer intlinkfunc;
-#endif
-#endif
-
-  GstPadBufferAllocFunction      bufferallocfunc;
-
-  /* whether to emit signals for have-data. counts number
-   * of handlers attached. */
-  gint                          do_buffer_signals;
-  gint                          do_event_signals;
+  GstPadIterIntLinkFunction      iterintlinkfunc;
+  GDestroyNotify                 iterintlinknotify;
 
-  /* ABI added */
-  /* iterate internal links */
-  GstPadIterIntLinkFunction     iterintlinkfunc;
+  /* counts number of probes attached. */
+  gint                          num_probes;
+  gint                          num_blocked;
 
-  /* free block_data */
-  GDestroyNotify block_destroy_data;
+  GstPadPrivate                 *priv;
 
-  /*< private >*/
-  union {
-    struct {
-      gboolean                      block_callback_called;
-      GstPadPrivate                *priv;
-    } ABI;
-    gpointer _gst_reserved[GST_PADDING - 2];
-  } abidata;
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstPadClass {
@@ -749,8 +691,6 @@ struct _GstPadClass {
   /* signal callbacks */
   void         (*linked)               (GstPad *pad, GstPad *peer);
   void         (*unlinked)             (GstPad *pad, GstPad *peer);
-  void         (*request_link)         (GstPad *pad);
-  gboolean     (*have_data)            (GstPad *pad, GstMiniObject *data);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -761,58 +701,47 @@ struct _GstPadClass {
 /* GstPad */
 #define GST_PAD_NAME(pad)              (GST_OBJECT_NAME(pad))
 #define GST_PAD_PARENT(pad)            (GST_ELEMENT_CAST(GST_OBJECT_PARENT(pad)))
-#define GST_PAD_ELEMENT_PRIVATE(pad)   (GST_PAD_CAST(pad)->element_private)
+#define GST_PAD_ELEMENT_PRIVATE(pad)    (GST_PAD_CAST(pad)->element_private)
 #define GST_PAD_PAD_TEMPLATE(pad)      (GST_PAD_CAST(pad)->padtemplate)
 #define GST_PAD_DIRECTION(pad)         (GST_PAD_CAST(pad)->direction)
 #define GST_PAD_TASK(pad)              (GST_PAD_CAST(pad)->task)
-#define GST_PAD_ACTIVATE_MODE(pad)     (GST_PAD_CAST(pad)->mode)
+#define GST_PAD_MODE(pad)              (GST_PAD_CAST(pad)->mode)
 
 #define GST_PAD_ACTIVATEFUNC(pad)      (GST_PAD_CAST(pad)->activatefunc)
-#define GST_PAD_ACTIVATEPUSHFUNC(pad)  (GST_PAD_CAST(pad)->activatepushfunc)
-#define GST_PAD_ACTIVATEPULLFUNC(pad)  (GST_PAD_CAST(pad)->activatepullfunc)
+#define GST_PAD_ACTIVATEMODEFUNC(pad)  (GST_PAD_CAST(pad)->activatemodefunc)
 #define GST_PAD_CHAINFUNC(pad)         (GST_PAD_CAST(pad)->chainfunc)
-#define GST_PAD_CHECKGETRANGEFUNC(pad) (GST_PAD_CAST(pad)->checkgetrangefunc)
+#define GST_PAD_CHAINLISTFUNC(pad)      (GST_PAD_CAST(pad)->chainlistfunc)
 #define GST_PAD_GETRANGEFUNC(pad)      (GST_PAD_CAST(pad)->getrangefunc)
 #define GST_PAD_EVENTFUNC(pad)         (GST_PAD_CAST(pad)->eventfunc)
-#define GST_PAD_QUERYTYPEFUNC(pad)     (GST_PAD_CAST(pad)->querytypefunc)
 #define GST_PAD_QUERYFUNC(pad)         (GST_PAD_CAST(pad)->queryfunc)
-#ifndef GST_DISABLE_DEPRECATED
-#define GST_PAD_INTLINKFUNC(pad)       (GST_PAD_CAST(pad)->intlinkfunc)
-#endif
 #define GST_PAD_ITERINTLINKFUNC(pad)    (GST_PAD_CAST(pad)->iterintlinkfunc)
 
 #define GST_PAD_PEER(pad)              (GST_PAD_CAST(pad)->peer)
 #define GST_PAD_LINKFUNC(pad)          (GST_PAD_CAST(pad)->linkfunc)
 #define GST_PAD_UNLINKFUNC(pad)                (GST_PAD_CAST(pad)->unlinkfunc)
 
-/**
- * GST_PAD_CAPS:
- * @pad: a #GstPad.
- *
- * The caps for this pad.
- */
-#define GST_PAD_CAPS(pad)              (GST_PAD_CAST(pad)->caps)
-#define GST_PAD_GETCAPSFUNC(pad)       (GST_PAD_CAST(pad)->getcapsfunc)
-#define GST_PAD_SETCAPSFUNC(pad)       (GST_PAD_CAST(pad)->setcapsfunc)
-#define GST_PAD_ACCEPTCAPSFUNC(pad)    (GST_PAD_CAST(pad)->acceptcapsfunc)
-#define GST_PAD_FIXATECAPSFUNC(pad)    (GST_PAD_CAST(pad)->fixatecapsfunc)
+#define GST_PAD_IS_SRC(pad)            (GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
+#define GST_PAD_IS_SINK(pad)           (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
 
-#define GST_PAD_BUFFERALLOCFUNC(pad)   (GST_PAD_CAST(pad)->bufferallocfunc)
+#define GST_PAD_IS_LINKED(pad)         (GST_PAD_PEER(pad) != NULL)
 
-#define GST_PAD_DO_BUFFER_SIGNALS(pad)         (GST_PAD_CAST(pad)->do_buffer_signals)
-#define GST_PAD_DO_EVENT_SIGNALS(pad)  (GST_PAD_CAST(pad)->do_event_signals)
+#define GST_PAD_IS_ACTIVE(pad)          (GST_PAD_MODE(pad) != GST_PAD_MODE_NONE)
 
-#define GST_PAD_IS_LINKED(pad)         (GST_PAD_PEER(pad) != NULL)
-#define GST_PAD_IS_BLOCKED(pad)                (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED))
-#define GST_PAD_IS_BLOCKING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING))
-#define GST_PAD_IS_FLUSHING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING))
-#define GST_PAD_IS_IN_GETCAPS(pad)     (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS))
-#define GST_PAD_IS_IN_SETCAPS(pad)     (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS))
-#define GST_PAD_IS_SRC(pad)            (GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
-#define GST_PAD_IS_SINK(pad)           (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
+#define GST_PAD_IS_BLOCKED(pad)                (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED))
+#define GST_PAD_IS_BLOCKING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING))
+
+#define GST_PAD_IS_FLUSHING(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING))
+#define GST_PAD_SET_FLUSHING(pad)      (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING))
+#define GST_PAD_UNSET_FLUSHING(pad)    (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING))
 
-#define GST_PAD_SET_FLUSHING(pad)      (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLUSHING))
-#define GST_PAD_UNSET_FLUSHING(pad)    (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLUSHING))
+#define GST_PAD_NEEDS_RECONFIGURE(pad)  (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE))
+#define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS))
+#define GST_PAD_IS_FIXED_CAPS(pad)     (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS))
+#define GST_PAD_NEEDS_PARENT(pad)       (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_PARENT))
+
+#define GST_PAD_IS_PROXY_CAPS(pad)      (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_CAPS))
+#define GST_PAD_SET_PROXY_CAPS(pad)     (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_CAPS))
+#define GST_PAD_UNSET_PROXY_CAPS(pad)   (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_CAPS))
 
 /**
  * GST_PAD_GET_STREAM_LOCK:
@@ -821,22 +750,14 @@ struct _GstPadClass {
  * Get the stream lock of @pad. The stream lock is protecting the
  * resources used in the data processing functions of @pad.
  */
-#define GST_PAD_GET_STREAM_LOCK(pad)    (GST_PAD_CAST(pad)->stream_rec_lock)
+#define GST_PAD_GET_STREAM_LOCK(pad)    (&(GST_PAD_CAST(pad)->stream_rec_lock))
 /**
  * GST_PAD_STREAM_LOCK:
  * @pad: a #GstPad
  *
  * Lock the stream lock of @pad.
  */
-#define GST_PAD_STREAM_LOCK(pad)        (g_static_rec_mutex_lock(GST_PAD_GET_STREAM_LOCK(pad)))
-/**
- * GST_PAD_STREAM_LOCK_FULL:
- * @pad: a #GstPad
- * @t: the number of times to recursively lock
- *
- * Lock the stream lock of @pad @t times.
- */
-#define GST_PAD_STREAM_LOCK_FULL(pad,t) (g_static_rec_mutex_lock_full(GST_PAD_GET_STREAM_LOCK(pad), t))
+#define GST_PAD_STREAM_LOCK(pad)        (g_rec_mutex_lock(GST_PAD_GET_STREAM_LOCK(pad)))
 /**
  * GST_PAD_STREAM_TRYLOCK:
  * @pad: a #GstPad
@@ -844,44 +765,20 @@ struct _GstPadClass {
  * Try to Lock the stream lock of the pad, return TRUE if the lock could be
  * taken.
  */
-#define GST_PAD_STREAM_TRYLOCK(pad)     (g_static_rec_mutex_trylock(GST_PAD_GET_STREAM_LOCK(pad)))
+#define GST_PAD_STREAM_TRYLOCK(pad)     (g_rec_mutex_trylock(GST_PAD_GET_STREAM_LOCK(pad)))
 /**
  * GST_PAD_STREAM_UNLOCK:
  * @pad: a #GstPad
  *
  * Unlock the stream lock of @pad.
  */
-#define GST_PAD_STREAM_UNLOCK(pad)      (g_static_rec_mutex_unlock(GST_PAD_GET_STREAM_LOCK(pad)))
-/**
- * GST_PAD_STREAM_UNLOCK_FULL:
- * @pad: a #GstPad
- *
- * Fully unlock the recursive stream lock of @pad, return the number of times
- * @pad was locked.
- */
-#define GST_PAD_STREAM_UNLOCK_FULL(pad) (g_static_rec_mutex_unlock_full(GST_PAD_GET_STREAM_LOCK(pad)))
-
-#define GST_PAD_GET_PREROLL_LOCK(pad)   (GST_PAD_CAST(pad)->preroll_lock)
-#define GST_PAD_PREROLL_LOCK(pad)       (g_mutex_lock(GST_PAD_GET_PREROLL_LOCK(pad)))
-#define GST_PAD_PREROLL_TRYLOCK(pad)    (g_mutex_trylock(GST_PAD_GET_PREROLL_LOCK(pad)))
-#define GST_PAD_PREROLL_UNLOCK(pad)     (g_mutex_unlock(GST_PAD_GET_PREROLL_LOCK(pad)))
-
-#define GST_PAD_GET_PREROLL_COND(pad)   (GST_PAD_CAST(pad)->preroll_cond)
-#define GST_PAD_PREROLL_WAIT(pad)       \
-    g_cond_wait (GST_PAD_GET_PREROLL_COND (pad), GST_PAD_GET_PREROLL_LOCK (pad))
-#define GST_PAD_PREROLL_TIMED_WAIT(pad, timeval) \
-    g_cond_timed_wait (GST_PAD_GET_PREROLL_COND (pad), GST_PAD_GET_PREROLL_LOCK (pad), timeval)
-#define GST_PAD_PREROLL_SIGNAL(pad)     g_cond_signal (GST_PAD_GET_PREROLL_COND (pad));
-#define GST_PAD_PREROLL_BROADCAST(pad)  g_cond_broadcast (GST_PAD_GET_PREROLL_COND (pad));
-
-#define GST_PAD_BLOCK_GET_COND(pad)     (GST_PAD_CAST(pad)->block_cond)
+#define GST_PAD_STREAM_UNLOCK(pad)      (g_rec_mutex_unlock(GST_PAD_GET_STREAM_LOCK(pad)))
+
+#define GST_PAD_BLOCK_GET_COND(pad)     (&GST_PAD_CAST(pad)->block_cond)
 #define GST_PAD_BLOCK_WAIT(pad)         (g_cond_wait(GST_PAD_BLOCK_GET_COND (pad), GST_OBJECT_GET_LOCK (pad)))
 #define GST_PAD_BLOCK_SIGNAL(pad)       (g_cond_signal(GST_PAD_BLOCK_GET_COND (pad)))
 #define GST_PAD_BLOCK_BROADCAST(pad)    (g_cond_broadcast(GST_PAD_BLOCK_GET_COND (pad)))
 
-/* FIXME: this awful circular dependency need to be resolved properly (see padtemplate.h) */
-#include <gst/gstpadtemplate.h>
-
 GType                  gst_pad_get_type                        (void);
 
 /* creating pads */
@@ -915,42 +812,69 @@ GstPadDirection           gst_pad_get_direction                   (GstPad *pad);
 
 gboolean               gst_pad_set_active                      (GstPad *pad, gboolean active);
 gboolean               gst_pad_is_active                       (GstPad *pad);
-gboolean               gst_pad_activate_pull                   (GstPad *pad, gboolean active);
-gboolean               gst_pad_activate_push                   (GstPad *pad, gboolean active);
-
-gboolean               gst_pad_set_blocked                     (GstPad *pad, gboolean blocked);
-gboolean               gst_pad_set_blocked_async               (GstPad *pad, gboolean blocked,
-                                                                GstPadBlockCallback callback, gpointer user_data);
-gboolean               gst_pad_set_blocked_async_full          (GstPad *pad, gboolean blocked,
-                                                                GstPadBlockCallback callback, gpointer user_data,
+gboolean               gst_pad_activate_mode                   (GstPad *pad, GstPadMode mode,
+                                                                 gboolean active);
+
+gulong                  gst_pad_add_probe                       (GstPad *pad,
+                                                                GstPadProbeType mask,
+                                                                GstPadProbeCallback callback,
+                                                                 gpointer user_data,
                                                                  GDestroyNotify destroy_data);
+void                    gst_pad_remove_probe                    (GstPad *pad, gulong id);
+
 gboolean               gst_pad_is_blocked                      (GstPad *pad);
 gboolean               gst_pad_is_blocking                     (GstPad *pad);
 
+void                    gst_pad_mark_reconfigure                (GstPad *pad);
+gboolean               gst_pad_check_reconfigure               (GstPad *pad);
+
 void                   gst_pad_set_element_private             (GstPad *pad, gpointer priv);
 gpointer               gst_pad_get_element_private             (GstPad *pad);
 
 GstPadTemplate*                gst_pad_get_pad_template                (GstPad *pad);
 
-void                   gst_pad_set_bufferalloc_function        (GstPad *pad, GstPadBufferAllocFunction bufalloc);
-GstFlowReturn          gst_pad_alloc_buffer                    (GstPad *pad, guint64 offset, gint size,
-                                                                GstCaps *caps, GstBuffer **buf);
-GstFlowReturn          gst_pad_alloc_buffer_and_set_caps       (GstPad *pad, guint64 offset, gint size,
-                                                                GstCaps *caps, GstBuffer **buf);
+GstEvent*               gst_pad_get_sticky_event                (GstPad *pad, GstEventType event_type,
+                                                                 guint idx);
+void                    gst_pad_sticky_events_foreach           (GstPad *pad, GstPadStickyEventsForeachFunction foreach_func, gpointer user_data);
 
 /* data passing setup functions */
-void                   gst_pad_set_activate_function           (GstPad *pad, GstPadActivateFunction activate);
-void                   gst_pad_set_activatepull_function       (GstPad *pad, GstPadActivateModeFunction activatepull);
-void                   gst_pad_set_activatepush_function       (GstPad *pad, GstPadActivateModeFunction activatepush);
-void                   gst_pad_set_chain_function              (GstPad *pad, GstPadChainFunction chain);
-void                   gst_pad_set_chain_list_function (GstPad *pad, GstPadChainListFunction chainlist);
-void                   gst_pad_set_getrange_function           (GstPad *pad, GstPadGetRangeFunction get);
-void                   gst_pad_set_checkgetrange_function      (GstPad *pad, GstPadCheckGetRangeFunction check);
-void                   gst_pad_set_event_function              (GstPad *pad, GstPadEventFunction event);
+void                   gst_pad_set_activate_function_full      (GstPad *pad,
+                                                                 GstPadActivateFunction activate,
+                                                                 GDestroyNotify notify);
+void                   gst_pad_set_activatemode_function_full  (GstPad *pad,
+                                                                 GstPadActivateModeFunction activatemode,
+                                                                 GDestroyNotify notify);
+/* data passing functions */
+void                   gst_pad_set_chain_function_full         (GstPad *pad,
+                                                                 GstPadChainFunction chain,
+                                                                 GDestroyNotify notify);
+void                   gst_pad_set_chain_list_function_full    (GstPad *pad,
+                                                                 GstPadChainListFunction chainlist,
+                                                                 GDestroyNotify notify);
+void                   gst_pad_set_getrange_function_full      (GstPad *pad,
+                                                                 GstPadGetRangeFunction get,
+                                                                 GDestroyNotify notify);
+void                   gst_pad_set_event_function_full         (GstPad *pad,
+                                                                 GstPadEventFunction event,
+                                                                 GDestroyNotify notify);
+
+#define gst_pad_set_activate_function(p,f)      gst_pad_set_activate_function_full((p),(f),NULL)
+#define gst_pad_set_activatemode_function(p,f)  gst_pad_set_activatemode_function_full((p),(f),NULL)
+#define gst_pad_set_chain_function(p,f)         gst_pad_set_chain_function_full((p),(f),NULL)
+#define gst_pad_set_chain_list_function(p,f)    gst_pad_set_chain_list_function_full((p),(f),NULL)
+#define gst_pad_set_getrange_function(p,f)      gst_pad_set_getrange_function_full((p),(f),NULL)
+#define gst_pad_set_event_function(p,f)         gst_pad_set_event_function_full((p),(f),NULL)
 
 /* pad links */
-void                   gst_pad_set_link_function               (GstPad *pad, GstPadLinkFunction link);
-void                   gst_pad_set_unlink_function             (GstPad *pad, GstPadUnlinkFunction unlink);
+void                   gst_pad_set_link_function_full          (GstPad *pad,
+                                                                 GstPadLinkFunction link,
+                                                                 GDestroyNotify notify);
+void                   gst_pad_set_unlink_function_full        (GstPad *pad,
+                                                                 GstPadUnlinkFunction unlink,
+                                                                 GDestroyNotify notify);
+
+#define gst_pad_set_link_function(p,f)          gst_pad_set_link_function_full((p),(f),NULL)
+#define gst_pad_set_unlink_function(p,f)        gst_pad_set_unlink_function_full((p),(f),NULL)
 
 gboolean                gst_pad_can_link                        (GstPad *srcpad, GstPad *sinkpad);
 GstPadLinkReturn        gst_pad_link                           (GstPad *srcpad, GstPad *sinkpad);
@@ -960,37 +884,28 @@ gboolean          gst_pad_is_linked                       (GstPad *pad);
 
 GstPad*                        gst_pad_get_peer                        (GstPad *pad);
 
-/* capsnego functions */
-void                   gst_pad_set_getcaps_function            (GstPad *pad, GstPadGetCapsFunction getcaps);
-void                   gst_pad_set_acceptcaps_function         (GstPad *pad, GstPadAcceptCapsFunction acceptcaps);
-void                   gst_pad_set_fixatecaps_function         (GstPad *pad, GstPadFixateCapsFunction fixatecaps);
-void                   gst_pad_set_setcaps_function            (GstPad *pad, GstPadSetCapsFunction setcaps);
-
-const GstCaps*         gst_pad_get_pad_template_caps           (GstPad *pad);
+GstCaps*                gst_pad_get_pad_template_caps          (GstPad *pad);
 
 /* capsnego function for linked/unlinked pads */
-GstCaps *              gst_pad_get_caps_reffed                 (GstPad * pad);
-GstCaps *              gst_pad_get_caps                        (GstPad * pad);
-void                   gst_pad_fixate_caps                     (GstPad * pad, GstCaps *caps);
-gboolean               gst_pad_accept_caps                     (GstPad * pad, GstCaps *caps);
+GstCaps *              gst_pad_get_current_caps                (GstPad * pad);
+gboolean               gst_pad_has_current_caps                (GstPad * pad);
 gboolean               gst_pad_set_caps                        (GstPad * pad, GstCaps *caps);
 
-GstCaps *              gst_pad_peer_get_caps_reffed            (GstPad * pad);
-GstCaps *              gst_pad_peer_get_caps                   (GstPad * pad);
-gboolean               gst_pad_peer_accept_caps                (GstPad * pad, GstCaps *caps);
-
 /* capsnego for linked pads */
 GstCaps *              gst_pad_get_allowed_caps                (GstPad * pad);
-GstCaps *              gst_pad_get_negotiated_caps             (GstPad * pad);
+
+/* pad offsets */
+gint64                  gst_pad_get_offset                      (GstPad *pad);
+void                    gst_pad_set_offset                      (GstPad *pad, gint64 offset);
 
 /* data passing functions to peer */
 GstFlowReturn          gst_pad_push                            (GstPad *pad, GstBuffer *buffer);
 GstFlowReturn          gst_pad_push_list                       (GstPad *pad, GstBufferList *list);
-gboolean               gst_pad_check_pull_range                (GstPad *pad);
 GstFlowReturn          gst_pad_pull_range                      (GstPad *pad, guint64 offset, guint size,
                                                                 GstBuffer **buffer);
 gboolean               gst_pad_push_event                      (GstPad *pad, GstEvent *event);
-gboolean               gst_pad_event_default                   (GstPad *pad, GstEvent *event);
+gboolean               gst_pad_event_default                   (GstPad *pad, GstObject *parent,
+                                                                 GstEvent *event);
 
 /* data passing functions on pad */
 GstFlowReturn          gst_pad_chain                           (GstPad *pad, GstBuffer *buffer);
@@ -1006,35 +921,27 @@ gboolean         gst_pad_pause_task                      (GstPad *pad);
 gboolean               gst_pad_stop_task                       (GstPad *pad);
 
 /* internal links */
-#ifndef GST_DISABLE_DEPRECATED
-void                   gst_pad_set_internal_link_function      (GstPad *pad, GstPadIntLinkFunction intlink);
-GList*                 gst_pad_get_internal_links              (GstPad *pad);
-GList*                 gst_pad_get_internal_links_default      (GstPad *pad);
-#endif
-
-void                    gst_pad_set_iterate_internal_links_function (GstPad * pad,
-                                                                 GstPadIterIntLinkFunction iterintlink);
+void                    gst_pad_set_iterate_internal_links_function_full (GstPad * pad,
+                                                                 GstPadIterIntLinkFunction iterintlink,
+                                                                 GDestroyNotify notify);
 GstIterator *           gst_pad_iterate_internal_links          (GstPad * pad);
-GstIterator *           gst_pad_iterate_internal_links_default  (GstPad * pad);
+GstIterator *           gst_pad_iterate_internal_links_default  (GstPad * pad, GstObject *parent);
 
+#define gst_pad_set_iterate_internal_links_function(p,f) gst_pad_set_iterate_internal_links_function_full((p),(f),NULL)
 
 /* generic query function */
-void                   gst_pad_set_query_type_function         (GstPad *pad, GstPadQueryTypeFunction type_func);
-const GstQueryType*    gst_pad_get_query_types                 (GstPad *pad);
-const GstQueryType*    gst_pad_get_query_types_default         (GstPad *pad);
-
 gboolean               gst_pad_query                           (GstPad *pad, GstQuery *query);
 gboolean               gst_pad_peer_query                      (GstPad *pad, GstQuery *query);
-void                   gst_pad_set_query_function              (GstPad *pad, GstPadQueryFunction query);
-gboolean               gst_pad_query_default                   (GstPad *pad, GstQuery *query);
+void                   gst_pad_set_query_function_full         (GstPad *pad, GstPadQueryFunction query,
+                                                                 GDestroyNotify notify);
+gboolean               gst_pad_query_default                   (GstPad *pad, GstObject *parent,
+                                                                 GstQuery *query);
 
-/* misc helper functions */
-gboolean               gst_pad_dispatcher                      (GstPad *pad, GstPadDispatcherFunction dispatch,
-                                                                gpointer data);
+#define gst_pad_set_query_function(p,f)   gst_pad_set_query_function_full((p),(f),NULL)
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED)
-void                   gst_pad_load_and_link                   (xmlNodePtr self, GstObject *parent);
-#endif
+/* misc helper functions */
+gboolean               gst_pad_forward                         (GstPad *pad, GstPadForwardFunction forward,
+                                                                gpointer user_data);
 
 G_END_DECLS
 
index 116cd77..d023bd0 100644 (file)
  * </example>
  *
  * The following example shows you how to add the padtemplate to an
- * element class, this is usually done in the base_init of the class:
+ * element class, this is usually done in the class_init of the class:
  * <informalexample>
  *   <programlisting>
  *   static void
- *   my_element_base_init (gpointer g_class)
+ *   my_element_class_init (GstMyElementClass *klass)
  *   {
- *     GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ *     GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
  *
  *     gst_element_class_add_pad_template (gstelement_class,
  *         gst_static_pad_template_get (&amp;my_template));
@@ -123,7 +123,6 @@ enum
   LAST_SIGNAL
 };
 
-static GstObject *parent_class = NULL;
 static guint gst_pad_template_signals[LAST_SIGNAL] = { 0 };
 
 static void gst_pad_template_dispose (GObject * object);
@@ -132,6 +131,7 @@ static void gst_pad_template_set_property (GObject * object, guint prop_id,
 static void gst_pad_template_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+#define gst_pad_template_parent_class parent_class
 G_DEFINE_TYPE (GstPadTemplate, gst_pad_template, GST_TYPE_OBJECT);
 
 static void
@@ -143,8 +143,6 @@ gst_pad_template_class_init (GstPadTemplateClass * klass)
   gobject_class = (GObjectClass *) klass;
   gstobject_class = (GstObjectClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
-
   /**
    * GstPadTemplate::pad-created:
    * @pad_template: the object which received the signal.
@@ -219,20 +217,6 @@ gst_pad_template_class_init (GstPadTemplateClass * klass)
 static void
 gst_pad_template_init (GstPadTemplate * templ)
 {
-  /* FIXME 0.11: Does anybody remember why this is here? If not, let's
-   * change it for 0.11 and let gst_element_class_add_pad_template() for
-   * example ref/sink the pad templates.
-   */
-  /* We ensure that the pad template we're creating has a sunken reference.
-   * Inconsistencies in pad templates being floating or sunken has caused
-   * problems in the past with leaks, etc.
-   *
-   * For consistency, then, we only produce them  with sunken references
-   * owned by the creator of the object
-   */
-  if (GST_OBJECT_IS_FLOATING (templ)) {
-    gst_object_ref_sink (templ);
-  }
 }
 
 static void
@@ -336,12 +320,10 @@ gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
  * @name_template: the name template.
  * @direction: the #GstPadDirection of the template.
  * @presence: the #GstPadPresence of the pad.
- * @caps: (transfer full): a #GstCaps set for the template. The caps are
- *     taken ownership of.
+ * @caps: (transfer none): a #GstCaps set for the template.
  *
  * Creates a new pad template with a name according to the given template
- * and with the given arguments. This functions takes ownership of the provided
- * caps, so be sure to not use them afterwards.
+ * and with the given arguments.
  *
  * Returns: (transfer full): a new #GstPadTemplate.
  */
@@ -359,7 +341,6 @@ gst_pad_template_new (const gchar * name_template,
       || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL);
 
   if (!name_is_valid (name_template, presence)) {
-    gst_caps_unref (caps);
     return NULL;
   }
 
@@ -367,8 +348,6 @@ gst_pad_template_new (const gchar * name_template,
       "name", name_template, "name-template", name_template,
       "direction", direction, "presence", presence, "caps", caps, NULL);
 
-  gst_caps_unref (caps);
-
   return new;
 }
 
@@ -397,15 +376,18 @@ gst_static_pad_template_get_caps (GstStaticPadTemplate * templ)
  *
  * Gets the capabilities of the pad template.
  *
- * Returns: (transfer none): the #GstCaps of the pad template. If you need to
- *     keep a reference to the caps, take a ref (see gst_caps_ref ()).
+ * Returns: (transfer full): the #GstCaps of the pad template.
+ * Unref after usage.
  */
 GstCaps *
 gst_pad_template_get_caps (GstPadTemplate * templ)
 {
+  GstCaps *caps;
   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
 
-  return GST_PAD_TEMPLATE_CAPS (templ);
+  caps = GST_PAD_TEMPLATE_CAPS (templ);
+
+  return (caps ? gst_caps_ref (caps) : NULL);
 }
 
 /**
@@ -439,12 +421,7 @@ gst_pad_template_set_property (GObject * object, guint prop_id,
           (GstPadPresence) g_value_get_enum (value);
       break;
     case PROP_CAPS:
-      /* allow caps == NULL for backwards compatibility (ie. g_object_new()
-       * called without any of the new properties) (FIXME 0.11) */
-      if (g_value_get_boxed (value) != NULL) {
-        GST_PAD_TEMPLATE_CAPS (object) =
-            gst_caps_copy (g_value_get_boxed (value));
-      }
+      GST_PAD_TEMPLATE_CAPS (object) = g_value_dup_boxed (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
index 0433d49..7bbbf16 100644 (file)
 
 #include <gst/gstconfig.h>
 
+typedef struct _GstPadTemplate GstPadTemplate;
+typedef struct _GstPadTemplateClass GstPadTemplateClass;
+typedef struct _GstStaticPadTemplate GstStaticPadTemplate;
+
 #include <gst/gstobject.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstcaps.h>
 
 G_BEGIN_DECLS
 
-/* FIXME: this awful circular dependency need to be resolved properly (see pad.h) */
-/*typedef struct _GstPadTemplate GstPadTemplate; */
-typedef struct _GstPadTemplateClass GstPadTemplateClass;
-typedef struct _GstStaticPadTemplate GstStaticPadTemplate;
-
 #define GST_TYPE_STATIC_PAD_TEMPLATE   (gst_static_pad_template_get_type ())
 
 #define GST_TYPE_PAD_TEMPLATE          (gst_pad_template_get_type ())
@@ -97,14 +96,11 @@ typedef enum {
 
 /**
  * GstPadTemplateFlags:
- * @GST_PAD_TEMPLATE_FIXED: the padtemplate has no variable properties
  * @GST_PAD_TEMPLATE_FLAG_LAST: first flag that can be used by subclasses.
  *
  * Flags for the padtemplate
  */
 typedef enum {
-  /* FIXME0.11: this is not used and the purpose is unclear */
-  GST_PAD_TEMPLATE_FIXED        = (GST_OBJECT_FLAG_LAST << 0),
   /* padding */
   GST_PAD_TEMPLATE_FLAG_LAST    = (GST_OBJECT_FLAG_LAST << 4)
 } GstPadTemplateFlags;
@@ -142,7 +138,7 @@ struct _GstPadTemplateClass {
   gpointer _gst_reserved[GST_PADDING];
 };
 
-/** 
+/**
  * GstStaticPadTemplate:
  * @name_template: the name of the template
  * @direction: the direction of the template
index e75a944..bed692d 100644 (file)
@@ -162,7 +162,7 @@ gst_param_spec_fraction_get_type (void)
  * used in connection with g_object_class_install_property() in a GObjects's
  * instance_init function.
  *
- * Returns: a newly created parameter specification
+ * Returns: (transfer full): a newly created parameter specification
  *
  * Since: 0.10.14
  */
index e6c8d84..0e22f40 100644 (file)
@@ -105,7 +105,7 @@ typedef struct _GstParamSpecFraction GstParamSpecFraction;
  */
 struct _GstParamSpecFraction {
   GParamSpec    parent_instance;
-  
+
   gint          min_num, min_den;
   gint          max_num, max_den;
   gint          def_num, def_den;
index 8612ae3..eb55a5f 100644 (file)
@@ -139,25 +139,14 @@ static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message);
 
 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
 
-#define _do_init(type) \
+#define _do_init \
 { \
   GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, \
       "debugging info for the 'pipeline' container element"); \
 }
 
-GST_BOILERPLATE_FULL (GstPipeline, gst_pipeline, GstBin, GST_TYPE_BIN,
-    _do_init);
-
-static void
-gst_pipeline_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class, "Pipeline object",
-      "Generic/Bin",
-      "Complete pipeline object",
-      "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
-}
+#define gst_pipeline_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstPipeline, gst_pipeline, GST_TYPE_BIN, _do_init);
 
 static void
 gst_pipeline_class_init (GstPipelineClass * klass)
@@ -203,6 +192,11 @@ gst_pipeline_class_init (GstPipelineClass * klass)
 
   gobject_class->dispose = gst_pipeline_dispose;
 
+  gst_element_class_set_metadata (gstelement_class, "Pipeline object",
+      "Generic/Bin",
+      "Complete pipeline object",
+      "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
   gstelement_class->provide_clock =
@@ -212,7 +206,7 @@ gst_pipeline_class_init (GstPipelineClass * klass)
 }
 
 static void
-gst_pipeline_init (GstPipeline * pipeline, GstPipelineClass * klass)
+gst_pipeline_init (GstPipeline * pipeline)
 {
   GstBus *bus;
 
@@ -556,15 +550,15 @@ gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
   GstPipeline *pipeline = GST_PIPELINE_CAST (bin);
 
   switch (GST_MESSAGE_TYPE (message)) {
-    case GST_MESSAGE_ASYNC_START:
+    case GST_MESSAGE_ASYNC_DONE:
     {
-      gboolean new_base_time;
+      gboolean reset_time;
 
-      gst_message_parse_async_start (message, &new_base_time);
+      gst_message_parse_async_done (message, &reset_time);
 
       /* reset our running time if we need to distribute a new base_time to the
        * children. */
-      if (new_base_time)
+      if (reset_time)
         reset_start_time (pipeline);
 
       break;
@@ -606,80 +600,6 @@ gst_pipeline_get_bus (GstPipeline * pipeline)
   return gst_element_get_bus (GST_ELEMENT_CAST (pipeline));
 }
 
-/**
- * gst_pipeline_set_new_stream_time:
- * @pipeline: a #GstPipeline
- * @time: the new running time to set
- *
- * Set the new start time of @pipeline to @time. The start time is used to
- * set the base time on the elements (see gst_element_set_base_time())
- * in the PAUSED->PLAYING state transition.
- *
- * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management
- * of element base time. The application will then be responsible for
- * performing base time distribution. This is sometimes useful if you want to
- * synchronize capture from multiple pipelines, and you can also ensure that the
- * pipelines have the same clock.
- *
- * MT safe.
- *
- * Deprecated: This function has the wrong name and is equivalent to
- * gst_element_set_start_time(). 
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void
-gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time);
-#endif
-void
-gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
-{
-  g_return_if_fail (GST_IS_PIPELINE (pipeline));
-
-  gst_element_set_start_time (GST_ELEMENT_CAST (pipeline), time);
-
-  if (time == GST_CLOCK_TIME_NONE)
-    GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time");
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
- * gst_pipeline_get_last_stream_time:
- * @pipeline: a #GstPipeline
- *
- * Gets the last running time of @pipeline. If the pipeline is PLAYING,
- * the returned time is the running time used to configure the element's
- * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the
- * returned time is the running time when the pipeline was paused.
- *
- * This function returns #GST_CLOCK_TIME_NONE if the pipeline was
- * configured to not handle the management of the element's base time
- * (see gst_pipeline_set_new_stream_time()).
- *
- * MT safe.
- *
- * Returns: a #GstClockTime.
- *
- * Deprecated: This function has the wrong name and is equivalent to
- * gst_element_get_start_time(). 
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-GstClockTime gst_pipeline_get_last_stream_time (GstPipeline * pipeline);
-#endif
-GstClockTime
-gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
-{
-  GstClockTime result;
-
-  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
-
-  result = gst_element_get_start_time (GST_ELEMENT_CAST (pipeline));
-
-  return result;
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
 static GstClock *
 gst_pipeline_provide_clock_func (GstElement * element)
 {
index acfbabb..43563cb 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_PIPELINE              (gst_pipeline_get_type ())
-#define GST_PIPELINE(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PIPELINE, GstPipeline))
-#define GST_IS_PIPELINE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PIPELINE))
-#define GST_PIPELINE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PIPELINE, GstPipelineClass))
-#define GST_IS_PIPELINE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PIPELINE))
-#define GST_PIPELINE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PIPELINE, GstPipelineClass))
-#define GST_PIPELINE_CAST(obj)                 ((GstPipeline*)(obj))
+#define GST_TYPE_PIPELINE               (gst_pipeline_get_type ())
+#define GST_PIPELINE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PIPELINE, GstPipeline))
+#define GST_IS_PIPELINE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PIPELINE))
+#define GST_PIPELINE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PIPELINE, GstPipelineClass))
+#define GST_IS_PIPELINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PIPELINE))
+#define GST_PIPELINE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PIPELINE, GstPipelineClass))
+#define GST_PIPELINE_CAST(obj)          ((GstPipeline*)(obj))
 
 typedef struct _GstPipeline GstPipeline;
 typedef struct _GstPipelineClass GstPipelineClass;
@@ -55,7 +55,7 @@ typedef enum {
 
 /**
  * GstPipeline:
- * @fixed_clock: The fixed clock of the pipeline, used when 
+ * @fixed_clock: The fixed clock of the pipeline, used when
  *               GST_PIPELINE_FLAG_FIXED_CLOCK is set.
  * @stream_time: The stream time of the pipeline. A better name for this
  *         property would be the running_time, the total time spent in the
@@ -67,18 +67,18 @@ typedef enum {
  * The #GstPipeline structure.
  */
 struct _GstPipeline {
-  GstBin        bin;
+  GstBin         bin;
 
   /*< public >*/ /* with LOCK */
   GstClock      *fixed_clock;
 
-  GstClockTime   stream_time;  
+  GstClockTime   stream_time;
   GstClockTime   delay;
 
   /*< private >*/
   GstPipelinePrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING-1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstPipelineClass {
@@ -88,15 +88,10 @@ struct _GstPipelineClass {
   gpointer _gst_reserved[GST_PADDING];
 };
 
-GType          gst_pipeline_get_type           (void);
-GstElement*    gst_pipeline_new                (const gchar *name) G_GNUC_MALLOC;
-
-GstBus*                gst_pipeline_get_bus            (GstPipeline *pipeline);
+GType           gst_pipeline_get_type           (void);
+GstElement*     gst_pipeline_new                (const gchar *name) G_GNUC_MALLOC;
 
-#ifndef GST_DISABLE_DEPRECATED
-void           gst_pipeline_set_new_stream_time  (GstPipeline *pipeline, GstClockTime time);
-GstClockTime   gst_pipeline_get_last_stream_time (GstPipeline *pipeline);
-#endif
+GstBus*         gst_pipeline_get_bus            (GstPipeline *pipeline);
 
 void            gst_pipeline_use_clock          (GstPipeline *pipeline, GstClock *clock);
 gboolean        gst_pipeline_set_clock          (GstPipeline *pipeline, GstClock *clock);
index 02e5cc9..8c2d7bb 100644 (file)
@@ -123,15 +123,20 @@ static void
 gst_plugin_finalize (GObject * object)
 {
   GstPlugin *plugin = GST_PLUGIN_CAST (object);
-  GstRegistry *registry = gst_registry_get_default ();
-  GList *g;
 
   GST_DEBUG ("finalizing plugin %" GST_PTR_FORMAT, plugin);
+
+  /* FIXME: make registry add a weak ref instead */
+#if 0
+  GstRegistry *registry = gst_registry_get ();
+  GList *g;
   for (g = registry->plugins; g; g = g->next) {
     if (g->data == (gpointer) plugin) {
       g_warning ("removing plugin that is still in registry");
     }
   }
+#endif
+
   g_free (plugin->filename);
   g_free (plugin->basename);
 
@@ -164,38 +169,6 @@ gst_plugin_error_quark (void)
   return quark;
 }
 
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void _gst_plugin_register_static (GstPluginDesc * desc);
-#endif
-/* this function can be called in the GCC constructor extension, before
- * the _gst_plugin_initialize() was called. In that case, we store the
- * plugin description in a list to initialize it when we open the main
- * module later on.
- * When the main module is known, we can register the plugin right away.
- */
-void
-_gst_plugin_register_static (GstPluginDesc * desc)
-{
-  g_return_if_fail (desc != NULL);
-
-  if (!_gst_plugin_inited) {
-    /* We can't use any GLib functions here, since g_thread_init hasn't been
-     * called yet, and we can't call it here either, or programs that don't
-     * guard their g_thread_init calls in main() will just abort */
-    ++_num_static_plugins;
-    _static_plugins =
-        realloc (_static_plugins, _num_static_plugins * sizeof (GstPluginDesc));
-    /* assume strings in the GstPluginDesc are static const or live forever */
-    _static_plugins[_num_static_plugins - 1] = *desc;
-  } else {
-    gst_plugin_register_static (desc->major_version, desc->minor_version,
-        desc->name, desc->description, desc->plugin_init, desc->version,
-        desc->license, desc->source, desc->package, desc->origin);
-  }
-}
-#endif
-
 /**
  * gst_plugin_register_static:
  * @major_version: the major version number of the GStreamer core that the
@@ -253,7 +226,7 @@ gst_plugin_register_static (gint major_version, gint minor_version,
   plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
   if (gst_plugin_register_func (plugin, &desc, NULL) != NULL) {
     GST_INFO ("registered static plugin \"%s\"", name);
-    res = gst_default_registry_add_plugin (plugin);
+    res = gst_registry_add_plugin (gst_registry_get (), plugin);
     GST_INFO ("added static plugin \"%s\", result: %d", name, res);
   }
   return res;
@@ -323,14 +296,14 @@ gst_plugin_register_static_full (gint major_version, gint minor_version,
   plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
   if (gst_plugin_register_func (plugin, &desc, user_data) != NULL) {
     GST_INFO ("registered static plugin \"%s\"", name);
-    res = gst_default_registry_add_plugin (plugin);
+    res = gst_registry_add_plugin (gst_registry_get (), plugin);
     GST_INFO ("added static plugin \"%s\", result: %d", name, res);
   }
   return res;
 }
 
 void
-_gst_plugin_initialize (void)
+_priv_gst_plugin_initialize (void)
 {
   const gchar *whitelist;
   guint i;
@@ -686,7 +659,7 @@ check_release_datetime (const gchar * date_time)
   return (*date_time == '\0');
 }
 
-static GStaticMutex gst_plugin_loading_mutex = G_STATIC_MUTEX_INIT;
+static GMutex gst_plugin_loading_mutex;
 
 #define CHECK_PLUGIN_DESC_FIELD(desc,field,fn)                               \
   if (G_UNLIKELY ((desc)->field == NULL)) {                                  \
@@ -718,14 +691,14 @@ gst_plugin_load_file (const gchar * filename, GError ** error)
 
   g_return_val_if_fail (filename != NULL, NULL);
 
-  registry = gst_registry_get_default ();
-  g_static_mutex_lock (&gst_plugin_loading_mutex);
+  registry = gst_registry_get ();
+  g_mutex_lock (&gst_plugin_loading_mutex);
 
   plugin = gst_registry_lookup (registry, filename);
   if (plugin) {
     if (plugin->module) {
       /* already loaded */
-      g_static_mutex_unlock (&gst_plugin_loading_mutex);
+      g_mutex_unlock (&gst_plugin_loading_mutex);
       return plugin;
     } else {
       /* load plugin and update fields */
@@ -860,17 +833,17 @@ gst_plugin_load_file (const gchar * filename, GError ** error)
 
   if (new_plugin) {
     gst_object_ref (plugin);
-    gst_default_registry_add_plugin (plugin);
+    gst_registry_add_plugin (gst_registry_get (), plugin);
   }
 
-  g_static_mutex_unlock (&gst_plugin_loading_mutex);
+  g_mutex_unlock (&gst_plugin_loading_mutex);
   return plugin;
 
 return_error:
   {
     if (plugin)
       gst_object_unref (plugin);
-    g_static_mutex_unlock (&gst_plugin_loading_mutex);
+    g_mutex_unlock (&gst_plugin_loading_mutex);
     return NULL;
   }
 }
@@ -1291,7 +1264,7 @@ gst_plugin_load_by_name (const gchar * name)
   GError *error = NULL;
 
   GST_DEBUG ("looking up plugin %s in default registry", name);
-  plugin = gst_registry_find_plugin (gst_registry_get_default (), name);
+  plugin = gst_registry_find_plugin (gst_registry_get (), name);
   if (plugin) {
     GST_DEBUG ("loading plugin %s from file %s", name, plugin->filename);
     newplugin = gst_plugin_load_file (plugin->filename, &error);
index 81ad00a..c946041 100644 (file)
@@ -175,7 +175,7 @@ struct _GstPluginDesc {
   const gchar *origin;
   const gchar *release_datetime;
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 
@@ -213,7 +213,8 @@ struct _GstPlugin {
                                  * that matches the plugin's basename */
 
   GstPluginPrivate *priv;
-  gpointer _gst_reserved[GST_PADDING - 1];
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstPluginClass {
@@ -273,53 +274,6 @@ GST_PLUGIN_EXPORT GstPluginDesc gst_plugin_desc = {        \
 G_END_DECLS
 
 /**
- * GST_PLUGIN_DEFINE_STATIC:
- * @major: major version number of the gstreamer-core that plugin was compiled for
- * @minor: minor version number of the gstreamer-core that plugin was compiled for
- * @name: short, but unique name of the plugin
- * @description: information about the purpose of the plugin
- * @init: function pointer to the plugin_init method with the signature of <code>static gboolean plugin_init (GstPlugin * plugin)</code>.
- * @version: full version string (e.g. VERSION from config.h)
- * @license: under which licence the package has been released, e.g. GPL, LGPL.
- * @package: the package-name (e.g. PACKAGE_NAME from config.h)
- * @origin: a description from where the package comes from (e.g. the homepage URL)
- *
- * This macro needs to be used to define the entry point and meta data of a
- * local plugin. One would use this macro to define a local plugin that can only
- * be used by the own application.
- *
- * The macro uses a define named PACKAGE for the #GstPluginDesc.source field.
- *
- * Deprecated: Use gst_plugin_register_static() instead. This macro was
- * deprecated because it uses constructors, which is a compiler feature not
- * available on all compilers.
- *
- */
-/* We don't have deprecation guards here on purpose, it's enough to have
- * deprecation guards around _gst_plugin_register_static(), and will result in
- * much better error messages when compiling with -DGST_DISABLE_DEPRECATED */
-#define GST_PLUGIN_DEFINE_STATIC(major,minor,name,description,init,version,license,package,origin)  \
-static void GST_GNUC_CONSTRUCTOR                       \
-_gst_plugin_static_init__ ##init (void)                        \
-{                                                      \
-  static GstPluginDesc plugin_desc_ = {                        \
-    major,                                             \
-    minor,                                             \
-    name,                                              \
-    (gchar *) description,                             \
-    init,                                              \
-    version,                                           \
-    license,                                           \
-    PACKAGE,                                           \
-    package,                                           \
-    origin,                                            \
-    NULL,                                              \
-    GST_PADDING_INIT                                   \
-  };                                                   \
-  _gst_plugin_register_static (&plugin_desc_);         \
-}
-
-/**
  * GST_LICENSE_UNKNOWN:
  *
  * To be used in GST_PLUGIN_DEFINE or GST_PLUGIN_DEFINE_STATIC if usure about
@@ -344,10 +298,6 @@ typedef gboolean        (*GstPluginFilter)              (GstPlugin *plugin,
 
 GType                   gst_plugin_get_type             (void);
 
-#ifndef GST_DISABLE_DEPRECATED
-void                   _gst_plugin_register_static     (GstPluginDesc *desc);
-#endif
-
 gboolean               gst_plugin_register_static      (gint major_version,
                                                          gint minor_version,
                                                          const gchar *name,
@@ -392,12 +342,11 @@ GstPlugin *               gst_plugin_load_file            (const gchar *filename, GError** error);
 GstPlugin *             gst_plugin_load                 (GstPlugin *plugin);
 GstPlugin *             gst_plugin_load_by_name         (const gchar *name);
 
-void                    gst_plugin_add_dependency (GstPlugin    * plugin,
-                                                   const gchar ** env_vars,
-                                                   const gchar ** paths,
-                                                   const gchar ** names,
-                                                   GstPluginDependencyFlags flags);
-
+void                    gst_plugin_add_dependency        (GstPlugin    * plugin,
+                                                          const gchar ** env_vars,
+                                                          const gchar ** paths,
+                                                          const gchar ** names,
+                                                          GstPluginDependencyFlags flags);
 void                    gst_plugin_add_dependency_simple (GstPlugin   * plugin,
                                                           const gchar * env_vars,
                                                           const gchar * paths,
index acdc621..58bab7e 100644 (file)
@@ -63,8 +63,7 @@ gst_plugin_feature_finalize (GObject * object)
 {
   GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (object);
 
-  GST_DEBUG ("finalizing feature %p: '%s'", feature,
-      GST_PLUGIN_FEATURE_NAME (feature));
+  GST_DEBUG ("finalizing feature %p: '%s'", feature, GST_OBJECT_NAME (feature));
 
   if (feature->plugin != NULL) {
     g_object_remove_weak_pointer ((GObject *) feature->plugin,
@@ -103,7 +102,7 @@ gst_plugin_feature_load (GstPluginFeature * feature)
   g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
 
   GST_DEBUG ("loading plugin for feature %p; '%s'", feature,
-      GST_PLUGIN_FEATURE_NAME (feature));
+      GST_OBJECT_NAME (feature));
   if (feature->loaded)
     return gst_object_ref (feature);
 
@@ -115,8 +114,8 @@ gst_plugin_feature_load (GstPluginFeature * feature)
   GST_DEBUG ("loaded plugin %s", feature->plugin_name);
   gst_object_unref (plugin);
 
-  real_feature =
-      gst_registry_lookup_feature (gst_registry_get_default (), feature->name);
+  real_feature = gst_registry_lookup_feature (gst_registry_get (),
+      GST_OBJECT_NAME (feature));
 
   if (real_feature == NULL)
     goto disappeared;
@@ -129,96 +128,25 @@ gst_plugin_feature_load (GstPluginFeature * feature)
 load_failed:
   {
     GST_WARNING ("Failed to load plugin containing feature '%s'.",
-        GST_PLUGIN_FEATURE_NAME (feature));
+        GST_OBJECT_NAME (feature));
     return NULL;
   }
 disappeared:
   {
     GST_INFO
         ("Loaded plugin containing feature '%s', but feature disappeared.",
-        feature->name);
+        GST_OBJECT_NAME (feature));
     return NULL;
   }
 not_found:
   {
     GST_INFO ("Tried to load plugin containing feature '%s', but feature was "
-        "not found.", real_feature->name);
+        "not found.", GST_OBJECT_NAME (real_feature));
     return NULL;
   }
 }
 
 /**
- * gst_plugin_feature_type_name_filter:
- * @feature: the #GstPluginFeature
- * @data: (in): the type and name to check against
- *
- * Compares type and name of plugin feature. Can be used with gst_filter_run().
- *
- * Returns: TRUE if equal.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-typedef struct
-{
-  const gchar *name;
-  GType type;
-} GstTypeNameData;
-gboolean gst_plugin_feature_type_name_filter (GstPluginFeature * feature,
-    GstTypeNameData * data);
-#endif
-gboolean
-gst_plugin_feature_type_name_filter (GstPluginFeature * feature,
-    GstTypeNameData * data)
-{
-  g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
-
-  return ((data->type == 0 || data->type == G_OBJECT_TYPE (feature)) &&
-      (data->name == NULL
-          || !strcmp (data->name, GST_PLUGIN_FEATURE_NAME (feature))));
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
- * gst_plugin_feature_set_name:
- * @feature: a feature
- * @name: the name to set
- *
- * Sets the name of a plugin feature. The name uniquely identifies a feature
- * within all features of the same type. Renaming a plugin feature is not
- * allowed. A copy is made of the name so you should free the supplied @name
- * after calling this function.
- */
-void
-gst_plugin_feature_set_name (GstPluginFeature * feature, const gchar * name)
-{
-  g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
-  g_return_if_fail (name != NULL);
-
-  if (G_UNLIKELY (feature->name)) {
-    g_return_if_fail (strcmp (feature->name, name) == 0);
-  } else {
-    gst_object_set_name (GST_OBJECT (feature), name);
-    feature->name = GST_OBJECT_NAME (GST_OBJECT (feature));
-  }
-}
-
-/**
- * gst_plugin_feature_get_name:
- * @feature: a feature
- *
- * Gets the name of a plugin feature.
- *
- * Returns: the name
- */
-const gchar *
-gst_plugin_feature_get_name (GstPluginFeature * feature)
-{
-  g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), NULL);
-
-  return feature->name;
-}
-
-/**
  * gst_plugin_feature_set_rank:
  * @feature: feature to rank
  * @rank: rank value - higher number means more priority rank
@@ -356,9 +284,9 @@ gst_plugin_feature_check_version (GstPluginFeature * feature,
   g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
 
   GST_DEBUG ("Looking up plugin '%s' containing plugin feature '%s'",
-      feature->plugin_name, feature->name);
+      feature->plugin_name, GST_OBJECT_NAME (feature));
 
-  registry = gst_registry_get_default ();
+  registry = gst_registry_get ();
   plugin = gst_registry_find_plugin (registry, feature->plugin_name);
 
   if (plugin) {
@@ -433,7 +361,7 @@ gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2)
   if (diff != 0)
     return diff;
 
-  diff = strcmp (f2->name, f1->name);
+  diff = strcmp (GST_OBJECT_NAME (f2), GST_OBJECT_NAME (f1));
 
   return diff;
 }
index 1a675cd..b99d9ee 100644 (file)
@@ -38,14 +38,6 @@ G_BEGIN_DECLS
 #define GST_PLUGIN_FEATURE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLUGIN_FEATURE, GstPluginFeatureClass))
 #define GST_PLUGIN_FEATURE_CAST(obj)            ((GstPluginFeature*)(obj))
 
-/**
- * GST_PLUGIN_FEATURE_NAME:
- * @feature: The feature to query
- *
- * Get the name of the feature
- */
-#define GST_PLUGIN_FEATURE_NAME(feature)  (GST_PLUGIN_FEATURE (feature)->name)
-
 typedef struct _GstPluginFeature GstPluginFeature;
 typedef struct _GstPluginFeatureClass GstPluginFeatureClass;
 
@@ -72,6 +64,27 @@ typedef enum {
 } GstRank;
 
 /**
+ * gst_plugin_feature_get_name:
+ * @feature: a #GstPluginFeature to get the name of @feature.
+ *
+ * Returns the name of @feature.
+ * For a nameless plugin feature, this returns NULL.
+ *
+ * Returns: (transfer none): the name of @feature. MT safe.
+ *
+ */
+#define                 gst_plugin_feature_get_name(feature)      GST_OBJECT_NAME(feature)
+
+/**
+ * gst_plugin_feature_set_name:
+ * @feature: a #GstPluginFeature to set the name of.
+ * @name: the new name
+ *
+ * Sets the name of the plugin feature, getting rid of the old name if there was one.
+ */
+#define                 gst_plugin_feature_set_name(feature,name) gst_object_set_name(GST_OBJECT_CAST(feature),name)
+
+/**
  * GstPluginFeature:
  *
  * Opaque #GstPluginFeature structure.
@@ -81,14 +94,13 @@ struct _GstPluginFeature {
 
   /*< private >*/
   gboolean       loaded;
-  gchar         *name; /* FIXME-0.11: remove variable, we use GstObject:name */
   guint          rank;
 
   const gchar   *plugin_name;
   GstPlugin     *plugin;      /* weak ref */
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstPluginFeatureClass {
@@ -99,20 +111,6 @@ struct _GstPluginFeatureClass {
 };
 
 /**
- * GstTypeNameData:
- * @name: a name
- * @type: a GType
- *
- * Structure used for filtering based on @name and @type.
- */
-#ifndef GST_DISABLE_DEPRECATED
-typedef struct {
-  const gchar   *name;
-  GType          type;
-} GstTypeNameData;
-#endif
-
-/**
  * GstPluginFeatureFilter:
  * @feature: the pluginfeature to check
  * @user_data: the user_data that has been passed on e.g.
@@ -132,15 +130,8 @@ GType           gst_plugin_feature_get_type             (void);
 GstPluginFeature *
                 gst_plugin_feature_load                 (GstPluginFeature *feature);
 
-#ifndef GST_DISABLE_DEPRECATED
-gboolean        gst_plugin_feature_type_name_filter     (GstPluginFeature *feature,
-                                                         GstTypeNameData *data);
-#endif
-
 void            gst_plugin_feature_set_rank             (GstPluginFeature *feature, guint rank);
-void            gst_plugin_feature_set_name             (GstPluginFeature *feature, const gchar *name);
 guint           gst_plugin_feature_get_rank             (GstPluginFeature *feature);
-const gchar    *gst_plugin_feature_get_name             (GstPluginFeature *feature);
 
 void            gst_plugin_feature_list_free            (GList *list);
 GList          *gst_plugin_feature_list_copy            (GList *list) G_GNUC_MALLOC;
index 8bb2df8..4539421 100644 (file)
@@ -701,7 +701,7 @@ do_plugin_load (GstPluginLoader * l, const gchar * filename, guint tag)
 
     /* Now serialise the plugin details and send */
     if (!_priv_gst_registry_chunks_save_plugin (&chunks,
-            gst_registry_get_default (), newplugin))
+            gst_registry_get (), newplugin))
       goto fail;
 
     /* Store where the header is, write an empty one, then write
index b2dbabd..448b034 100644 (file)
@@ -26,10 +26,10 @@ G_BEGIN_DECLS
 typedef struct _GstPluginLoader GstPluginLoader;
 
 typedef struct _GstPluginLoaderFuncs {
-  GstPluginLoader * (*create)(GstRegistry *registry);
-  gboolean (*destroy)(GstPluginLoader *loader);
-  gboolean (*load)(GstPluginLoader *loader, const gchar *filename,
-      off_t file_size, time_t file_mtime);
+  GstPluginLoader * (*create)   (GstRegistry *registry);
+  gboolean          (*destroy)  (GstPluginLoader *loader);
+  gboolean          (*load)     (GstPluginLoader *loader, const gchar *filename,
+                                 off_t file_size, time_t file_mtime);
 } GstPluginLoaderFuncs;
 
 extern const GstPluginLoaderFuncs _priv_gst_plugin_loader_funcs;
index 5585508..e68b14a 100644 (file)
@@ -125,7 +125,7 @@ struct _GstPoll
 {
   GstPollMode mode;
 
-  GMutex *lock;
+  GMutex lock;
   /* array of fds, always written to and read from with lock */
   GArray *fds;
   /* array of active fds, only written to from the waiting thread with the
@@ -160,8 +160,8 @@ static gboolean gst_poll_add_fd_unlocked (GstPoll * set, GstPollFD * fd);
 #define IS_FLUSHING(s)      (g_atomic_int_get(&(s)->flushing))
 #define SET_FLUSHING(s,val) (g_atomic_int_set(&(s)->flushing, (val)))
 
-#define INC_WAITING(s)      (G_ATOMIC_INT_ADD(&(s)->waiting, 1))
-#define DEC_WAITING(s)      (G_ATOMIC_INT_ADD(&(s)->waiting, -1))
+#define INC_WAITING(s)      (g_atomic_int_add(&(s)->waiting, 1))
+#define DEC_WAITING(s)      (g_atomic_int_add(&(s)->waiting, -1))
 #define GET_WAITING(s)      (g_atomic_int_get(&(s)->waiting))
 
 #define TEST_REBUILD(s)     (g_atomic_int_compare_and_exchange(&(s)->rebuild, 1, 0))
@@ -182,8 +182,9 @@ raise_wakeup (GstPoll * set)
 {
   gboolean result = TRUE;
 
-  if (G_ATOMIC_INT_ADD (&set->control_pending, 1) == 0) {
+  if (g_atomic_int_add (&set->control_pending, 1) == 0) {
     /* raise when nothing pending */
+    GST_LOG ("%p: raise", set);
     result = WAKE_EVENT (set);
   }
   return result;
@@ -198,6 +199,7 @@ release_wakeup (GstPoll * set)
   gboolean result = TRUE;
 
   if (g_atomic_int_dec_and_test (&set->control_pending)) {
+    GST_LOG ("%p: release", set);
     result = RELEASE_EVENT (set);
   }
   return result;
@@ -220,7 +222,7 @@ release_all_wakeup (GstPoll * set)
         break;
       else
         /* retry again until we read it successfully */
-        G_ATOMIC_INT_ADD (&set->control_pending, 1);
+        g_atomic_int_add (&set->control_pending, 1);
     }
   }
   return old;
@@ -274,20 +276,20 @@ selectable_fds (const GstPoll * set)
 {
   guint i;
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
   for (i = 0; i < set->fds->len; i++) {
     struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, i);
 
     if (pfd->fd >= FD_SETSIZE)
       goto too_many;
   }
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return TRUE;
 
 too_many:
   {
-    g_mutex_unlock (set->lock);
+    g_mutex_unlock (&set->lock);
     return FALSE;
   }
 }
@@ -350,7 +352,7 @@ pollfd_to_fd_set (GstPoll * set, fd_set * readfds, fd_set * writefds,
   FD_ZERO (writefds);
   FD_ZERO (errorfds);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   for (i = 0; i < set->active_fds->len; i++) {
     struct pollfd *pfd = &g_array_index (set->fds, struct pollfd, i);
@@ -367,7 +369,7 @@ pollfd_to_fd_set (GstPoll * set, fd_set * readfds, fd_set * writefds,
     }
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return max_fd;
 }
@@ -378,7 +380,7 @@ fd_set_to_pollfd (GstPoll * set, fd_set * readfds, fd_set * writefds,
 {
   guint i;
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   for (i = 0; i < set->active_fds->len; i++) {
     struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, i);
@@ -394,7 +396,7 @@ fd_set_to_pollfd (GstPoll * set, fd_set * readfds, fd_set * writefds,
     }
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 }
 #else /* G_OS_WIN32 */
 /*
@@ -535,7 +537,7 @@ gst_poll_collect_winsock_events (GstPoll * set)
 #endif
 
 /**
- * gst_poll_new:
+ * gst_poll_new: (skip)
  * @controllable: whether it should be possible to control a wait.
  *
  * Create a new file descriptor set. If @controllable, it
@@ -557,7 +559,7 @@ gst_poll_new (gboolean controllable)
   GST_DEBUG ("controllable : %d", controllable);
 
   nset = g_slice_new0 (GstPoll);
-  nset->lock = g_mutex_new ();
+  g_mutex_init (&nset->lock);
 #ifndef G_OS_WIN32
   nset->mode = GST_POLL_MODE_AUTO;
   nset->fds = g_array_new (FALSE, FALSE, sizeof (struct pollfd));
@@ -609,7 +611,7 @@ no_socket_pair:
 }
 
 /**
- * gst_poll_new_timer:
+ * gst_poll_new_timer: (skip)
  *
  * Create a new poll object that can be used for scheduling cancellable
  * timeouts.
@@ -677,7 +679,7 @@ gst_poll_free (GstPoll * set)
 
   g_array_free (set->active_fds, TRUE);
   g_array_free (set->fds, TRUE);
-  g_mutex_free (set->lock);
+  g_mutex_clear (&set->lock);
   g_slice_free (GstPoll, set);
 }
 
@@ -790,11 +792,11 @@ gst_poll_add_fd (GstPoll * set, GstPollFD * fd)
   g_return_val_if_fail (fd != NULL, FALSE);
   g_return_val_if_fail (fd->fd >= 0, FALSE);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   ret = gst_poll_add_fd_unlocked (set, fd);
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return ret;
 }
@@ -822,7 +824,7 @@ gst_poll_remove_fd (GstPoll * set, GstPollFD * fd)
 
   GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   /* get the index, -1 is an fd that is not added */
   idx = find_index (set->fds, fd);
@@ -843,7 +845,7 @@ gst_poll_remove_fd (GstPoll * set, GstPollFD * fd)
     GST_WARNING ("%p: couldn't find fd !", set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return idx >= 0;
 }
@@ -873,7 +875,7 @@ gst_poll_fd_ctl_write (GstPoll * set, GstPollFD * fd, gboolean active)
   GST_DEBUG ("%p: fd (fd:%d, idx:%d), active : %d", set,
       fd->fd, fd->idx, active);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   idx = find_index (set->fds, fd);
   if (idx >= 0) {
@@ -895,7 +897,7 @@ gst_poll_fd_ctl_write (GstPoll * set, GstPollFD * fd, gboolean active)
     GST_WARNING ("%p: couldn't find fd !", set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return idx >= 0;
 }
@@ -951,11 +953,11 @@ gst_poll_fd_ctl_read (GstPoll * set, GstPollFD * fd, gboolean active)
   g_return_val_if_fail (fd != NULL, FALSE);
   g_return_val_if_fail (fd->fd >= 0, FALSE);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   ret = gst_poll_fd_ctl_read_unlocked (set, fd, active);
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 
   return ret;
 }
@@ -986,7 +988,7 @@ gst_poll_fd_ignored (GstPoll * set, GstPollFD * fd)
   g_return_if_fail (fd != NULL);
   g_return_if_fail (fd->fd >= 0);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&set->lock);
 
   idx = find_index (set->fds, fd);
   if (idx >= 0) {
@@ -996,7 +998,7 @@ gst_poll_fd_ignored (GstPoll * set, GstPollFD * fd)
     MARK_REBUILD (set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&set->lock);
 #endif
 }
 
@@ -1023,7 +1025,7 @@ gst_poll_fd_has_closed (const GstPoll * set, GstPollFD * fd)
 
   GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&((GstPoll *) set)->lock);
 
   idx = find_index (set->active_fds, fd);
   if (idx >= 0) {
@@ -1040,7 +1042,7 @@ gst_poll_fd_has_closed (const GstPoll * set, GstPollFD * fd)
     GST_WARNING ("%p: couldn't find fd !", set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&((GstPoll *) set)->lock);
 
   return res;
 }
@@ -1068,7 +1070,7 @@ gst_poll_fd_has_error (const GstPoll * set, GstPollFD * fd)
 
   GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&((GstPoll *) set)->lock);
 
   idx = find_index (set->active_fds, fd);
   if (idx >= 0) {
@@ -1089,7 +1091,7 @@ gst_poll_fd_has_error (const GstPoll * set, GstPollFD * fd)
     GST_WARNING ("%p: couldn't find fd !", set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&((GstPoll *) set)->lock);
 
   return res;
 }
@@ -1140,11 +1142,11 @@ gst_poll_fd_can_read (const GstPoll * set, GstPollFD * fd)
   g_return_val_if_fail (fd != NULL, FALSE);
   g_return_val_if_fail (fd->fd >= 0, FALSE);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&((GstPoll *) set)->lock);
 
   res = gst_poll_fd_can_read_unlocked (set, fd);
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&((GstPoll *) set)->lock);
 
   return res;
 }
@@ -1172,7 +1174,7 @@ gst_poll_fd_can_write (const GstPoll * set, GstPollFD * fd)
 
   GST_DEBUG ("%p: fd (fd:%d, idx:%d)", set, fd->fd, fd->idx);
 
-  g_mutex_lock (set->lock);
+  g_mutex_lock (&((GstPoll *) set)->lock);
 
   idx = find_index (set->active_fds, fd);
   if (idx >= 0) {
@@ -1189,7 +1191,7 @@ gst_poll_fd_can_write (const GstPoll * set, GstPollFD * fd)
     GST_WARNING ("%p: couldn't find fd !", set);
   }
 
-  g_mutex_unlock (set->lock);
+  g_mutex_unlock (&((GstPoll *) set)->lock);
 
   return res;
 }
@@ -1250,7 +1252,7 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout)
     mode = choose_mode (set, timeout);
 
     if (TEST_REBUILD (set)) {
-      g_mutex_lock (set->lock);
+      g_mutex_lock (&set->lock);
 #ifndef G_OS_WIN32
       g_array_set_size (set->active_fds, set->fds->len);
       memcpy (set->active_fds->data, set->fds->data,
@@ -1259,7 +1261,7 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout)
       if (!gst_poll_prepare_winsock_active_sets (set))
         goto winsock_error;
 #endif
-      g_mutex_unlock (set->lock);
+      g_mutex_unlock (&set->lock);
     }
 
     switch (mode) {
@@ -1423,12 +1425,10 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout)
         restarting = TRUE;
     }
 
-    if (G_UNLIKELY (IS_FLUSHING (set))) {
-      /* we got woken up and we are flushing, we need to stop */
-      errno = EBUSY;
-      res = -1;
-      break;
-    }
+    /* we got woken up and we are flushing, we need to stop */
+    if (G_UNLIKELY (IS_FLUSHING (set)))
+      goto flushing;
+
   } while (G_UNLIKELY (restarting));
 
   DEC_WAITING (set);
@@ -1438,12 +1438,14 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout)
   /* ERRORS */
 already_waiting:
   {
+    GST_LOG ("%p: we are already waiting", set);
     DEC_WAITING (set);
     errno = EPERM;
     return -1;
   }
 flushing:
   {
+    GST_LOG ("%p: we are flushing", set);
     DEC_WAITING (set);
     errno = EBUSY;
     return -1;
@@ -1451,7 +1453,8 @@ flushing:
 #ifdef G_OS_WIN32
 winsock_error:
   {
-    g_mutex_unlock (set->lock);
+    GST_LOG ("%p: winsock error", set);
+    g_mutex_unlock (&set->lock);
     DEC_WAITING (set);
     return -1;
   }
@@ -1523,6 +1526,8 @@ gst_poll_set_flushing (GstPoll * set, gboolean flushing)
 {
   g_return_if_fail (set != NULL);
 
+  GST_LOG ("%p: flushing: %d", set, flushing);
+
   /* update the new state first */
   SET_FLUSHING (set, flushing);
 
index 2cd0879..a30d2e6 100644 (file)
@@ -158,9 +158,9 @@ preset_get_paths (GstPreset * preset, const gchar ** preset_user_path,
     if (!(preset_path = g_type_get_qdata (type, preset_user_path_quark))) {
       gchar *preset_dir;
 
-      /* user presets go in '$HOME/.gstreamer-0.10/presets/GstSimSyn.prs' */
-      preset_dir = g_build_filename (g_get_home_dir (),
-          ".gstreamer-" GST_MAJORMINOR, "presets", NULL);
+      /* user presets go in  user's XDG data directory. */
+      preset_dir = g_build_filename (g_get_user_data_dir (),
+          "gstreamer-" GST_MAJORMINOR, "presets", NULL);
       GST_INFO_OBJECT (preset, "user_preset_dir: '%s'", preset_dir);
       preset_path =
           g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", preset_dir,
index 4e60712..bb512dc 100644 (file)
@@ -67,7 +67,7 @@ struct _GstPresetInterface
   gboolean     (*rename_preset)       (GstPreset *preset, const gchar *old_name,
                                        const gchar *new_name);
   gboolean     (*delete_preset)       (GstPreset *preset, const gchar *name);
-  
+
   gboolean     (*set_meta)            (GstPreset *preset, const gchar *name,
                                        const gchar *tag, const gchar *value);
   gboolean     (*get_meta)            (GstPreset *preset, const gchar *name,
index 91a2012..b687095 100644 (file)
@@ -33,24 +33,29 @@ static const gchar *_quark_strings[] = {
   "gerror", "debug", "buffer-percent", "buffering-mode",
   "avg-in-rate", "avg-out-rate", "buffering-left",
   "estimated-total", "old-state", "new-state", "pending-state",
-  "clock", "ready", "position", "new-base-time", "live", "min-latency",
+  "clock", "ready", "position", "reset-time", "live", "min-latency",
   "max-latency", "busy", "type", "owner", "update", "applied-rate",
   "start", "stop", "minsize", "maxsize", "async", "proportion",
   "diff", "timestamp", "flags", "cur-type", "cur", "stop-type",
-  "latency", "uri", "object", "taglist", "GstEventNewsegment",
+  "latency", "uri", "object", "taglist", "GstEventSegment",
   "GstEventBufferSize", "GstEventQOS", "GstEventSeek", "GstEventLatency",
   "GstMessageError", "GstMessageWarning", "GstMessageInfo",
   "GstMessageBuffering", "GstMessageState", "GstMessageClockProvide",
   "GstMessageClockLost", "GstMessageNewClock", "GstMessageStructureChange",
   "GstMessageSegmentStart", "GstMessageSegmentDone", "GstMessageDuration",
-  "GstMessageAsyncStart", "GstMessageRequestState", "GstMessageStreamStatus",
+  "GstMessageAsyncDone", "GstMessageRequestState", "GstMessageStreamStatus",
   "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert",
   "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
   "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
   "intermediate", "GstMessageStepStart", "active", "eos", "sink-message",
   "message", "GstMessageQOS", "running-time", "stream-time", "jitter",
   "quality", "processed", "dropped", "buffering-ranges", "GstMessageProgress",
-  "code", "text", "percent", "timeout"
+  "code", "text", "percent", "timeout", "GstBufferPoolConfig", "caps", "size",
+  "min-buffers", "max-buffers", "prefix", "postfix", "align", "time",
+  "GstQueryAllocation", "need-pool", "meta", "pool", "GstEventCaps",
+  "GstEventReconfigure", "segment", "GstQueryScheduling", "pull-mode",
+  "allocator", "GstEventFlushStop", "options", "GstQueryAcceptCaps",
+  "result", "GstQueryCaps", "filter", "modes"
 };
 
 GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index 6e16ee5..758345c 100644 (file)
@@ -55,7 +55,7 @@ typedef enum _GstQuarkId
   GST_QUARK_CLOCK = 26,
   GST_QUARK_READY = 27,
   GST_QUARK_POSITION = 28,
-  GST_QUARK_NEW_BASE_TIME = 29,
+  GST_QUARK_RESET_TIME = 29,
   GST_QUARK_LIVE = 30,
   GST_QUARK_MIN_LATENCY = 31,
   GST_QUARK_MAX_LATENCY = 32,
@@ -80,7 +80,7 @@ typedef enum _GstQuarkId
   GST_QUARK_URI = 51,
   GST_QUARK_OBJECT = 52,
   GST_QUARK_TAGLIST = 53,
-  GST_QUARK_EVENT_NEWSEGMENT = 54,
+  GST_QUARK_EVENT_SEGMENT = 54,
   GST_QUARK_EVENT_BUFFER_SIZE = 55,
   GST_QUARK_EVENT_QOS = 56,
   GST_QUARK_EVENT_SEEK = 57,
@@ -97,7 +97,7 @@ typedef enum _GstQuarkId
   GST_QUARK_MESSAGE_SEGMENT_START = 68,
   GST_QUARK_MESSAGE_SEGMENT_DONE = 69,
   GST_QUARK_MESSAGE_DURATION = 70,
-  GST_QUARK_MESSAGE_ASYNC_START = 71,
+  GST_QUARK_MESSAGE_ASYNC_DONE = 71,
   GST_QUARK_MESSAGE_REQUEST_STATE = 72,
   GST_QUARK_MESSAGE_STREAM_STATUS = 73,
   GST_QUARK_QUERY_POSITION = 74,
@@ -132,8 +132,34 @@ typedef enum _GstQuarkId
   GST_QUARK_TEXT = 103,
   GST_QUARK_PERCENT = 104,
   GST_QUARK_TIMEOUT = 105,
+  GST_QUARK_BUFFER_POOL_CONFIG = 106,
+  GST_QUARK_CAPS = 107,
+  GST_QUARK_SIZE = 108,
+  GST_QUARK_MIN_BUFFERS = 109,
+  GST_QUARK_MAX_BUFFERS = 110,
+  GST_QUARK_PREFIX = 111,
+  GST_QUARK_POSTFIX = 112,
+  GST_QUARK_ALIGN = 113,
+  GST_QUARK_TIME = 114,
+  GST_QUARK_QUERY_ALLOCATION = 115,
+  GST_QUARK_NEED_POOL = 116,
+  GST_QUARK_META = 117,
+  GST_QUARK_POOL = 118,
+  GST_QUARK_EVENT_CAPS = 119,
+  GST_QUARK_EVENT_RECONFIGURE = 120,
+  GST_QUARK_SEGMENT = 121,
+  GST_QUARK_QUERY_SCHEDULING = 122,
+  GST_QUARK_PULL_MODE = 123,
+  GST_QUARK_ALLOCATOR = 124,
+  GST_QUARK_EVENT_FLUSH_STOP = 125,
+  GST_QUARK_OPTIONS = 126,
+  GST_QUARK_QUERY_ACCEPT_CAPS = 127,
+  GST_QUARK_RESULT = 128,
+  GST_QUARK_QUERY_CAPS = 129,
+  GST_QUARK_FILTER = 130,
+  GST_QUARK_MODES = 131,
 
-  GST_QUARK_MAX = 106
+  GST_QUARK_MAX = 132
 } GstQuarkId;
 
 extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
index 2b1c382..e4efe3e 100644 (file)
 #include "gstenumtypes.h"
 #include "gstquark.h"
 #include "gsturi.h"
+#include "gstbufferpool.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
 #define GST_CAT_DEFAULT gst_query_debug
 
-static void gst_query_finalize (GstQuery * query);
-static GstQuery *_gst_query_copy (GstQuery * query);
+static GType _gst_query_type = 0;
 
-static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+typedef struct
+{
+  GstQuery query;
+
+  GstStructure *structure;
+} GstQueryImpl;
+
+#define GST_QUERY_STRUCTURE(q)  (((GstQueryImpl *)(q))->structure)
+
+static GMutex mutex;
 static GList *_gst_queries = NULL;
 static GHashTable *_nick_to_query = NULL;
 static GHashTable *_query_type_to_nick = NULL;
 static guint32 _n_values = 1;   /* we start from 1 because 0 reserved for NONE */
 
-static GstMiniObjectClass *parent_class = NULL;
-
 static GstQueryTypeDefinition standard_definitions[] = {
   {GST_QUERY_POSITION, "position", "Current position", 0},
   {GST_QUERY_DURATION, "duration", "Total duration", 0},
@@ -96,11 +103,17 @@ static GstQueryTypeDefinition standard_definitions[] = {
   {GST_QUERY_BUFFERING, "buffering", "Buffering status", 0},
   {GST_QUERY_CUSTOM, "custom", "Custom query", 0},
   {GST_QUERY_URI, "uri", "URI of the source or sink", 0},
+  {GST_QUERY_ALLOCATION, "allocation", "Allocation properties", 0},
+  {GST_QUERY_SCHEDULING, "scheduling", "Scheduling properties", 0},
+  {GST_QUERY_ACCEPT_CAPS, "accept-caps", "Accept caps", 0},
+  {GST_QUERY_CAPS, "caps", "Caps", 0},
   {GST_QUERY_NONE, NULL, NULL, 0}
 };
 
+GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query);
+
 void
-_gst_query_initialize (void)
+_priv_gst_query_initialize (void)
 {
   GstQueryTypeDefinition *standards = standard_definitions;
 
@@ -108,7 +121,7 @@ _gst_query_initialize (void)
 
   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   if (_nick_to_query == NULL) {
     _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
     _query_type_to_nick = g_hash_table_new (NULL, NULL);
@@ -124,9 +137,9 @@ _gst_query_initialize (void)
     standards++;
     _n_values++;
   }
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
-  g_type_class_ref (gst_query_get_type ());
+  _gst_query_type = gst_query_get_type ();
 }
 
 /**
@@ -143,6 +156,7 @@ gst_query_type_get_name (GstQueryType query)
   const GstQueryTypeDefinition *def;
 
   def = gst_query_type_get_details (query);
+  g_return_val_if_fail (def != NULL, NULL);
 
   return def->nick;
 }
@@ -161,61 +175,11 @@ gst_query_type_to_quark (GstQueryType query)
   const GstQueryTypeDefinition *def;
 
   def = gst_query_type_get_details (query);
+  g_return_val_if_fail (def != NULL, 0);
 
   return def->quark;
 }
 
-G_DEFINE_TYPE (GstQuery, gst_query, GST_TYPE_MINI_OBJECT);
-
-static void
-gst_query_class_init (GstQueryClass * klass)
-{
-  parent_class = g_type_class_peek_parent (klass);
-
-  klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
-  klass->mini_object_class.finalize =
-      (GstMiniObjectFinalizeFunction) gst_query_finalize;
-
-}
-
-static void
-gst_query_init (GstQuery * query)
-{
-}
-
-static void
-gst_query_finalize (GstQuery * query)
-{
-  g_return_if_fail (query != NULL);
-
-  if (query->structure) {
-    gst_structure_set_parent_refcount (query->structure, NULL);
-    gst_structure_free (query->structure);
-  }
-
-/*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query)); */
-}
-
-static GstQuery *
-_gst_query_copy (GstQuery * query)
-{
-  GstQuery *copy;
-
-  copy = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
-
-  copy->type = query->type;
-
-  if (query->structure) {
-    copy->structure = gst_structure_copy (query->structure);
-    gst_structure_set_parent_refcount (copy->structure,
-        &query->mini_object.refcount);
-  }
-
-  return copy;
-}
-
-
-
 /**
  * gst_query_type_register:
  * @nick: The nick of the new query
@@ -246,13 +210,13 @@ gst_query_type_register (const gchar * nick, const gchar * description)
   query->description = g_strdup (description);
   query->quark = g_quark_from_static_string (query->nick);
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   g_hash_table_insert (_nick_to_query, (gpointer) query->nick, query);
   g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value),
       query);
   _gst_queries = g_list_append (_gst_queries, query);
   _n_values++;
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   return query->value;
 }
@@ -273,9 +237,9 @@ gst_query_type_get_by_nick (const gchar * nick)
 
   g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   query = g_hash_table_lookup (_nick_to_query, nick);
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   if (query != NULL)
     return query->value;
@@ -321,9 +285,9 @@ gst_query_type_get_details (GstQueryType type)
 {
   const GstQueryTypeDefinition *result;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type));
-  g_static_mutex_unlock (&mutex);
+  g_mutex_unlock (&mutex);
 
   return result;
 }
@@ -343,36 +307,66 @@ gst_query_type_iterate_definitions (void)
 {
   GstIterator *result;
 
-  g_static_mutex_lock (&mutex);
+  g_mutex_lock (&mutex);
   /* FIXME: register a boxed type for GstQueryTypeDefinition */
   result = gst_iterator_new_list (G_TYPE_POINTER,
-      g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_queries,
-      NULL, NULL, NULL);
-  g_static_mutex_unlock (&mutex);
+      &mutex, &_n_values, &_gst_queries, NULL, NULL);
+  g_mutex_unlock (&mutex);
 
   return result;
 }
 
+static void
+_gst_query_free (GstQuery * query)
+{
+  GstStructure *s;
+
+  g_return_if_fail (query != NULL);
+
+  s = GST_QUERY_STRUCTURE (query);
+  if (s) {
+    gst_structure_set_parent_refcount (s, NULL);
+    gst_structure_free (s);
+  }
+
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (query), query);
+}
+
+static GstQuery *gst_query_new (GstQueryType type, GstStructure * structure);
+
+static GstQuery *
+_gst_query_copy (GstQuery * query)
+{
+  GstQuery *copy;
+
+  copy = gst_query_new (query->type, GST_QUERY_STRUCTURE (query));
+
+  return copy;
+}
+
 static GstQuery *
 gst_query_new (GstQueryType type, GstStructure * structure)
 {
-  GstQuery *query;
+  GstQueryImpl *query;
+
+  query = g_slice_new0 (GstQueryImpl);
 
-  query = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (query),
+      _gst_query_type, sizeof (GstQueryImpl));
+
+  query->query.mini_object.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
+  query->query.mini_object.free = (GstMiniObjectFreeFunction) _gst_query_free;
 
   GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type));
 
-  query->type = type;
+  GST_QUERY_TYPE (query) = type;
+  query->structure = structure;
 
-  if (structure) {
-    query->structure = structure;
-    gst_structure_set_parent_refcount (query->structure,
-        &query->mini_object.refcount);
-  } else {
-    query->structure = NULL;
-  }
+  if (structure)
+    gst_structure_set_parent_refcount (structure,
+        &query->query.mini_object.refcount);
 
-  return query;
+  return GST_QUERY_CAST (query);
 }
 
 /**
@@ -393,7 +387,7 @@ gst_query_new_position (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_POSITION),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
@@ -413,9 +407,15 @@ gst_query_new_position (GstFormat format)
 void
 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
 {
+  GstStructure *s;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
 
-  gst_structure_id_set (query->structure,
+  s = GST_QUERY_STRUCTURE (query);
+  g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
+              GST_QUARK (FORMAT))));
+
+  gst_structure_id_set (s,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
 }
@@ -437,7 +437,7 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -466,7 +466,7 @@ gst_query_new_duration (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_DURATION),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
@@ -486,10 +486,14 @@ gst_query_new_duration (GstFormat format)
 void
 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
 {
+  GstStructure *s;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
 
-  gst_structure_id_set (query->structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+  s = GST_QUERY_STRUCTURE (query);
+  g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
+              GST_QUARK (FORMAT))));
+  gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
 }
 
@@ -511,7 +515,7 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -541,7 +545,7 @@ gst_query_new_latency (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_LATENCY),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY),
       GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (-1), NULL);
@@ -566,9 +570,12 @@ void
 gst_query_set_latency (GstQuery * query, gboolean live,
     GstClockTime min_latency, GstClockTime max_latency)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
@@ -593,7 +600,7 @@ gst_query_parse_latency (GstQuery * query, gboolean * live,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (live)
     *live =
         g_value_get_boolean (gst_structure_id_get_value (structure,
@@ -627,7 +634,7 @@ gst_query_new_convert (GstFormat src_format, gint64 value,
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_CONVERT),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT),
       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
@@ -652,9 +659,12 @@ void
 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
     GstFormat dest_format, gint64 dest_value)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
@@ -683,7 +693,7 @@ gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (src_format)
     *src_format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -718,7 +728,7 @@ gst_query_new_segment (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_SEGMENT),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT),
       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
@@ -753,9 +763,12 @@ void
 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
     gint64 start_value, gint64 stop_value)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
@@ -784,7 +797,7 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (rate)
     *rate = g_value_get_double (gst_structure_id_get_value (structure,
             GST_QUARK (RATE)));
@@ -801,11 +814,11 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
 }
 
 /**
- * gst_query_new_application:
+ * gst_query_new_custom:
  * @type: the query type
  * @structure: a structure for the query
  *
- * Constructs a new custom application query object. Use gst_query_unref()
+ * Constructs a new custom query object. Use gst_query_unref()
  * when done with it.
  *
  * Free-function: gst_query_unref
@@ -813,7 +826,7 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
  * Returns: (transfer full): a new #GstQuery
  */
 GstQuery *
-gst_query_new_application (GstQueryType type, GstStructure * structure)
+gst_query_new_custom (GstQueryType type, GstStructure * structure)
 {
   g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL);
   g_return_val_if_fail (structure != NULL, NULL);
@@ -831,12 +844,31 @@ gst_query_new_application (GstQueryType type, GstStructure * structure)
  *     still owned by the query and will therefore be freed when the query
  *     is unreffed.
  */
-GstStructure *
+const GstStructure *
 gst_query_get_structure (GstQuery * query)
 {
   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
 
-  return query->structure;
+  return GST_QUERY_STRUCTURE (query);
+}
+
+/**
+ * gst_query_writable_structure:
+ * @query: a #GstQuery
+ *
+ * Get the structure of a query.
+ *
+ * Returns: (transfer none): the #GstStructure of the query. The structure is
+ *     still owned by the query and will therefore be freed when the query
+ *     is unreffed.
+ */
+GstStructure *
+gst_query_writable_structure (GstQuery * query)
+{
+  g_return_val_if_fail (GST_IS_QUERY (query), NULL);
+  g_return_val_if_fail (gst_query_is_writable (query), NULL);
+
+  return GST_QUERY_STRUCTURE (query);
 }
 
 /**
@@ -856,7 +888,7 @@ gst_query_new_seeking (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_SEEKING),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING),
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
       GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
@@ -881,9 +913,13 @@ void
 gst_query_set_seeking (GstQuery * query, GstFormat format,
     gboolean seekable, gint64 segment_start, gint64 segment_end)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
+  g_return_if_fail (gst_query_is_writable (query));
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
       GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
@@ -911,7 +947,7 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -927,6 +963,28 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format,
             GST_QUARK (SEGMENT_END)));
 }
 
+static GValueArray *
+ensure_array (GstStructure * s, GQuark quark)
+{
+  GValueArray *array;
+  const GValue *value;
+
+  value = gst_structure_id_get_value (s, quark);
+  if (value) {
+    array = (GValueArray *) g_value_get_boxed (value);
+  } else {
+    GValue new_array_val = { 0, };
+
+    array = g_value_array_new (0);
+
+    g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
+    g_value_take_boxed (&new_array_val, array);
+
+    gst_structure_id_take_value (s, quark, &new_array_val);
+  }
+  return array;
+}
+
 /**
  * gst_query_new_formats:
  *
@@ -945,7 +1003,7 @@ gst_query_new_formats (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS));
+  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS));
   query = gst_query_new (GST_QUERY_FORMATS, structure);
 
   return query;
@@ -977,8 +1035,10 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
   va_list ap;
   GValue list = { 0, };
   gint i;
+  GstStructure *structure;
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
+  g_return_if_fail (gst_query_is_writable (query));
 
   g_value_init (&list, GST_TYPE_LIST);
 
@@ -988,7 +1048,8 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
   }
   va_end (ap);
 
-  gst_structure_set_value (query->structure, "formats", &list);
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_set_value (structure, "formats", &list);
 
   g_value_unset (&list);
 
@@ -1012,20 +1073,23 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats,
 {
   GValue list = { 0, };
   gint i;
+  GstStructure *structure;
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
+  g_return_if_fail (gst_query_is_writable (query));
 
   g_value_init (&list, GST_TYPE_LIST);
   for (i = 0; i < n_formats; i++) {
     gst_query_list_add_format (&list, formats[i]);
   }
-  gst_structure_set_value (query->structure, "formats", &list);
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_set_value (structure, "formats", &list);
 
   g_value_unset (&list);
 }
 
 /**
- * gst_query_parse_formats_length:
+ * gst_query_parse_n_formats:
  * @query: a #GstQuery
  * @n_formats: (out): the number of formats in this query.
  *
@@ -1034,14 +1098,17 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats,
  * Since: 0.10.4
  */
 void
-gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
+gst_query_parse_n_formats (GstQuery * query, guint * n_formats)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
 
   if (n_formats) {
     const GValue *list;
 
-    list = gst_structure_get_value (query->structure, "formats");
+    structure = GST_QUERY_STRUCTURE (query);
+    list = gst_structure_get_value (structure, "formats");
     if (list == NULL)
       *n_formats = 0;
     else
@@ -1050,7 +1117,7 @@ gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
 }
 
 /**
- * gst_query_parse_formats_nth:
+ * gst_query_parse_nth_format:
  * @query: a #GstQuery
  * @nth: (out): the nth format to retrieve.
  * @format: (out): a pointer to store the nth format
@@ -1058,18 +1125,19 @@ gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
  * Parse the format query and retrieve the @nth format from it into
  * @format. If the list contains less elements than @nth, @format will be
  * set to GST_FORMAT_UNDEFINED.
- *
- * Since: 0.10.4
  */
 void
-gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format)
+gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
 
   if (format) {
     const GValue *list;
 
-    list = gst_structure_get_value (query->structure, "formats");
+    structure = GST_QUERY_STRUCTURE (query);
+    list = gst_structure_get_value (structure, "formats");
     if (list == NULL) {
       *format = GST_FORMAT_UNDEFINED;
     } else {
@@ -1083,13 +1151,13 @@ gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format)
 }
 
 /**
- * gst_query_new_buffering
+ * gst_query_new_buffering:
  * @format: the default #GstFormat for the new query
  *
  * Constructs a new query object for querying the buffering status of
  * a stream.
  *
- * Free-function: gst_query_new
+ * Free-function: gst_query_unref
  *
  * Returns: (transfer full): a new #GstQuery
  *
@@ -1103,7 +1171,7 @@ gst_query_new_buffering (GstFormat format)
 
   /* by default, we configure the answer as no buffering with a 100% buffering
    * progress */
-  structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERING),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING),
       GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
@@ -1121,7 +1189,7 @@ gst_query_new_buffering (GstFormat format)
 }
 
 /**
- * gst_query_set_buffering_percent
+ * gst_query_set_buffering_percent:
  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
  * @busy: if buffering is busy
  * @percent: a buffering percent
@@ -1134,16 +1202,20 @@ gst_query_new_buffering (GstFormat format)
 void
 gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+  g_return_if_fail (gst_query_is_writable (query));
   g_return_if_fail (percent >= 0 && percent <= 100);
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
 }
 
 /**
- * gst_query_parse_buffering_percent
+ * gst_query_parse_buffering_percent:
  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
  * @busy: (out) (allow-none): if buffering is busy, or NULL
  * @percent: (out) (allow-none): a buffering percent, or NULL
@@ -1157,13 +1229,16 @@ void
 gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
     gint * percent)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
 
+  structure = GST_QUERY_STRUCTURE (query);
   if (busy)
-    *busy = g_value_get_boolean (gst_structure_id_get_value (query->structure,
+    *busy = g_value_get_boolean (gst_structure_id_get_value (structure,
             GST_QUARK (BUSY)));
   if (percent)
-    *percent = g_value_get_int (gst_structure_id_get_value (query->structure,
+    *percent = g_value_get_int (gst_structure_id_get_value (structure,
             GST_QUARK (BUFFER_PERCENT)));
 }
 
@@ -1183,9 +1258,13 @@ void
 gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
     gint avg_in, gint avg_out, gint64 buffering_left)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+  g_return_if_fail (gst_query_is_writable (query));
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
@@ -1209,21 +1288,24 @@ gst_query_parse_buffering_stats (GstQuery * query,
     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
     gint64 * buffering_left)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
 
+  structure = GST_QUERY_STRUCTURE (query);
   if (mode)
     *mode = (GstBufferingMode)
-        g_value_get_enum (gst_structure_id_get_value (query->structure,
+        g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (BUFFERING_MODE)));
   if (avg_in)
-    *avg_in = g_value_get_int (gst_structure_id_get_value (query->structure,
+    *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
             GST_QUARK (AVG_IN_RATE)));
   if (avg_out)
-    *avg_out = g_value_get_int (gst_structure_id_get_value (query->structure,
+    *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
             GST_QUARK (AVG_OUT_RATE)));
   if (buffering_left)
     *buffering_left =
-        g_value_get_int64 (gst_structure_id_get_value (query->structure,
+        g_value_get_int64 (gst_structure_id_get_value (structure,
             GST_QUARK (BUFFERING_LEFT)));
 }
 
@@ -1244,9 +1326,13 @@ void
 gst_query_set_buffering_range (GstQuery * query, GstFormat format,
     gint64 start, gint64 stop, gint64 estimated_total)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
+  g_return_if_fail (gst_query_is_writable (query));
 
-  gst_structure_id_set (query->structure,
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
       GST_QUARK (START_VALUE), G_TYPE_INT64, start,
       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
@@ -1277,7 +1363,7 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
 
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
 
-  structure = query->structure;
+  structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
@@ -1295,7 +1381,7 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
 }
 
 /**
- * gst_query_add_buffering_range
+ * gst_query_add_buffering_range:
  * @query: a GST_QUERY_BUFFERING type query #GstQuery
  * @start: start position of the range
  * @stop: stop position of the range
@@ -1311,47 +1397,35 @@ gboolean
 gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
 {
   GValueArray *array;
-  GValue *last_array_value;
-  const GValue *value;
-  GValue range_value = { 0 };
+  GValue value = { 0 };
+  GstStructure *structure;
 
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
+  g_return_val_if_fail (gst_query_is_writable (query), FALSE);
 
   if (G_UNLIKELY (start >= stop))
     return FALSE;
 
-  value =
-      gst_structure_id_get_value (query->structure,
-      GST_QUARK (BUFFERING_RANGES));
-  if (value) {
-    array = (GValueArray *) g_value_get_boxed (value);
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES));
+  if (array->n_values > 1) {
+    GValue *last_array_value;
+
     last_array_value = g_value_array_get_nth (array, array->n_values - 1);
     if (G_UNLIKELY (start <= gst_value_get_int64_range_min (last_array_value)))
       return FALSE;
-  } else {
-    GValue new_array_val = { 0, };
-
-    array = g_value_array_new (0);
-
-    g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
-    g_value_take_boxed (&new_array_val, array);
-
-    /* set the value array only once, so we then modify (append to) the
-     * existing value array owned by the GstStructure / the field's GValue */
-    gst_structure_id_take_value (query->structure, GST_QUARK (BUFFERING_RANGES),
-        &new_array_val);
   }
 
-  g_value_init (&range_value, GST_TYPE_INT64_RANGE);
-  gst_value_set_int64_range (&range_value, start, stop);
-  g_value_array_append (array, &range_value);
-  /* skip the g_value_unset(&range_value) here, we know it's not needed */
+  g_value_init (&value, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&value, start, stop);
+  g_value_array_append (array, &value);
+  /* skip the g_value_unset(&value) here, we know it's not needed */
 
   return TRUE;
 }
 
 /**
- * gst_query_get_n_buffering_ranges
+ * gst_query_get_n_buffering_ranges:
  * @query: a GST_QUERY_BUFFERING type query #GstQuery
  *
  * Retrieve the number of values currently stored in the
@@ -1365,24 +1439,19 @@ guint
 gst_query_get_n_buffering_ranges (GstQuery * query)
 {
   GValueArray *array;
-  const GValue *value;
-  guint size = 0;
+  GstStructure *structure;
 
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
 
-  value =
-      gst_structure_id_get_value (query->structure,
-      GST_QUARK (BUFFERING_RANGES));
-  if (value) {
-    array = (GValueArray *) g_value_get_boxed (value);
-    size = array->n_values;
-  }
-  return size;
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES));
+
+  return array->n_values;
 }
 
 
 /**
- * gst_query_parse_nth_buffering_range
+ * gst_query_parse_nth_buffering_range:
  * @query: a GST_QUERY_BUFFERING type query #GstQuery
  * @index: position in the buffered-ranges array to read
  * @start: (out) (allow-none): the start position to set, or NULL
@@ -1399,23 +1468,21 @@ gboolean
 gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
     gint64 * start, gint64 * stop)
 {
+  GValueArray *array;
   const GValue *value;
-  GValueArray *ranges;
-  GValue *range_value;
   gboolean ret = FALSE;
+  GstStructure *structure;
 
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, ret);
 
-  value =
-      gst_structure_id_get_value (query->structure,
-      GST_QUARK (BUFFERING_RANGES));
-  ranges = (GValueArray *) g_value_get_boxed (value);
-  range_value = g_value_array_get_nth (ranges, index);
-  if (range_value) {
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES));
+
+  if ((value = g_value_array_get_nth (array, index))) {
     if (start)
-      *start = gst_value_get_int64_range_min (range_value);
+      *start = gst_value_get_int64_range_min (value);
     if (stop)
-      *stop = gst_value_get_int64_range_max (range_value);
+      *stop = gst_value_get_int64_range_max (value);
     ret = TRUE;
   }
 
@@ -1442,7 +1509,7 @@ gst_query_new_uri (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_id_new (GST_QUARK (QUERY_URI),
+  structure = gst_structure_new_id (GST_QUARK (QUERY_URI),
       GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
 
   query = gst_query_new (GST_QUERY_URI, structure);
@@ -1462,11 +1529,14 @@ gst_query_new_uri (void)
 void
 gst_query_set_uri (GstQuery * query, const gchar * uri)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
+  g_return_if_fail (gst_query_is_writable (query));
   g_return_if_fail (gst_uri_is_valid (uri));
 
-  gst_structure_id_set (query->structure, GST_QUARK (URI), G_TYPE_STRING, uri,
-      NULL);
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
 }
 
 /**
@@ -1484,9 +1554,687 @@ gst_query_set_uri (GstQuery * query, const gchar * uri)
 void
 gst_query_parse_uri (GstQuery * query, gchar ** uri)
 {
+  GstStructure *structure;
+
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
 
+  structure = GST_QUERY_STRUCTURE (query);
   if (uri)
-    *uri = g_value_dup_string (gst_structure_id_get_value (query->structure,
+    *uri = g_value_dup_string (gst_structure_id_get_value (structure,
             GST_QUARK (URI)));
 }
+
+/**
+ * gst_query_new_allocation:
+ * @caps: the negotiated caps
+ * @need_pool: return a pool
+ *
+ * Constructs a new query object for querying the allocation properties.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ */
+GstQuery *
+gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool,
+      GST_QUARK (SIZE), G_TYPE_UINT, 0,
+      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, 0,
+      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, 0,
+      GST_QUARK (PREFIX), G_TYPE_UINT, 0,
+      GST_QUARK (ALIGN), G_TYPE_UINT, 0,
+      GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, NULL, NULL);
+
+  query = gst_query_new (GST_QUERY_ALLOCATION, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_parse_allocation:
+ * @query: a #GstQuery
+ * @caps: (out callee-allocates) (allow-none): The #GstCaps
+ * @need_pool: (out) (allow-none): Whether a #GstBufferPool is needed
+ *
+ * Parse an allocation query, writing the requested caps in @caps and
+ * whether a pool is needed in @need_pool, if the respective parameters
+ * are non-NULL.
+ */
+void
+gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
+    gboolean * need_pool)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_get (structure,
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
+}
+
+/**
+ * gst_query_set_allocation_params:
+ * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
+ * @size: the size
+ * @min_buffers: the min buffers
+ * @max_buffers: the max buffers
+ * @prefix: the prefix
+ * @alignment: the alignment
+ * @pool: the #GstBufferPool
+ *
+ * Set the allocation parameters in @query.
+ */
+void
+gst_query_set_allocation_params (GstQuery * query, guint size,
+    guint min_buffers, guint max_buffers, guint prefix,
+    guint alignment, GstBufferPool * pool)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
+  g_return_if_fail (gst_query_is_writable (query));
+  g_return_if_fail (((alignment + 1) & alignment) == 0);
+  g_return_if_fail (size != 0 || pool == NULL);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
+      GST_QUARK (SIZE), G_TYPE_UINT, size,
+      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
+      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
+      GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
+      GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
+      GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
+}
+
+/**
+ * gst_query_parse_allocation_params:
+ * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
+ * @size: the size
+ * @min_buffers: the min buffers
+ * @max_buffers: the max buffers
+ * @prefix: the prefix
+ * @alignment: the alignment
+ * @pool: the #GstBufferPool
+ *
+ * Get the allocation parameters in @query.
+ */
+void
+gst_query_parse_allocation_params (GstQuery * query, guint * size,
+    guint * min_buffers, guint * max_buffers, guint * prefix,
+    guint * alignment, GstBufferPool ** pool)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_get (structure,
+      GST_QUARK (SIZE), G_TYPE_UINT, size,
+      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
+      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
+      GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
+      GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
+      GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
+}
+
+/**
+ * gst_query_add_allocation_meta:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ * @api: the metadata API
+ *
+ * Add @api as aone of the supported metadata API to @query.
+ */
+void
+gst_query_add_allocation_meta (GstQuery * query, const gchar * api)
+{
+  GValueArray *array;
+  GValue api_value = { 0 };
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
+  g_return_if_fail (api != NULL);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (META));
+
+  g_value_init (&api_value, G_TYPE_STRING);
+  g_value_set_string (&api_value, api);
+  g_value_array_append (array, &api_value);
+  g_value_unset (&api_value);
+}
+
+/**
+ * gst_query_get_n_allocation_metas:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ *
+ * Retrieve the number of values currently stored in the
+ * meta API array of the query's structure.
+ *
+ * Returns: the metadata API array size as a #guint.
+ */
+guint
+gst_query_get_n_allocation_metas (GstQuery * query)
+{
+  GValueArray *array;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (META));
+
+  return array->n_values;
+}
+
+/**
+ * gst_query_parse_nth_allocation_meta:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ * @index: position in the metadata API array to read
+ *
+ * Parse an available query and get the metadata API
+ * at @index of the metadata API array.
+ *
+ * Returns: a #gchar of the metadata API at @index.
+ */
+const gchar *
+gst_query_parse_nth_allocation_meta (GstQuery * query, guint index)
+{
+  GValueArray *array;
+  GValue *value;
+  const gchar *ret = NULL;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, NULL);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (META));
+
+  if ((value = g_value_array_get_nth (array, index)))
+    ret = g_value_get_string (value);
+
+  return ret;
+}
+
+/**
+ * gst_query_has_allocation_meta:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ * @api: the metadata API
+ *
+ * Check if @query has metadata @api set.
+ *
+ * Returns: TRUE when @api is in the list of metadata.
+ */
+gboolean
+gst_query_has_allocation_meta (GstQuery * query, const gchar * api)
+{
+  GValueArray *array;
+  GValue *value;
+  GstStructure *structure;
+  guint i;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE);
+  g_return_val_if_fail (api != NULL, FALSE);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (META));
+
+  for (i = 0; i < array->n_values; i++) {
+    value = g_value_array_get_nth (array, i);
+    if (!strcmp (api, g_value_get_string (value)))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * gst_query_add_allocation_memory:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ * @alloc: the memory allocator
+ *
+ * Add @alloc as a supported memory allocator.
+ */
+void
+gst_query_add_allocation_memory (GstQuery * query, const gchar * alloc)
+{
+  GValueArray *array;
+  GValue value = { 0 };
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (ALLOCATOR));
+
+  g_value_init (&value, G_TYPE_STRING);
+  g_value_set_string (&value, alloc);
+  g_value_array_append (array, &value);
+  g_value_unset (&value);
+}
+
+/**
+ * gst_query_get_n_allocation_memories:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ *
+ * Retrieve the number of values currently stored in the
+ * allocator array of the query's structure.
+ *
+ * If no memory allocator is specified, the downstream element can handle
+ * the default memory allocator.
+ *
+ * Returns: the allocator array size as a #guint.
+ */
+guint
+gst_query_get_n_allocation_memories (GstQuery * query)
+{
+  GValueArray *array;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (ALLOCATOR));
+
+  return array->n_values;
+}
+
+/**
+ * gst_query_parse_nth_allocation_memory:
+ * @query: a GST_QUERY_ALLOCATION type query #GstQuery
+ * @index: position in the allocator array to read
+ *
+ * Parse an available query and get the alloctor
+ * at @index of the allocator array.
+ *
+ * Returns: the name of the allocator at @index.
+ */
+const gchar *
+gst_query_parse_nth_allocation_memory (GstQuery * query, guint index)
+{
+  GValueArray *array;
+  GValue *value;
+  const gchar *ret = NULL;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, NULL);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (ALLOCATOR));
+
+  if ((value = g_value_array_get_nth (array, index)))
+    ret = g_value_get_string (value);
+
+  return ret;
+}
+
+/**
+ * gst_query_new_scheduling:
+ *
+ * Constructs a new query object for querying the scheduling properties.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ */
+GstQuery *
+gst_query_new_scheduling (void)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING),
+      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0,
+      GST_QUARK (MINSIZE), G_TYPE_INT, 1,
+      GST_QUARK (MAXSIZE), G_TYPE_INT, -1,
+      GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL);
+  query = gst_query_new (GST_QUERY_SCHEDULING, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_set_scheduling:
+ * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
+ * @flags: #GstSchedulingFlags
+ * @minsize: the suggested minimum size of pull requests
+ * @maxsize: the suggested maximum size of pull requests
+ * @align: the suggested alignment of pull requests
+ *
+ * Set the scheduling properties.
+ */
+void
+gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
+    gint minsize, gint maxsize, gint align)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
+      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
+      GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
+      GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
+      GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
+}
+
+/**
+ * gst_query_parse_scheduling:
+ * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
+ * @flags: #GstSchedulingFlags
+ * @minsize: the suggested minimum size of pull requests
+ * @maxsize: the suggested maximum size of pull requests:
+ * @align: the suggested alignment of pull requests
+ *
+ * Set the scheduling properties.
+ */
+void
+gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags,
+    gint * minsize, gint * maxsize, gint * align)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_get (structure,
+      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
+      GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
+      GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
+      GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
+}
+
+/**
+ * gst_query_add_scheduling_mode:
+ * @query: a GST_QUERY_SCHEDULING type query #GstQuery
+ * @mode: a #GstPadMode
+ *
+ * Add @mode as aone of the supported scheduling modes to @query.
+ */
+void
+gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
+{
+  GValueArray *array;
+  GValue value = { 0 };
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (MODES));
+
+  g_value_init (&value, GST_TYPE_PAD_MODE);
+  g_value_set_enum (&value, mode);
+  g_value_array_append (array, &value);
+  g_value_unset (&value);
+}
+
+/**
+ * gst_query_get_n_scheduling_modes:
+ * @query: a GST_QUERY_SCHEDULING type query #GstQuery
+ *
+ * Retrieve the number of values currently stored in the
+ * scheduling mode array of the query's structure.
+ *
+ * Returns: the scheduling mode array size as a #guint.
+ */
+guint
+gst_query_get_n_scheduling_modes (GstQuery * query)
+{
+  GValueArray *array;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (MODES));
+
+  return array->n_values;
+}
+
+/**
+ * gst_query_parse_nth_scheduling_mode:
+ * @query: a GST_QUERY_SCHEDULING type query #GstQuery
+ * @index: position in the scheduling modes array to read
+ *
+ * Parse an available query and get the scheduling mode
+ * at @index of the scheduling modes array.
+ *
+ * Returns: a #GstPadMode of the scheduling mode at @index.
+ */
+GstPadMode
+gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index)
+{
+  GValueArray *array;
+  GValue *value;
+  GstPadMode ret = GST_PAD_MODE_NONE;
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, ret);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (MODES));
+
+  if ((value = g_value_array_get_nth (array, index)))
+    ret = g_value_get_enum (value);
+
+  return ret;
+}
+
+/**
+ * gst_query_has_scheduling_mode:
+ * @query: a GST_QUERY_SCHEDULING type query #GstQuery
+ * @mode: the scheduling mode
+ *
+ * Check if @query has scheduling mode set.
+ *
+ * Returns: TRUE when @mode is in the list of scheduling modes.
+ */
+gboolean
+gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode)
+{
+  GValueArray *array;
+  GValue *value;
+  GstStructure *structure;
+  guint i;
+
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  array = ensure_array (structure, GST_QUARK (MODES));
+
+  for (i = 0; i < array->n_values; i++) {
+    value = g_value_array_get_nth (array, i);
+    if (mode == g_value_get_enum (value))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * gst_query_new_accept_caps:
+ * @caps: a #GstCaps
+ *
+ * Constructs a new query object for querying if @caps are accepted.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ */
+GstQuery *
+gst_query_new_accept_caps (GstCaps * caps)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS),
+      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
+      GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL);
+  query = gst_query_new (GST_QUERY_ACCEPT_CAPS, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_parse_accept_caps:
+ * @query: The query to parse
+ * @caps: (out): A pointer to the caps
+ *
+ * Get the caps from @query. The caps remains valid as long as @query remains
+ * valid.
+ */
+void
+gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
+          GST_QUARK (CAPS)));
+}
+
+void
+gst_query_set_accept_caps_result (GstQuery * query, gboolean result)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure,
+      GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
+}
+
+void
+gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_get (structure,
+      GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
+}
+
+/**
+ * gst_query_new_caps:
+ * @filter: a filter
+ *
+ * Constructs a new query object for querying the caps.
+ *
+ * The CAPS query should return the* allowable caps for a pad in the context
+ * of the element's state, its link to other elements, and the devices or files
+ * it has opened. These caps must be a subset of the pad template caps. In the
+ * NULL state with no links, the CAPS query should ideally return the same caps
+ * as the pad template. In rare circumstances, an object property can affect
+ * the caps returned by the CAPS query, but this is discouraged.
+ *
+ * For most filters, the caps returned by CAPS query is directly affected by the
+ * allowed caps on other pads. For demuxers and decoders, the caps returned by
+ * the srcpad's getcaps function is directly related to the stream data. Again,
+ * the CAPS query should return the most specific caps it reasonably can, since this
+ * helps with autoplugging.
+ *
+ * Free-function: gst_query_unref
+ *
+ * Returns: (transfer full): a new #GstQuery
+ */
+GstQuery *
+gst_query_new_caps (GstCaps * filter)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS),
+      GST_QUARK (FILTER), GST_TYPE_CAPS, filter,
+      GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL);
+  query = gst_query_new (GST_QUERY_CAPS, structure);
+
+  return query;
+}
+
+/**
+ * gst_query_parse_caps:
+ * @query: The query to parse
+ * @filter: (out): A pointer to the caps filter
+ *
+ * Get the filter from the caps @query. The caps remains valid as long as
+ * @query remains valid.
+ */
+void
+gst_query_parse_caps (GstQuery * query, GstCaps ** filter)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  *filter = g_value_get_boxed (gst_structure_id_get_value (structure,
+          GST_QUARK (FILTER)));
+}
+
+/**
+ * gst_query_set_caps_result:
+ * @query: The query to use
+ * @caps: (in): A pointer to the caps
+ *
+ * Set the @caps result in @query.
+ */
+void
+gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
+  g_return_if_fail (gst_query_is_writable (query));
+
+  structure = GST_QUERY_STRUCTURE (query);
+  gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL);
+}
+
+/**
+ * gst_query_parse_caps_result:
+ * @query: The query to parse
+ * @caps: (out): A pointer to the caps
+ *
+ * Get the caps result from @query. The caps remains valid as long as
+ * @query remains valid.
+ */
+void
+gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
+
+  structure = GST_QUERY_STRUCTURE (query);
+  *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
+          GST_QUARK (CAPS)));
+}
+
+void
+gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter,
+    GstCapsIntersectMode mode)
+{
+  GstCaps *res, *caps = NULL;
+
+  gst_query_parse_caps_result (query, &caps);
+  res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+  gst_query_set_caps_result (query, res);
+  gst_caps_unref (res);
+}
index 2166537..aa2983d 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000 Wim Taymans <wim.taymans@chello.be>
  *                    2005 Wim Taymans <wim@fluendo.com>
+ *                    2011 Wim Taymans <wim.taymans@gmail.com>
  *
  * gstquery.h: GstQuery API declaration
  *
@@ -31,6 +32,7 @@
 #include <gst/gstminiobject.h>
 #include <gst/gststructure.h>
 #include <gst/gstformat.h>
+#include <gst/gstpad.h>
 
 G_BEGIN_DECLS
 
@@ -51,6 +53,10 @@ G_BEGIN_DECLS
  * @GST_QUERY_CUSTOM: a custom application or element defined query. Since
  * 0.10.22.
  * @GST_QUERY_URI: query the URI of the source or sink. Since 0.10.22.
+ * @GST_QUERY_ALLOCATION: the buffer allocation properties
+ * @GST_QUERY_SCHEDULING: the scheduling properties
+ * @GST_QUERY_ACCEPT_CAPS: the accept caps query
+ * @GST_QUERY_CAPS: the caps query
  *
  * Standard predefined Query types
  */
@@ -69,28 +75,15 @@ typedef enum {
   GST_QUERY_FORMATS,
   GST_QUERY_BUFFERING,
   GST_QUERY_CUSTOM,
-  GST_QUERY_URI
+  GST_QUERY_URI,
+  GST_QUERY_ALLOCATION,
+  GST_QUERY_SCHEDULING,
+  GST_QUERY_ACCEPT_CAPS,
+  GST_QUERY_CAPS
 } GstQueryType;
 
-/**
- * GstBufferingMode:
- * @GST_BUFFERING_STREAM: a small amount of data is buffered
- * @GST_BUFFERING_DOWNLOAD: the stream is being downloaded
- * @GST_BUFFERING_TIMESHIFT: the stream is being downloaded in a ringbuffer
- * @GST_BUFFERING_LIVE: the stream is a live stream
- *
- * The different types of buffering methods.
- */
-typedef enum {
-  GST_BUFFERING_STREAM,
-  GST_BUFFERING_DOWNLOAD,
-  GST_BUFFERING_TIMESHIFT,
-  GST_BUFFERING_LIVE
-} GstBufferingMode;
-
 typedef struct _GstQueryTypeDefinition GstQueryTypeDefinition;
 typedef struct _GstQuery GstQuery;
-typedef struct _GstQueryClass GstQueryClass;
 
 /**
  * GstQueryTypeDefinition:
@@ -109,13 +102,10 @@ struct _GstQueryTypeDefinition
   GQuark         quark;
 };
 
-#define GST_TYPE_QUERY                          (gst_query_get_type())
-#define GST_IS_QUERY(obj)                      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_QUERY))
-#define GST_IS_QUERY_CLASS(klass)              (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_QUERY))
-#define GST_QUERY_GET_CLASS(obj)               (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QUERY, GstQueryClass))
-#define GST_QUERY(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QUERY, GstQuery))
-#define GST_QUERY_CAST(obj)                    ((GstQuery*)(obj)) /* only since 0.10.23 */
-#define GST_QUERY_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QUERY, GstQueryClass))
+#define GST_TYPE_QUERY                         (gst_query_get_type())
+#define GST_IS_QUERY(obj)                      (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_QUERY))
+#define GST_QUERY_CAST(obj)                    ((GstQuery*)(obj))
+#define GST_QUERY(obj)                         (GST_QUERY_CAST(obj))
 
 
 /**
@@ -141,7 +131,6 @@ struct _GstQueryTypeDefinition
  * GstQuery:
  * @mini_object: The parent #GstMiniObject type
  * @type: the #GstQueryType
- * @structure: the #GstStructure containing the query details.
  *
  * The #GstQuery structure.
  */
@@ -151,18 +140,6 @@ struct _GstQuery
 
   /*< public > *//* with COW */
   GstQueryType type;
-
-  GstStructure *structure;
-
-  /*< private >*/
-  gpointer _gst_reserved;
-};
-
-struct _GstQueryClass {
-  GstMiniObjectClass mini_object_class;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
 };
 
 const gchar*    gst_query_type_get_name        (GstQueryType query);
@@ -243,6 +220,13 @@ gst_query_copy (const GstQuery * q)
 }
 
 /**
+ * gst_query_is_writable:
+ * @q: a #GstQuery
+ *
+ * Tests if you can safely write data into a query's structure.
+ */
+#define         gst_query_is_writable(q)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (q))
+/**
  * gst_query_make_writable:
  * @q: (transfer full): a #GstQuery to make writable
  *
@@ -251,6 +235,37 @@ gst_query_copy (const GstQuery * q)
  * Returns: (transfer full): a new writable query (possibly same as @q)
  */
 #define         gst_query_make_writable(q)      GST_QUERY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (q)))
+/**
+ * gst_query_replace:
+ * @old_query: (inout) (transfer full): pointer to a pointer to a #GstQuery
+ *     to be replaced.
+ * @new_query: (allow-none) (transfer none): pointer to a #GstQuery that will
+ *     replace the query pointed to by @old_query.
+ *
+ * Modifies a pointer to a #GstQuery to point to a different #GstQuery. The
+ * modification is done atomically (so this is useful for ensuring thread safety
+ * in some cases), and the reference counts are updated appropriately (the old
+ * query is unreffed, the new one is reffed).
+ *
+ * Either @new_query or the #GstQuery pointed to by @old_query may be NULL.
+ *
+ * Returns: TRUE if @new_query was different from @old_query
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC gboolean gst_query_replace (GstQuery **old_query, GstQuery *new_query);
+#endif
+
+static inline gboolean
+gst_query_replace (GstQuery **old_query, GstQuery *new_query)
+{
+  return gst_mini_object_replace ((GstMiniObject **) old_query, (GstMiniObject *) new_query);
+}
+
+/* application specific query */
+GstQuery *      gst_query_new_custom            (GstQueryType type, GstStructure *structure) G_GNUC_MALLOC;
+const GstStructure *
+                gst_query_get_structure         (GstQuery *query);
+GstStructure *  gst_query_writable_structure    (GstQuery *query);
 
 /* position query */
 GstQuery*       gst_query_new_position          (GstFormat format) G_GNUC_MALLOC;
@@ -282,11 +297,6 @@ void            gst_query_set_segment           (GstQuery *query, gdouble rate,
 void            gst_query_parse_segment         (GstQuery *query, gdouble *rate, GstFormat *format,
                                                  gint64 *start_value, gint64 *stop_value);
 
-/* application specific query */
-GstQuery *      gst_query_new_application       (GstQueryType type,
-                                                 GstStructure *structure) G_GNUC_MALLOC;
-GstStructure *  gst_query_get_structure         (GstQuery *query);
-
 /* seeking query */
 GstQuery*       gst_query_new_seeking           (GstFormat format) G_GNUC_MALLOC;
 void            gst_query_set_seeking           (GstQuery *query, GstFormat format,
@@ -301,10 +311,26 @@ void            gst_query_parse_seeking         (GstQuery *query, GstFormat *for
 GstQuery*       gst_query_new_formats           (void) G_GNUC_MALLOC;
 void            gst_query_set_formats           (GstQuery *query, gint n_formats, ...);
 void            gst_query_set_formatsv          (GstQuery *query, gint n_formats, const GstFormat *formats);
-void            gst_query_parse_formats_length  (GstQuery *query, guint *n_formats);
-void            gst_query_parse_formats_nth     (GstQuery *query, guint nth, GstFormat *format);
+void            gst_query_parse_n_formats       (GstQuery *query, guint *n_formats);
+void            gst_query_parse_nth_format      (GstQuery *query, guint nth, GstFormat *format);
 
 /* buffering query */
+/**
+ * GstBufferingMode:
+ * @GST_BUFFERING_STREAM: a small amount of data is buffered
+ * @GST_BUFFERING_DOWNLOAD: the stream is being downloaded
+ * @GST_BUFFERING_TIMESHIFT: the stream is being downloaded in a ringbuffer
+ * @GST_BUFFERING_LIVE: the stream is a live stream
+ *
+ * The different types of buffering methods.
+ */
+typedef enum {
+  GST_BUFFERING_STREAM,
+  GST_BUFFERING_DOWNLOAD,
+  GST_BUFFERING_TIMESHIFT,
+  GST_BUFFERING_LIVE
+} GstBufferingMode;
+
 GstQuery*       gst_query_new_buffering           (GstFormat format) G_GNUC_MALLOC;
 void            gst_query_set_buffering_percent   (GstQuery *query, gboolean busy, gint percent);
 void            gst_query_parse_buffering_percent (GstQuery *query, gboolean *busy, gint *percent);
@@ -322,11 +348,10 @@ void            gst_query_set_buffering_range     (GstQuery *query, GstFormat fo
 void            gst_query_parse_buffering_range   (GstQuery *query, GstFormat *format,
                                                    gint64 *start, gint64 *stop,
                                                    gint64 *estimated_total);
-gboolean        gst_query_add_buffering_range     (GstQuery *query,
-                                                   gint64 start, gint64 stop);
-
-guint           gst_query_get_n_buffering_ranges  (GstQuery *query);
 
+gboolean        gst_query_add_buffering_range       (GstQuery *query,
+                                                     gint64 start, gint64 stop);
+guint           gst_query_get_n_buffering_ranges    (GstQuery *query);
 gboolean        gst_query_parse_nth_buffering_range (GstQuery *query,
                                                      guint index, gint64 *start,
                                                      gint64 *stop);
@@ -336,6 +361,67 @@ GstQuery *      gst_query_new_uri                 (void) G_GNUC_MALLOC;
 void            gst_query_parse_uri               (GstQuery *query, gchar **uri);
 void            gst_query_set_uri                 (GstQuery *query, const gchar *uri);
 
+/* allocation query */
+GstQuery *      gst_query_new_allocation          (GstCaps *caps, gboolean need_pool) G_GNUC_MALLOC;
+void            gst_query_parse_allocation        (GstQuery *query, GstCaps **caps, gboolean *need_pool);
+
+void            gst_query_set_allocation_params   (GstQuery *query, guint size, guint min_buffers,
+                                                   guint max_buffers, guint prefix, guint alignment,
+                                                   GstBufferPool *pool);
+void            gst_query_parse_allocation_params (GstQuery *query, guint *size, guint *min_buffers,
+                                                   guint *max_buffers, guint *prefix, guint *alignment,
+                                                   GstBufferPool **pool);
+
+void            gst_query_add_allocation_meta       (GstQuery *query, const gchar *api);
+guint           gst_query_get_n_allocation_metas    (GstQuery *query);
+const gchar *   gst_query_parse_nth_allocation_meta (GstQuery *query, guint index);
+gboolean        gst_query_has_allocation_meta       (GstQuery *query, const gchar *api);
+
+void            gst_query_add_allocation_memory       (GstQuery *query, const gchar *alloc);
+guint           gst_query_get_n_allocation_memories   (GstQuery *query);
+const gchar *   gst_query_parse_nth_allocation_memory (GstQuery *query, guint index);
+
+/* scheduling query */
+/**
+ * GstSchedulingFlags:
+ * @GST_SCHEDULING_FLAG_SEEKABLE: if seeking is possible
+ * @GST_SCHEDULING_FLAG_SEQUENTIAL: if sequential access is recommended
+ *
+ * The different scheduling flags.
+ */
+typedef enum {
+  GST_SCHEDULING_FLAG_SEEKABLE      = (1 << 0),
+  GST_SCHEDULING_FLAG_SEQUENTIAL    = (1 << 1)
+} GstSchedulingFlags;
+
+GstQuery *      gst_query_new_scheduling          (void) G_GNUC_MALLOC;
+
+void            gst_query_set_scheduling          (GstQuery *query, GstSchedulingFlags flags,
+                                                   gint minsize, gint maxsize, gint align);
+void            gst_query_parse_scheduling        (GstQuery *query, GstSchedulingFlags *flags,
+                                                   gint *minsize, gint *maxsize, gint *align);
+
+void            gst_query_add_scheduling_mode       (GstQuery *query, GstPadMode mode);
+guint           gst_query_get_n_scheduling_modes    (GstQuery *query);
+GstPadMode      gst_query_parse_nth_scheduling_mode (GstQuery *query, guint index);
+gboolean        gst_query_has_scheduling_mode       (GstQuery *query, GstPadMode mode);
+
+/* accept-caps query */
+GstQuery *      gst_query_new_accept_caps          (GstCaps *caps) G_GNUC_MALLOC;
+void            gst_query_parse_accept_caps        (GstQuery *query, GstCaps **caps);
+void            gst_query_set_accept_caps_result   (GstQuery *query, gboolean result);
+void            gst_query_parse_accept_caps_result (GstQuery *query, gboolean *result);
+
+/* caps query */
+GstQuery *      gst_query_new_caps                 (GstCaps *filter) G_GNUC_MALLOC;
+void            gst_query_parse_caps               (GstQuery *query, GstCaps **filter);
+
+void            gst_query_set_caps_result          (GstQuery *query, GstCaps *caps);
+void            gst_query_parse_caps_result        (GstQuery *query, GstCaps **caps);
+
+void            gst_query_intersect_caps_result    (GstQuery *query, GstCaps *filter,
+                                                    GstCapsIntersectMode mode);
+
 G_END_DECLS
 
 #endif /* __GST_QUERY_H__ */
index 0878a00..18cddab 100644 (file)
 #include "gsterror.h"
 #include "gstregistry.h"
 #include "gstmarshal.h"
-#include "gstfilter.h"
 
 #include "gstpluginloader.h"
 
@@ -146,6 +145,18 @@ extern HMODULE _priv_gst_dll_handle;
 
 struct _GstRegistryPrivate
 {
+  GList *plugins;
+  GList *features;
+
+  GList *paths;
+
+  int cache_file;
+
+  /* hash to speedup _lookup_feature_locked() */
+  GHashTable *feature_hash;
+  /* hash to speedup _lookup */
+  GHashTable *basename_hash;
+
   /* updated whenever the feature list changes */
   guint32 cookie;
   /* speedup for searching features */
@@ -157,7 +168,7 @@ struct _GstRegistryPrivate
 
 /* the one instance of the default registry and the mutex protecting the
  * variable. */
-static GStaticMutex _gst_registry_mutex = G_STATIC_MUTEX_INIT;
+static GMutex _gst_registry_mutex;
 static GstRegistry *_gst_registry_default = NULL;
 
 /* defaults */
@@ -196,8 +207,8 @@ static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry *
 static GstPlugin *gst_registry_lookup_bn_locked (GstRegistry * registry,
     const char *basename);
 
+#define gst_registry_parent_class parent_class
 G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT);
-static GstObjectClass *parent_class = NULL;
 
 static void
 gst_registry_class_init (GstRegistryClass * klass)
@@ -206,7 +217,6 @@ gst_registry_class_init (GstRegistryClass * klass)
 
   gobject_class = (GObjectClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
   g_type_class_add_private (klass, sizeof (GstRegistryPrivate));
 
   /**
@@ -219,8 +229,8 @@ gst_registry_class_init (GstRegistryClass * klass)
    */
   gst_registry_signals[PLUGIN_ADDED] =
       g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL,
-      NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_marshal_VOID__OBJECT,
+      G_TYPE_NONE, 1, GST_TYPE_PLUGIN);
 
   /**
    * GstRegistry::feature-added:
@@ -232,8 +242,8 @@ gst_registry_class_init (GstRegistryClass * klass)
    */
   gst_registry_signals[FEATURE_ADDED] =
       g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, feature_added),
-      NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_marshal_VOID__OBJECT,
+      G_TYPE_NONE, 1, GST_TYPE_PLUGIN_FEATURE);
 
   gobject_class->finalize = gst_registry_finalize;
 }
@@ -241,11 +251,11 @@ gst_registry_class_init (GstRegistryClass * klass)
 static void
 gst_registry_init (GstRegistry * registry)
 {
-  registry->feature_hash = g_hash_table_new (g_str_hash, g_str_equal);
-  registry->basename_hash = g_hash_table_new (g_str_hash, g_str_equal);
   registry->priv =
       G_TYPE_INSTANCE_GET_PRIVATE (registry, GST_TYPE_REGISTRY,
       GstRegistryPrivate);
+  registry->priv->feature_hash = g_hash_table_new (g_str_hash, g_str_equal);
+  registry->priv->basename_hash = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 static void
@@ -255,8 +265,8 @@ gst_registry_finalize (GObject * object)
   GList *plugins, *p;
   GList *features, *f;
 
-  plugins = registry->plugins;
-  registry->plugins = NULL;
+  plugins = registry->priv->plugins;
+  registry->priv->plugins = NULL;
 
   GST_DEBUG_OBJECT (registry, "registry finalize");
   p = plugins;
@@ -272,26 +282,26 @@ gst_registry_finalize (GObject * object)
   }
   g_list_free (plugins);
 
-  features = registry->features;
-  registry->features = NULL;
+  features = registry->priv->features;
+  registry->priv->features = NULL;
 
   f = features;
   while (f) {
     GstPluginFeature *feature = f->data;
 
     if (feature) {
-      GST_LOG_OBJECT (registry, "removing feature %p (%s)",
-          feature, gst_plugin_feature_get_name (feature));
+      GST_LOG_OBJECT (registry, "removing feature %p (%s)", feature,
+          GST_OBJECT_NAME (feature));
       gst_object_unparent (GST_OBJECT_CAST (feature));
     }
     f = g_list_next (f);
   }
   g_list_free (features);
 
-  g_hash_table_destroy (registry->feature_hash);
-  registry->feature_hash = NULL;
-  g_hash_table_destroy (registry->basename_hash);
-  registry->basename_hash = NULL;
+  g_hash_table_destroy (registry->priv->feature_hash);
+  registry->priv->feature_hash = NULL;
+  g_hash_table_destroy (registry->priv->basename_hash);
+  registry->priv->basename_hash = NULL;
 
   if (registry->priv->element_factory_list) {
     GST_DEBUG_OBJECT (registry, "Cleaning up cached element factory list");
@@ -307,25 +317,26 @@ gst_registry_finalize (GObject * object)
 }
 
 /**
- * gst_registry_get_default:
+ * gst_registry_get:
  *
- * Retrieves the default registry. The caller does not own a reference on the
- * registry, as it is alive as long as GStreamer is initialized.
+ * Retrieves the singleton plugin registry. The caller does not own a
+ * reference on the registry, as it is alive as long as GStreamer is
+ * initialized.
  *
- * Returns: (transfer none): The default #GstRegistry.
+ * Returns: (transfer none): the #GstRegistry.
  */
 GstRegistry *
-gst_registry_get_default (void)
+gst_registry_get (void)
 {
   GstRegistry *registry;
 
-  g_static_mutex_lock (&_gst_registry_mutex);
+  g_mutex_lock (&_gst_registry_mutex);
   if (G_UNLIKELY (!_gst_registry_default)) {
     _gst_registry_default = g_object_newv (GST_TYPE_REGISTRY, 0, NULL);
     gst_object_ref_sink (GST_OBJECT_CAST (_gst_registry_default));
   }
   registry = _gst_registry_default;
-  g_static_mutex_unlock (&_gst_registry_mutex);
+  g_mutex_unlock (&_gst_registry_mutex);
 
   return registry;
 }
@@ -349,11 +360,12 @@ gst_registry_add_path (GstRegistry * registry, const gchar * path)
     goto empty_path;
 
   GST_OBJECT_LOCK (registry);
-  if (g_list_find_custom (registry->paths, path, (GCompareFunc) strcmp))
+  if (g_list_find_custom (registry->priv->paths, path, (GCompareFunc) strcmp))
     goto was_added;
 
   GST_INFO ("Adding plugin path: \"%s\"", path);
-  registry->paths = g_list_append (registry->paths, g_strdup (path));
+  registry->priv->paths =
+      g_list_append (registry->priv->paths, g_strdup (path));
   GST_OBJECT_UNLOCK (registry);
 
   return;
@@ -392,7 +404,7 @@ gst_registry_get_path_list (GstRegistry * registry)
   GST_OBJECT_LOCK (registry);
   /* We don't need to copy the strings, because they won't be deleted
    * as long as the GstRegistry is around */
-  list = g_list_copy (registry->paths);
+  list = g_list_copy (registry->priv->paths);
   GST_OBJECT_UNLOCK (registry);
 
   return list;
@@ -440,9 +452,10 @@ gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
         GST_OBJECT_UNLOCK (registry);
         return FALSE;
       }
-      registry->plugins = g_list_remove (registry->plugins, existing_plugin);
+      registry->priv->plugins =
+          g_list_remove (registry->priv->plugins, existing_plugin);
       if (G_LIKELY (existing_plugin->basename))
-        g_hash_table_remove (registry->basename_hash,
+        g_hash_table_remove (registry->priv->basename_hash,
             existing_plugin->basename);
       gst_object_unref (existing_plugin);
     }
@@ -451,9 +464,10 @@ gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
   GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"",
       plugin, GST_STR_NULL (plugin->filename));
 
-  registry->plugins = g_list_prepend (registry->plugins, plugin);
+  registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin);
   if (G_LIKELY (plugin->basename))
-    g_hash_table_replace (registry->basename_hash, plugin->basename, plugin);
+    g_hash_table_replace (registry->priv->basename_hash, plugin->basename,
+        plugin);
 
   gst_object_ref_sink (plugin);
   GST_OBJECT_UNLOCK (registry);
@@ -475,7 +489,7 @@ gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry,
   g_return_if_fail (GST_IS_PLUGIN (plugin));
 
   /* Remove all features for this plugin */
-  f = registry->features;
+  f = registry->priv->features;
   while (f != NULL) {
     GList *next = g_list_next (f);
     GstPluginFeature *feature = f->data;
@@ -485,8 +499,10 @@ gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry,
           feature, gst_plugin_feature_get_name (feature), plugin,
           plugin->desc.name);
 
-      registry->features = g_list_delete_link (registry->features, f);
-      g_hash_table_remove (registry->feature_hash, feature->name);
+      registry->priv->features =
+          g_list_delete_link (registry->priv->features, f);
+      g_hash_table_remove (registry->priv->feature_hash,
+          GST_OBJECT_NAME (feature));
       gst_object_unparent (GST_OBJECT_CAST (feature));
     }
     f = next;
@@ -513,9 +529,9 @@ gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
       plugin, gst_plugin_get_name (plugin));
 
   GST_OBJECT_LOCK (registry);
-  registry->plugins = g_list_remove (registry->plugins, plugin);
+  registry->priv->plugins = g_list_remove (registry->priv->plugins, plugin);
   if (G_LIKELY (plugin->basename))
-    g_hash_table_remove (registry->basename_hash, plugin->basename);
+    g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
   gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
   GST_OBJECT_UNLOCK (registry);
   gst_object_unref (plugin);
@@ -540,25 +556,28 @@ gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
 
   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
   g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
-  g_return_val_if_fail (feature->name != NULL, FALSE);
+  g_return_val_if_fail (GST_OBJECT_NAME (feature) != NULL, FALSE);
   g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
 
   GST_OBJECT_LOCK (registry);
   existing_feature = gst_registry_lookup_feature_locked (registry,
-      feature->name);
+      GST_OBJECT_NAME (feature));
   if (G_UNLIKELY (existing_feature)) {
     GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)",
-        existing_feature, feature->name);
+        existing_feature, GST_OBJECT_NAME (feature));
     /* Remove the existing feature from the list now, before we insert the new
      * one, but don't unref yet because the hash is still storing a reference to
      * it. */
-    registry->features = g_list_remove (registry->features, existing_feature);
+    registry->priv->features =
+        g_list_remove (registry->priv->features, existing_feature);
   }
 
-  GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
+  GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature,
+      GST_OBJECT_NAME (feature));
 
-  registry->features = g_list_prepend (registry->features, feature);
-  g_hash_table_replace (registry->feature_hash, feature->name, feature);
+  registry->priv->features = g_list_prepend (registry->priv->features, feature);
+  g_hash_table_replace (registry->priv->feature_hash, GST_OBJECT_NAME (feature),
+      feature);
 
   if (G_UNLIKELY (existing_feature)) {
     /* We unref now. No need to remove the feature name from the hash table, it
@@ -571,7 +590,8 @@ gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
   registry->priv->cookie++;
   GST_OBJECT_UNLOCK (registry);
 
-  GST_LOG_OBJECT (registry, "emitting feature-added for %s", feature->name);
+  GST_LOG_OBJECT (registry, "emitting feature-added for %s",
+      GST_OBJECT_NAME (feature));
   g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature);
 
   return TRUE;
@@ -596,8 +616,8 @@ gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
       feature, gst_plugin_feature_get_name (feature));
 
   GST_OBJECT_LOCK (registry);
-  registry->features = g_list_remove (registry->features, feature);
-  g_hash_table_remove (registry->feature_hash, feature->name);
+  registry->priv->features = g_list_remove (registry->priv->features, feature);
+  g_hash_table_remove (registry->priv->feature_hash, GST_OBJECT_NAME (feature));
   registry->priv->cookie++;
   GST_OBJECT_UNLOCK (registry);
 
@@ -634,7 +654,7 @@ gst_registry_plugin_filter (GstRegistry * registry,
   {
     const GList *walk;
 
-    for (walk = registry->plugins; walk != NULL; walk = walk->next) {
+    for (walk = registry->priv->plugins; walk != NULL; walk = walk->next) {
       GstPlugin *plugin = walk->data;
 
       if (filter == NULL || filter (plugin, user_data)) {
@@ -650,12 +670,12 @@ gst_registry_plugin_filter (GstRegistry * registry,
   return list;
 }
 
-#ifdef GST_DISABLE_DEPRECATED
 typedef struct
 {
   const gchar *name;
   GType type;
 } GstTypeNameData;
+
 static gboolean
 gst_plugin_feature_type_name_filter (GstPluginFeature * feature,
     GstTypeNameData * data)
@@ -663,10 +683,8 @@ gst_plugin_feature_type_name_filter (GstPluginFeature * feature,
   g_assert (GST_IS_PLUGIN_FEATURE (feature));
 
   return ((data->type == 0 || data->type == G_OBJECT_TYPE (feature)) &&
-      (data->name == NULL
-          || !strcmp (data->name, GST_PLUGIN_FEATURE_NAME (feature))));
+      (data->name == NULL || !strcmp (data->name, GST_OBJECT_NAME (feature))));
 }
-#endif
 
 /* returns TRUE if the list was changed
  *
@@ -690,7 +708,7 @@ gst_registry_get_feature_list_or_create (GstRegistry * registry,
     data.type = type;
     data.name = NULL;
 
-    for (walk = registry->features; walk != NULL; walk = walk->next) {
+    for (walk = registry->priv->features; walk != NULL; walk = walk->next) {
       GstPluginFeature *feature = walk->data;
 
       if (gst_plugin_feature_type_name_filter (feature, &data)) {
@@ -714,7 +732,7 @@ type_find_factory_rank_cmp (const GstPluginFeature * fac1,
 
   /* to make the order in which things happen more deterministic,
    * sort by name when the ranks are the same. */
-  return strcmp (fac1->name, fac2->name);
+  return strcmp (GST_OBJECT_NAME (fac1), GST_OBJECT_NAME (fac2));
 }
 
 static GList *
@@ -787,7 +805,7 @@ gst_registry_feature_filter (GstRegistry * registry,
   {
     const GList *walk;
 
-    for (walk = registry->features; walk != NULL; walk = walk->next) {
+    for (walk = registry->priv->features; walk != NULL; walk = walk->next) {
       GstPluginFeature *feature = walk->data;
 
       if (filter == NULL || filter (feature, user_data)) {
@@ -924,7 +942,7 @@ gst_registry_get_plugin_list (GstRegistry * registry)
   g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
 
   GST_OBJECT_LOCK (registry);
-  list = g_list_copy (registry->plugins);
+  list = g_list_copy (registry->priv->plugins);
   for (g = list; g; g = g->next) {
     gst_object_ref (GST_PLUGIN_CAST (g->data));
   }
@@ -936,7 +954,7 @@ gst_registry_get_plugin_list (GstRegistry * registry)
 static GstPluginFeature *
 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
 {
-  return g_hash_table_lookup (registry->feature_hash, name);
+  return g_hash_table_lookup (registry->priv->feature_hash, name);
 }
 
 /**
@@ -971,7 +989,7 @@ gst_registry_lookup_feature (GstRegistry * registry, const char *name)
 static GstPlugin *
 gst_registry_lookup_bn_locked (GstRegistry * registry, const char *basename)
 {
-  return g_hash_table_lookup (registry->basename_hash, basename);
+  return g_hash_table_lookup (registry->priv->basename_hash, basename);
 }
 
 static GstPlugin *
@@ -1370,11 +1388,11 @@ _priv_gst_registry_cleanup (void)
 {
   GstRegistry *registry;
 
-  g_static_mutex_lock (&_gst_registry_mutex);
+  g_mutex_lock (&_gst_registry_mutex);
   if ((registry = _gst_registry_default) != NULL) {
     _gst_registry_default = NULL;
   }
-  g_static_mutex_unlock (&_gst_registry_mutex);
+  g_mutex_unlock (&_gst_registry_mutex);
 
   /* unref outside of the lock because we can. */
   if (registry)
@@ -1382,32 +1400,32 @@ _priv_gst_registry_cleanup (void)
 }
 
 /**
- * gst_default_registry_check_feature_version:
+ * gst_registry_check_feature_version:
+ * @registry: a #GstRegistry
  * @feature_name: the name of the feature (e.g. "oggdemux")
  * @min_major: the minimum major version number
  * @min_minor: the minimum minor version number
  * @min_micro: the minimum micro version number
  *
- * Checks whether a plugin feature by the given name exists in the
- * default registry and whether its version is at least the
+ * Checks whether a plugin feature by the given name exists in
+ * @registry and whether its version is at least the
  * version required.
  *
  * Returns: #TRUE if the feature could be found and the version is
  * the same as the required version or newer, and #FALSE otherwise.
  */
 gboolean
-gst_default_registry_check_feature_version (const gchar * feature_name,
-    guint min_major, guint min_minor, guint min_micro)
+gst_registry_check_feature_version (GstRegistry * registry,
+    const gchar * feature_name, guint min_major, guint min_minor,
+    guint min_micro)
 {
   GstPluginFeature *feature;
-  GstRegistry *registry;
   gboolean ret = FALSE;
 
   g_return_val_if_fail (feature_name != NULL, FALSE);
 
   GST_DEBUG ("Looking up plugin feature '%s'", feature_name);
 
-  registry = gst_registry_get_default ();
   feature = gst_registry_lookup_feature (registry, feature_name);
   if (feature) {
     ret = gst_plugin_feature_check_version (feature, min_major, min_minor,
@@ -1435,7 +1453,7 @@ load_plugin_func (gpointer data, gpointer user_data)
   if (plugin) {
     GST_INFO ("Loaded plugin: \"%s\"", filename);
 
-    gst_default_registry_add_plugin (plugin);
+    gst_registry_add_plugin (gst_registry_get (), plugin);
   } else {
     if (err) {
       /* Report error to user, and free error */
@@ -1463,16 +1481,16 @@ gst_registry_remove_cache_plugins (GstRegistry * registry)
   GST_OBJECT_LOCK (registry);
 
   GST_DEBUG_OBJECT (registry, "removing cached plugins");
-  g = registry->plugins;
+  g = registry->priv->plugins;
   while (g) {
     g_next = g->next;
     plugin = g->data;
     if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
       GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"",
           GST_STR_NULL (plugin->filename));
-      registry->plugins = g_list_delete_link (registry->plugins, g);
+      registry->priv->plugins = g_list_delete_link (registry->priv->plugins, g);
       if (G_LIKELY (plugin->basename))
-        g_hash_table_remove (registry->basename_hash, plugin->basename);
+        g_hash_table_remove (registry->priv->basename_hash, plugin->basename);
       gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
       gst_object_unref (plugin);
       changed = TRUE;
@@ -1559,8 +1577,9 @@ scan_and_update_registry (GstRegistry * default_registry,
 
     /* plugins in the user's home directory take precedence over
      * system-installed ones */
-    home_plugins = g_build_filename (g_get_home_dir (),
-        ".gstreamer-" GST_MAJORMINOR, "plugins", NULL);
+    home_plugins = g_build_filename (g_get_user_data_dir (),
+        "gstreamer-" GST_MAJORMINOR, "plugins", NULL);
+
     GST_DEBUG ("scanning home plugins %s", home_plugins);
     changed |= gst_registry_scan_path_internal (&context, home_plugins);
     g_free (home_plugins);
@@ -1616,7 +1635,8 @@ scan_and_update_registry (GstRegistry * default_registry,
   }
 
   GST_INFO ("Registry cache changed. Writing new registry cache");
-  if (!gst_registry_binary_write_cache (default_registry, registry_file)) {
+  if (!priv_gst_registry_binary_write_cache (default_registry,
+          default_registry->priv->plugins, registry_file)) {
     g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
         _("Error writing registry cache to %s: %s"),
         registry_file, g_strerror (errno));
@@ -1636,16 +1656,16 @@ ensure_current_registry (GError ** error)
   gboolean do_update = TRUE;
   gboolean have_cache = TRUE;
 
-  default_registry = gst_registry_get_default ();
+  default_registry = gst_registry_get ();
   registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
   if (registry_file == NULL) {
-    registry_file = g_build_filename (g_get_home_dir (),
-        ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
+    registry_file = g_build_filename (g_get_user_cache_dir (),
+        "gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
   }
 
   if (!_gst_disable_registry_cache) {
     GST_INFO ("reading registry cache: %s", registry_file);
-    have_cache = gst_registry_binary_read_cache (default_registry,
+    have_cache = priv_gst_registry_binary_read_cache (default_registry,
         registry_file);
     /* Only ever read the registry cache once, then disable it for
      * subsequent updates during the program lifetime */
index 0088a6f..b7c4835 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_REGISTRY              (gst_registry_get_type ())
-#define GST_REGISTRY(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REGISTRY, GstRegistry))
-#define GST_IS_REGISTRY(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REGISTRY))
-#define GST_REGISTRY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REGISTRY, GstRegistryClass))
-#define GST_IS_REGISTRY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REGISTRY))
-#define GST_REGISTRY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_REGISTRY, GstRegistryClass))
+#define GST_TYPE_REGISTRY               (gst_registry_get_type ())
+#define GST_REGISTRY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REGISTRY, GstRegistry))
+#define GST_IS_REGISTRY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REGISTRY))
+#define GST_REGISTRY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REGISTRY, GstRegistryClass))
+#define GST_IS_REGISTRY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REGISTRY))
+#define GST_REGISTRY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_REGISTRY, GstRegistryClass))
 
 typedef struct _GstRegistry GstRegistry;
 typedef struct _GstRegistryClass GstRegistryClass;
@@ -47,189 +47,54 @@ typedef struct _GstRegistryPrivate GstRegistryPrivate;
  * Opaque #GstRegistry structure.
  */
 struct _GstRegistry {
-  GstObject     object;
+  GstObject      object;
 
   /*< private >*/
-  GList *plugins;
-  GList *features;
-
-  GList        *paths;
-
-  /* FIXME move these elsewhere */
-  int            cache_file;
-
-  /* hash to speedup _lookup_feature_locked() */
-  GHashTable *feature_hash;
-  /* hash to speedup _lookup */
-  GHashTable *basename_hash;
-
   GstRegistryPrivate *priv;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING-3];
 };
 
 struct _GstRegistryClass {
-  GstObjectClass       parent_class;
-
-  /* signals */
-  void                         (*plugin_added)         (GstRegistry *registry, GstPlugin *plugin);
-  void                         (*feature_added)        (GstRegistry *registry, GstPluginFeature *feature);
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  GstObjectClass        parent_class;
 };
 
+GType                   gst_registry_get_type           (void);
 
-/* normal GObject stuff */
-GType                  gst_registry_get_type           (void);
-
-GstRegistry *           gst_registry_get_default        (void);
+GstRegistry *           gst_registry_get                (void);
 
-gboolean                       gst_registry_scan_path          (GstRegistry *registry, const gchar *path);
+gboolean                gst_registry_scan_path          (GstRegistry *registry, const gchar *path);
 void                    gst_registry_add_path           (GstRegistry * registry, const gchar * path);
-GList*                 gst_registry_get_path_list      (GstRegistry *registry);
+GList*                  gst_registry_get_path_list      (GstRegistry *registry);
 
-gboolean               gst_registry_add_plugin         (GstRegistry *registry, GstPlugin *plugin);
-void                   gst_registry_remove_plugin      (GstRegistry *registry, GstPlugin *plugin);
+gboolean                gst_registry_add_plugin         (GstRegistry *registry, GstPlugin *plugin);
+void                    gst_registry_remove_plugin      (GstRegistry *registry, GstPlugin *plugin);
 gboolean                gst_registry_add_feature        (GstRegistry * registry, GstPluginFeature * feature);
 void                    gst_registry_remove_feature     (GstRegistry * registry, GstPluginFeature * feature);
 
 GList*                  gst_registry_get_plugin_list    (GstRegistry *registry);
-GList*                 gst_registry_plugin_filter      (GstRegistry *registry,
-                                                        GstPluginFilter filter,
-                                                        gboolean first,
-                                                        gpointer user_data);
-GList*                 gst_registry_feature_filter     (GstRegistry *registry,
-                                                        GstPluginFeatureFilter filter,
-                                                        gboolean first,
-                                                        gpointer user_data);
+GList*                  gst_registry_plugin_filter      (GstRegistry *registry,
+                                                         GstPluginFilter filter,
+                                                         gboolean first,
+                                                         gpointer user_data);
+GList*                  gst_registry_feature_filter     (GstRegistry *registry,
+                                                         GstPluginFeatureFilter filter,
+                                                         gboolean first,
+                                                         gpointer user_data);
 GList *                 gst_registry_get_feature_list   (GstRegistry *registry,
                                                          GType type);
 GList *                 gst_registry_get_feature_list_by_plugin (GstRegistry *registry, const gchar *name);
 guint32                 gst_registry_get_feature_list_cookie (GstRegistry *registry);
 
-GstPlugin*             gst_registry_find_plugin        (GstRegistry *registry, const gchar *name);
-GstPluginFeature*      gst_registry_find_feature       (GstRegistry *registry, const gchar *name, GType type);
-
-GstPlugin *            gst_registry_lookup             (GstRegistry *registry, const char *filename);
-GstPluginFeature *     gst_registry_lookup_feature     (GstRegistry *registry, const char *name);
-
-/* These are only here because at some point they were in a public header
- * (even though they should have been private) and we can't really remove
- * them now (FIXME: 0.11). They don't do anything other than return FALSE. */
-#ifndef GST_DISABLE_DEPRECATED
-gboolean               gst_registry_xml_read_cache     (GstRegistry * registry, const char *location);
-gboolean               gst_registry_xml_write_cache    (GstRegistry * registry, const char *location);
-#endif
-
-/* convenience defines for the default registry */
+GstPlugin*              gst_registry_find_plugin        (GstRegistry *registry, const gchar *name);
+GstPluginFeature*       gst_registry_find_feature       (GstRegistry *registry, const gchar *name, GType type);
 
-/**
- * gst_default_registry_add_plugin:
- * @plugin: (transfer full): the plugin to add
- *
- * Add the plugin to the default registry.
- * The plugin-added signal will be emitted.
- *
- * Returns: TRUE on success.
- */
-#define gst_default_registry_add_plugin(plugin) \
-  gst_registry_add_plugin (gst_registry_get_default(), plugin)
-
-/**
- * gst_default_registry_add_path:
- * @path: the path to add to the registry
- *
- * Add the given path to the default registry. The syntax of the
- * path is specific to the registry. If the path has already been
- * added, do nothing.
- */
-#define gst_default_registry_add_path(path) \
-  gst_registry_add_path (gst_registry_get_default(), path)
-
-/**
- * gst_default_registry_get_path_list:
- *
- * Get the list of paths for the default registry.
- *
- * Returns: (transfer container) (element-type char*): a #GList of paths as
- *     strings. g_list_free() after use.
- */
-#define gst_default_registry_get_path_list() \
-  gst_registry_get_path_list (gst_registry_get_default())
-  
-/**
- * gst_default_registry_get_plugin_list:
- *
- * Get a copy of all plugins registered in the default registry.
- *
- * Returns: (transfer full) (element-type Gst.Plugin): a copy of the list.
- *     Free after use.
- */
-#define gst_default_registry_get_plugin_list() \
-  gst_registry_get_plugin_list (gst_registry_get_default())
-
-/**
- * gst_default_registry_find_feature:
- * @name: the pluginfeature name to find
- * @type: the pluginfeature type to find
- *
- * Find the pluginfeature with the given name and type in the default registry.
- *
- * Returns: (transfer full): the pluginfeature with the given name and type or
- *    NULL if the plugin was not found.
- */
-#define gst_default_registry_find_feature(name,type) \
-  gst_registry_find_feature (gst_registry_get_default(),name,type)
-
-/**
- * gst_default_registry_find_plugin:
- * @name: the plugin name to find
- *
- * Find the plugin with the given name in the default registry.
- * The plugin will be reffed; caller is responsible for unreffing.
- *
- * Returns: (transfer full): The plugin with the given name or NULL if the
- *     plugin was not found.
- */
-#define gst_default_registry_find_plugin(name) \
-  gst_registry_find_plugin (gst_registry_get_default(),name)
-
-/**
- * gst_default_registry_feature_filter:
- * @filter: the filter to use
- * @first: only return first match
- * @user_data: user data passed to the filter function
- *
- * Runs a filter against all features of the plugins in the default registry
- * and returns a GList with the results.
- * If the first flag is set, only the first match is
- * returned (as a list with a single object).
- *
- * Returns: (transfer full) (element-type Gst.PluginFeature): a #GList of
- *     plugin features, gst_plugin_feature_list_free after use.
- */
-#define gst_default_registry_feature_filter(filter,first,user_data) \
-  gst_registry_feature_filter (gst_registry_get_default(),filter,first,user_data)
-
-/**
- * gst_default_registry_get_feature_list_cookie:
- *
- * Returns the default registrys feature list cookie. This changes
- * every time a feature is added or removed from the registry.
- *
- * Returns: the feature list cookie.
- *
- * Since: 0.10.26
- */
-#define gst_default_registry_get_feature_list_cookie() \
-  gst_registry_get_feature_list_cookie (gst_registry_get_default())
+GstPlugin *             gst_registry_lookup             (GstRegistry *registry, const char *filename);
+GstPluginFeature *      gst_registry_lookup_feature     (GstRegistry *registry, const char *name);
 
-gboolean                gst_default_registry_check_feature_version (const gchar *feature_name,
-                                                                    guint        min_major,
-                                                                    guint        min_minor,
-                                                                    guint        min_micro);
+gboolean                gst_registry_check_feature_version (GstRegistry *registry,
+                                                            const gchar *feature_name,
+                                                            guint        min_major,
+                                                            guint        min_minor,
+                                                            guint        min_micro);
 
 G_END_DECLS
 
index 1a58837..348b3a7 100644 (file)
@@ -353,7 +353,8 @@ gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m)
  * Returns: %TRUE on success.
  */
 gboolean
-gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
+priv_gst_registry_binary_write_cache (GstRegistry * registry, GList * plugins,
+    const char *location)
 {
   GList *walk;
   GstBinaryRegistryMagic magic;
@@ -369,7 +370,7 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
     goto fail;
 
   /* iterate trough the list of plugins and fit them into binary structures */
-  for (walk = registry->plugins; walk; walk = g_list_next (walk)) {
+  for (walk = plugins; walk != NULL; walk = walk->next) {
     GstPlugin *plugin = GST_PLUGIN (walk->data);
 
     if (!plugin->filename)
@@ -503,7 +504,8 @@ fail:
  * Returns: %TRUE on success.
  */
 gboolean
-gst_registry_binary_read_cache (GstRegistry * registry, const char *location)
+priv_gst_registry_binary_read_cache (GstRegistry * registry,
+    const char *location)
 {
   GMappedFile *mapped = NULL;
   gchar *contents = NULL;
@@ -521,7 +523,6 @@ gst_registry_binary_read_cache (GstRegistry * registry, const char *location)
   /* make sure these types exist */
   GST_TYPE_ELEMENT_FACTORY;
   GST_TYPE_TYPE_FIND_FACTORY;
-  GST_TYPE_INDEX_FACTORY;
 
 #ifndef GST_DISABLE_GST_DEBUG
   timer = g_timer_new ();
@@ -627,27 +628,3 @@ Error:
   }
   return res;
 }
-
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_registry_xml_read_cache (GstRegistry * registry, const char *location);
-#endif
-/* FIXME 0.11: these symbols are here for backwards compatibility and should
- * be removed or made private */
-gboolean
-gst_registry_xml_read_cache (GstRegistry * registry, const char *location)
-{
-  return FALSE;
-}
-
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_registry_xml_write_cache (GstRegistry * registry, const char *location);
-#endif
-gboolean
-gst_registry_xml_write_cache (GstRegistry * registry, const char *location)
-{
-  return FALSE;
-}
-#endif /* GST_REMOVE_DEPRECATED */
index 98cff90..d2900b7 100644 (file)
@@ -240,14 +240,6 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
   if (GST_IS_ELEMENT_FACTORY (feature)) {
     GstRegistryChunkElementFactory *ef;
     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
-    GstElementDetails *details = &factory->details;
-
-    /* do the utf-8 validation of the element factory details here to avoid
-     * doing it every time we load */
-    VALIDATE_UTF8 (details, longname);
-    VALIDATE_UTF8 (details, klass);
-    VALIDATE_UTF8 (details, description);
-    VALIDATE_UTF8 (details, author);
 
     /* Initialize with zeroes because of struct padding and
      * valgrind complaining about copying unitialized memory
@@ -265,7 +257,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
       gst_registry_chunks_save_const_string (list, (gchar *) walk->data);
     }
     GST_DEBUG ("Feature %s: saved %d interfaces %d pad templates",
-        feature->name, ef->ninterfaces, ef->npadtemplates);
+        GST_OBJECT_NAME (feature), ef->ninterfaces, ef->npadtemplates);
 
     /* save uritypes */
     if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
@@ -287,7 +279,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
         GST_DEBUG ("Saved %d UriTypes", ef->nuriprotocols);
       } else {
         g_warning ("GStreamer feature '%s' is URI handler but does not provide"
-            " any protocols it can handle", feature->name);
+            " any protocols it can handle", GST_OBJECT_NAME (feature));
       }
     }
 
@@ -302,17 +294,9 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
       }
     }
 
-    /* pack element factory strings */
-    gst_registry_chunks_save_const_string (list, details->author);
-    gst_registry_chunks_save_const_string (list, details->description);
-    gst_registry_chunks_save_const_string (list, details->klass);
-    gst_registry_chunks_save_const_string (list, details->longname);
-    if (factory->meta_data) {
-      gst_registry_chunks_save_string (list,
-          gst_structure_to_string (factory->meta_data));
-    } else {
-      gst_registry_chunks_save_const_string (list, "");
-    }
+    /* pack element metadata strings */
+    gst_registry_chunks_save_string (list,
+        gst_structure_to_string (factory->metadata));
   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
     GstRegistryChunkTypeFindFactory *tff;
     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
@@ -348,16 +332,6 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
     } else {
       gst_registry_chunks_save_const_string (list, "");
     }
-  } else if (GST_IS_INDEX_FACTORY (feature)) {
-    GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
-
-    pf = g_slice_new (GstRegistryChunkPluginFeature);
-    chk =
-        gst_registry_chunks_make_data (pf,
-        sizeof (GstRegistryChunkPluginFeature));
-
-    /* pack element factory strings */
-    gst_registry_chunks_save_const_string (list, factory->longdesc);
   } else {
     GST_WARNING ("unhandled feature type '%s'", type_name);
   }
@@ -367,7 +341,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
     *list = g_list_prepend (*list, chk);
 
     /* pack plugin feature strings */
-    gst_registry_chunks_save_const_string (list, feature->name);
+    gst_registry_chunks_save_const_string (list, GST_OBJECT_NAME (feature));
     gst_registry_chunks_save_const_string (list, (gchar *) type_name);
 
     return TRUE;
@@ -519,7 +493,7 @@ gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in,
   template = g_slice_new (GstStaticPadTemplate);
   template->presence = pt->presence;
   template->direction = (GstPadDirection) pt->direction;
-  template->static_caps.caps.refcount = 0;
+  template->static_caps.caps.mini_object.refcount = 0;
 
   /* unpack pad template strings */
   unpack_const_string (*in, template->name_template, end, fail);
@@ -604,21 +578,16 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
     /* unpack element factory strings */
     unpack_string_nocopy (*in, meta_data_str, end, fail);
     if (meta_data_str && *meta_data_str) {
-      factory->meta_data = gst_structure_from_string (meta_data_str, NULL);
-      if (!factory->meta_data) {
+      factory->metadata = gst_structure_from_string (meta_data_str, NULL);
+      if (!factory->metadata) {
         GST_ERROR
             ("Error when trying to deserialize structure for metadata '%s'",
             meta_data_str);
         goto fail;
       }
     }
-    unpack_string (*in, factory->details.longname, end, fail);
-    unpack_string (*in, factory->details.klass, end, fail);
-    unpack_string (*in, factory->details.description, end, fail);
-    unpack_string (*in, factory->details.author, end, fail);
     n = ef->npadtemplates;
-    GST_DEBUG ("Element factory : '%s' with npadtemplates=%d",
-        factory->details.longname, n);
+    GST_DEBUG ("Element factory : npadtemplates=%d", n);
 
     /* load pad templates */
     for (i = 0; i < n; i++) {
@@ -681,17 +650,6 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
         factory->extensions[i - 1] = str;
       }
     }
-  } else if (GST_IS_INDEX_FACTORY (feature)) {
-    GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
-
-    align (*in);
-    GST_DEBUG
-        ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
-        *in);
-    unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail);
-
-    /* unpack index factory strings */
-    unpack_string (*in, factory->longdesc, end, fail);
   } else {
     GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
     goto fail;
@@ -705,8 +663,8 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
       (gpointer *) & feature->plugin);
 
   gst_registry_add_feature (registry, feature);
-  GST_DEBUG ("Added feature %s, plugin %p %s", feature->name, plugin,
-      plugin_name);
+  GST_DEBUG ("Added feature %s, plugin %p %s", GST_OBJECT_NAME (feature),
+      plugin, plugin_name);
 
   return TRUE;
 
diff --git a/gst/gstsample.c b/gst/gstsample.c
new file mode 100644 (file)
index 0000000..4c5681f
--- /dev/null
@@ -0,0 +1,206 @@
+/* GStreamer
+ * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * gstsample.c: media sample
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstsample
+ * @short_description: A media sample
+ * @see_also: #GstBuffer, #GstCaps, #GstSegment
+ *
+ * A #GstSample is a small object containing data, a type, timing and
+ * extra arbitrary information.
+ */
+#include "gst_private.h"
+
+#include "gstsample.h"
+
+/**
+ * GstSample:
+ *
+ */
+struct _GstSample
+{
+  GstMiniObject mini_object;
+
+  GstBuffer *buffer;
+  GstCaps *caps;
+  GstSegment segment;
+  GstStructure *info;
+};
+
+GType _gst_sample_type = 0;
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstSample, gst_sample);
+
+void
+_priv_gst_sample_initialize (void)
+{
+  _gst_sample_type = gst_sample_get_type ();
+}
+
+static GstSample *
+_gst_sample_copy (GstSample * sample)
+{
+  GstSample *copy;
+
+  copy = gst_sample_new (sample->buffer, sample->caps, &sample->segment,
+      gst_structure_copy (sample->info));
+
+  return copy;
+}
+
+static void
+_gst_sample_free (GstSample * sample)
+{
+  GST_LOG ("free %p", sample);
+
+  if (sample->buffer)
+    gst_buffer_unref (sample->buffer);
+  if (sample->caps)
+    gst_caps_unref (sample->caps);
+
+  g_slice_free1 (GST_MINI_OBJECT_SIZE (sample), sample);
+}
+
+/**
+ * gst_sample_new:
+ * @buffer: a #GstBuffer
+ * @caps: a #GstCaps
+ * @segment: a #GstSegment
+ * @info: a #GstStructure
+ *
+ * Create a new #GstSample with the provided details.
+ *
+ * Free-function: gst_sample_unref
+ *
+ * Returns: (transfer full): the new #GstSample. gst_sample_unref()
+ *     after usage.
+ *
+ * Since: 0.10.24
+ */
+GstSample *
+gst_sample_new (GstBuffer * buffer, GstCaps * caps, const GstSegment * segment,
+    GstStructure * info)
+{
+  GstSample *sample;
+
+  sample = g_slice_new0 (GstSample);
+
+  GST_LOG ("new %p", sample);
+
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (sample), _gst_sample_type,
+      sizeof (GstSample));
+
+  sample->mini_object.copy = (GstMiniObjectCopyFunction) _gst_sample_copy;
+  sample->mini_object.free = (GstMiniObjectFreeFunction) _gst_sample_free;
+
+  sample->buffer = buffer ? gst_buffer_ref (buffer) : NULL;
+  sample->caps = caps ? gst_caps_ref (caps) : NULL;
+
+  if (segment)
+    gst_segment_copy_into (segment, &sample->segment);
+  else
+    gst_segment_init (&sample->segment, GST_FORMAT_TIME);
+
+  if (info) {
+    if (!gst_structure_set_parent_refcount (info,
+            &sample->mini_object.refcount))
+      goto had_parent;
+
+    sample->info = info;
+  }
+  return sample;
+
+  /* ERRORS */
+had_parent:
+  {
+    gst_sample_unref (sample);
+    g_warning ("structure is already owned by another object");
+    return NULL;
+  }
+}
+
+/**
+ * gst_sample_get_buffer:
+ * @sample: a #GstSample
+ *
+ * Get the buffer associated with @sample
+ *
+ * Returns: (transfer none): the buffer of @sample or NULL when there
+ *  is no buffer. The buffer remains valid as long as @sample is valid.
+ */
+GstBuffer *
+gst_sample_get_buffer (GstSample * sample)
+{
+  g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
+
+  return sample->buffer;
+}
+
+/**
+ * gst_sample_get_caps:
+ * @sample: a #GstSample
+ *
+ * Get the caps associated with @sample
+ *
+ * Returns: (transfer none): the caps of @sample or NULL when there
+ *  is no caps. The caps remain valid as long as @sample is valid.
+ */
+GstCaps *
+gst_sample_get_caps (GstSample * sample)
+{
+  g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
+
+  return sample->caps;
+}
+
+/**
+ * gst_sample_get_segment:
+ * @sample: a #GstSample
+ *
+ * Get the segment associated with @sample
+ *
+ * Returns: (transfer none): the segment of @sample.
+ *  The segment remains valid as long as @sample is valid.
+ */
+GstSegment *
+gst_sample_get_segment (GstSample * sample)
+{
+  g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
+
+  return &sample->segment;
+}
+
+/**
+ * gst_sample_get_info:
+ * @sample: a #GstSample
+ *
+ * Get extra information associated with @sample.
+ *
+ * Returns: (transfer none): the extra info of @sample.
+ *  The info remains valid as long as @sample is valid.
+ */
+const GstStructure *
+gst_sample_get_info (GstSample * sample)
+{
+  g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
+
+  return sample->info;
+}
diff --git a/gst/gstsample.h b/gst/gstsample.h
new file mode 100644 (file)
index 0000000..280ff0d
--- /dev/null
@@ -0,0 +1,136 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstsample.h: Header for GstSample object
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_SAMPLE_H__
+#define __GST_SAMPLE_H__
+
+#include <gst/gstbuffer.h>
+#include <gst/gstcaps.h>
+#include <gst/gstsegment.h>
+
+G_BEGIN_DECLS
+
+GST_EXPORT GType _gst_sample_type;
+
+#define GST_TYPE_SAMPLE      (_gst_sample_type)
+#define GST_IS_SAMPLE(obj)   (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_SAMPLE))
+#define GST_SAMPLE_CAST(obj) ((GstSample *)obj)
+#define GST_SAMPLE(obj)      (GST_SAMPLE_CAST(obj))
+
+/**
+ * GstSample:
+ *
+ * The opaque structure of a #GstSample. A sample contains a typed memory
+ * block and the associated timing information. It is mainly used to
+ * exchange buffers with and application.
+ */
+typedef struct _GstSample GstSample;
+
+/**
+ * GST_SAMPLE_TRACE_NAME:
+ *
+ * The name used for tracing memory allocations.
+ */
+#define GST_SAMPLE_TRACE_NAME           "GstSample"
+
+GType gst_sample_get_type            (void);
+
+/* allocation */
+GstSample *          gst_sample_new           (GstBuffer          *buffer,
+                                               GstCaps            *caps,
+                                               const GstSegment   *segment,
+                                               GstStructure       *info);
+
+GstBuffer *          gst_sample_get_buffer    (GstSample *sample);
+GstCaps *            gst_sample_get_caps      (GstSample *sample);
+GstSegment *         gst_sample_get_segment   (GstSample *sample);
+const GstStructure * gst_sample_get_info      (GstSample *sample);
+
+/* refcounting */
+/**
+ * gst_sample_ref:
+ * @sample: a #GstSample
+ *
+ * Increases the refcount of the given sample by one.
+ *
+ * Returns: (transfer full): @sample
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC GstSample * gst_sample_ref (GstSample * sample);
+#endif
+
+static inline GstSample *
+gst_sample_ref (GstSample * sample)
+{
+  return GST_SAMPLE_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (
+      sample)));
+}
+
+/**
+ * gst_sample_unref:
+ * @sample: (transfer full): a #GstSample
+ *
+ * Decreases the refcount of the sample. If the refcount reaches 0, the
+ * sample will be freed.
+ */
+#ifdef _FOOL_GTK_DOC_
+G_INLINE_FUNC void gst_sample_unref (GstSample * sample);
+#endif
+
+static inline void
+gst_sample_unref (GstSample * sample)
+{
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample));
+}
+
+/**
+ * gst_value_set_sample:
+ * @v: a #GValue to receive the data
+ * @b: (transfer none): a #GstSample to assign to the GstValue
+ *
+ * Sets @b as the value of @v.  Caller retains reference to sample.
+ */
+#define         gst_value_set_sample(v,b)       g_value_set_boxed((v),(b))
+/**
+ * gst_value_take_sample:
+ * @v: a #GValue to receive the data
+ * @b: (transfer full): a #GstSample to assign to the GstValue
+ *
+ * Sets @b as the value of @v.  Caller gives away reference to sample.
+ */
+#define         gst_value_take_sample(v,b)      g_value_take_boxed(v,(b))
+/**
+ * gst_value_get_sample:
+ * @v: a #GValue to query
+ *
+ * Receives a #GstSample as the value of @v. Does not return a reference to
+ * the sample, so the pointer is only valid for as long as the caller owns
+ * a reference to @v.
+ *
+ * Returns: (transfer none): sample
+ */
+#define         gst_value_get_sample(v)         GST_SAMPLE_CAST (g_value_get_boxed(v))
+
+G_END_DECLS
+
+#endif /* __GST_SAMPLE_H__ */
index 0b090a3..84e217a 100644 (file)
@@ -33,7 +33,7 @@
  * @see_also: #GstEvent
  *
  * This helper structure holds the relevant values for tracking the region of
- * interest in a media file, called a segment. 
+ * interest in a media file, called a segment.
  *
  * The structure can be used for two purposes:
  * <itemizedlist>
@@ -41,7 +41,7 @@
  *   <listitem><para>tracking playback regions (handling newsegment events)</para></listitem>
  * </itemizedlist>
  *
- * The segment is usually configured by the application with a seek event which 
+ * The segment is usually configured by the application with a seek event which
  * is propagated upstream and eventually handled by an element that performs the seek.
  *
  * The configured segment is then propagated back downstream with a newsegment event.
@@ -54,7 +54,7 @@
  *
  * If the segment is used for managing seeks, the segment duration should be set with
  * gst_segment_set_duration(). The public duration field contains the duration of the
- * segment. When using the segment for seeking, the start and time members should 
+ * segment. When using the segment for seeking, the start and time members should
  * normally be left to their default 0 value. The stop position is left to -1 unless
  * explicitly configured to a different value after a seek event.
  *
@@ -77,7 +77,7 @@
  * to the clock. This function takes into account all accumulated segments as well as
  * any rate or applied_rate conversions.
  *
- * For elements that need to perform operations on media data in stream_time, 
+ * For elements that need to perform operations on media data in stream_time,
  * gst_segment_to_stream_time() can be used to convert a timestamp and the segment
  * info to stream time (which is always between 0 and the duration of the stream).
  *
@@ -97,7 +97,7 @@
  * Since: 0.10.20
  */
 GstSegment *
-gst_segment_copy (GstSegment * segment)
+gst_segment_copy (const GstSegment * segment)
 {
   GstSegment *result = NULL;
 
@@ -107,6 +107,12 @@ gst_segment_copy (GstSegment * segment)
   return result;
 }
 
+void
+gst_segment_copy_into (const GstSegment * src, GstSegment * dest)
+{
+  memcpy (dest, src, sizeof (GstSegment));
+}
+
 GType
 gst_segment_get_type (void)
 {
@@ -123,7 +129,7 @@ gst_segment_get_type (void)
 /**
  * gst_segment_new:
  *
- * Allocate a new #GstSegment structure and initialize it using 
+ * Allocate a new #GstSegment structure and initialize it using
  * gst_segment_init().
  *
  * Free-function: gst_segment_free
@@ -169,94 +175,41 @@ gst_segment_init (GstSegment * segment, GstFormat format)
 {
   g_return_if_fail (segment != NULL);
 
+  segment->flags = GST_SEGMENT_FLAG_NONE;
   segment->rate = 1.0;
-  segment->abs_rate = 1.0;
   segment->applied_rate = 1.0;
   segment->format = format;
-  segment->flags = GST_SEEK_FLAG_NONE;
+  segment->base = 0;
   segment->start = 0;
   segment->stop = -1;
   segment->time = 0;
-  segment->accum = 0;
-  segment->last_stop = 0;
+  segment->position = 0;
   segment->duration = -1;
 }
 
 /**
- * gst_segment_set_duration:
- * @segment: a #GstSegment structure.
- * @format: the format of the segment.
- * @duration: the duration of the segment info or -1 if unknown.
- *
- * Set the duration of the segment to @duration. This function is mainly
- * used by elements that perform seeking and know the total duration of the
- * segment. 
- * 
- * This field should be set to allow seeking requests relative to the
- * duration.
- */
-void
-gst_segment_set_duration (GstSegment * segment, GstFormat format,
-    gint64 duration)
-{
-  g_return_if_fail (segment != NULL);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
-  else
-    g_return_if_fail (segment->format == format);
-
-  segment->duration = duration;
-}
-
-/**
- * gst_segment_set_last_stop:
- * @segment: a #GstSegment structure.
- * @format: the format of the segment.
- * @position: the position 
- *
- * Set the last observed stop position in the segment to @position.
- *
- * This field should be set to allow seeking requests relative to the
- * current playing position.
- */
-void
-gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
-    gint64 position)
-{
-  g_return_if_fail (segment != NULL);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
-  else
-    g_return_if_fail (segment->format == format);
-
-  segment->last_stop = MAX (segment->start, position);
-}
-
-/**
- * gst_segment_set_seek:
+ * gst_segment_do_seek:
  * @segment: a #GstSegment structure.
  * @rate: the rate of the segment.
  * @format: the format of the segment.
- * @flags: the seek flags for the segment
+ * @flags: the segment flags for the segment
  * @start_type: the seek method
  * @start: the seek start value
  * @stop_type: the seek method
  * @stop: the seek stop value
- * @update: boolean holding whether last_stop was updated.
+ * @update: boolean holding whether position was updated.
  *
  * Update the segment structure with the field values of a seek event (see
  * gst_event_new_seek()).
  *
- * After calling this method, the segment field last_stop and time will
+ * After calling this method, the segment field position and time will
  * contain the requested new position in the segment. The new requested
- * position in the segment depends on @rate and @start_type and @stop_type. 
+ * position in the segment depends on @rate and @start_type and @stop_type.
  *
  * For positive @rate, the new position in the segment is the new @segment
  * start field when it was updated with a @start_type different from
  * #GST_SEEK_TYPE_NONE. If no update was performed on @segment start position
- * (#GST_SEEK_TYPE_NONE), @start is ignored and @segment last_stop is
+ * (#GST_SEEK_TYPE_NONE), @start is ignored and @segment position is
  * unmodified.
  *
  * For negative @rate, the new position in the segment is the new @segment
@@ -264,33 +217,42 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
  * #GST_SEEK_TYPE_NONE. If no stop was previously configured in the segment, the
  * duration of the segment will be used to update the stop position.
  * If no update was performed on @segment stop position (#GST_SEEK_TYPE_NONE),
- * @stop is ignored and @segment last_stop is unmodified.
+ * @stop is ignored and @segment position is unmodified.
  *
  * The applied rate of the segment will be set to 1.0 by default.
  * If the caller can apply a rate change, it should update @segment
  * rate and applied_rate after calling this function.
  *
- * @update will be set to TRUE if a seek should be performed to the segment 
- * last_stop field. This field can be FALSE if, for example, only the @rate
+ * @update will be set to TRUE if a seek should be performed to the segment
+ * position field. This field can be FALSE if, for example, only the @rate
  * has been changed but not the playback position.
+ *
+ * Returns: %TRUE if the seek could be performed.
  */
-void
-gst_segment_set_seek (GstSegment * segment, gdouble rate,
+gboolean
+gst_segment_do_seek (GstSegment * segment, gdouble rate,
     GstFormat format, GstSeekFlags flags,
-    GstSeekType start_type, gint64 start,
-    GstSeekType stop_type, gint64 stop, gboolean * update)
+    GstSeekType start_type, guint64 start,
+    GstSeekType stop_type, guint64 stop, gboolean * update)
 {
   gboolean update_stop, update_start;
-  gint64 last_stop;
+  guint64 position, base;
 
-  g_return_if_fail (rate != 0.0);
-  g_return_if_fail (segment != NULL);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
+  g_return_val_if_fail (rate != 0.0, FALSE);
+  g_return_val_if_fail (segment != NULL, FALSE);
+  g_return_val_if_fail (segment->format == format, FALSE);
 
   update_start = update_stop = TRUE;
 
+  position = segment->position;
+
+  if (flags & GST_SEEK_FLAG_FLUSH) {
+    /* flush resets the running_time */
+    base = 0;
+  } else {
+    base = gst_segment_to_running_time (segment, format, position);
+  }
+
   /* segment->start is never invalid */
   switch (start_type) {
     case GST_SEEK_TYPE_NONE:
@@ -302,17 +264,9 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
       /* start holds desired position, map -1 to the start */
       if (start == -1)
         start = 0;
-      /* start must be 0 or the formats must match */
-      g_return_if_fail (start == 0 || segment->format == format);
-      break;
-    case GST_SEEK_TYPE_CUR:
-      g_return_if_fail (start == 0 || segment->format == format);
-      /* add start to currently configured segment */
-      start = segment->start + start;
       break;
     case GST_SEEK_TYPE_END:
       if (segment->duration != -1) {
-        g_return_if_fail (start == 0 || segment->format == format);
         /* add start to total length */
         start = segment->duration + start;
       } else {
@@ -324,7 +278,7 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
   }
   /* bring in sane range */
   if (segment->duration != -1)
-    start = CLAMP (start, 0, segment->duration);
+    start = MIN (start, segment->duration);
   else
     start = MAX (start, 0);
 
@@ -335,22 +289,10 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
       update_stop = FALSE;
       break;
     case GST_SEEK_TYPE_SET:
-      /* stop holds required value, if it's not -1, it must be of the same
-       * format as the segment. */
-      g_return_if_fail (stop == -1 || segment->format == format);
-      break;
-    case GST_SEEK_TYPE_CUR:
-      if (segment->stop != -1) {
-        /* only add compatible formats or 0 */
-        g_return_if_fail (stop == 0 || segment->format == format);
-        stop = segment->stop + stop;
-      } else
-        stop = -1;
+      /* stop holds required value */
       break;
     case GST_SEEK_TYPE_END:
       if (segment->duration != -1) {
-        /* only add compatible formats or 0 */
-        g_return_if_fail (stop == 0 || segment->format == format);
         stop = segment->duration + stop;
       } else {
         stop = segment->stop;
@@ -368,168 +310,42 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
   }
 
   /* we can't have stop before start */
-  if (stop != -1)
-    g_return_if_fail (start <= stop);
+  if (stop != -1) {
+    if (start > stop) {
+      g_return_val_if_fail (start <= stop, FALSE);
+      return FALSE;
+    }
+  }
 
   segment->rate = rate;
-  segment->abs_rate = ABS (rate);
   segment->applied_rate = 1.0;
-  segment->flags = flags;
+  segment->base = base;
+  segment->flags = (GstSegmentFlags) flags;
   segment->start = start;
   segment->stop = stop;
   segment->time = start;
 
-  last_stop = segment->last_stop;
   if (update_start && rate > 0.0) {
-    last_stop = start;
+    position = start;
   }
   if (update_stop && rate < 0.0) {
     if (stop != -1)
-      last_stop = stop;
+      position = stop;
     else {
       if (segment->duration != -1)
-        last_stop = segment->duration;
+        position = segment->duration;
       else
-        last_stop = 0;
+        position = 0;
     }
   }
-  /* set update arg to reflect update of last_stop */
+  /* set update arg to reflect update of position */
   if (update)
-    *update = last_stop != segment->last_stop;
+    *update = position != segment->position;
 
   /* update new position */
-  segment->last_stop = last_stop;
-}
+  segment->position = position;
 
-/**
- * gst_segment_set_newsegment:
- * @segment: a #GstSegment structure.
- * @update: flag indicating a new segment is started or updated
- * @rate: the rate of the segment.
- * @format: the format of the segment.
- * @start: the new start value
- * @stop: the new stop value
- * @time: the new stream time
- *
- * Update the segment structure with the field values of a new segment event and
- * with a default applied_rate of 1.0.
- *
- * Since: 0.10.6
- */
-void
-gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
-    GstFormat format, gint64 start, gint64 stop, gint64 time)
-{
-  gst_segment_set_newsegment_full (segment, update, rate, 1.0, format, start,
-      stop, time);
-}
-
-/**
- * gst_segment_set_newsegment_full:
- * @segment: a #GstSegment structure.
- * @update: flag indicating a new segment is started or updated
- * @rate: the rate of the segment.
- * @applied_rate: the applied rate of the segment.
- * @format: the format of the segment.
- * @start: the new start value
- * @stop: the new stop value
- * @time: the new stream time
- *
- * Update the segment structure with the field values of a new segment event.
- */
-void
-gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
-    gdouble rate, gdouble applied_rate, GstFormat format, gint64 start,
-    gint64 stop, gint64 time)
-{
-  gint64 duration, last_stop;
-
-  g_return_if_fail (rate != 0.0);
-  g_return_if_fail (applied_rate != 0.0);
-  g_return_if_fail (segment != NULL);
-
-  GST_DEBUG ("configuring segment update %d, rate %lf, format %s, "
-      "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
-      G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
-      stop, time);
-  GST_DEBUG ("old segment was: %" GST_SEGMENT_FORMAT, segment);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
-
-  /* any other format with 0 also gives time 0, the other values are
-   * invalid in the format though. */
-  if (format != segment->format && start == 0) {
-    format = segment->format;
-    if (stop != 0)
-      stop = -1;
-    if (time != 0)
-      time = -1;
-  }
-
-  g_return_if_fail (segment->format == format);
-
-  if (update) {
-    if (G_LIKELY (segment->rate > 0.0)) {
-      /* an update to the current segment is done, elapsed time is
-       * difference between the old start and new start. */
-      if (start > segment->start)
-        duration = start - segment->start;
-      else
-        duration = 0;
-    } else {
-      /* for negative rates, the elapsed duration is the diff between the stop
-       * positions */
-      if (stop != -1 && stop < segment->stop)
-        duration = segment->stop - stop;
-      else
-        duration = 0;
-    }
-    /* update last_stop to be a valid value in the updated segment */
-    if (start > segment->last_stop)
-      last_stop = start;
-    else if (stop != -1 && stop < segment->last_stop)
-      last_stop = stop;
-    else
-      last_stop = segment->last_stop;
-  } else {
-    /* the new segment has to be aligned with the old segment.
-     * We first update the accumulated time of the previous
-     * segment. the accumulated time is used when syncing to the
-     * clock. */
-    if (segment->stop != -1) {
-      duration = segment->stop - segment->start;
-    } else if (segment->last_stop != -1) {
-      /* else use last seen timestamp as segment stop */
-      duration = segment->last_stop - segment->start;
-    } else {
-      /* else we don't know and throw a warning.. really, this should
-       * be fixed in the element. */
-      g_warning ("closing segment of unknown duration, assuming duration of 0");
-      duration = 0;
-    }
-    /* position the last_stop to the next expected position in the new segment,
-     * which is the start or the stop of the segment */
-    if (rate > 0.0)
-      last_stop = start;
-    else
-      last_stop = stop;
-  }
-  /* use previous rate to calculate duration */
-  if (G_LIKELY (segment->abs_rate != 1.0))
-    duration /= segment->abs_rate;
-
-  /* accumulate duration */
-  segment->accum += duration;
-
-  /* then update the current segment */
-  segment->rate = rate;
-  segment->abs_rate = ABS (rate);
-  segment->applied_rate = applied_rate;
-  segment->start = start;
-  segment->last_stop = last_stop;
-  segment->stop = stop;
-  segment->time = time;
+  return TRUE;
 }
 
 /**
@@ -538,25 +354,25 @@ gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
  * @format: the format of the segment.
  * @position: the position in the segment
  *
- * Translate @position to stream time using the currently configured 
+ * Translate @position to stream time using the currently configured
  * segment. The @position value must be between @segment start and
- * stop value. 
+ * stop value.
  *
  * This function is typically used by elements that need to operate on
  * the stream time of the buffers it receives, such as effect plugins.
- * In those use cases, @position is typically the buffer timestamp or 
+ * In those use cases, @position is typically the buffer timestamp or
  * clock time that one wants to convert to the stream time.
- * The stream time is always between 0 and the total duration of the 
- * media stream. 
+ * The stream time is always between 0 and the total duration of the
+ * media stream.
  *
  * Returns: the position in stream_time or -1 when an invalid position
  * was given.
  */
-gint64
-gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
-    gint64 position)
+guint64
+gst_segment_to_stream_time (const GstSegment * segment, GstFormat format,
+    guint64 position)
 {
-  gint64 result, start, stop, time;
+  guint64 result, start, stop, time;
   gdouble abs_applied_rate;
 
   /* format does not matter for -1 */
@@ -564,9 +380,7 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
     return -1;
 
   g_return_val_if_fail (segment != NULL, -1);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
+  g_return_val_if_fail (segment->format == format, -1);
 
   /* if we have the position for the same format as the segment, we can compare
    * the start and stop values, otherwise we assume 0 and -1 */
@@ -624,7 +438,7 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
  * @format: the format of the segment.
  * @position: the position in the segment
  *
- * Translate @position to the total running time using the currently configured 
+ * Translate @position to the total running time using the currently configured
  * and previously accumulated segments. Position is a value between @segment
  * start and stop time.
  *
@@ -638,31 +452,30 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
  * Returns: the position as the total running time or -1 when an invalid position
  * was given.
  */
-gint64
-gst_segment_to_running_time (GstSegment * segment, GstFormat format,
-    gint64 position)
+guint64
+gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
+    guint64 position)
 {
-  gint64 result;
-  gint64 start, stop, accum;
+  guint64 result;
+  guint64 start, stop, base;
+  gdouble abs_rate;
 
   if (G_UNLIKELY (position == -1))
     return -1;
 
   g_return_val_if_fail (segment != NULL, -1);
-
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
+  g_return_val_if_fail (segment->format == format, -1);
 
   /* if we have the position for the same format as the segment, we can compare
    * the start and stop values, otherwise we assume 0 and -1 */
   if (G_LIKELY (segment->format == format)) {
     start = segment->start;
     stop = segment->stop;
-    accum = segment->accum;
+    base = segment->base;
   } else {
     start = 0;
     stop = -1;
-    accum = 0;
+    base = 0;
   }
 
   /* before the segment boundary */
@@ -686,13 +499,14 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
     result = stop - position;
   }
 
-  /* scale based on the rate, avoid division by and conversion to 
+  /* scale based on the rate, avoid division by and conversion to
    * float when not needed */
-  if (G_UNLIKELY (segment->abs_rate != 1.0))
-    result /= segment->abs_rate;
+  abs_rate = ABS (segment->rate);
+  if (G_UNLIKELY (abs_rate != 1.0))
+    result /= abs_rate;
 
-  /* correct for accumulated segments */
-  result += accum;
+  /* correct for base of the segment */
+  result += base;
 
   return result;
 }
@@ -707,7 +521,7 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
  * @clip_stop: (out) (allow-none): the clipped stop position in the segment
  *
  * Clip the given @start and @stop values to the segment boundaries given
- * in @segment. @start and @stop are compared and clipped to @segment 
+ * in @segment. @start and @stop are compared and clipped to @segment
  * start and stop values.
  *
  * If the function returns FALSE, @start and @stop are known to fall
@@ -720,22 +534,18 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
  * Note that when @stop is -1, @clip_stop will be set to the end of the
  * segment. Depending on the use case, this may or may not be what you want.
  *
- * Returns: TRUE if the given @start and @stop times fall partially or 
- *     completely in @segment, FALSE if the values are completely outside 
+ * Returns: TRUE if the given @start and @stop times fall partially or
+ *     completely in @segment, FALSE if the values are completely outside
  *     of the segment.
  */
 gboolean
-gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
-    gint64 stop, gint64 * clip_start, gint64 * clip_stop)
+gst_segment_clip (const GstSegment * segment, GstFormat format, guint64 start,
+    guint64 stop, guint64 * clip_start, guint64 * clip_stop)
 {
   g_return_val_if_fail (segment != NULL, FALSE);
+  g_return_val_if_fail (segment->format == format, FALSE);
 
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
-  else
-    g_return_val_if_fail (segment->format == format, FALSE);
-
-  /* if we have a stop position and a valid start and start is bigger, 
+  /* if we have a stop position and a valid start and start is bigger,
    * we're outside of the segment */
   if (G_UNLIKELY (segment->stop != -1 && start != -1 && start >= segment->stop))
     return FALSE;
@@ -759,11 +569,11 @@ gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
     if (stop == -1)
       *clip_stop = segment->stop;
     else if (segment->stop == -1)
-      *clip_stop = MAX (-1, stop);
+      *clip_stop = stop;
     else
       *clip_stop = MIN (stop, segment->stop);
 
-    if (segment->duration != -1)
+    if (segment->duration != -1 && *clip_stop != -1)
       *clip_stop = MIN (*clip_stop, segment->duration);
   }
 
@@ -784,43 +594,43 @@ gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
  *
  * Since: 0.10.24
  */
-gint64
-gst_segment_to_position (GstSegment * segment, GstFormat format,
-    gint64 running_time)
+guint64
+gst_segment_to_position (const GstSegment * segment, GstFormat format,
+    guint64 running_time)
 {
-  gint64 result;
-  gint64 start, stop, accum;
-
-  g_return_val_if_fail (segment != NULL, -1);
+  guint64 result;
+  guint64 start, stop, base;
+  gdouble abs_rate;
 
   if (G_UNLIKELY (running_time == -1))
     return -1;
 
-  if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
-    segment->format = format;
+  g_return_val_if_fail (segment != NULL, -1);
+  g_return_val_if_fail (segment->format == format, FALSE);
 
   /* if we have the position for the same format as the segment, we can compare
    * the start and stop values, otherwise we assume 0 and -1 */
   if (G_LIKELY (segment->format == format)) {
     start = segment->start;
     stop = segment->stop;
-    accum = segment->accum;
+    base = segment->base;
   } else {
     start = 0;
     stop = -1;
-    accum = 0;
+    base = 0;
   }
 
   /* this running_time was for a previous segment */
-  if (running_time < accum)
+  if (running_time < base)
     return -1;
 
-  /* start by subtracting the accumulated time */
-  result = running_time - accum;
+  /* start by subtracting the base time */
+  result = running_time - base;
 
   /* move into the segment at the right rate */
-  if (G_UNLIKELY (segment->abs_rate != 1.0))
-    result = ceil (result * segment->abs_rate);
+  abs_rate = ABS (segment->rate);
+  if (G_UNLIKELY (abs_rate != 1.0))
+    result = ceil (result * abs_rate);
 
   if (G_LIKELY (segment->rate > 0.0)) {
     /* bring to corrected position in segment */
@@ -848,7 +658,7 @@ gst_segment_to_position (GstSegment * segment, GstFormat format,
  * @format: the format of the segment.
  * @running_time: the running_time in the segment
  *
- * Adjust the start/stop and accum values of @segment such that the next valid
+ * Adjust the start/stop and base values of @segment such that the next valid
  * buffer will be one with @running_time.
  *
  * Returns: %TRUE if the segment could be updated successfully. If %FALSE is
@@ -858,10 +668,10 @@ gst_segment_to_position (GstSegment * segment, GstFormat format,
  */
 gboolean
 gst_segment_set_running_time (GstSegment * segment, GstFormat format,
-    gint64 running_time)
+    guint64 running_time)
 {
-  gint64 position;
-  gint64 start, stop, last_stop;
+  guint64 position;
+  guint64 start, stop;
 
   /* start by bringing the running_time into the segment position */
   position = gst_segment_to_position (segment, format, running_time);
@@ -872,26 +682,19 @@ gst_segment_set_running_time (GstSegment * segment, GstFormat format,
 
   start = segment->start;
   stop = segment->stop;
-  last_stop = segment->last_stop;
 
   if (G_LIKELY (segment->rate > 0.0)) {
-    /* update the start/last_stop and time values */
+    /* update the start and time values */
     start = position;
-    if (last_stop < start)
-      last_stop = start;
   } else {
     /* reverse, update stop */
     stop = position;
-    /* if we were past the position, go back */
-    if (last_stop > stop)
-      last_stop = stop;
   }
-  /* and accumulated time is exactly the running time */
+  /* and base time is exactly the running time */
   segment->time = gst_segment_to_stream_time (segment, format, start);
   segment->start = start;
   segment->stop = stop;
-  segment->last_stop = last_stop;
-  segment->accum = running_time;
+  segment->base = running_time;
 
   return TRUE;
 }
index ff53f32..92bd32c 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef __GST_SEGMENT_H__
 #define __GST_SEGMENT_H__
 
-#include <gst/gstevent.h>
 #include <gst/gstformat.h>
 
 G_BEGIN_DECLS
@@ -33,76 +32,141 @@ G_BEGIN_DECLS
 typedef struct _GstSegment GstSegment;
 
 /**
+ * GstSeekType:
+ * @GST_SEEK_TYPE_NONE: no change in position is required
+ * @GST_SEEK_TYPE_SET: absolute position is requested
+ * @GST_SEEK_TYPE_END: relative position to duration is requested
+ *
+ * The different types of seek events. When constructing a seek event with
+ * gst_event_new_seek() or when doing gst_segment_do_seek ().
+ */
+typedef enum {
+  /* one of these */
+  GST_SEEK_TYPE_NONE            = 0,
+  GST_SEEK_TYPE_SET             = 1,
+  GST_SEEK_TYPE_END             = 2
+} GstSeekType;
+
+/**
+ * GstSeekFlags:
+ * @GST_SEEK_FLAG_NONE: no flag
+ * @GST_SEEK_FLAG_FLUSH: flush pipeline
+ * @GST_SEEK_FLAG_ACCURATE: accurate position is requested, this might
+ *                     be considerably slower for some formats.
+ * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be
+ *                     faster but less accurate.
+ * @GST_SEEK_FLAG_SEGMENT: perform a segment seek.
+ * @GST_SEEK_FLAG_SKIP: when doing fast foward or fast reverse playback, allow
+ *                     elements to skip frames instead of generating all
+ *                     frames. Since 0.10.22.
+ *
+ * Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags
+ * can be used together.
+ *
+ * A non flushing seek might take some time to perform as the currently
+ * playing data in the pipeline will not be cleared.
+ *
+ * An accurate seek might be slower for formats that don't have any indexes
+ * or timestamp markers in the stream. Specifying this flag might require a
+ * complete scan of the file in those cases.
+ *
+ * When performing a segment seek: after the playback of the segment completes,
+ * no EOS will be emmited by the element that performed the seek, but a
+ * #GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element.
+ * When this message is posted, it is possible to send a new seek event to
+ * continue playback. With this seek method it is possible to perform seamless
+ * looping or simple linear editing.
+ *
+ * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode
+ * playback, the @GST_SEEK_FLAG_SKIP flag can be used to instruct decoders
+ * and demuxers to adjust the playback rate by skipping frames. This can improve
+ * performance and decrease CPU usage because not all frames need to be decoded.
+ *
+ * Also see part-seeking.txt in the GStreamer design documentation for more
+ * details on the meaning of these flags and the behaviour expected of
+ * elements that handle them.
+ */
+typedef enum {
+  GST_SEEK_FLAG_NONE            = 0,
+  GST_SEEK_FLAG_FLUSH           = (1 << 0),
+  GST_SEEK_FLAG_ACCURATE        = (1 << 1),
+  GST_SEEK_FLAG_KEY_UNIT        = (1 << 2),
+  GST_SEEK_FLAG_SEGMENT         = (1 << 3),
+  GST_SEEK_FLAG_SKIP            = (1 << 4)
+} GstSeekFlags;
+
+/**
+ * GstSegmentFlags:
+ * @GST_SEGMENT_FLAG_NONE: no flags
+ * @GST_SEGMENT_FLAG_RESET: reset the pipeline running_time to the segment
+ *                          running_time
+ * @GST_SEGMENT_FLAG_SKIP: perform skip playback
+ *
+ * Flags for the GstSegment structure. Currently mapped to the corresponding
+ * values of the seek flags.
+ */
+typedef enum {
+  GST_SEGMENT_FLAG_NONE            = GST_SEEK_FLAG_NONE,
+  GST_SEGMENT_FLAG_RESET           = GST_SEEK_FLAG_FLUSH,
+  GST_SEGMENT_FLAG_SKIP            = GST_SEEK_FLAG_SKIP
+} GstSegmentFlags;
+
+/**
  * GstSegment:
+ * @flags: flags for this segment
  * @rate: the rate of the segment
- * @abs_rate: absolute value of @rate
+ * @applied_rate: the already applied rate to the segment
  * @format: the format of the segment values
- * @flags: flags for this segment
+ * @base: the base time of the segment
  * @start: the start of the segment
  * @stop: the stop of the segment
  * @time: the stream time of the segment
- * @accum: accumulated segment
- * @last_stop: last known stop time
- * @duration: total duration of segment
- * @applied_rate: the already applied rate to the segment
+ * @position: the position in the segment
+ * @duration: the duration of the segment
  *
  * A helper structure that holds the configured region of
  * interest in a media file.
  */
 struct _GstSegment {
   /*< public >*/
-  gdouble        rate;
-  gdouble        abs_rate;
-  GstFormat      format;
-  GstSeekFlags   flags;
-  gint64         start;
-  gint64         stop;
-  gint64         time;
-  gint64         accum;
-
-  gint64         last_stop;
-  gint64         duration;
-
-  /* API added 0.10.6 */
-  gdouble        applied_rate;
-
-  /*< private >*/
-  /*gpointer _gst_reserved[GST_PADDING-2];*/
-  guint8 _gst_reserved[(sizeof (gpointer) * GST_PADDING) - sizeof (gdouble)];
+  GstSegmentFlags flags;
+
+  gdouble         rate;
+  gdouble         applied_rate;
+
+  GstFormat       format;
+  guint64         base;
+  guint64         start;
+  guint64         stop;
+  guint64         time;
+
+  guint64         position;
+  guint64         duration;
 };
 
 GType        gst_segment_get_type            (void);
 
 GstSegment * gst_segment_new                 (void) G_GNUC_MALLOC;
-GstSegment * gst_segment_copy                (GstSegment *segment) G_GNUC_MALLOC;
+GstSegment * gst_segment_copy                (const GstSegment *segment) G_GNUC_MALLOC;
+void         gst_segment_copy_into           (const GstSegment *src, GstSegment *dest);
 void         gst_segment_free                (GstSegment *segment);
 
 void         gst_segment_init                (GstSegment *segment, GstFormat format);
 
-void         gst_segment_set_duration        (GstSegment *segment, GstFormat format, gint64 duration);
-void         gst_segment_set_last_stop       (GstSegment *segment, GstFormat format, gint64 position);
+guint64      gst_segment_to_stream_time      (const GstSegment *segment, GstFormat format, guint64 position);
+guint64      gst_segment_to_running_time     (const GstSegment *segment, GstFormat format, guint64 position);
+guint64      gst_segment_to_position         (const GstSegment *segment, GstFormat format, guint64 running_time);
 
-void         gst_segment_set_seek            (GstSegment *segment, gdouble rate,
-                                              GstFormat format, GstSeekFlags flags,
-                                              GstSeekType start_type, gint64 start,
-                                              GstSeekType stop_type, gint64 stop,
-                                              gboolean *update);
+gboolean     gst_segment_set_running_time    (GstSegment *segment, GstFormat format, guint64 running_time);
 
-void         gst_segment_set_newsegment      (GstSegment *segment, gboolean update, gdouble rate,
-                                              GstFormat format, gint64 start, gint64 stop, gint64 time);
-void         gst_segment_set_newsegment_full (GstSegment *segment, gboolean update, gdouble rate,
-                                              gdouble applied_rate, GstFormat format, gint64 start,
-                                              gint64 stop, gint64 time);
+gboolean     gst_segment_clip                (const GstSegment *segment, GstFormat format, guint64 start,
+                                              guint64 stop, guint64 *clip_start, guint64 *clip_stop);
 
-gint64       gst_segment_to_stream_time      (GstSegment *segment, GstFormat format, gint64 position);
-gint64       gst_segment_to_running_time     (GstSegment *segment, GstFormat format, gint64 position);
-gint64       gst_segment_to_position         (GstSegment *segment, GstFormat format, gint64 running_time);
-
-gboolean     gst_segment_clip                (GstSegment *segment, GstFormat format, gint64 start,
-                                              gint64 stop, gint64 *clip_start, gint64 *clip_stop);
-
-gboolean     gst_segment_set_running_time    (GstSegment *segment, GstFormat format, gint64 running_time);
 
+gboolean     gst_segment_do_seek             (GstSegment * segment, gdouble rate,
+                                              GstFormat format, GstSeekFlags flags,
+                                              GstSeekType start_type, guint64 start,
+                                              GstSeekType stop_type, guint64 stop, gboolean * update);
 
 G_END_DECLS
 
index 23c54b3..5310092 100644 (file)
@@ -36,7 +36,7 @@
  * provides a means to enforce mutability using the refcount of the parent
  * with the gst_structure_set_parent_refcount() method.
  *
- * A #GstStructure can be created with gst_structure_empty_new() or
+ * A #GstStructure can be created with gst_structure_new_empty() or
  * gst_structure_new(), which both take a name and an optional set of
  * key/value pairs along with the types of the values.
  *
@@ -74,12 +74,25 @@ struct _GstStructureField
   GValue value;
 };
 
+typedef struct
+{
+  GstStructure s;
+
+  /* owned by parent structure, NULL if no parent */
+  gint *parent_refcount;
+
+  GArray *fields;
+} GstStructureImpl;
+
+#define GST_STRUCTURE_REFCOUNT(s) (((GstStructureImpl*)(s))->parent_refcount)
+#define GST_STRUCTURE_FIELDS(s) (((GstStructureImpl*)(s))->fields)
+
 #define GST_STRUCTURE_FIELD(structure, index) \
-    &g_array_index((structure)->fields, GstStructureField, (index))
+    &g_array_index(GST_STRUCTURE_FIELDS(structure), GstStructureField, (index))
 
 #define IS_MUTABLE(structure) \
-    (!(structure)->parent_refcount || \
-     g_atomic_int_get ((structure)->parent_refcount) == 1)
+    (!GST_STRUCTURE_REFCOUNT(structure) || \
+     g_atomic_int_get (GST_STRUCTURE_REFCOUNT(structure)) == 1)
 
 #define IS_TAGLIST(structure) \
     (structure->name == GST_QUARK (TAGLIST))
@@ -98,40 +111,38 @@ static gboolean gst_structure_parse_value (gchar * str, gchar ** after,
     GValue * value, GType default_type);
 static gboolean gst_structure_parse_simple_string (gchar * s, gchar ** end);
 
-GType
-gst_structure_get_type (void)
-{
-  static GType gst_structure_type = 0;
+GType _gst_structure_type = 0;
 
-  if (G_UNLIKELY (gst_structure_type == 0)) {
-    gst_structure_type = g_boxed_type_register_static ("GstStructure",
-        (GBoxedCopyFunc) gst_structure_copy_conditional,
-        (GBoxedFreeFunc) gst_structure_free);
 
-    g_value_register_transform_func (gst_structure_type, G_TYPE_STRING,
-        gst_structure_transform_to_string);
-  }
+G_DEFINE_BOXED_TYPE (GstStructure, gst_structure,
+    gst_structure_copy_conditional, gst_structure_free);
 
-  return gst_structure_type;
+void
+_priv_gst_structure_initialize (void)
+{
+  _gst_structure_type = gst_structure_get_type ();
+
+  g_value_register_transform_func (_gst_structure_type, G_TYPE_STRING,
+      gst_structure_transform_to_string);
 }
 
 static GstStructure *
-gst_structure_id_empty_new_with_size (GQuark quark, guint prealloc)
+gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
 {
-  GstStructure *structure;
+  GstStructureImpl *structure;
 
-  structure = g_slice_new (GstStructure);
-  structure->type = gst_structure_get_type ();
-  structure->name = quark;
-  structure->parent_refcount = NULL;
-  structure->fields =
+  structure = g_slice_new (GstStructureImpl);
+  ((GstStructure *) structure)->type = _gst_structure_type;
+  ((GstStructure *) structure)->name = quark;
+  GST_STRUCTURE_REFCOUNT (structure) = NULL;
+  GST_STRUCTURE_FIELDS (structure) =
       g_array_sized_new (FALSE, FALSE, sizeof (GstStructureField), prealloc);
 
-  return structure;
+  return GST_STRUCTURE_CAST (structure);
 }
 
 /**
- * gst_structure_id_empty_new:
+ * gst_structure_new_id_empty:
  * @quark: name of new structure
  *
  * Creates a new, empty #GstStructure with the given name as a GQuark.
@@ -141,11 +152,11 @@ gst_structure_id_empty_new_with_size (GQuark quark, guint prealloc)
  * Returns: (transfer full): a new, empty #GstStructure
  */
 GstStructure *
-gst_structure_id_empty_new (GQuark quark)
+gst_structure_new_id_empty (GQuark quark)
 {
   g_return_val_if_fail (quark != 0, NULL);
 
-  return gst_structure_id_empty_new_with_size (quark, 0);
+  return gst_structure_new_id_empty_with_size (quark, 0);
 }
 
 #ifndef G_DISABLE_CHECKS
@@ -156,17 +167,15 @@ gst_structure_validate_name (const gchar * name)
 
   g_return_val_if_fail (name != NULL, FALSE);
 
-  /* FIXME 0.11: use g_ascii_isalpha() */
-  if (G_UNLIKELY (!g_ascii_isalnum (*name))) {
+  if (G_UNLIKELY (!g_ascii_isalpha (*name))) {
     GST_WARNING ("Invalid character '%c' at offset 0 in structure name: %s",
         *name, name);
     return FALSE;
   }
 
-  /* FIXME 0.11: don't allow spaces */
   /* FIXME: test name string more */
   s = &name[1];
-  while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+ ", *s) != NULL))
+  while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL))
     s++;
   if (G_UNLIKELY (*s != '\0')) {
     GST_WARNING ("Invalid character '%c' at offset %" G_GUINTPTR_FORMAT " in"
@@ -179,7 +188,7 @@ gst_structure_validate_name (const gchar * name)
 #endif
 
 /**
- * gst_structure_empty_new:
+ * gst_structure_new_empty:
  * @name: name of new structure
  *
  * Creates a new, empty #GstStructure with the given @name.
@@ -191,11 +200,11 @@ gst_structure_validate_name (const gchar * name)
  * Returns: (transfer full): a new, empty #GstStructure
  */
 GstStructure *
-gst_structure_empty_new (const gchar * name)
+gst_structure_new_empty (const gchar * name)
 {
   g_return_val_if_fail (gst_structure_validate_name (name), NULL);
 
-  return gst_structure_id_empty_new_with_size (g_quark_from_string (name), 0);
+  return gst_structure_new_id_empty_with_size (g_quark_from_string (name), 0);
 }
 
 /**
@@ -248,7 +257,7 @@ gst_structure_new_valist (const gchar * name,
 {
   GstStructure *structure;
 
-  structure = gst_structure_empty_new (name);
+  structure = gst_structure_new_empty (name);
 
   if (structure)
     gst_structure_set_valist (structure, firstfield, varargs);
@@ -265,20 +274,31 @@ gst_structure_new_valist (const gchar * name,
  * determine whether a structure is mutable or not. This function should only be
  * called by code implementing parent objects of #GstStructure, as described in
  * the MT Refcounting section of the design documents.
+ *
+ * Returns: %TRUE if the parent refcount could be set.
  */
-void
+gboolean
 gst_structure_set_parent_refcount (GstStructure * structure, gint * refcount)
 {
-  g_return_if_fail (structure != NULL);
+  g_return_val_if_fail (structure != NULL, FALSE);
 
   /* if we have a parent_refcount already, we can only clear
    * if with a NULL refcount */
-  if (structure->parent_refcount)
-    g_return_if_fail (refcount == NULL);
-  else
-    g_return_if_fail (refcount != NULL);
+  if (GST_STRUCTURE_REFCOUNT (structure)) {
+    if (refcount != NULL) {
+      g_return_val_if_fail (refcount == NULL, FALSE);
+      return FALSE;
+    }
+  } else {
+    if (refcount == NULL) {
+      g_return_val_if_fail (refcount != NULL, FALSE);
+      return FALSE;
+    }
+  }
 
-  structure->parent_refcount = refcount;
+  GST_STRUCTURE_REFCOUNT (structure) = refcount;
+
+  return TRUE;
 }
 
 /**
@@ -300,8 +320,8 @@ gst_structure_copy (const GstStructure * structure)
 
   g_return_val_if_fail (structure != NULL, NULL);
 
-  len = structure->fields->len;
-  new_structure = gst_structure_id_empty_new_with_size (structure->name, len);
+  len = GST_STRUCTURE_FIELDS (structure)->len;
+  new_structure = gst_structure_new_id_empty_with_size (structure->name, len);
 
   for (i = 0; i < len; i++) {
     GstStructureField new_field = { 0 };
@@ -310,7 +330,7 @@ gst_structure_copy (const GstStructure * structure)
 
     new_field.name = field->name;
     gst_value_init_and_copy (&new_field.value, &field->value);
-    g_array_append_val (new_structure->fields, new_field);
+    g_array_append_val (GST_STRUCTURE_FIELDS (new_structure), new_field);
   }
 
   return new_structure;
@@ -330,9 +350,9 @@ gst_structure_free (GstStructure * structure)
   guint i, len;
 
   g_return_if_fail (structure != NULL);
-  g_return_if_fail (structure->parent_refcount == NULL);
+  g_return_if_fail (GST_STRUCTURE_REFCOUNT (structure) == NULL);
 
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
@@ -340,11 +360,11 @@ gst_structure_free (GstStructure * structure)
       g_value_unset (&field->value);
     }
   }
-  g_array_free (structure->fields, TRUE);
+  g_array_free (GST_STRUCTURE_FIELDS (structure), TRUE);
 #ifdef USE_POISONING
   memset (structure, 0xff, sizeof (GstStructure));
 #endif
-  g_slice_free (GstStructure, structure);
+  g_slice_free1 (sizeof (GstStructureImpl), structure);
 }
 
 /**
@@ -561,10 +581,6 @@ gst_structure_set_valist_internal (GstStructure * structure,
 
     type = va_arg (varargs, GType);
 
-    if (G_UNLIKELY (type == G_TYPE_DATE)) {
-      g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
-      type = GST_TYPE_DATE;
-    }
     G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
     if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
@@ -631,10 +647,6 @@ gst_structure_id_set_valist_internal (GstStructure * structure,
 
     type = va_arg (varargs, GType);
 
-    if (G_UNLIKELY (type == G_TYPE_DATE)) {
-      g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
-      type = GST_TYPE_DATE;
-    }
 #ifndef G_VALUE_COLLECT_INIT
     g_value_init (&field.value, type);
     G_VALUE_COLLECT (&field.value, varargs, 0, &err);
@@ -698,7 +710,7 @@ gst_structure_id_set_valist (GstStructure * structure,
 }
 
 /**
- * gst_structure_id_new:
+ * gst_structure_new_id:
  * @name_quark: name of new structure
  * @field_quark: the GQuark for the name of the field to set
  * @...: variable arguments
@@ -706,7 +718,7 @@ gst_structure_id_set_valist (GstStructure * structure,
  * Creates a new #GstStructure with the given name as a GQuark, followed by
  * fieldname quark, GType, argument(s) "triplets" in the same format as
  * gst_structure_id_set(). Basically a convenience wrapper around
- * gst_structure_id_empty_new() and gst_structure_id_set().
+ * gst_structure_new_id_empty() and gst_structure_id_set().
  *
  * The last variable argument must be NULL (or 0).
  *
@@ -717,7 +729,7 @@ gst_structure_id_set_valist (GstStructure * structure,
  * Since: 0.10.24
  */
 GstStructure *
-gst_structure_id_new (GQuark name_quark, GQuark field_quark, ...)
+gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
 {
   GstStructure *s;
   va_list varargs;
@@ -725,7 +737,7 @@ gst_structure_id_new (GQuark name_quark, GQuark field_quark, ...)
   g_return_val_if_fail (name_quark != 0, NULL);
   g_return_val_if_fail (field_quark != 0, NULL);
 
-  s = gst_structure_id_empty_new (name_quark);
+  s = gst_structure_new_id_empty (name_quark);
 
   va_start (varargs, field_quark);
   gst_structure_id_set_valist_internal (s, field_quark, varargs);
@@ -748,7 +760,7 @@ static void
 gst_structure_set_field (GstStructure * structure, GstStructureField * field)
 {
   GstStructureField *f;
-  guint i, len = structure->fields->len;
+  guint i, len = GST_STRUCTURE_FIELDS (structure)->len;
 
   if (G_UNLIKELY (G_VALUE_HOLDS_STRING (&field->value))) {
     const gchar *s;
@@ -777,10 +789,10 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field)
       g_value_unset (&field->value);
       return;
     }
-  } else if (G_UNLIKELY (GST_VALUE_HOLDS_DATE (&field->value))) {
+  } else if (G_UNLIKELY (G_VALUE_HOLDS (&field->value, G_TYPE_DATE))) {
     const GDate *d;
 
-    d = gst_value_get_date (&field->value);
+    d = g_value_get_boxed (&field->value);
     /* only check for NULL GDates in taglists, as they might make sense
      * in other, generic structs */
     if (G_UNLIKELY ((IS_TAGLIST (structure) && d == NULL))) {
@@ -808,7 +820,7 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field)
     }
   }
 
-  g_array_append_val (structure->fields, *field);
+  g_array_append_val (GST_STRUCTURE_FIELDS (structure), *field);
 }
 
 /* If there is no field with the given ID, NULL is returned.
@@ -819,7 +831,7 @@ gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
   GstStructureField *field;
   guint i, len;
 
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -913,7 +925,7 @@ gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
   g_return_if_fail (IS_MUTABLE (structure));
 
   id = g_quark_from_string (fieldname);
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -922,7 +934,8 @@ gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
       if (G_IS_VALUE (&field->value)) {
         g_value_unset (&field->value);
       }
-      structure->fields = g_array_remove_index (structure->fields, i);
+      GST_STRUCTURE_FIELDS (structure) =
+          g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
       return;
     }
   }
@@ -991,13 +1004,14 @@ gst_structure_remove_all_fields (GstStructure * structure)
   g_return_if_fail (structure != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
 
-  for (i = structure->fields->len - 1; i >= 0; i--) {
+  for (i = GST_STRUCTURE_FIELDS (structure)->len - 1; i >= 0; i--) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
     if (G_IS_VALUE (&field->value)) {
       g_value_unset (&field->value);
     }
-    structure->fields = g_array_remove_index (structure->fields, i);
+    GST_STRUCTURE_FIELDS (structure) =
+        g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
   }
 }
 
@@ -1041,7 +1055,7 @@ gst_structure_n_fields (const GstStructure * structure)
 {
   g_return_val_if_fail (structure != NULL, 0);
 
-  return structure->fields->len;
+  return GST_STRUCTURE_FIELDS (structure)->len;
 }
 
 /**
@@ -1059,7 +1073,7 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index)
   GstStructureField *field;
 
   g_return_val_if_fail (structure != NULL, NULL);
-  g_return_val_if_fail (index < structure->fields->len, NULL);
+  g_return_val_if_fail (index < GST_STRUCTURE_FIELDS (structure)->len, NULL);
 
   field = GST_STRUCTURE_FIELD (structure, index);
 
@@ -1089,7 +1103,7 @@ gst_structure_foreach (const GstStructure * structure,
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
 
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1126,7 +1140,7 @@ gst_structure_map_in_place (GstStructure * structure,
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
   g_return_val_if_fail (func != NULL, FALSE);
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
 
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
@@ -1344,42 +1358,6 @@ gst_structure_get_uint (const GstStructure * structure,
 }
 
 /**
- * gst_structure_get_fourcc:
- * @structure: a #GstStructure
- * @fieldname: the name of a field
- * @value: (out): a pointer to a 32bit unsigned int to set
- *
- * Sets the Fourcc pointed to by @value corresponding to the value of the
- * given field.  Caller is responsible for making sure the field exists
- * and has the correct type.
- *
- * Returns: TRUE if the value could be set correctly. If there was no field
- * with @fieldname or the existing field did not contain a fourcc, this function
- * returns FALSE.
- */
-gboolean
-gst_structure_get_fourcc (const GstStructure * structure,
-    const gchar * fieldname, guint32 * value)
-{
-  GstStructureField *field;
-
-  g_return_val_if_fail (structure != NULL, FALSE);
-  g_return_val_if_fail (fieldname != NULL, FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
-
-  field = gst_structure_get_field (structure, fieldname);
-
-  if (field == NULL)
-    return FALSE;
-  if (!GST_VALUE_HOLDS_FOURCC (&field->value))
-    return FALSE;
-
-  *value = gst_value_get_fourcc (&field->value);
-
-  return TRUE;
-}
-
-/**
  * gst_structure_get_date:
  * @structure: a #GstStructure
  * @fieldname: the name of a field
@@ -1412,7 +1390,7 @@ gst_structure_get_date (const GstStructure * structure, const gchar * fieldname,
 
   if (field == NULL)
     return FALSE;
-  if (!GST_VALUE_HOLDS_DATE (&field->value))
+  if (!G_VALUE_HOLDS (&field->value, G_TYPE_DATE))
     return FALSE;
 
   /* FIXME: 0.11 g_value_dup_boxed() -> g_value_get_boxed() */
@@ -1685,10 +1663,6 @@ gst_structure_get_abbrs (gint * n_abbrs)
       ,
       {"buffer", GST_TYPE_BUFFER}
       ,
-      {"fourcc", GST_TYPE_FOURCC}
-      ,
-      {"4", GST_TYPE_FOURCC}
-      ,
       {"fraction", GST_TYPE_FRACTION}
       ,
       {"boolean", G_TYPE_BOOLEAN}
@@ -1705,9 +1679,11 @@ gst_structure_get_abbrs (gint * n_abbrs)
       ,
       {"structure", GST_TYPE_STRUCTURE}
       ,
-      {"date", GST_TYPE_DATE}
+      {"date", G_TYPE_DATE}
       ,
       {"datetime", GST_TYPE_DATE_TIME}
+      ,
+      {"bitmask", GST_TYPE_BITMASK}
     };
     _num = G_N_ELEMENTS (dyn_abbrs);
     /* permanently allocate and copy the array now */
@@ -1799,7 +1775,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
   g_return_val_if_fail (s != NULL, FALSE);
 
   g_string_append (s, g_quark_to_string (structure->name));
-  len = structure->fields->len;
+  len = GST_STRUCTURE_FIELDS (structure)->len;
   for (i = 0; i < len; i++) {
     char *t;
     GType type;
@@ -1924,8 +1900,9 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
 {
   GValue value1 = { 0 };
   GValue value2 = { 0 };
+  GValue value3 = { 0 };
   GType range_type;
-  gboolean ret;
+  gboolean ret, have_step = FALSE;
 
   if (*s != '[')
     return FALSE;
@@ -1952,12 +1929,34 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
   while (g_ascii_isspace (*s))
     s++;
 
+  /* optional step for int and int64 */
+  if (G_VALUE_TYPE (&value1) == G_TYPE_INT
+      || G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
+    if (*s == ',') {
+      s++;
+
+      while (g_ascii_isspace (*s))
+        s++;
+
+      ret = gst_structure_parse_value (s, &s, &value3, type);
+      if (ret == FALSE)
+        return FALSE;
+
+      while (g_ascii_isspace (*s))
+        s++;
+
+      have_step = TRUE;
+    }
+  }
+
   if (*s != ']')
     return FALSE;
   s++;
 
   if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
     return FALSE;
+  if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
+    return FALSE;
 
   if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
     range_type = GST_TYPE_DOUBLE_RANGE;
@@ -1968,13 +1967,26 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
   } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
     range_type = GST_TYPE_INT_RANGE;
     g_value_init (value, range_type);
-    gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
-        gst_g_value_get_int_unchecked (&value2));
+    if (have_step)
+      gst_value_set_int_range_step (value,
+          gst_g_value_get_int_unchecked (&value1),
+          gst_g_value_get_int_unchecked (&value2),
+          gst_g_value_get_int_unchecked (&value3));
+    else
+      gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
+          gst_g_value_get_int_unchecked (&value2));
   } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
     range_type = GST_TYPE_INT64_RANGE;
     g_value_init (value, range_type);
-    gst_value_set_int64_range (value, gst_g_value_get_int64_unchecked (&value1),
-        gst_g_value_get_int64_unchecked (&value2));
+    if (have_step)
+      gst_value_set_int64_range_step (value,
+          gst_g_value_get_int64_unchecked (&value1),
+          gst_g_value_get_int64_unchecked (&value2),
+          gst_g_value_get_int64_unchecked (&value3));
+    else
+      gst_value_set_int64_range (value,
+          gst_g_value_get_int64_unchecked (&value1),
+          gst_g_value_get_int64_unchecked (&value2));
   } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
     range_type = GST_TYPE_FRACTION_RANGE;
     g_value_init (value, range_type);
@@ -2260,7 +2272,7 @@ gst_structure_from_string (const gchar * string, gchar ** end)
 
   save = *w;
   *w = '\0';
-  structure = gst_structure_empty_new (name);
+  structure = gst_structure_new_empty (name);
   *w = save;
 
   if (G_UNLIKELY (structure == NULL))
@@ -2663,6 +2675,42 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
   return FALSE;
 }
 
+static gboolean
+default_fixate (GQuark field_id, const GValue * value, gpointer data)
+{
+  GstStructure *s = data;
+  GValue v = { 0 };
+
+  if (gst_value_fixate (&v, value)) {
+    gst_structure_id_set_value (s, field_id, &v);
+    g_value_unset (&v);
+  }
+  return TRUE;
+}
+
+/**
+ * gst_structure_fixate_field:
+ * @structure: a #GstStructure
+ * @field_name: a field in @structure
+ *
+ * Fixates a #GstStructure by changing the given field with its fixated value.
+ *
+ * Returns: TRUE if the structure field could be fixated
+ */
+gboolean
+gst_structure_fixate_field (GstStructure * structure, const char *field_name)
+{
+  GstStructureField *field;
+
+  g_return_val_if_fail (structure != NULL, FALSE);
+  g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
+
+  if (!(field = gst_structure_get_field (structure, field_name)))
+    return FALSE;
+
+  return default_fixate (field->name, &field->value, structure);
+}
+
 /* our very own version of G_VALUE_LCOPY that allows NULL return locations
  * (useful for message parsing functions where the return location is user
  * supplied and the user may pass NULL if the value isn't of interest) */
@@ -2952,7 +3000,8 @@ gst_structure_is_equal (const GstStructure * structure1,
   if (structure1->name != structure2->name) {
     return FALSE;
   }
-  if (structure1->fields->len != structure2->fields->len) {
+  if (GST_STRUCTURE_FIELDS (structure1)->len !=
+      GST_STRUCTURE_FIELDS (structure2)->len) {
     return FALSE;
   }
 
@@ -3025,7 +3074,7 @@ gst_structure_intersect (const GstStructure * struct1,
 
   /* copy fields from struct1 which we have not in struct2 to target
    * intersect if we have the field in both */
-  data.dest = gst_structure_id_empty_new (struct1->name);
+  data.dest = gst_structure_new_id_empty (struct1->name);
   data.intersect = struct2;
   if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
               gst_structure_intersect_field1, &data)))
@@ -3119,32 +3168,7 @@ gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
   if (comparison != GST_VALUE_UNORDERED)
     return FALSE;
 
-  /*
-   * 1 - [1,2] = empty
-   * -> !subset
-   *
-   * [1,2] - 1 = 2
-   *  -> 1 - [1,2] = empty
-   *  -> subset
-   *
-   * [1,3] - [1,2] = 3
-   * -> [1,2] - [1,3] = empty
-   * -> subset
-   *
-   * {1,2} - {1,3} = 2
-   * -> {1,3} - {1,2} = 3
-   * -> !subset
-   *
-   *  First caps subtraction needs to return a non-empty set, second
-   *  subtractions needs to give en empty set.
-   *  Both substractions are switched below, as it's faster that way.
-   */
-  if (!gst_value_subtract (NULL, value, other)) {
-    if (gst_value_subtract (NULL, other, value)) {
-      return TRUE;
-    }
-  }
-  return FALSE;
+  return gst_value_is_subset (value, other);
 }
 
 /**
@@ -3171,3 +3195,19 @@ gst_structure_is_subset (const GstStructure * subset,
   return gst_structure_foreach ((GstStructure *) subset,
       gst_caps_structure_is_subset_field, (gpointer) superset);
 }
+
+
+/**
+ * gst_structure_fixate:
+ * @structure: a #GstStructure
+ *
+ * Fixate all values in @structure using gst_value_fixate().
+ * @structure will be modified in-place and should be writable.
+ */
+void
+gst_structure_fixate (GstStructure * structure)
+{
+  g_return_if_fail (GST_IS_STRUCTURE (structure));
+
+  gst_structure_foreach (structure, default_fixate, structure);
+}
index 8483f00..90c4b59 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_STRUCTURE             (gst_structure_get_type ())
-#define GST_STRUCTURE(object)          ((GstStructure *)(object))
-#define GST_IS_STRUCTURE(object)       ((object) && (GST_STRUCTURE(object)->type == GST_TYPE_STRUCTURE))
+GST_EXPORT GType _gst_structure_type;
 
 typedef struct _GstStructure GstStructure;
 
+#define GST_TYPE_STRUCTURE             (_gst_structure_type)
+#define GST_IS_STRUCTURE(object)       ((object) && (GST_STRUCTURE(object)->type == GST_TYPE_STRUCTURE))
+#define GST_STRUCTURE_CAST(object)     ((GstStructure *)(object))
+#define GST_STRUCTURE(object)          (GST_STRUCTURE_CAST(object))
+
+
 /**
  * GstStructureForeachFunc:
  * @field_id: the #GQuark of the field name
@@ -77,31 +81,24 @@ struct _GstStructure {
 
   /*< private >*/
   GQuark name;
-
-  /* owned by parent structure, NULL if no parent */
-  gint *parent_refcount;
-
-  GArray *fields;
-
-  gpointer _gst_reserved;
 };
 
 GType                   gst_structure_get_type             (void);
 
-GstStructure *          gst_structure_empty_new            (const gchar *            name) G_GNUC_MALLOC;
-GstStructure *          gst_structure_id_empty_new         (GQuark                   quark) G_GNUC_MALLOC;
+GstStructure *          gst_structure_new_empty            (const gchar *            name) G_GNUC_MALLOC;
+GstStructure *          gst_structure_new_id_empty         (GQuark                   quark) G_GNUC_MALLOC;
 GstStructure *          gst_structure_new                  (const gchar *            name,
                                                            const gchar *            firstfield,
-                                                           ...) G_GNUC_MALLOC;
+                                                           ...) G_GNUC_NULL_TERMINATED  G_GNUC_MALLOC;
 GstStructure *          gst_structure_new_valist           (const gchar *            name,
                                                            const gchar *            firstfield,
                                                            va_list                  varargs) G_GNUC_MALLOC;
-GstStructure *          gst_structure_id_new               (GQuark                   name_quark,
+GstStructure *          gst_structure_new_id               (GQuark                   name_quark,
                                                             GQuark                   field_quark,
                                                             ...) G_GNUC_MALLOC;
 GstStructure *          gst_structure_copy                 (const GstStructure      *structure) G_GNUC_MALLOC;
-void                   gst_structure_set_parent_refcount  (GstStructure            *structure,
-                                                            gint            *refcount);
+gboolean               gst_structure_set_parent_refcount  (GstStructure            *structure,
+                                                            gint                    *refcount);
 void                    gst_structure_free                 (GstStructure            *structure);
 
 const gchar *          gst_structure_get_name             (const GstStructure      *structure);
@@ -200,9 +197,6 @@ gboolean                gst_structure_get_int              (const GstStructure
 gboolean                gst_structure_get_uint             (const GstStructure      *structure,
                                                            const gchar             *fieldname,
                                                            guint                   *value);
-gboolean                gst_structure_get_fourcc           (const GstStructure      *structure,
-                                                           const gchar             *fieldname,
-                                                           guint32                 *value);
 gboolean                gst_structure_get_double           (const GstStructure      *structure,
                                                            const gchar             *fieldname,
                                                            gdouble                 *value);
@@ -247,6 +241,8 @@ gboolean                 gst_structure_fixate_field_nearest_fraction (GstStructu
                                                                         const char   *field_name,
                                                                         const gint target_numerator,
                                                                         const gint target_denominator);
+gboolean                 gst_structure_fixate_field  (GstStructure *structure,
+                                                     const char   *field_name);
 
 gboolean                 gst_structure_is_equal(const GstStructure *structure1,
                                                const GstStructure *structure2);
@@ -255,7 +251,8 @@ gboolean                 gst_structure_is_subset(const GstStructure *subset,
 gboolean                 gst_structure_can_intersect(const GstStructure *struct1,
                                                     const GstStructure *struct2);
 GstStructure*            gst_structure_intersect (const GstStructure *struct1,
-                                                  const GstStructure *struct2) G_GNUC_MALLOC;
+                                                  const GstStructure *struct2)  G_GNUC_MALLOC;
+void                     gst_structure_fixate    (GstStructure *structure);
 
 G_END_DECLS
 
index 2c71489..462f7a1 100644 (file)
@@ -57,7 +57,7 @@
 
 #define GET_ENTRY_STATUS(e)          ((GstClockReturn) g_atomic_int_get(&GST_CLOCK_ENTRY_STATUS(e)))
 #define SET_ENTRY_STATUS(e,val)      (g_atomic_int_set(&GST_CLOCK_ENTRY_STATUS(e),(val)))
-#define CAS_ENTRY_STATUS(e,old,val)  (G_ATOMIC_INT_COMPARE_AND_EXCHANGE(\
+#define CAS_ENTRY_STATUS(e,old,val)  (g_atomic_int_compare_and_exchange(\
                                        (&GST_CLOCK_ENTRY_STATUS(e)), (old), (val)))
 
 /* Define this to get some extra debug about jitter from each clock_wait */
@@ -121,12 +121,11 @@ static void gst_system_clock_async_thread (GstClock * clock);
 static gboolean gst_system_clock_start_async (GstSystemClock * clock);
 static void gst_system_clock_add_wakeup (GstSystemClock * sysclock);
 
-static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
-
-static GstClockClass *parent_class = NULL;
+static GMutex _gst_sysclock_mutex;
 
 /* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
 
+#define gst_system_clock_parent_class parent_class
 G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK);
 
 static void
@@ -138,8 +137,6 @@ gst_system_clock_class_init (GstSystemClockClass * klass)
   gobject_class = (GObjectClass *) klass;
   gstclock_class = (GstClockClass *) klass;
 
-  parent_class = g_type_class_peek_parent (klass);
-
   g_type_class_add_private (klass, sizeof (GstSystemClockPrivate));
 
   gobject_class->dispose = gst_system_clock_dispose;
@@ -154,7 +151,7 @@ gst_system_clock_class_init (GstSystemClockClass * klass)
 
   gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
   gstclock_class->get_resolution = gst_system_clock_get_resolution;
-  gstclock_class->wait_jitter = gst_system_clock_id_wait_jitter;
+  gstclock_class->wait = gst_system_clock_id_wait_jitter;
   gstclock_class->wait_async = gst_system_clock_id_wait_async;
   gstclock_class->unschedule = gst_system_clock_id_unschedule;
 }
@@ -279,7 +276,7 @@ gst_system_clock_obtain (void)
 {
   GstClock *clock;
 
-  g_static_mutex_lock (&_gst_sysclock_mutex);
+  g_mutex_lock (&_gst_sysclock_mutex);
   clock = _the_system_clock;
 
   if (clock == NULL) {
@@ -292,9 +289,9 @@ gst_system_clock_obtain (void)
     gst_object_ref_sink (clock);
 
     _the_system_clock = clock;
-    g_static_mutex_unlock (&_gst_sysclock_mutex);
+    g_mutex_unlock (&_gst_sysclock_mutex);
   } else {
-    g_static_mutex_unlock (&_gst_sysclock_mutex);
+    g_mutex_unlock (&_gst_sysclock_mutex);
     GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
   }
 
@@ -735,13 +732,8 @@ gst_system_clock_start_async (GstSystemClock * clock)
   if (G_LIKELY (clock->thread != NULL))
     return TRUE;                /* Thread already running. Nothing to do */
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
-      clock, TRUE, &error);
-#else
   clock->thread = g_thread_try_new ("GstSystemClock",
       (GThreadFunc) gst_system_clock_async_thread, clock, &error);
-#endif
 
   if (G_UNLIKELY (error))
     goto no_thread;
index 4f372de..490f700 100644 (file)
@@ -70,7 +70,7 @@ struct _GstSystemClock {
   /* ABI added */
   GstSystemClockPrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstSystemClockClass {
index ac88c79..7e3de44 100644 (file)
 #include "gstvalue.h"
 #include "gstbuffer.h"
 #include "gstquark.h"
+#include "gststructure.h"
 
 #include <gobject/gvaluecollector.h>
 #include <string.h>
 
 #define GST_TAG_IS_VALID(tag)           (gst_tag_get_info (tag) != NULL)
 
+/* FIXME 0.11: make taglists refcounted maybe? */
+/* a tag list is basically a structure, but we don't make this fact public */
+struct _GstTagList
+{
+  GstStructure structure;
+};
+
 /* FIXME 0.11: use GParamSpecs or something similar for tag registrations,
  * possibly even gst_tag_register(). Especially value ranges might be
  * useful for some tags. */
@@ -65,19 +73,11 @@ typedef struct
 }
 GstTagInfo;
 
-#if GLIB_CHECK_VERSION (2, 31, 0)
 #define g_value_get_char g_value_get_schar
-#endif
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-static GMutex *__tag_mutex;
-#define TAG_LOCK g_mutex_lock (__tag_mutex)
-#define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
-#else
 static GMutex __tag_mutex;
 #define TAG_LOCK g_mutex_lock (&__tag_mutex)
 #define TAG_UNLOCK g_mutex_unlock (&__tag_mutex)
-#endif
 
 /* tags hash table: maps tag name string => GstTagInfo */
 static GHashTable *__tags;
@@ -101,13 +101,10 @@ gst_tag_list_get_type (void)
 }
 
 void
-_gst_tag_initialize (void)
+_priv_gst_tag_initialize (void)
 {
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  __tag_mutex = g_mutex_new ();
-#else
   g_mutex_init (&__tag_mutex);
-#endif
+
   __tags = g_hash_table_new (g_str_hash, g_str_equal);
   gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META,
       G_TYPE_STRING,
@@ -141,9 +138,9 @@ _gst_tag_initialize (void)
       G_TYPE_STRING,
       _("album artist sortname"),
       _("The artist of the entire album, as it should be sorted"), NULL);
-  gst_tag_register (GST_TAG_DATE, GST_TAG_FLAG_META, GST_TYPE_DATE,
+  gst_tag_register (GST_TAG_DATE, GST_TAG_FLAG_META, G_TYPE_DATE,
       _("date"), _("date the data was created (as a GDate structure)"), NULL);
-  gst_tag_register (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, GST_TYPE_DATE_TIME,
+  gst_tag_register (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, G_TYPE_DATE_TIME,
       _("datetime"),
       _("date and time the data was created (as a GstDateTime structure)"),
       NULL);
@@ -279,12 +276,12 @@ _gst_tag_initialize (void)
   gst_tag_register (GST_TAG_LANGUAGE_NAME, GST_TAG_FLAG_META, G_TYPE_STRING,
       _("language name"),
       _("freeform name of the language this stream is in"), NULL);
-  gst_tag_register (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
+  gst_tag_register (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE,
       _("image"), _("image related to this stream"), gst_tag_merge_use_first);
-  gst_tag_register (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
+  gst_tag_register (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE,
       /* TRANSLATORS: 'preview image' = image that shows a preview of the full image */
       _("preview image"), _("preview image related to this stream"), NULL);
-  gst_tag_register (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, GST_TYPE_BUFFER,
+  gst_tag_register (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, GST_TYPE_SAMPLE,
       _("attachment"), _("file attached to this stream"),
       gst_tag_merge_use_first);
   gst_tag_register (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, G_TYPE_DOUBLE,
@@ -635,7 +632,7 @@ gst_tag_is_fixed (const gchar * tag)
 }
 
 /**
- * gst_tag_list_new:
+ * gst_tag_list_new_empty:
  *
  * Creates a new empty GstTagList.
  *
@@ -644,13 +641,13 @@ gst_tag_is_fixed (const gchar * tag)
  * Returns: (transfer full): An empty tag list
  */
 GstTagList *
-gst_tag_list_new (void)
+gst_tag_list_new_empty (void)
 {
-  return GST_TAG_LIST (gst_structure_id_empty_new (GST_QUARK (TAGLIST)));
+  return GST_TAG_LIST (gst_structure_new_id_empty (GST_QUARK (TAGLIST)));
 }
 
 /**
- * gst_tag_list_new_full:
+ * gst_tag_list_new:
  * @tag: tag
  * @...: NULL-terminated list of values to set
  *
@@ -669,16 +666,15 @@ gst_tag_list_new (void)
  *
  * Since: 0.10.24
  */
-/* FIXME 0.11: rename gst_tag_list_new_full to _new and _new to _new_empty */
 GstTagList *
-gst_tag_list_new_full (const gchar * tag, ...)
+gst_tag_list_new (const gchar * tag, ...)
 {
   GstTagList *list;
   va_list args;
 
   g_return_val_if_fail (tag != NULL, NULL);
 
-  list = gst_tag_list_new ();
+  list = gst_tag_list_new_empty ();
   va_start (args, tag);
   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, args);
   va_end (args);
@@ -687,10 +683,10 @@ gst_tag_list_new_full (const gchar * tag, ...)
 }
 
 /**
- * gst_tag_list_new_full_valist:
+ * gst_tag_list_new_valist:
  * @var_args: tag / value pairs to set
  *
- * Just like gst_tag_list_new_full(), only that it takes a va_list argument.
+ * Just like gst_tag_list_new(), only that it takes a va_list argument.
  * Useful mostly for language bindings.
  *
  * Free-function: gst_tag_list_free
@@ -701,12 +697,12 @@ gst_tag_list_new_full (const gchar * tag, ...)
  * Since: 0.10.24
  */
 GstTagList *
-gst_tag_list_new_full_valist (va_list var_args)
+gst_tag_list_new_valist (va_list var_args)
 {
   GstTagList *list;
   const gchar *tag;
 
-  list = gst_tag_list_new ();
+  list = gst_tag_list_new_empty ();
 
   tag = va_arg (var_args, gchar *);
   gst_tag_list_add_valist (list, GST_TAG_MERGE_APPEND, tag, var_args);
@@ -753,6 +749,41 @@ gst_tag_list_new_from_string (const gchar * str)
 }
 
 /**
+ * gst_tag_list_n_tags:
+ * @list: A #GstTagList.
+ *
+ * Get the number of tags in @list.
+ *
+ * Returns: The number of tags in @list.
+ */
+gint
+gst_tag_list_n_tags (const GstTagList * list)
+{
+  g_return_val_if_fail (list != NULL, 0);
+  g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
+
+  return gst_structure_n_fields ((GstStructure *) list);
+}
+
+/**
+ * gst_tag_list_nth_tag_name:
+ * @list: A #GstTagList.
+ * @index: the index
+ *
+ * Get the name of the tag in @list at @index.
+ *
+ * Returns: The name of the tag at @index.
+ */
+const gchar *
+gst_tag_list_nth_tag_name (const GstTagList * list, guint index)
+{
+  g_return_val_if_fail (list != NULL, 0);
+  g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
+
+  return gst_structure_nth_field_name ((GstStructure *) list, index);
+}
+
+/**
  * gst_tag_list_is_empty:
  * @list: A #GstTagList.
  *
@@ -862,15 +893,16 @@ gst_is_tag_list (gconstpointer p)
 
 typedef struct
 {
-  GstStructure *list;
+  GstTagList *list;
   GstTagMergeMode mode;
 }
 GstTagCopyData;
 
 static void
-gst_tag_list_add_value_internal (GstStructure * list, GstTagMergeMode mode,
+gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
     const gchar * tag, const GValue * value, GstTagInfo * info)
 {
+  GstStructure *list = GST_STRUCTURE (tag_list);
   const GValue *value2;
   GQuark tag_quark;
 
@@ -962,10 +994,10 @@ gst_tag_list_insert (GstTagList * into, const GstTagList * from,
   g_return_if_fail (GST_IS_TAG_LIST (from));
   g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
 
-  data.list = (GstStructure *) into;
+  data.list = into;
   data.mode = mode;
   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
-    gst_structure_remove_all_fields (data.list);
+    gst_structure_remove_all_fields (GST_STRUCTURE (data.list));
   }
   gst_structure_foreach ((GstStructure *) from, gst_tag_list_copy_foreach,
       &data);
@@ -1019,8 +1051,8 @@ gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
   }
 
   /* create empty list, we need to do this to correctly handling merge modes */
-  list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new ();
-  list2_cp = (list2) ? list2 : gst_tag_list_new ();
+  list1_cp = (list1) ? gst_tag_list_copy (list1) : gst_tag_list_new_empty ();
+  list2_cp = (list2) ? list2 : gst_tag_list_new_empty ();
 
   gst_tag_list_insert (list1_cp, list2_cp, mode);
 
@@ -1137,7 +1169,7 @@ gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
   g_return_if_fail (tag != NULL);
 
   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
-    gst_structure_remove_all_fields (list);
+    gst_structure_remove_all_fields (GST_STRUCTURE (list));
   }
 
   while (tag != NULL) {
@@ -1181,7 +1213,7 @@ gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
   g_return_if_fail (tag != NULL);
 
   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
-    gst_structure_remove_all_fields (list);
+    gst_structure_remove_all_fields (GST_STRUCTURE (list));
   }
 
   while (tag != NULL) {
@@ -1406,64 +1438,8 @@ gst_tag_list_get_ ## name ## _index (const GstTagList *list,            \
   return ret;                                                           \
 }
 
-/* FIXME 0.11: maybe get rid of _get_char*(), _get_uchar*(), _get_long*(),
- * _get_ulong*() and _get_pointer*()? - they are not really useful/common
- * enough to warrant convenience accessor functions */
-
 #define COPY_FUNC /**/
 /**
- * gst_tag_list_get_char:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @value: (out): location for the result
- *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-/**
- * gst_tag_list_get_char_index:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @index: number of entry to read out
- * @value: (out): location for the result
- *
- * Gets the value that is at the given index for the given tag in the given
- * list.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-TAG_MERGE_FUNCS (char, gchar, TRUE);
-/**
- * gst_tag_list_get_uchar:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @value: (out): location for the result
- *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-/**
- * gst_tag_list_get_uchar_index:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @index: number of entry to read out
- * @value: (out): location for the result
- *
- * Gets the value that is at the given index for the given tag in the given
- * list.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-TAG_MERGE_FUNCS (uchar, guchar, TRUE);
-/**
  * gst_tag_list_get_boolean:
  * @list: a #GstTagList to get the tag from
  * @tag: tag to read out
@@ -1542,70 +1518,6 @@ TAG_MERGE_FUNCS (int, gint, TRUE);
  */
 TAG_MERGE_FUNCS (uint, guint, TRUE);
 /**
- * gst_tag_list_get_long:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @value: (out): location for the result
- *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-/**
- * gst_tag_list_get_long_index:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @index: number of entry to read out
- * @value: (out): location for the result
- *
- * Gets the value that is at the given index for the given tag in the given
- * list.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-TAG_MERGE_FUNCS (long, glong, TRUE);
-/**
- * gst_tag_list_get_ulong:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @value: (out): location for the result
- *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-/**
- * gst_tag_list_get_ulong_index:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @index: number of entry to read out
- * @value: (out): location for the result
- *
- * Gets the value that is at the given index for the given tag in the given
- * list.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-TAG_MERGE_FUNCS (ulong, gulong, TRUE);
-/**
- * gst_tag_list_get_int64:
- * @list: a #GstTagList to get the tag from
- * @tag: tag to read out
- * @value: (out): location for the result
- *
- * Copies the contents for the given tag into the value, merging multiple values
- * into one if multiple values are associated with the tag.
- *
- * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
- *              given list.
- */
-/**
  * gst_tag_list_get_int64_index:
  * @list: a #GstTagList to get the tag from
  * @tag: tag to read out
@@ -1983,7 +1895,7 @@ gst_tag_list_get_buffer (const GstTagList * list, const gchar * tag,
 
   if (!gst_tag_list_copy_value (&v, list, tag))
     return FALSE;
-  *value = (GstBuffer *) gst_value_dup_mini_object (&v);
+  *value = g_value_dup_boxed (&v);
   g_value_unset (&v);
   return (*value != NULL);
 }
@@ -2019,6 +1931,6 @@ gst_tag_list_get_buffer_index (const GstTagList * list,
 
   if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
     return FALSE;
-  *value = (GstBuffer *) gst_value_dup_mini_object (v);
+  *value = g_value_dup_boxed (v);
   return (*value != NULL);
 }
index 96fcdb5..00a2770 100644 (file)
@@ -24,8 +24,8 @@
 #define __GST_TAGLIST_H__
 
 #include <gst/gstdatetime.h>
+#include <gst/gstsample.h>
 #include <gst/gstbuffer.h>
-#include <gst/gststructure.h>
 #include <gst/glib-compat.h>
 
 G_BEGIN_DECLS
@@ -142,24 +142,12 @@ typedef enum {
 
 #define GST_TAG_FLAG_IS_VALID(flag)     (((flag) > GST_TAG_FLAG_UNDEFINED) && ((flag) < GST_TAG_FLAG_COUNT))
 
-/* FIXME 0.11: Don't typedef GstTagList to be a GstStructure, they're
- *             internally the same but not from an API point of view.
- *             See bug #518934.
- */
 /**
  * GstTagList:
  *
  * Opaque #GstTagList data structure.
  */
-#ifdef _FOOL_GTK_DOC_
-typedef struct _GstTagList GstTagList;
-#else
-#ifdef IN_GOBJECT_INTROSPECTION
 typedef struct _GstTagList GstTagList;
-#else
-typedef GstStructure GstTagList;
-#endif
-#endif
 
 #define GST_TAG_LIST(x)       ((GstTagList *) (x))
 #define GST_IS_TAG_LIST(x)    ((x) != NULL && gst_is_tag_list (GST_TAG_LIST (x)))
@@ -211,15 +199,17 @@ GstTagFlag             gst_tag_get_flag        (const gchar * tag);
 gboolean               gst_tag_is_fixed        (const gchar * tag);
 
 /* tag lists */
-GstTagList * gst_tag_list_new               (void) G_GNUC_MALLOC;
-GstTagList * gst_tag_list_new_full          (const gchar * tag, ...) G_GNUC_MALLOC;
-GstTagList * gst_tag_list_new_full_valist   (va_list var_args) G_GNUC_MALLOC;
+GstTagList * gst_tag_list_new_empty         (void) G_GNUC_MALLOC;
+GstTagList * gst_tag_list_new               (const gchar * tag, ...) G_GNUC_MALLOC;
+GstTagList * gst_tag_list_new_valist        (va_list var_args) G_GNUC_MALLOC;
 
 gchar      * gst_tag_list_to_string         (const GstTagList * list) G_GNUC_MALLOC;
 GstTagList * gst_tag_list_new_from_string   (const gchar      * str) G_GNUC_MALLOC;
 
 gboolean     gst_is_tag_list                (gconstpointer p);
 GstTagList * gst_tag_list_copy              (const GstTagList * list) G_GNUC_MALLOC;
+gint         gst_tag_list_n_tags            (const GstTagList * list);
+const gchar* gst_tag_list_nth_tag_name      (const GstTagList * list, guint index);
 gboolean     gst_tag_list_is_empty          (const GstTagList * list);
 gboolean     gst_tag_list_is_equal          (const GstTagList * list1,
                                              const GstTagList * list2);
@@ -267,20 +257,6 @@ gboolean     gst_tag_list_copy_value        (GValue           * dest,
                                              const gchar      * tag);
 
 /* simplifications (FIXME: do we want them?) */
-gboolean     gst_tag_list_get_char          (const GstTagList * list,
-                                             const gchar      * tag,
-                                             gchar            * value);
-gboolean     gst_tag_list_get_char_index    (const GstTagList * list,
-                                             const gchar      * tag,
-                                             guint              index,
-                                             gchar            * value);
-gboolean     gst_tag_list_get_uchar         (const GstTagList * list,
-                                             const gchar      * tag,
-                                             guchar           * value);
-gboolean     gst_tag_list_get_uchar_index   (const GstTagList * list,
-                                             const gchar      * tag,
-                                             guint              index,
-                                             guchar           * value);
 gboolean     gst_tag_list_get_boolean       (const GstTagList * list,
                                              const gchar      * tag,
                                              gboolean         * value);
@@ -302,20 +278,6 @@ gboolean     gst_tag_list_get_uint_index    (const GstTagList * list,
                                              const gchar      * tag,
                                              guint              index,
                                              guint            * value);
-gboolean     gst_tag_list_get_long          (const GstTagList * list,
-                                             const gchar      * tag,
-                                             glong            * value);
-gboolean     gst_tag_list_get_long_index    (const GstTagList * list,
-                                             const gchar      * tag,
-                                             guint              index,
-                                             glong            * value);
-gboolean     gst_tag_list_get_ulong         (const GstTagList * list,
-                                             const gchar      * tag,
-                                             gulong           * value);
-gboolean     gst_tag_list_get_ulong_index   (const GstTagList * list,
-                                             const gchar      * tag,
-                                             guint              index,
-                                             gulong           * value);
 gboolean     gst_tag_list_get_int64         (const GstTagList * list,
                                              const gchar      * tag,
                                              gint64           * value);
@@ -422,8 +384,7 @@ gboolean     gst_tag_list_get_buffer_index  (const GstTagList * list,
  *
  * Since: 0.10.15
  */
-/* FIXME 0.11: change to "artist-sortname" */
-#define GST_TAG_ARTIST_SORTNAME        "musicbrainz-sortname"
+#define GST_TAG_ARTIST_SORTNAME        "artist-sortname"
 /**
  * GST_TAG_ALBUM:
  *
@@ -762,7 +723,7 @@ gboolean     gst_tag_list_get_buffer_index  (const GstTagList * list,
 /**
  * GST_TAG_IMAGE:
  *
- * image (buffer) (buffer caps should specify the content type and preferably
+ * image (sample) (sample caps should specify the content type and preferably
  * also set "image-type" field as #GstTagImageType)
  *
  * Since: 0.10.6
@@ -772,7 +733,7 @@ gboolean     gst_tag_list_get_buffer_index  (const GstTagList * list,
  * GST_TAG_PREVIEW_IMAGE:
  *
  * image that is meant for preview purposes, e.g. small icon-sized version
- * (buffer) (buffer caps should specify the content type)
+ * (sample) (sample caps should specify the content type)
  *
  * Since: 0.10.7
  */
@@ -781,7 +742,7 @@ gboolean     gst_tag_list_get_buffer_index  (const GstTagList * list,
 /**
  * GST_TAG_ATTACHMENT:
  *
- * generic file attachment (buffer) (buffer caps should specify the content
+ * generic file attachment (sample) (sample caps should specify the content
  * type and if possible set "filename" to the file name of the
  * attachment)
  *
index 72830c8..2ed099d 100644 (file)
@@ -83,20 +83,11 @@ typedef struct
 {
   GstTagMergeMode mode;
   GstTagList *list;
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  GStaticMutex lock;
-#else
   GMutex lock;
-#endif
 } GstTagData;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-#define GST_TAG_DATA_LOCK(data) g_static_mutex_lock(&data->lock)
-#define GST_TAG_DATA_UNLOCK(data) g_static_mutex_unlock(&data->lock)
-#else
 #define GST_TAG_DATA_LOCK(data) g_mutex_lock(&data->lock)
 #define GST_TAG_DATA_UNLOCK(data) g_mutex_unlock(&data->lock)
-#endif
 
 GType
 gst_tag_setter_get_type (void)
@@ -106,7 +97,7 @@ gst_tag_setter_get_type (void)
   if (g_once_init_enter (&tag_setter_type)) {
     GType _type;
     static const GTypeInfo tag_setter_info = {
-      sizeof (GstTagSetterIFace),       /* class_size */
+      sizeof (GstTagSetterInterface),   /* class_size */
       NULL,                     /* base_init */
       NULL,                     /* base_finalize */
       NULL,
@@ -137,11 +128,7 @@ gst_tag_data_free (gpointer p)
   if (data->list)
     gst_tag_list_free (data->list);
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_static_mutex_free (&data->lock);
-#else
   g_mutex_clear (&data->lock);
-#endif
 
   g_slice_free (GstTagData, data);
 }
@@ -154,34 +141,21 @@ gst_tag_setter_get_data (GstTagSetter * setter)
   data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
   if (!data) {
     /* make sure no other thread is creating a GstTagData at the same time */
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    static GStaticMutex create_mutex = G_STATIC_MUTEX_INIT;
-
-    g_static_mutex_lock (&create_mutex);
-#else
     static GMutex create_mutex; /* no initialisation required */
 
     g_mutex_lock (&create_mutex);
-#endif
 
     data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
     if (!data) {
       data = g_slice_new (GstTagData);
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-      g_static_mutex_init (&data->lock);
-#else
       g_mutex_init (&data->lock);
-#endif
       data->list = NULL;
       data->mode = GST_TAG_MERGE_KEEP;
       g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data,
           gst_tag_data_free);
     }
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    g_static_mutex_unlock (&create_mutex);
-#else
+
     g_mutex_unlock (&create_mutex);
-#endif
   }
 
   return data;
@@ -314,7 +288,7 @@ gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode,
 
   GST_TAG_DATA_LOCK (data);
   if (!data->list)
-    data->list = gst_tag_list_new ();
+    data->list = gst_tag_list_new_empty ();
 
   gst_tag_list_add_valist (data->list, mode, tag, var_args);
 
@@ -345,7 +319,7 @@ gst_tag_setter_add_tag_valist_values (GstTagSetter * setter,
   GST_TAG_DATA_LOCK (data);
 
   if (!data->list)
-    data->list = gst_tag_list_new ();
+    data->list = gst_tag_list_new_empty ();
 
   gst_tag_list_add_valist_values (data->list, mode, tag, var_args);
 
@@ -377,7 +351,7 @@ gst_tag_setter_add_tag_value (GstTagSetter * setter,
   GST_TAG_DATA_LOCK (data);
 
   if (!data->list)
-    data->list = gst_tag_list_new ();
+    data->list = gst_tag_list_new_empty ();
 
   gst_tag_list_add_value (data->list, mode, tag, value);
 
index 44c794b..580053c 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_TAG_SETTER            (gst_tag_setter_get_type ())
-#define GST_TAG_SETTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
-#define GST_IS_TAG_SETTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_SETTER))
-#define GST_TAG_SETTER_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TAG_SETTER, GstTagSetterIFace))
+#define GST_TYPE_TAG_SETTER             (gst_tag_setter_get_type ())
+#define GST_TAG_SETTER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
+#define GST_IS_TAG_SETTER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_SETTER))
+#define GST_TAG_SETTER_GET_INTERFACE(obj)       (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TAG_SETTER, GstTagSetterInterface))
 
 /**
  * GstTagSetter:
  *
  * Opaque #GstTagSetter data structure.
  */
-typedef struct _GstTagSetter                   GstTagSetter; /* Dummy typedef */
-typedef struct _GstTagSetterIFace              GstTagSetterIFace;
+typedef struct _GstTagSetter                    GstTagSetter; /* Dummy typedef */
+typedef struct _GstTagSetterInterface           GstTagSetterInterface;
 
 /**
- * GstTagSetterIFace:
+ * GstTagSetterInterface:
  * @g_iface: parent interface type.
  *
- * #GstTagSetterIFace interface.
+ * #GstTagSetterInterface interface.
  */
 /* use an empty interface here to allow detection of elements using user-set
    tags */
-struct _GstTagSetterIFace
+struct _GstTagSetterInterface
 {
   GTypeInterface g_iface;
 
@@ -56,44 +56,44 @@ struct _GstTagSetterIFace
   /* virtual table */
 };
 
-GType          gst_tag_setter_get_type             (void);
+GType           gst_tag_setter_get_type             (void);
 
-void           gst_tag_setter_reset_tags             (GstTagSetter * setter);
+void            gst_tag_setter_reset_tags             (GstTagSetter * setter);
 
-void           gst_tag_setter_merge_tags           (GstTagSetter *     setter,
-                                                    const GstTagList * list,
-                                                    GstTagMergeMode    mode);
-void           gst_tag_setter_add_tags             (GstTagSetter *     setter,
-                                                    GstTagMergeMode    mode,
-                                                    const gchar *      tag,
-                                                    ...) G_GNUC_NULL_TERMINATED;
+void            gst_tag_setter_merge_tags           (GstTagSetter *     setter,
+                                                     const GstTagList * list,
+                                                     GstTagMergeMode    mode);
+void            gst_tag_setter_add_tags             (GstTagSetter *     setter,
+                                                     GstTagMergeMode    mode,
+                                                     const gchar *      tag,
+                                                     ...) G_GNUC_NULL_TERMINATED;
 
-void           gst_tag_setter_add_tag_values       (GstTagSetter *     setter,
-                                                    GstTagMergeMode    mode,
-                                                    const gchar *      tag,
-                                                    ...) G_GNUC_NULL_TERMINATED;
+void            gst_tag_setter_add_tag_values       (GstTagSetter *     setter,
+                                                     GstTagMergeMode    mode,
+                                                     const gchar *      tag,
+                                                     ...) G_GNUC_NULL_TERMINATED;
 
-void            gst_tag_setter_add_tag_valist              (GstTagSetter *     setter,
-                                                    GstTagMergeMode    mode,
-                                                    const gchar *      tag,
-                                                    va_list            var_args);
+void            gst_tag_setter_add_tag_valist       (GstTagSetter *     setter,
+                                                     GstTagMergeMode    mode,
+                                                     const gchar *      tag,
+                                                     va_list            var_args);
 
-void            gst_tag_setter_add_tag_valist_values(GstTagSetter *    setter,
-                                                    GstTagMergeMode    mode,
-                                                    const gchar *      tag,
-                                                    va_list            var_args);
+void            gst_tag_setter_add_tag_valist_values(GstTagSetter *     setter,
+                                                     GstTagMergeMode    mode,
+                                                     const gchar *      tag,
+                                                     va_list            var_args);
 
-void           gst_tag_setter_add_tag_value        (GstTagSetter *     setter,
-                                                    GstTagMergeMode    mode,
-                                                    const gchar *      tag,
-                                                    const GValue *     value);
+void            gst_tag_setter_add_tag_value        (GstTagSetter *     setter,
+                                                     GstTagMergeMode    mode,
+                                                     const gchar *      tag,
+                                                     const GValue *     value);
 
 const GstTagList *
-               gst_tag_setter_get_tag_list          (GstTagSetter *    setter);
+                gst_tag_setter_get_tag_list          (GstTagSetter *    setter);
 
-void           gst_tag_setter_set_tag_merge_mode    (GstTagSetter *    setter,
-                                                     GstTagMergeMode   mode);
-GstTagMergeMode        gst_tag_setter_get_tag_merge_mode    (GstTagSetter *    setter);
+void            gst_tag_setter_set_tag_merge_mode    (GstTagSetter *    setter,
+                                                      GstTagMergeMode   mode);
+GstTagMergeMode gst_tag_setter_get_tag_merge_mode    (GstTagSetter *    setter);
 
 G_END_DECLS
 
index 4aae349..6d8c2d8 100644 (file)
@@ -45,7 +45,7 @@
  * and gst_task_stop() respectively or with the gst_task_set_state() function.
  *
  * A #GstTask will repeatedly call the #GstTaskFunction with the user data
- * that was provided when creating the task with gst_task_create(). While calling
+ * that was provided when creating the task with gst_task_new(). While calling
  * the function it will acquire the provided lock. The provided lock is released
  * when the task pauses or stops.
  *
@@ -68,9 +68,6 @@
  * Last reviewed on 2010-03-15 (0.10.29)
  */
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "gst_private.h"
 
 #include "gstinfo.h"
@@ -144,7 +141,7 @@ static void gst_task_finalize (GObject * object);
 
 static void gst_task_func (GstTask * task);
 
-static GStaticMutex pool_lock = G_STATIC_MUTEX_INIT;
+static GMutex pool_lock;
 
 #define _do_init \
 { \
@@ -156,14 +153,14 @@ G_DEFINE_TYPE_WITH_CODE (GstTask, gst_task, GST_TYPE_OBJECT, _do_init);
 static void
 init_klass_pool (GstTaskClass * klass)
 {
-  g_static_mutex_lock (&pool_lock);
+  g_mutex_lock (&pool_lock);
   if (klass->pool) {
     gst_task_pool_cleanup (klass->pool);
     gst_object_unref (klass->pool);
   }
   klass->pool = gst_task_pool_new ();
   gst_task_pool_prepare (klass->pool, NULL);
-  g_static_mutex_unlock (&pool_lock);
+  g_mutex_unlock (&pool_lock);
 }
 
 static void
@@ -189,17 +186,17 @@ gst_task_init (GstTask * task)
 
   task->priv = GST_TASK_GET_PRIVATE (task);
   task->running = FALSE;
-  task->abidata.ABI.thread = NULL;
+  task->thread = NULL;
   task->lock = NULL;
-  task->cond = g_cond_new ();
+  g_cond_init (&task->cond);
   SET_TASK_STATE (task, GST_TASK_STOPPED);
   task->priv->prio_set = FALSE;
 
   /* use the default klass pool for this task, users can
    * override this later */
-  g_static_mutex_lock (&pool_lock);
+  g_mutex_lock (&pool_lock);
   task->priv->pool = gst_object_ref (klass->pool);
-  g_static_mutex_unlock (&pool_lock);
+  g_mutex_unlock (&pool_lock);
 }
 
 static void
@@ -219,8 +216,7 @@ gst_task_finalize (GObject * object)
 
   /* task thread cannot be running here since it holds a ref
    * to the task so that the finalize could not have happened */
-  g_cond_free (task->cond);
-  task->cond = NULL;
+  g_cond_clear (&task->cond);
 
   G_OBJECT_CLASS (gst_task_parent_class)->finalize (object);
 }
@@ -259,7 +255,7 @@ gst_task_configure_name (GstTask * task)
 static void
 gst_task_func (GstTask * task)
 {
-  GStaticRecMutex *lock;
+  GRecMutex *lock;
   GThread *tself;
   GstTaskPrivate *priv;
 
@@ -278,14 +274,10 @@ gst_task_func (GstTask * task)
   lock = GST_TASK_GET_LOCK (task);
   if (G_UNLIKELY (lock == NULL))
     goto no_lock;
-  task->abidata.ABI.thread = tself;
+  task->thread = tself;
   /* only update the priority when it was changed */
   if (priv->prio_set) {
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    g_thread_set_priority (tself, priv->priority);
-#else
     GST_INFO_OBJECT (task, "Thread priorities no longer have any effect");
-#endif
   }
   GST_OBJECT_UNLOCK (task);
 
@@ -294,7 +286,7 @@ gst_task_func (GstTask * task)
     priv->thr_callbacks.enter_thread (task, tself, priv->thr_user_data);
 
   /* locking order is TASK_LOCK, LOCK */
-  g_static_rec_mutex_lock (lock);
+  g_rec_mutex_lock (lock);
   /* configure the thread name now */
   gst_task_configure_name (task);
 
@@ -302,18 +294,13 @@ gst_task_func (GstTask * task)
     if (G_UNLIKELY (GET_TASK_STATE (task) == GST_TASK_PAUSED)) {
       GST_OBJECT_LOCK (task);
       while (G_UNLIKELY (GST_TASK_STATE (task) == GST_TASK_PAUSED)) {
-        gint t;
+        g_rec_mutex_unlock (lock);
 
-        t = g_static_rec_mutex_unlock_full (lock);
-        if (t <= 0) {
-          g_warning ("wrong STREAM_LOCK count %d", t);
-        }
         GST_TASK_SIGNAL (task);
         GST_TASK_WAIT (task);
         GST_OBJECT_UNLOCK (task);
         /* locking order.. */
-        if (t > 0)
-          g_static_rec_mutex_lock_full (lock, t);
+        g_rec_mutex_lock (lock);
 
         GST_OBJECT_LOCK (task);
         if (G_UNLIKELY (GET_TASK_STATE (task) == GST_TASK_STOPPED)) {
@@ -327,10 +314,10 @@ gst_task_func (GstTask * task)
     task->func (task->data);
   }
 done:
-  g_static_rec_mutex_unlock (lock);
+  g_rec_mutex_unlock (lock);
 
   GST_OBJECT_LOCK (task);
-  task->abidata.ABI.thread = NULL;
+  task->thread = NULL;
 
 exit:
   if (priv->thr_callbacks.leave_thread) {
@@ -339,12 +326,6 @@ exit:
     GST_OBJECT_UNLOCK (task);
     priv->thr_callbacks.leave_thread (task, tself, priv->thr_user_data);
     GST_OBJECT_LOCK (task);
-  } else {
-    /* restore normal priority when releasing back into the pool, we will not
-     * touch the priority when a custom callback has been installed. */
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    g_thread_set_priority (tself, G_THREAD_PRIORITY_NORMAL);
-#endif
   }
   /* now we allow messing with the lock again by setting the running flag to
    * FALSE. Together with the SIGNAL this is the sign for the _join() to
@@ -388,7 +369,7 @@ gst_task_cleanup_all (void)
 }
 
 /**
- * gst_task_create:
+ * gst_task_new:
  * @func: The #GstTaskFunction to use
  * @data: (closure): User data to pass to @func
  *
@@ -411,7 +392,7 @@ gst_task_cleanup_all (void)
  * MT safe.
  */
 GstTask *
-gst_task_create (GstTaskFunction func, gpointer data)
+gst_task_new (GstTaskFunction func, gpointer data)
 {
   GstTask *task;
 
@@ -427,7 +408,7 @@ gst_task_create (GstTaskFunction func, gpointer data)
 /**
  * gst_task_set_lock:
  * @task: The #GstTask to use
- * @mutex: The #GMutex to use
+ * @mutex: The #GRecMutex to use
  *
  * Set the mutex used by the task. The mutex will be acquired before
  * calling the #GstTaskFunction.
@@ -438,7 +419,7 @@ gst_task_create (GstTaskFunction func, gpointer data)
  * MT safe.
  */
 void
-gst_task_set_lock (GstTask * task, GStaticRecMutex * mutex)
+gst_task_set_lock (GstTask * task, GRecMutex * mutex)
 {
   GST_OBJECT_LOCK (task);
   if (G_UNLIKELY (task->running))
@@ -469,6 +450,7 @@ is_running:
  *
  * Since: 0.10.24
  */
+/* FIXME 0.11: remove gst_task_set_priority() */
 void
 gst_task_set_priority (GstTask * task, GThreadPriority priority)
 {
@@ -482,15 +464,11 @@ gst_task_set_priority (GstTask * task, GThreadPriority priority)
   GST_OBJECT_LOCK (task);
   priv->prio_set = TRUE;
   priv->priority = priority;
-  thread = task->abidata.ABI.thread;
+  thread = task->thread;
   if (thread != NULL) {
     /* if this task already has a thread, we can configure the priority right
      * away, else we do that when we assign a thread to the task. */
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    g_thread_set_priority (thread, priority);
-#else
     GST_INFO_OBJECT (task, "Thread priorities no longer have any effect");
-#endif
   }
   GST_OBJECT_UNLOCK (task);
 }
@@ -827,7 +805,7 @@ gst_task_join (GstTask * task)
   /* we don't use a real thread join here because we are using
    * thread pools */
   GST_OBJECT_LOCK (task);
-  if (G_UNLIKELY (tself == task->abidata.ABI.thread))
+  if (G_UNLIKELY (tself == task->thread))
     goto joining_self;
   SET_TASK_STATE (task, GST_TASK_STOPPED);
   /* signal the state change for when it was blocked in PAUSED. */
@@ -838,7 +816,7 @@ gst_task_join (GstTask * task)
   while (G_LIKELY (task->running))
     GST_TASK_WAIT (task);
   /* clean the thread */
-  task->abidata.ABI.thread = NULL;
+  task->thread = NULL;
   /* get the id and pool to join */
   pool = priv->pool_id;
   id = priv->id;
index 2081815..492052b 100644 (file)
@@ -78,7 +78,7 @@ typedef enum {
  *
  * Get access to the cond of the task.
  */
-#define GST_TASK_GET_COND(task)         (GST_TASK_CAST(task)->cond)
+#define GST_TASK_GET_COND(task)         (&GST_TASK_CAST(task)->cond)
 /**
  * GST_TASK_WAIT:
  * @task: Task to wait for
@@ -116,7 +116,7 @@ typedef enum {
  * @leave_thread: a thread is exiting, this is called when the thread is about
  *   to leave its function
  *
- * Custom GstTask thread callback functions that can be installed. 
+ * Custom GstTask thread callback functions that can be installed.
  *
  * Since: 0.10.24
  */
@@ -144,9 +144,9 @@ struct _GstTask {
 
   /*< public >*/ /* with LOCK */
   GstTaskState     state;
-  GCond           *cond;
+  GCond            cond;
 
-  GStaticRecMutex *lock;
+  GRecMutex       *lock;
 
   GstTaskFunction  func;
   gpointer         data;
@@ -154,15 +154,11 @@ struct _GstTask {
   gboolean         running;
 
   /*< private >*/
-  union {
-    struct {
-      /* thread this task is currently running in */
-      GThread  *thread;
-    } ABI;
-    gpointer _gst_reserved[GST_PADDING - 1];
-  } abidata;
-
-  GstTaskPrivate *priv;
+  GThread         *thread;
+
+  GstTaskPrivate  *priv;
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstTaskClass {
@@ -179,8 +175,8 @@ void            gst_task_cleanup_all    (void);
 
 GType           gst_task_get_type       (void);
 
-GstTask*        gst_task_create         (GstTaskFunction func, gpointer data);
-void            gst_task_set_lock       (GstTask *task, GStaticRecMutex *mutex);
+GstTask*        gst_task_new            (GstTaskFunction func, gpointer data);
+void            gst_task_set_lock       (GstTask *task, GRecMutex *mutex);
 void            gst_task_set_priority   (GstTask *task, GThreadPriority priority);
 
 GstTaskPool *   gst_task_get_pool       (GstTask *task);
index 912015e..6f2ac66 100644 (file)
@@ -92,7 +92,7 @@ GType           gst_task_pool_get_type    (void);
 GstTaskPool *   gst_task_pool_new         (void);
 void            gst_task_pool_prepare     (GstTaskPool *pool, GError **error);
 
-gpointer        gst_task_pool_push        (GstTaskPool *pool, GstTaskPoolFunction func, 
+gpointer        gst_task_pool_push        (GstTaskPool *pool, GstTaskPoolFunction func,
                                            gpointer user_data, GError **error);
 void            gst_task_pool_join        (GstTaskPool *pool, gpointer id);
 
index b857458..4758691 100644 (file)
 
 #include "gsttrace.h"
 
-GStaticMutex _gst_trace_mutex = G_STATIC_MUTEX_INIT;
+GMutex _gst_trace_mutex;
 
-static
-#ifdef __inline__
-  __inline__
-#endif
-    void
+static inline void
 read_tsc (gint64 * dst)
 {
 #if defined(HAVE_RDTSC) && defined(__GNUC__)
index 817ae1f..b49ff7c 100644 (file)
@@ -39,10 +39,10 @@ G_BEGIN_DECLS
 typedef enum {
   GST_ALLOC_TRACE_NONE      = 0,
   GST_ALLOC_TRACE_LIVE      = (1 << 0),
-  GST_ALLOC_TRACE_MEM_LIVE     = (1 << 1)
+  GST_ALLOC_TRACE_MEM_LIVE  = (1 << 1)
 } GstAllocTraceFlags;
 
-typedef struct _GstAllocTrace  GstAllocTrace;
+typedef struct _GstAllocTrace   GstAllocTrace;
 
 /**
  * GstAllocTrace:
@@ -54,17 +54,17 @@ typedef struct _GstAllocTrace       GstAllocTrace;
  * The main tracing object
  */
 struct _GstAllocTrace {
-  gchar                *name;
-  gint          flags;
+  gchar         *name;
+  gint           flags;
 
-  gint          live;
-  GSList       *mem_live;
+  gint           live;
+  GSList        *mem_live;
 };
 
 #ifndef GST_DISABLE_TRACE
 
-typedef struct _GstTrace       GstTrace;
-typedef struct _GstTraceEntry  GstTraceEntry;
+typedef struct _GstTrace        GstTrace;
+typedef struct _GstTraceEntry   GstTraceEntry;
 
 /**
  * GstTrace:
@@ -90,54 +90,54 @@ struct _GstTraceEntry {
   gchar message[112];
 };
 
-GstTrace*      gst_trace_new                   (const gchar *filename, gint size);
+GstTrace*       gst_trace_new                   (const gchar *filename, gint size);
 
-void           gst_trace_destroy               (GstTrace *trace);
-void           gst_trace_flush                 (GstTrace *trace);
-void           gst_trace_text_flush            (GstTrace *trace);
+void            gst_trace_destroy               (GstTrace *trace);
+void            gst_trace_flush                 (GstTrace *trace);
+void            gst_trace_text_flush            (GstTrace *trace);
 /**
  * gst_trace_get_size:
  * @trace: a #GstTrace
  *
  * Retrieve the buffer size of @trace.
  */
-#define        gst_trace_get_size(trace)       ((trace)->bufsize)
+#define         gst_trace_get_size(trace)       ((trace)->bufsize)
 /**
  * gst_trace_get_offset:
  * @trace: a #GstTrace
  *
  * Retrieve the current buffer offset of @trace.
  */
-#define        gst_trace_get_offset(trace)     ((trace)->bufoffset)
+#define         gst_trace_get_offset(trace)     ((trace)->bufoffset)
 /**
  * gst_trace_get_remaining:
  * @trace: a #GstTrace
  *
  * Retrieve the remaining size in the @trace buffer.
  */
-#define        gst_trace_get_remaining(trace)  ((trace)->bufsize - (trace)->bufoffset)
-void           gst_trace_set_default           (GstTrace *trace);
+#define         gst_trace_get_remaining(trace)  ((trace)->bufsize - (trace)->bufoffset)
+void            gst_trace_set_default           (GstTrace *trace);
 
-void           _gst_trace_add_entry            (GstTrace *trace, guint32 seq,
-                                                guint32 data, gchar *msg);
+void            _gst_trace_add_entry            (GstTrace *trace, guint32 seq,
+                                                 guint32 data, gchar *msg);
 
-void           gst_trace_read_tsc              (gint64 *dst);
+void            gst_trace_read_tsc              (gint64 *dst);
 
 
-extern GStaticMutex     _gst_trace_mutex;
+GST_EXPORT GMutex       _gst_trace_mutex;
 
-gboolean               gst_alloc_trace_available       (void);
-const GList*           gst_alloc_trace_list            (void);
-GstAllocTrace*         _gst_alloc_trace_register       (const gchar *name);
+gboolean                gst_alloc_trace_available       (void);
+const GList*            gst_alloc_trace_list            (void);
+GstAllocTrace*          _gst_alloc_trace_register       (const gchar *name);
 
-int                    gst_alloc_trace_live_all        (void);
-void                   gst_alloc_trace_print_all       (void);
-void                   gst_alloc_trace_print_live      (void);
-void                   gst_alloc_trace_set_flags_all   (GstAllocTraceFlags flags);
+int                     gst_alloc_trace_live_all        (void);
+void                    gst_alloc_trace_print_all       (void);
+void                    gst_alloc_trace_print_live      (void);
+void                    gst_alloc_trace_set_flags_all   (GstAllocTraceFlags flags);
 
-GstAllocTrace*         gst_alloc_trace_get             (const gchar *name);
-void                   gst_alloc_trace_print           (const GstAllocTrace *trace);
-void                   gst_alloc_trace_set_flags       (GstAllocTrace *trace, GstAllocTraceFlags flags);
+GstAllocTrace*          gst_alloc_trace_get             (const gchar *name);
+void                    gst_alloc_trace_print           (const GstAllocTrace *trace);
+void                    gst_alloc_trace_set_flags       (GstAllocTrace *trace, GstAllocTraceFlags flags);
 
 
 #ifndef GST_DISABLE_ALLOC_TRACE
@@ -147,7 +147,7 @@ void                        gst_alloc_trace_set_flags       (GstAllocTrace *trace, GstAllocTraceFlags flags
  *
  * Register a new alloc tracer with the given name
  */
-#define        gst_alloc_trace_register(name) _gst_alloc_trace_register (name);
+#define gst_alloc_trace_register(name) _gst_alloc_trace_register (name);
 
 /**
  * gst_alloc_trace_new:
@@ -156,16 +156,16 @@ void                      gst_alloc_trace_set_flags       (GstAllocTrace *trace, GstAllocTraceFlags flags
  *
  * Use the tracer to trace a new memory allocation
  */
-#define        gst_alloc_trace_new(trace, mem)                 \
-G_STMT_START {                                         \
+#define gst_alloc_trace_new(trace, mem)                 \
+G_STMT_START {                                          \
   if (G_UNLIKELY ((trace)->flags)) {                    \
-    g_static_mutex_lock (&_gst_trace_mutex);            \
-    if ((trace)->flags & GST_ALLOC_TRACE_LIVE)                 \
-      (trace)->live++;                                 \
-    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE)     \
-      (trace)->mem_live =                              \
-        g_slist_prepend ((trace)->mem_live, mem);      \
-    g_static_mutex_unlock (&_gst_trace_mutex);          \
+    g_mutex_lock (&_gst_trace_mutex);            \
+    if ((trace)->flags & GST_ALLOC_TRACE_LIVE)          \
+      (trace)->live++;                                  \
+    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE)      \
+      (trace)->mem_live =                               \
+        g_slist_prepend ((trace)->mem_live, mem);       \
+    g_mutex_unlock (&_gst_trace_mutex);          \
   }                                                     \
 } G_STMT_END
 
@@ -176,27 +176,27 @@ G_STMT_START {                                            \
  *
  * Trace a memory free operation
  */
-#define        gst_alloc_trace_free(trace, mem)                \
-G_STMT_START {                                         \
+#define gst_alloc_trace_free(trace, mem)                \
+G_STMT_START {                                          \
   if (G_UNLIKELY ((trace)->flags)) {                    \
-    g_static_mutex_lock (&_gst_trace_mutex);            \
-    if ((trace)->flags & GST_ALLOC_TRACE_LIVE)                 \
-      (trace)->live--;                                 \
-    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE)     \
-      (trace)->mem_live =                              \
-        g_slist_remove ((trace)->mem_live, mem);       \
-    g_static_mutex_unlock (&_gst_trace_mutex);          \
+    g_mutex_lock (&_gst_trace_mutex);            \
+    if ((trace)->flags & GST_ALLOC_TRACE_LIVE)          \
+      (trace)->live--;                                  \
+    if ((trace)->flags & GST_ALLOC_TRACE_MEM_LIVE)      \
+      (trace)->mem_live =                               \
+        g_slist_remove ((trace)->mem_live, mem);        \
+    g_mutex_unlock (&_gst_trace_mutex);          \
   }                                                     \
 } G_STMT_END
 
 #else
-#define        gst_alloc_trace_register(name) (NULL)
-#define        gst_alloc_trace_new(trace, mem)
-#define        gst_alloc_trace_free(trace, mem)
+#define gst_alloc_trace_register(name) (NULL)
+#define gst_alloc_trace_new(trace, mem)
+#define gst_alloc_trace_free(trace, mem)
 #endif
 
 
-extern gint _gst_trace_on;
+GST_EXPORT gint _gst_trace_on;
 /**
  * gst_trace_add_entry:
  * @trace: a #GstTrace
@@ -215,34 +215,34 @@ extern gint _gst_trace_on;
 #else /* GST_DISABLE_TRACE */
 
 #if defined __GNUC__ && __GNUC__ >= 3
-#pragma GCC poison     gst_trace_new
-#pragma GCC poison     gst_trace_destroy
-#pragma GCC poison     gst_trace_flush
-#pragma GCC poison     gst_trace_text_flush
-#pragma GCC poison     gst_trace_get_size
-#pragma GCC poison     gst_trace_get_offset
-#pragma GCC poison     gst_trace_get_remaining
-#pragma GCC poison     gst_trace_set_default
-#pragma GCC poison     _gst_trace_add_entry
-#pragma GCC poison     gst_trace_read_tsc
+#pragma GCC poison      gst_trace_new
+#pragma GCC poison      gst_trace_destroy
+#pragma GCC poison      gst_trace_flush
+#pragma GCC poison      gst_trace_text_flush
+#pragma GCC poison      gst_trace_get_size
+#pragma GCC poison      gst_trace_get_offset
+#pragma GCC poison      gst_trace_get_remaining
+#pragma GCC poison      gst_trace_set_default
+#pragma GCC poison      _gst_trace_add_entry
+#pragma GCC poison      gst_trace_read_tsc
 #endif
 
-#define                gst_alloc_trace_register(name)  (NULL)
-#define                gst_alloc_trace_new(trace, mem)
-#define                gst_alloc_trace_free(trace, mem)
+#define         gst_alloc_trace_register(name)  (NULL)
+#define         gst_alloc_trace_new(trace, mem)
+#define         gst_alloc_trace_free(trace, mem)
 
-#define                gst_alloc_trace_available()     (FALSE)
-#define                gst_alloc_trace_list()          (NULL)
-#define                _gst_alloc_trace_register(name) (NULL)
+#define         gst_alloc_trace_available()     (FALSE)
+#define         gst_alloc_trace_list()          (NULL)
+#define         _gst_alloc_trace_register(name) (NULL)
 
-#define                gst_alloc_trace_live_all()      (0)
-#define                gst_alloc_trace_print_all()
-#define                gst_alloc_trace_print_live()
-#define                gst_alloc_trace_set_flags_all(flags)
+#define         gst_alloc_trace_live_all()      (0)
+#define         gst_alloc_trace_print_all()
+#define         gst_alloc_trace_print_live()
+#define         gst_alloc_trace_set_flags_all(flags)
 
-#define                gst_alloc_trace_get(name)       (NULL)
-#define                gst_alloc_trace_print(trace)
-#define                gst_alloc_trace_set_flags(trace,flags)
+#define         gst_alloc_trace_get(name)       (NULL)
+#define         gst_alloc_trace_print(trace)
+#define         gst_alloc_trace_set_flags(trace,flags)
 
 #define         gst_trace_add_entry(trace,seq,data,msg)
 
index 3827265..d635388 100644 (file)
@@ -74,7 +74,7 @@ gst_type_find_get_type (void)
 gboolean
 gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank,
     GstTypeFindFunction func, gchar ** extensions,
-    const GstCaps * possible_caps, gpointer data, GDestroyNotify data_notify)
+    GstCaps * possible_caps, gpointer data, GDestroyNotify data_notify)
 {
   GstTypeFindFactory *factory;
 
@@ -93,7 +93,7 @@ gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank,
     g_strfreev (factory->extensions);
   factory->extensions = g_strdupv (extensions);
 
-  gst_caps_replace (&factory->caps, (GstCaps *) possible_caps);
+  gst_caps_replace (&factory->caps, possible_caps);
   factory->function = func;
   factory->user_data = data;
   factory->user_data_notify = data_notify;
@@ -108,7 +108,7 @@ gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank,
   }
   GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE;
 
-  gst_registry_add_feature (gst_registry_get_default (),
+  gst_registry_add_feature (gst_registry_get (),
       GST_PLUGIN_FEATURE_CAST (factory));
 
   return TRUE;
@@ -131,7 +131,7 @@ gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank,
  * Returns: (transfer none) (array length=size): the requested data, or NULL
  *     if that data is not available.
  */
-guint8 *
+const guint8 *
 gst_type_find_peek (GstTypeFind * find, gint64 offset, guint size)
 {
   g_return_val_if_fail (find->peek != NULL, NULL);
index 77b89f7..4dcdc85 100644 (file)
@@ -74,18 +74,18 @@ typedef enum {
  */
 struct _GstTypeFind {
   /* private to the caller of the typefind function */
-  guint8 *  (* peek)       (gpointer         data,
-                            gint64           offset,
-                            guint            size);
+  const guint8 *  (* peek)       (gpointer         data,
+                                  gint64           offset,
+                                  guint            size);
 
-  void      (* suggest)    (gpointer         data,
-                            guint            probability,
-                            const GstCaps *  caps);
+  void            (* suggest)    (gpointer         data,
+                                  guint            probability,
+                                  const GstCaps *  caps);
 
-  gpointer     data;
+  gpointer         data;
 
   /* optional */
-  guint64   (* get_length) (gpointer data);
+  guint64         (* get_length) (gpointer data);
 
   /* <private> */
   gpointer _gst_reserved[GST_PADDING];
@@ -94,18 +94,18 @@ struct _GstTypeFind {
 GType     gst_type_find_get_type   (void);
 
 /* typefind function interface */
-guint8 *  gst_type_find_peek       (GstTypeFind   * find,
-                                    gint64          offset,
-                                    guint           size);
+const guint8 *  gst_type_find_peek       (GstTypeFind   * find,
+                                          gint64          offset,
+                                          guint           size);
 
-void      gst_type_find_suggest    (GstTypeFind   * find,
-                                    guint           probability,
-                                    const GstCaps * caps);
+void            gst_type_find_suggest    (GstTypeFind   * find,
+                                          guint           probability,
+                                          const GstCaps * caps);
 
-void      gst_type_find_suggest_simple (GstTypeFind * find,
-                                        guint         probability,
-                                        const char  * media_type,
-                                        const char  * fieldname, ...);
+void            gst_type_find_suggest_simple (GstTypeFind * find,
+                                              guint         probability,
+                                              const char  * media_type,
+                                              const char  * fieldname, ...);
 
 guint64   gst_type_find_get_length (GstTypeFind   * find);
 
@@ -115,7 +115,7 @@ gboolean  gst_type_find_register   (GstPlugin            * plugin,
                                     guint                  rank,
                                     GstTypeFindFunction    func,
                                     gchar               ** extensions,
-                                    const GstCaps        * possible_caps,
+                                    GstCaps              * possible_caps,
                                     gpointer               data,
                                     GDestroyNotify         data_notify);
 
index 26cbfb5..aca0698 100644 (file)
@@ -91,14 +91,13 @@ GST_DEBUG_CATEGORY (type_find_debug);
 
 static void gst_type_find_factory_dispose (GObject * object);
 
-static GstPluginFeatureClass *parent_class = NULL;
-
 #define _do_init \
 { \
   GST_DEBUG_CATEGORY_INIT (type_find_debug, "GST_TYPEFIND", \
       GST_DEBUG_FG_GREEN, "typefinding subsystem"); \
 }
 
+#define gst_type_find_factory_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstTypeFindFactory, gst_type_find_factory,
     GST_TYPE_PLUGIN_FEATURE, _do_init);
 
@@ -107,8 +106,6 @@ gst_type_find_factory_class_init (GstTypeFindFactoryClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
   object_class->dispose = gst_type_find_factory_dispose;
 }
 
@@ -157,7 +154,7 @@ gst_type_find_factory_dispose (GObject * object)
 GList *
 gst_type_find_factory_get_list (void)
 {
-  return gst_registry_get_feature_list (gst_registry_get_default (),
+  return gst_registry_get_feature_list (gst_registry_get (),
       GST_TYPE_TYPE_FIND_FACTORY);
 }
 
index 19792ee..3d8ff31 100644 (file)
@@ -45,21 +45,21 @@ typedef struct _GstTypeFindFactoryClass GstTypeFindFactoryClass;
  * Object that stores information about a typefind function.
  */
 struct _GstTypeFindFactory {
-  GstPluginFeature             feature;
+  GstPluginFeature              feature;
   /* <private> */
 
-  GstTypeFindFunction          function;
-  gchar **                     extensions;
-  GstCaps *                    caps; /* FIXME: not yet saved in registry */
+  GstTypeFindFunction           function;
+  gchar **                      extensions;
+  GstCaps *                     caps; /* FIXME: not yet saved in registry */
 
-  gpointer                     user_data;
-  GDestroyNotify               user_data_notify;
+  gpointer                      user_data;
+  GDestroyNotify                user_data_notify;
 
   gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstTypeFindFactoryClass {
-  GstPluginFeatureClass                parent;
+  GstPluginFeatureClass         parent;
   /* <private> */
 
   gpointer _gst_reserved[GST_PADDING];
@@ -67,14 +67,14 @@ struct _GstTypeFindFactoryClass {
 
 /* typefinding interface */
 
-GType           gst_type_find_factory_get_type         (void);
+GType           gst_type_find_factory_get_type          (void);
 
-GList *                gst_type_find_factory_get_list          (void);
+GList *         gst_type_find_factory_get_list          (void);
 
-gchar **       gst_type_find_factory_get_extensions    (GstTypeFindFactory *factory);
-GstCaps *      gst_type_find_factory_get_caps          (GstTypeFindFactory *factory);
-void           gst_type_find_factory_call_function     (GstTypeFindFactory *factory,
-                                                        GstTypeFind *find);
+gchar **        gst_type_find_factory_get_extensions    (GstTypeFindFactory *factory);
+GstCaps *       gst_type_find_factory_get_caps          (GstTypeFindFactory *factory);
+void            gst_type_find_factory_call_function     (GstTypeFindFactory *factory,
+                                                         GstTypeFind *find);
 
 G_END_DECLS
 
index 30244e5..5b09965 100644 (file)
 #include "gstmarshal.h"
 #include "gstregistry.h"
 
+#include "gst-i18n-lib.h"
+
 #include <string.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_uri_handler_debug);
 #define GST_CAT_DEFAULT gst_uri_handler_debug
 
-enum
-{
-  NEW_URI,
-  LAST_SIGNAL
-};
-
-static guint gst_uri_handler_signals[LAST_SIGNAL] = { 0 };
-
-static void gst_uri_handler_base_init (gpointer g_class);
-
 GType
 gst_uri_handler_get_type (void)
 {
@@ -71,7 +63,7 @@ gst_uri_handler_get_type (void)
     GType _type;
     static const GTypeInfo urihandler_info = {
       sizeof (GstURIHandlerInterface),
-      gst_uri_handler_base_init,
+      NULL,
       NULL,
       NULL,
       NULL,
@@ -92,27 +84,10 @@ gst_uri_handler_get_type (void)
   return urihandler_type;
 }
 
-static void
-gst_uri_handler_base_init (gpointer g_class)
+GQuark
+gst_uri_error_quark (void)
 {
-  static gboolean initialized = FALSE;
-
-  if (G_UNLIKELY (!initialized)) {
-
-    /**
-     * GstURIHandler::new-uri:
-     * @handler: The #GstURIHandler which emitted the signal
-     * @uri: (transfer none): The new URI, or NULL if the URI was removed
-     *
-     * The URI of the given @handler has changed.
-     */
-
-    gst_uri_handler_signals[NEW_URI] =
-        g_signal_new ("new-uri", GST_TYPE_URI_HANDLER, G_SIGNAL_RUN_LAST,
-        G_STRUCT_OFFSET (GstURIHandlerInterface, new_uri), NULL, NULL,
-        gst_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
-    initialized = TRUE;
-  }
+  return g_quark_from_static_string ("gst-uri-error-quark");
 }
 
 static const guchar acceptable[96] = {  /* X0   X1   X2   X3   X4   X5   X6   X7   X8   X9   XA   XB   XC   XD   XE   XF */
@@ -503,7 +478,7 @@ SearchEntry;
 static gboolean
 search_by_entry (GstPluginFeature * feature, gpointer search_entry)
 {
-  gchar **protocols;
+  const gchar *const *protocols;
   GstElementFactory *factory;
   SearchEntry *entry = (SearchEntry *) search_entry;
 
@@ -548,7 +523,7 @@ get_element_factories_from_uri_protocol (const GstURIType type,
 
   entry.type = type;
   entry.protocol = protocol;
-  possibilities = gst_registry_feature_filter (gst_registry_get_default (),
+  possibilities = gst_registry_feature_filter (gst_registry_get (),
       search_by_entry, FALSE, &entry);
 
   return possibilities;
@@ -622,7 +597,7 @@ gst_element_make_from_uri (const GstURIType type, const gchar * uri,
                 elementname)) != NULL) {
       GstURIHandler *handler = GST_URI_HANDLER (ret);
 
-      if (gst_uri_handler_set_uri (handler, uri))
+      if (gst_uri_handler_set_uri (handler, uri, NULL))
         break;
       gst_object_unref (ret);
       ret = NULL;
@@ -655,13 +630,9 @@ gst_uri_handler_get_uri_type (GstURIHandler * handler)
 
   iface = GST_URI_HANDLER_GET_INTERFACE (handler);
   g_return_val_if_fail (iface != NULL, GST_URI_UNKNOWN);
-  g_return_val_if_fail (iface->get_type != NULL
-      || iface->get_type_full != NULL, GST_URI_UNKNOWN);
+  g_return_val_if_fail (iface->get_type != NULL, GST_URI_UNKNOWN);
 
-  if (iface->get_type != NULL)
-    ret = iface->get_type ();
-  else
-    ret = iface->get_type_full (G_OBJECT_TYPE (handler));
+  ret = iface->get_type (G_OBJECT_TYPE (handler));
   g_return_val_if_fail (GST_URI_TYPE_IS_VALID (ret), GST_URI_UNKNOWN);
 
   return ret;
@@ -678,24 +649,19 @@ gst_uri_handler_get_uri_type (GstURIHandler * handler)
  *     supported protocols. Returns NULL if the @handler isn't implemented
  *     properly, or the @handler doesn't support any protocols.
  */
-gchar **
+const gchar *const *
 gst_uri_handler_get_protocols (GstURIHandler * handler)
 {
   GstURIHandlerInterface *iface;
-  gchar **ret;
+  const gchar *const *ret;
 
   g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
 
   iface = GST_URI_HANDLER_GET_INTERFACE (handler);
   g_return_val_if_fail (iface != NULL, NULL);
-  g_return_val_if_fail (iface->get_protocols != NULL ||
-      iface->get_protocols_full != NULL, NULL);
+  g_return_val_if_fail (iface->get_protocols != NULL, NULL);
 
-  if (iface->get_protocols != NULL) {
-    ret = iface->get_protocols ();
-  } else {
-    ret = iface->get_protocols_full (G_OBJECT_TYPE (handler));
-  }
+  ret = iface->get_protocols (G_OBJECT_TYPE (handler));
   g_return_val_if_fail (ret != NULL, NULL);
 
   return ret;
@@ -707,15 +673,15 @@ gst_uri_handler_get_protocols (GstURIHandler * handler)
  *
  * Gets the currently handled URI.
  *
- * Returns: (transfer none): the URI currently handled by the @handler.
+ * Returns: (transfer full): the URI currently handled by the @handler.
  *   Returns NULL if there are no URI currently handled. The
- *   returned string must not be modified or freed.
+ *   returned string must be freed with g_free() when no longer needed.
  */
-const gchar *
+gchar *
 gst_uri_handler_get_uri (GstURIHandler * handler)
 {
   GstURIHandlerInterface *iface;
-  const gchar *ret;
+  gchar *ret;
 
   g_return_val_if_fail (GST_IS_URI_HANDLER (handler), NULL);
 
@@ -733,13 +699,16 @@ gst_uri_handler_get_uri (GstURIHandler * handler)
  * gst_uri_handler_set_uri:
  * @handler: A #GstURIHandler
  * @uri: URI to set
+ * @error: (allow-none): address where to store a #GError in case of
+ *    an error, or NULL
  *
  * Tries to set the URI of the given handler.
  *
  * Returns: TRUE if the URI was set successfully, else FALSE.
  */
 gboolean
-gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** error)
 {
   GstURIHandlerInterface *iface;
   gboolean ret;
@@ -747,6 +716,7 @@ gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
 
   g_return_val_if_fail (GST_IS_URI_HANDLER (handler), FALSE);
   g_return_val_if_fail (gst_uri_is_valid (uri), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   iface = GST_URI_HANDLER_GET_INTERFACE (handler);
   g_return_val_if_fail (iface != NULL, FALSE);
@@ -754,12 +724,35 @@ gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
 
   protocol = gst_uri_get_protocol (uri);
 
+  if (iface->get_protocols) {
+    const gchar *const *protocols;
+    const gchar *const *p;
+    gboolean found_protocol = FALSE;
+
+    protocols = iface->get_protocols (G_OBJECT_TYPE (handler));
+    if (protocols != NULL) {
+      for (p = protocols; *p != NULL; ++p) {
+        if (g_ascii_strcasecmp (protocol, *p) == 0) {
+          found_protocol = TRUE;
+          break;
+        }
+      }
+
+      if (!found_protocol) {
+        g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_PROTOCOL,
+            _("URI scheme '%s' not supported"), protocol);
+        g_free (protocol);
+        return FALSE;
+      }
+    }
+  }
+
   colon = strstr (uri, ":");
   location = g_strdup (colon);
 
   new_uri = g_strdup_printf ("%s%s", protocol, location);
 
-  ret = iface->set_uri (handler, uri);
+  ret = iface->set_uri (handler, uri, error);
 
   g_free (new_uri);
   g_free (location);
@@ -768,22 +761,6 @@ gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
   return ret;
 }
 
-/**
- * gst_uri_handler_new_uri:
- * @handler: A #GstURIHandler
- * @uri: new URI or NULL if it was unset
- *
- * Emits the new-uri signal for a given handler, when that handler has a new URI.
- * This function should only be called by URI handlers themselves.
- */
-void
-gst_uri_handler_new_uri (GstURIHandler * handler, const gchar * uri)
-{
-  g_return_if_fail (GST_IS_URI_HANDLER (handler));
-
-  g_signal_emit (handler, gst_uri_handler_signals[NEW_URI], 0, uri);
-}
-
 static gchar *
 gst_file_utils_canonicalise_path (const gchar * path)
 {
index 5c3f705..539bbcb 100644 (file)
 
 #include <glib.h>
 #include <gst/gstelement.h>
-#include <gst/gstpluginfeature.h>
 
 G_BEGIN_DECLS
 
+GQuark gst_uri_error_quark (void);
+
+/**
+ * GST_URI_ERROR:
+ *
+ * Get access to the error quark of the uri subsystem.
+ */
+#define GST_URI_ERROR gst_uri_error_quark ()
+
+/**
+ * GstURIError:
+ * @GST_URI_ERROR_BAD_PROTOCOL: The protocol is not supported
+ * @GST_URI_ERROR_BAD_URI: There was a problem with the URI
+ * @GST_URI_ERROR_BAD_STATE: Could not set or change the URI because the
+ *     URI handler was in a state where that is not possible or not permitted
+ * @GST_URI_ERROR_BAD_REFERENCE: There was a problem with the entity that
+ *     the URI references
+ *
+ * Different URI-related errors that can occur.
+ */
+typedef enum
+{
+  GST_URI_ERROR_BAD_PROTOCOL,
+  GST_URI_ERROR_BAD_URI,
+  GST_URI_ERROR_BAD_STATE,
+  GST_URI_ERROR_BAD_REFERENCE
+} GstURIError;
+
 /**
  * GstURIType:
- * @GST_URI_UNKNOWN    : The URI direction is unknown
- * @GST_URI_SINK       : The URI is a consumer.
- * @GST_URI_SRC                : The URI is a producer.
+ * @GST_URI_UNKNOWN: The URI direction is unknown
+ * @GST_URI_SINK: The URI is a consumer.
+ * @GST_URI_SRC: The URI is a producer.
  *
  * The different types of URI direction.
  */
@@ -54,10 +81,10 @@ typedef enum {
 #define GST_URI_TYPE_IS_VALID(type) ((type) == GST_URI_SRC || (type) == GST_URI_SINK)
 
 /* uri handler functions */
-#define GST_TYPE_URI_HANDLER           (gst_uri_handler_get_type ())
-#define GST_URI_HANDLER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
-#define GST_IS_URI_HANDLER(obj)                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER))
-#define GST_URI_HANDLER_GET_INTERFACE(obj)     (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerInterface))
+#define GST_TYPE_URI_HANDLER               (gst_uri_handler_get_type ())
+#define GST_URI_HANDLER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_URI_HANDLER, GstURIHandler))
+#define GST_IS_URI_HANDLER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_URI_HANDLER))
+#define GST_URI_HANDLER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_URI_HANDLER, GstURIHandlerInterface))
 
 /**
  * GstURIHandler:
@@ -74,82 +101,54 @@ typedef struct _GstURIHandlerInterface GstURIHandlerInterface;
  * @get_protocols: Method to return the list of protocols handled by the element.
  * @get_uri: Method to return the URI currently handled by the element.
  * @set_uri: Method to set a new URI.
- * @get_type_full: Variant of get_type which takes a GType argument. This is 
- *   for use by bindings that need to pass context when creating a URI Handler.
- *   If implemented, get_type will be used in preference to get_type_full.
- *   Since: 0.10.15.
- * @get_protocols_full: Variant of get_protocols which takes a GType argument.
- *   This is for use by bindings that need to pass context when creating a URI
- *   Handler. If implemented, get_protocols will be used in preference to
- *   get_protocols_full. Since: 0.10.15.
  *
  * Any #GstElement using this interface should implement these methods.
  */
 struct _GstURIHandlerInterface {
-  GTypeInterface       parent;
-
-  /*< private >*/
-  /* signals */
-  void         (* new_uri)                     (GstURIHandler * handler,
-                                                const gchar *   uri);
-  /* idea for the future ?
-  gboolean     (* require_password)            (GstURIHandler * handler,
-                                                gchar **        username,
-                                                gchar **        password);
-   */
+  GTypeInterface parent;
 
   /* vtable */
-
   /*< public >*/
   /* querying capabilities */
-  GstURIType           (* get_type)            (void);
-  gchar **             (* get_protocols)       (void);
+  GstURIType             (* get_type)           (GType type);
+  const gchar * const *  (* get_protocols)      (GType type);
 
   /* using the interface */
-  const gchar *                (* get_uri)             (GstURIHandler * handler);
-  gboolean             (* set_uri)             (GstURIHandler * handler,
-                                                const gchar *   uri);
-
-  GstURIType           (* get_type_full)       (GType type);
-  gchar **             (* get_protocols_full)  (GType type);
-
-  /*< private >*/
-  /* we might want to add functions here to query features,
-   * someone with gnome-vfs knowledge go ahead */
-
-  gpointer _gst_reserved[GST_PADDING - 2];
+  gchar *                (* get_uri)            (GstURIHandler * handler);
+  gboolean               (* set_uri)            (GstURIHandler * handler,
+                                                 const gchar   * uri,
+                                                 GError       ** error);
 };
 
 /* general URI functions */
 
-gboolean       gst_uri_protocol_is_valid       (const gchar * protocol);
-gboolean       gst_uri_protocol_is_supported   (const GstURIType type,
-                                                const gchar *protocol);
-gboolean       gst_uri_is_valid                (const gchar * uri);
-gchar *                gst_uri_get_protocol            (const gchar * uri) G_GNUC_MALLOC;
+gboolean        gst_uri_protocol_is_valid       (const gchar * protocol);
+gboolean        gst_uri_protocol_is_supported   (const GstURIType type,
+                                                 const gchar *protocol);
+gboolean        gst_uri_is_valid                (const gchar * uri);
+gchar *         gst_uri_get_protocol            (const gchar * uri) G_GNUC_MALLOC;
 gboolean        gst_uri_has_protocol            (const gchar * uri,
                                                  const gchar * protocol);
-gchar *                gst_uri_get_location            (const gchar * uri) G_GNUC_MALLOC;
-gchar *                gst_uri_construct               (const gchar * protocol,
-                                                const gchar * location) G_GNUC_MALLOC;
+gchar *         gst_uri_get_location            (const gchar * uri) G_GNUC_MALLOC;
+gchar *         gst_uri_construct               (const gchar * protocol,
+                                                 const gchar * location) G_GNUC_MALLOC;
 
 gchar *         gst_filename_to_uri             (const gchar * filename,
                                                  GError     ** error) G_GNUC_MALLOC;
 
-GstElement *   gst_element_make_from_uri       (const GstURIType type,
-                                                const gchar *    uri,
-                                                const gchar *    elementname) G_GNUC_MALLOC;
+GstElement *    gst_element_make_from_uri       (const GstURIType type,
+                                                 const gchar *    uri,
+                                                 const gchar *    elementname) G_GNUC_MALLOC;
 
 /* accessing the interface */
-GType          gst_uri_handler_get_type        (void);
-
-guint          gst_uri_handler_get_uri_type    (GstURIHandler * handler);
-gchar **       gst_uri_handler_get_protocols   (GstURIHandler * handler);
-const gchar *  gst_uri_handler_get_uri         (GstURIHandler * handler);
-gboolean       gst_uri_handler_set_uri         (GstURIHandler * handler,
-                                                const gchar *   uri);
-void           gst_uri_handler_new_uri         (GstURIHandler * handler,
-                                                const gchar *   uri);
+GType                 gst_uri_handler_get_type (void);
+
+GstURIType            gst_uri_handler_get_uri_type  (GstURIHandler * handler);
+const gchar * const * gst_uri_handler_get_protocols (GstURIHandler * handler);
+gchar *               gst_uri_handler_get_uri       (GstURIHandler * handler) G_GNUC_MALLOC;
+gboolean              gst_uri_handler_set_uri       (GstURIHandler * handler,
+                                                     const gchar   * uri,
+                                                     GError       ** error);
 
 G_END_DECLS
 
index 9a0e807..363dee0 100644 (file)
  * SECTION:gstutils
  * @short_description: Various utility functions
  *
- * When defining own plugins, use the GST_BOILERPLATE ease gobject creation.
  */
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "gst_private.h"
 #include <stdio.h>
 #include <string.h>
@@ -708,7 +704,7 @@ guint32
 gst_util_seqnum_next (void)
 {
   static gint counter = 0;
-  return G_ATOMIC_INT_ADD (&counter, 1);
+  return g_atomic_int_add (&counter, 1);
 }
 
 /**
@@ -762,7 +758,7 @@ gst_print_pad_caps (GString * buf, gint indent, GstPad * pad)
 {
   GstCaps *caps;
 
-  caps = pad->caps;
+  caps = gst_pad_get_current_caps (pad);
 
   if (!caps) {
     string_append_indent (buf, indent);
@@ -774,6 +770,8 @@ gst_print_pad_caps (GString * buf, gint indent, GstPad * pad)
     s = gst_caps_to_string (caps);
     g_string_append (buf, s);
     g_free (s);
+
+    gst_caps_unref (caps);
   }
 }
 
@@ -1092,6 +1090,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
   GstCaps *templcaps;
   GstPad *foundpad = NULL;
   gboolean done;
+  GValue padptr = { 0, };
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
@@ -1114,8 +1113,6 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
   }
 
   while (!done) {
-    gpointer padptr;
-
     switch (gst_iterator_next (pads, &padptr)) {
       case GST_ITERATOR_OK:
       {
@@ -1124,7 +1121,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
         GstPad *srcpad;
         GstPad *sinkpad;
 
-        current = GST_PAD (padptr);
+        current = g_value_get_object (&padptr);
 
         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
             GST_DEBUG_PAD_NAME (current));
@@ -1143,7 +1140,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
           gboolean compatible;
 
           /* Now check if the two pads' caps are compatible */
-          temp = gst_pad_get_caps_reffed (pad);
+          temp = gst_pad_query_caps (pad, NULL);
           if (caps) {
             intersection = gst_caps_intersect (temp, caps);
             gst_caps_unref (temp);
@@ -1151,7 +1148,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
             intersection = temp;
           }
 
-          temp = gst_pad_get_caps_reffed (current);
+          temp = gst_pad_query_caps (current, NULL);
           compatible = gst_caps_can_intersect (temp, intersection);
           gst_caps_unref (temp);
           gst_caps_unref (intersection);
@@ -1162,6 +1159,9 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
                 GST_DEBUG_PAD_NAME (current));
             gst_iterator_free (pads);
 
+            current = gst_object_ref (current);
+            g_value_unset (&padptr);
+
             return current;
           } else {
             GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads");
@@ -1172,7 +1172,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
         }
         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
 
-        gst_object_unref (current);
+        g_value_reset (&padptr);
         if (peer)
           gst_object_unref (peer);
         break;
@@ -1188,6 +1188,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
         break;
     }
   }
+  g_value_unset (&padptr);
   gst_iterator_free (pads);
 
   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
@@ -1197,10 +1198,10 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
   /* try to create a new one */
   /* requesting is a little crazy, we need a template. Let's create one */
   /* FIXME: why not gst_pad_get_pad_template (pad); */
-  templcaps = gst_pad_get_caps_reffed (pad);
-
+  templcaps = gst_pad_query_caps (pad, NULL);
   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
+  gst_caps_unref (templcaps);
 
   foundpad = gst_element_request_compatible_pad (element, templ);
   gst_object_unref (templ);
@@ -1334,56 +1335,6 @@ gst_element_factory_can_accept_any_caps_in_direction (GstElementFactory *
 }
 
 /**
- * gst_element_factory_can_src_caps:
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can source the given capability.
- *
- * Returns: %TRUE if it can src the capabilities
- *
- * Deprecated: use gst_element_factory_can_src_all_caps() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean gst_element_factory_can_src_caps (GstElementFactory * factory,
-    const GstCaps * caps);
-#endif
-gboolean
-gst_element_factory_can_src_caps (GstElementFactory * factory,
-    const GstCaps * caps)
-{
-  return gst_element_factory_can_accept_all_caps_in_direction (factory, caps,
-      GST_PAD_SRC);
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
- * gst_element_factory_can_sink_caps:
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can sink the given capability.
- *
- * Returns: %TRUE if it can sink the capabilities
- *
- * Deprecated: use gst_element_factory_can_sink_all_caps() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean gst_element_factory_can_sink_caps (GstElementFactory * factory,
-    const GstCaps * caps);
-#endif
-gboolean
-gst_element_factory_can_sink_caps (GstElementFactory * factory,
-    const GstCaps * caps)
-{
-  return gst_element_factory_can_accept_all_caps_in_direction (factory, caps,
-      GST_PAD_SINK);
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-/**
  * gst_element_factory_can_sink_all_caps:
  * @factory: factory to query
  * @caps: the caps to check
@@ -1893,8 +1844,11 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
           desttempl = (GstPadTemplate *) l->data;
           if (desttempl->presence == GST_PAD_REQUEST &&
               desttempl->direction != srctempl->direction) {
-            if (gst_caps_is_always_compatible (gst_pad_template_get_caps
-                    (srctempl), gst_pad_template_get_caps (desttempl))) {
+            GstCaps *srccaps, *destcaps;
+
+            srccaps = gst_pad_template_get_caps (srctempl);
+            destcaps = gst_pad_template_get_caps (desttempl);
+            if (gst_caps_is_always_compatible (srccaps, destcaps)) {
               srcpad =
                   gst_element_request_pad (src, srctempl,
                   srctempl->name_template, NULL);
@@ -1908,6 +1862,8 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
                     GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
                 gst_object_unref (srcpad);
                 gst_object_unref (destpad);
+                gst_caps_unref (srccaps);
+                gst_caps_unref (destcaps);
                 return TRUE;
               }
               /* it failed, so we release the request pads */
@@ -1916,6 +1872,8 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname,
               if (destpad)
                 gst_element_release_request_pad (dest, destpad);
             }
+            gst_caps_unref (srccaps);
+            gst_caps_unref (destcaps);
           }
         }
       }
@@ -2226,6 +2184,7 @@ gst_element_unlink (GstElement * src, GstElement * dest)
 {
   GstIterator *pads;
   gboolean done = FALSE;
+  GValue data = { 0, };
 
   g_return_if_fail (GST_IS_ELEMENT (src));
   g_return_if_fail (GST_IS_ELEMENT (dest));
@@ -2235,12 +2194,10 @@ gst_element_unlink (GstElement * src, GstElement * dest)
 
   pads = gst_element_iterate_pads (src);
   while (!done) {
-    gpointer data;
-
     switch (gst_iterator_next (pads, &data)) {
       case GST_ITERATOR_OK:
       {
-        GstPad *pad = GST_PAD_CAST (data);
+        GstPad *pad = g_value_get_object (&data);
 
         if (GST_PAD_IS_SRC (pad)) {
           GstPad *peerpad = gst_pad_get_peer (pad);
@@ -2260,7 +2217,7 @@ gst_element_unlink (GstElement * src, GstElement * dest)
             gst_object_unref (peerpad);
           }
         }
-        gst_object_unref (pad);
+        g_value_reset (&data);
         break;
       }
       case GST_ITERATOR_RESYNC:
@@ -2274,14 +2231,14 @@ gst_element_unlink (GstElement * src, GstElement * dest)
         break;
     }
   }
+  g_value_unset (&data);
   gst_iterator_free (pads);
 }
 
 /**
  * gst_element_query_position:
  * @element: a #GstElement to invoke the position query on.
- * @format: (inout): a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @cur: (out) (allow-none): a location in which to store the current
  *     position, or NULL.
  *
@@ -2291,20 +2248,20 @@ gst_element_unlink (GstElement * src, GstElement * dest)
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_element_query_position (GstElement * element, GstFormat format,
+gst_element_query_position (GstElement * element, GstFormat format,
     gint64 * cur)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
-  query = gst_query_new_position (*format);
+  query = gst_query_new_position (format);
   ret = gst_element_query (element, query);
 
   if (ret)
-    gst_query_parse_position (query, format, cur);
+    gst_query_parse_position (query, NULL, cur);
 
   gst_query_unref (query);
 
@@ -2314,8 +2271,7 @@ gst_element_query_position (GstElement * element, GstFormat * format,
 /**
  * gst_element_query_duration:
  * @element: a #GstElement to invoke the duration query on.
- * @format: (inout): a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @duration: (out): A location in which to store the total duration, or NULL.
  *
  * Queries an element for the total stream duration.
@@ -2323,20 +2279,20 @@ gst_element_query_position (GstElement * element, GstFormat * format,
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_element_query_duration (GstElement * element, GstFormat format,
+gst_element_query_duration (GstElement * element, GstFormat format,
     gint64 * duration)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
-  query = gst_query_new_duration (*format);
+  query = gst_query_new_duration (format);
   ret = gst_element_query (element, query);
 
   if (ret)
-    gst_query_parse_duration (query, format, duration);
+    gst_query_parse_duration (query, NULL, duration);
 
   gst_query_unref (query);
 
@@ -2348,7 +2304,7 @@ gst_element_query_duration (GstElement * element, GstFormat * format,
  * @element: a #GstElement to invoke the convert query on.
  * @src_format: (inout): a #GstFormat to convert from.
  * @src_val: a value to convert.
- * @dest_format: (inout): a pointer to the #GstFormat to convert to.
+ * @dest_format: the #GstFormat to convert to.
  * @dest_val: (out): a pointer to the result.
  *
  * Queries an element to convert @src_val in @src_format to @dest_format.
@@ -2357,25 +2313,25 @@ gst_element_query_duration (GstElement * element, GstFormat * format,
  */
 gboolean
 gst_element_query_convert (GstElement * element, GstFormat src_format,
-    gint64 src_val, GstFormat dest_format, gint64 * dest_val)
+    gint64 src_val, GstFormat dest_format, gint64 * dest_val)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
+  g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
   g_return_val_if_fail (dest_val != NULL, FALSE);
 
-  if (*dest_format == src_format || src_val == -1) {
+  if (dest_format == src_format || src_val == -1) {
     *dest_val = src_val;
     return TRUE;
   }
 
-  query = gst_query_new_convert (src_format, src_val, *dest_format);
+  query = gst_query_new_convert (src_format, src_val, dest_format);
   ret = gst_element_query (element, query);
 
   if (ret)
-    gst_query_parse_convert (query, NULL, NULL, dest_format, dest_val);
+    gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
 
   gst_query_unref (query);
 
@@ -2428,9 +2384,8 @@ gst_element_seek_simple (GstElement * element, GstFormat format,
  * gst_pad_use_fixed_caps:
  * @pad: the pad to use
  *
- * A helper function you can use that sets the
- * @gst_pad_get_fixed_caps_func as the getcaps function for the
- * pad. This way the function will always return the negotiated caps
+ * A helper function you can use that sets the FIXED_CAPS flag
+ * This way the default getcaps function will always return the negotiated caps
  * or in case the pad is not negotiated, the padtemplate caps.
  *
  * Use this function on a pad that, once gst_pad_set_caps() has been called
@@ -2439,52 +2394,7 @@ gst_element_seek_simple (GstElement * element, GstFormat format,
 void
 gst_pad_use_fixed_caps (GstPad * pad)
 {
-  gst_pad_set_getcaps_function (pad, gst_pad_get_fixed_caps_func);
-}
-
-/**
- * gst_pad_get_fixed_caps_func:
- * @pad: the pad to use
- *
- * A helper function you can use as a GetCaps function that
- * will return the currently negotiated caps or the padtemplate
- * when NULL.
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full): the currently negotiated caps or the padtemplate.
- */
-GstCaps *
-gst_pad_get_fixed_caps_func (GstPad * pad)
-{
-  GstCaps *result;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  GST_OBJECT_LOCK (pad);
-  if (GST_PAD_CAPS (pad)) {
-    result = GST_PAD_CAPS (pad);
-
-    GST_CAT_DEBUG (GST_CAT_CAPS,
-        "using pad caps %p %" GST_PTR_FORMAT, result, result);
-
-    result = gst_caps_ref (result);
-  } else if (GST_PAD_PAD_TEMPLATE (pad)) {
-    GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
-
-    result = GST_PAD_TEMPLATE_CAPS (templ);
-    GST_CAT_DEBUG (GST_CAT_CAPS,
-        "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
-        result);
-
-    result = gst_caps_ref (result);
-  } else {
-    GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
-    result = gst_caps_new_empty ();
-  }
-  GST_OBJECT_UNLOCK (pad);
-
-  return result;
+  GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FIXED_CAPS);
 }
 
 /**
@@ -2521,7 +2431,8 @@ gst_pad_get_parent_element (GstPad * pad)
  * @error: (in): the GError.
  * @debug: (in) (allow-none): an additional debug information string, or NULL
  *
- * A default error function.
+ * A default error function that uses g_printerr() to display the error message
+ * and the optional debug sting..
  *
  * The default handler will simply print the error string using g_print.
  */
@@ -2531,10 +2442,9 @@ gst_object_default_error (GstObject * source, const GError * error,
 {
   gchar *name = gst_object_get_path_string (source);
 
-  /* FIXME 0.11: should change this to g_printerr() */
-  g_print (_("ERROR: from element %s: %s\n"), name, error->message);
+  g_printerr (_("ERROR: from element %s: %s\n"), name, error->message);
   if (debug)
-    g_print (_("Additional debug info:\n%s\n"), debug);
+    g_printerr (_("Additional debug info:\n%s\n"), debug);
 
   g_free (name);
 }
@@ -2740,9 +2650,13 @@ GstBuffer *
 gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2)
 {
   GstBuffer *result;
+  gsize size1, size2;
+
+  size1 = gst_buffer_get_size (buf1);
+  size2 = gst_buffer_get_size (buf2);
 
   /* we're just a specific case of the more general gst_buffer_span() */
-  result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
+  result = gst_buffer_span (buf1, 0, buf2, size1 + size2);
 
   return result;
 }
@@ -2770,270 +2684,150 @@ GstBuffer *
 gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
 {
   GstBuffer *result;
+  gsize size1, size2;
 
-  result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
+  size1 = gst_buffer_get_size (buf1);
+  size2 = gst_buffer_get_size (buf2);
+
+  result = gst_buffer_span (buf1, 0, buf2, size1 + size2);
   gst_buffer_unref (buf1);
   gst_buffer_unref (buf2);
 
   return result;
 }
 
-
-/**
- * gst_buffer_stamp:
- * @dest: (transfer none): buffer to stamp
- * @src: buffer to stamp from
- *
- * Copies additional information (the timestamp, duration, and offset start
- * and end) from one buffer to the other.
- *
- * This function does not copy any buffer flags or caps and is equivalent to
- * gst_buffer_copy_metadata(@dest, @src, GST_BUFFER_COPY_TIMESTAMPS).
- *
- * Deprecated: use gst_buffer_copy_metadata() instead, it provides more
- * control.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
-#endif
-void
-gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src)
+typedef struct
 {
-  gst_buffer_copy_metadata (dest, src, GST_BUFFER_COPY_TIMESTAMPS);
-}
-#endif /* GST_REMOVE_DEPRECATED */
+  GstQuery *query;
+  gboolean ret;
+} QueryAcceptCapsData;
 
 static gboolean
-getcaps_fold_func (GstPad * pad, GValue * ret, GstPad * orig)
+query_accept_caps_func (GstPad * pad, QueryAcceptCapsData * data)
 {
-  gboolean empty = FALSE;
-  GstCaps *peercaps, *existing;
-
-  existing = g_value_get_pointer (ret);
-  peercaps = gst_pad_peer_get_caps_reffed (pad);
-  if (G_LIKELY (peercaps)) {
-    GstCaps *intersection = gst_caps_intersect (existing, peercaps);
-
-    empty = gst_caps_is_empty (intersection);
+  if (G_LIKELY (gst_pad_peer_query (pad, data->query))) {
+    gboolean result;
 
-    g_value_set_pointer (ret, intersection);
-    gst_caps_unref (existing);
-    gst_caps_unref (peercaps);
+    gst_query_parse_accept_caps_result (data->query, &result);
+    data->ret &= result;
   }
-  gst_object_unref (pad);
-  return !empty;
+  return FALSE;
 }
 
 /**
- * gst_pad_proxy_getcaps:
+ * gst_pad_proxy_query_accept_caps:
  * @pad: a #GstPad to proxy.
+ * @query: an ACCEPT_CAPS #GstQuery.
  *
- * Calls gst_pad_get_allowed_caps() for every other pad belonging to the
- * same element as @pad, and returns the intersection of the results.
- *
- * This function is useful as a default getcaps function for an element
- * that can handle any stream format, but requires all its pads to have
- * the same caps.  Two such elements are tee and adder.
+ * Calls gst_pad_accept_caps() for all internally linked pads of @pad and
+ * returns the intersection of the results.
  *
- * Free-function: gst_caps_unref
+ * This function is useful as a default accept caps query function for an element
+ * that can handle any stream format, but requires caps that are acceptable for
+ * all oposite pads.
  *
- * Returns: (transfer full): the intersection of the other pads' allowed caps.
+ * Returns: TRUE if @query could be executed
  */
-GstCaps *
-gst_pad_proxy_getcaps (GstPad * pad)
+gboolean
+gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query)
 {
-  GstElement *element;
-  GstCaps *caps, *intersected;
-  GstIterator *iter;
-  GstIteratorResult res;
-  GValue ret = { 0, };
+  QueryAcceptCapsData data;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS, FALSE);
 
-  GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s",
+  GST_CAT_DEBUG (GST_CAT_PADS, "proxying accept caps query for %s:%s",
       GST_DEBUG_PAD_NAME (pad));
 
-  element = gst_pad_get_parent_element (pad);
-  if (element == NULL)
-    goto no_parent;
+  data.query = query;
+  /* value to hold the return, by default it holds TRUE */
+  data.ret = TRUE;
 
-  /* value to hold the return, by default it holds ANY, the ref is taken by
-   * the GValue. */
-  g_value_init (&ret, G_TYPE_POINTER);
-  g_value_set_pointer (&ret, gst_caps_new_any ());
+  gst_pad_forward (pad, (GstPadForwardFunction) query_accept_caps_func, &data);
+  gst_query_set_accept_caps_result (query, data.ret);
 
-  /* only iterate the pads in the oposite direction */
-  if (GST_PAD_IS_SRC (pad))
-    iter = gst_element_iterate_sink_pads (element);
-  else
-    iter = gst_element_iterate_src_pads (element);
-
-  while (1) {
-    res =
-        gst_iterator_fold (iter, (GstIteratorFoldFunction) getcaps_fold_func,
-        &ret, pad);
-    switch (res) {
-      case GST_ITERATOR_RESYNC:
-        /* unref any value stored */
-        if ((caps = g_value_get_pointer (&ret)))
-          gst_caps_unref (caps);
-        /* need to reset the result again to ANY */
-        g_value_set_pointer (&ret, gst_caps_new_any ());
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_DONE:
-        /* all pads iterated, return collected value */
-        goto done;
-      case GST_ITERATOR_OK:
-        /* premature exit (happens if caps intersection is empty) */
-        goto done;
-      default:
-        /* iterator returned _ERROR, mark an error and exit */
-        if ((caps = g_value_get_pointer (&ret)))
-          gst_caps_unref (caps);
-        g_value_set_pointer (&ret, NULL);
-        goto error;
-    }
-  }
-done:
-  gst_iterator_free (iter);
-
-  gst_object_unref (element);
-
-  caps = g_value_get_pointer (&ret);
-  g_value_unset (&ret);
-
-  if (caps) {
-    intersected =
-        gst_caps_intersect (caps, gst_pad_get_pad_template_caps (pad));
-    gst_caps_unref (caps);
-  } else {
-    intersected = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-  }
-
-  return intersected;
-
-  /* ERRORS */
-no_parent:
-  {
-    GST_DEBUG_OBJECT (pad, "no parent");
-    return gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-  }
-error:
-  {
-    g_warning ("Pad list returned error on element %s",
-        GST_ELEMENT_NAME (element));
-    gst_iterator_free (iter);
-    gst_object_unref (element);
-    return gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-  }
+  return TRUE;
 }
 
 typedef struct
 {
-  GstPad *orig;
-  GstCaps *caps;
-} SetCapsFoldData;
+  GstQuery *query;
+  GstCaps *ret;
+} QueryCapsData;
 
 static gboolean
-setcaps_fold_func (GstPad * pad, GValue * ret, SetCapsFoldData * data)
+query_caps_func (GstPad * pad, QueryCapsData * data)
 {
-  gboolean success = TRUE;
+  gboolean empty = FALSE;
 
-  if (pad != data->orig) {
-    success = gst_pad_set_caps (pad, data->caps);
-    g_value_set_boolean (ret, success);
-  }
-  gst_object_unref (pad);
+  if (G_LIKELY (gst_pad_peer_query (pad, data->query))) {
+    GstCaps *peercaps, *intersection;
 
-  return success;
+    gst_query_parse_caps_result (data->query, &peercaps);
+    GST_DEBUG_OBJECT (pad, "intersect with result %" GST_PTR_FORMAT, peercaps);
+    intersection = gst_caps_intersect (data->ret, peercaps);
+    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, intersection);
+
+    gst_caps_unref (data->ret);
+    data->ret = intersection;
+
+    /* stop when empty */
+    empty = gst_caps_is_empty (intersection);
+  }
+  return empty;
 }
 
 /**
- * gst_pad_proxy_setcaps
- * @pad: a #GstPad to proxy from
- * @caps: (transfer none): the #GstCaps to link with
+ * gst_pad_proxy_query_caps:
+ * @pad: a #GstPad to proxy.
+ * @query: a CAPS #GstQuery.
  *
- * Calls gst_pad_set_caps() for every other pad belonging to the
- * same element as @pad.  If gst_pad_set_caps() fails on any pad,
- * the proxy setcaps fails. May be used only during negotiation.
+ * Calls gst_pad_query_caps() for all internally linked pads fof @pad and returns
+ * the intersection of the results.
  *
- * Returns: TRUE if successful
+ * This function is useful as a default caps query function for an element
+ * that can handle any stream format, but requires all its pads to have
+ * the same caps.  Two such elements are tee and adder.
+ *
+ * Returns: TRUE if @query could be executed
  */
 gboolean
-gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps)
+gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query)
 {
-  GstElement *element;
-  GstIterator *iter;
-  GstIteratorResult res;
-  GValue ret = { 0, };
-  SetCapsFoldData data;
+  GstCaps *intersected;
+  QueryCapsData data;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (caps != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
+  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS, FALSE);
 
-  GST_CAT_DEBUG (GST_CAT_PADS, "proxying pad link for %s:%s",
+  GST_CAT_DEBUG (GST_CAT_PADS, "proxying caps query for %s:%s",
       GST_DEBUG_PAD_NAME (pad));
 
-  element = gst_pad_get_parent_element (pad);
-  if (element == NULL)
-    return FALSE;
-
-  /* only iterate the pads in the oposite direction */
-  if (GST_PAD_IS_SRC (pad))
-    iter = gst_element_iterate_sink_pads (element);
-  else
-    iter = gst_element_iterate_src_pads (element);
+  data.query = query;
+  /* value to hold the return, by default it holds ANY */
+  data.ret = gst_caps_new_any ();
 
-  g_value_init (&ret, G_TYPE_BOOLEAN);
-  g_value_set_boolean (&ret, TRUE);
-  data.orig = pad;
-  data.caps = caps;
+  gst_pad_forward (pad, (GstPadForwardFunction) query_caps_func, &data);
 
-  while (1) {
-    res = gst_iterator_fold (iter, (GstIteratorFoldFunction) setcaps_fold_func,
-        &ret, &data);
-
-    switch (res) {
-      case GST_ITERATOR_RESYNC:
-        /* reset return value */
-        g_value_set_boolean (&ret, TRUE);
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_DONE:
-        /* all pads iterated, return collected value */
-        goto done;
-      default:
-        /* iterator returned _ERROR or premature end with _OK,
-         * mark an error and exit */
-        goto error;
-    }
+  if (data.ret) {
+    intersected =
+        gst_caps_intersect (data.ret, gst_pad_get_pad_template_caps (pad));
+    gst_caps_unref (data.ret);
+  } else {
+    intersected = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
   }
-done:
-  gst_iterator_free (iter);
+  gst_query_set_caps_result (query, intersected);
+  gst_caps_unref (intersected);
 
-  gst_object_unref (element);
-
-  /* ok not to unset the gvalue */
-  return g_value_get_boolean (&ret);
-
-  /* ERRORS */
-error:
-  {
-    g_warning ("Pad list return error on element %s",
-        GST_ELEMENT_NAME (element));
-    gst_iterator_free (iter);
-    gst_object_unref (element);
-    return FALSE;
-  }
+  return TRUE;
 }
 
 /**
  * gst_pad_query_position:
  * @pad: a #GstPad to invoke the position query on.
- * @format: (inout): a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @cur: (out): A location in which to store the current position, or NULL.
  *
  * Queries a pad for the stream position.
@@ -3041,31 +2835,27 @@ error:
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
+gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
-
-  query = gst_query_new_position (*format);
-  ret = gst_pad_query (pad, query);
-
-  if (ret)
-    gst_query_parse_position (query, format, cur);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
+  query = gst_query_new_position (format);
+  if ((ret = gst_pad_query (pad, query)))
+    gst_query_parse_position (query, NULL, cur);
   gst_query_unref (query);
 
   return ret;
 }
 
 /**
- * gst_pad_query_peer_position:
+ * gst_pad_peer_query_position:
  * @pad: a #GstPad on whose peer to invoke the position query on.
  *       Must be a sink pad.
- * @format: (inout): a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @cur: (out) (allow-none): a location in which to store the current
  *     position, or NULL.
  *
@@ -3074,20 +2864,19 @@ gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur)
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_pad_query_peer_position (GstPad * pad, GstFormat * format, gint64 * cur)
+gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur)
 {
+  GstQuery *query;
   gboolean ret = FALSE;
-  GstPad *peer;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
-  peer = gst_pad_get_peer (pad);
-  if (peer) {
-    ret = gst_pad_query_position (peer, format, cur);
-    gst_object_unref (peer);
-  }
+  query = gst_query_new_position (format);
+  if ((ret = gst_pad_peer_query (pad, query)))
+    gst_query_parse_position (query, NULL, cur);
+  gst_query_unref (query);
 
   return ret;
 }
@@ -3095,8 +2884,7 @@ gst_pad_query_peer_position (GstPad * pad, GstFormat * format, gint64 * cur)
 /**
  * gst_pad_query_duration:
  * @pad: a #GstPad to invoke the duration query on.
- * @format: (inout): a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @duration: (out) (allow-none): a location in which to store the total
  *     duration, or NULL.
  *
@@ -3105,31 +2893,27 @@ gst_pad_query_peer_position (GstPad * pad, GstFormat * format, gint64 * cur)
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
+gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
-
-  query = gst_query_new_duration (*format);
-  ret = gst_pad_query (pad, query);
-
-  if (ret)
-    gst_query_parse_duration (query, format, duration);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
+  query = gst_query_new_duration (format);
+  if ((ret = gst_pad_query (pad, query)))
+    gst_query_parse_duration (query, NULL, duration);
   gst_query_unref (query);
 
   return ret;
 }
 
 /**
- * gst_pad_query_peer_duration:
+ * gst_pad_peer_query_duration:
  * @pad: a #GstPad on whose peer pad to invoke the duration query on.
  *       Must be a sink pad.
- * @format: (inout) :a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
+ * @format: the #GstFormat requested
  * @duration: (out) (allow-none): a location in which to store the total
  *     duration, or NULL.
  *
@@ -3138,21 +2922,19 @@ gst_pad_query_duration (GstPad * pad, GstFormat * format, gint64 * duration)
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_pad_query_peer_duration (GstPad * pad, GstFormat * format,
-    gint64 * duration)
+gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
 {
+  GstQuery *query;
   gboolean ret = FALSE;
-  GstPad *peer;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
+  g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
 
-  peer = gst_pad_get_peer (pad);
-  if (peer) {
-    ret = gst_pad_query_duration (peer, format, duration);
-    gst_object_unref (peer);
-  }
+  query = gst_query_new_duration (format);
+  if ((ret = gst_pad_peer_query (pad, query)))
+    gst_query_parse_duration (query, NULL, duration);
+  gst_query_unref (query);
 
   return ret;
 }
@@ -3162,7 +2944,7 @@ gst_pad_query_peer_duration (GstPad * pad, GstFormat * format,
  * @pad: a #GstPad to invoke the convert query on.
  * @src_format: a #GstFormat to convert from.
  * @src_val: a value to convert.
- * @dest_format: (inout): a pointer to the #GstFormat to convert to.
+ * @dest_format: the #GstFormat to convert to.
  * @dest_val: (out): a pointer to the result.
  *
  * Queries a pad to convert @src_val in @src_format to @dest_format.
@@ -3171,38 +2953,35 @@ gst_pad_query_peer_duration (GstPad * pad, GstFormat * format,
  */
 gboolean
 gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
-    GstFormat dest_format, gint64 * dest_val)
+    GstFormat dest_format, gint64 * dest_val)
 {
   GstQuery *query;
   gboolean ret;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
+  g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
   g_return_val_if_fail (dest_val != NULL, FALSE);
 
-  if (*dest_format == src_format || src_val == -1) {
+  if (dest_format == src_format || src_val == -1) {
     *dest_val = src_val;
     return TRUE;
   }
 
-  query = gst_query_new_convert (src_format, src_val, *dest_format);
-  ret = gst_pad_query (pad, query);
-
-  if (ret)
-    gst_query_parse_convert (query, NULL, NULL, dest_format, dest_val);
-
+  query = gst_query_new_convert (src_format, src_val, dest_format);
+  if ((ret = gst_pad_query (pad, query)))
+    gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
   gst_query_unref (query);
 
   return ret;
 }
 
 /**
- * gst_pad_query_peer_convert:
+ * gst_pad_peer_query_convert:
  * @pad: a #GstPad, on whose peer pad to invoke the convert query on.
  *       Must be a sink pad.
  * @src_format: a #GstFormat to convert from.
  * @src_val: a value to convert.
- * @dest_format: (inout): a pointer to the #GstFormat to convert to.
+ * @dest_format: the #GstFormat to convert to.
  * @dest_val: (out): a pointer to the result.
  *
  * Queries the peer pad of a given sink pad to convert @src_val in @src_format
@@ -3211,395 +2990,172 @@ gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
  * Returns: TRUE if the query could be performed.
  */
 gboolean
-gst_pad_query_peer_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
-    GstFormat dest_format, gint64 * dest_val)
+gst_pad_peer_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
+    GstFormat dest_format, gint64 * dest_val)
 {
+  GstQuery *query;
   gboolean ret = FALSE;
-  GstPad *peer;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
+  g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
   g_return_val_if_fail (dest_val != NULL, FALSE);
 
-  peer = gst_pad_get_peer (pad);
-  if (peer) {
-    ret = gst_pad_query_convert (peer, src_format, src_val, dest_format,
-        dest_val);
-    gst_object_unref (peer);
-  }
+  query = gst_query_new_convert (src_format, src_val, dest_format);
+  if ((ret = gst_pad_peer_query (pad, query)))
+    gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
+  gst_query_unref (query);
 
   return ret;
 }
 
 /**
- * gst_atomic_int_set:
- * @atomic_int: (inout): pointer to an atomic integer
- * @value: value to set
+ * gst_pad_query_caps:
+ * @pad: a  #GstPad to get the capabilities of.
+ * @filter: (allow-none): suggested #GstCaps, or NULL
  *
- * Unconditionally sets the atomic integer to @value.
+ * Gets the capabilities this pad can produce or consume.
+ * Note that this method doesn't necessarily return the caps set by
+ * gst_pad_set_caps() - use gst_pad_get_current_caps() for that instead.
+ * gst_pad_query_caps returns all possible caps a pad can operate with, using
+ * the pad's CAPS query function, If the query fails, this function will return
+ * @filter, if not #NULL, otherwise ANY.
  *
- * Deprecated: Use g_atomic_int_set().
+ * When called on sinkpads @filter contains the caps that
+ * upstream could produce in the order preferred by upstream. When
+ * called on srcpads @filter contains the caps accepted by
+ * downstream in the preffered order. @filter might be %NULL but
+ * if it is not %NULL the returned caps will be a subset of @filter.
  *
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void gst_atomic_int_set (gint * atomic_int, gint value);
-#endif
-void
-gst_atomic_int_set (gint * atomic_int, gint value)
-{
-  g_atomic_int_set (atomic_int, value);
-}
-#endif
-
-/**
- * gst_pad_add_data_probe:
- * @pad: pad to add the data probe handler to
- * @handler: function to call when data is passed over pad
- * @data: (closure): data to pass along with the handler
- *
- * Adds a "data probe" to a pad. This function will be called whenever data
- * passes through a pad. In this case data means both events and buffers. The
- * probe will be called with the data as an argument, meaning @handler should
- * have the same callback signature as the #GstPad::have-data signal.
- * Note that the data will have a reference count greater than 1, so it will
- * be immutable -- you must not change it.
- *
- * For source pads, the probe will be called after the blocking function, if any
- * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
- * to. For sink pads, the probe function will be called before configuring the
- * sink with new caps, if any, and before calling the pad's chain function.
- *
- * Your data probe should return TRUE to let the data continue to flow, or FALSE
- * to drop it. Dropping data is rarely useful, but occasionally comes in handy
- * with events.
- *
- * Although probes are implemented internally by connecting @handler to the
- * have-data signal on the pad, if you want to remove a probe it is insufficient
- * to only call g_signal_handler_disconnect on the returned handler id. To
- * remove a probe, use the appropriate function, such as
- * gst_pad_remove_data_probe().
- *
- * Returns: The handler id.
- */
-gulong
-gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
-{
-  return gst_pad_add_data_probe_full (pad, handler, data, NULL);
-}
-
-/**
- * gst_pad_add_data_probe_full:
- * @pad: pad to add the data probe handler to
- * @handler: function to call when data is passed over pad
- * @data: (closure): data to pass along with the handler
- * @notify: (allow-none): function to call when the probe is disconnected,
- *     or NULL
- *
- * Adds a "data probe" to a pad. This function will be called whenever data
- * passes through a pad. In this case data means both events and buffers. The
- * probe will be called with the data as an argument, meaning @handler should
- * have the same callback signature as the #GstPad::have-data signal.
- * Note that the data will have a reference count greater than 1, so it will
- * be immutable -- you must not change it.
- *
- * For source pads, the probe will be called after the blocking function, if any
- * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
- * to. For sink pads, the probe function will be called before configuring the
- * sink with new caps, if any, and before calling the pad's chain function.
- *
- * Your data probe should return TRUE to let the data continue to flow, or FALSE
- * to drop it. Dropping data is rarely useful, but occasionally comes in handy
- * with events.
- *
- * Although probes are implemented internally by connecting @handler to the
- * have-data signal on the pad, if you want to remove a probe it is insufficient
- * to only call g_signal_handler_disconnect on the returned handler id. To
- * remove a probe, use the appropriate function, such as
- * gst_pad_remove_data_probe().
- *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
- *
- * Returns: The handler id.
+ * Note that this function does not return writable #GstCaps, use
+ * gst_caps_make_writable() before modifying the caps.
  *
- * Since: 0.10.20
- */
-gulong
-gst_pad_add_data_probe_full (GstPad * pad, GCallback handler,
-    gpointer data, GDestroyNotify notify)
-{
-  gulong sigid;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), 0);
-  g_return_val_if_fail (handler != NULL, 0);
-
-  GST_OBJECT_LOCK (pad);
-
-  /* we only expose a GDestroyNotify in our API because that's less confusing */
-  sigid = g_signal_connect_data (pad, "have-data", handler, data,
-      (GClosureNotify) notify, 0);
-
-  GST_PAD_DO_EVENT_SIGNALS (pad)++;
-  GST_PAD_DO_BUFFER_SIGNALS (pad)++;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-      "adding data probe, now %d data, %d event probes",
-      GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
-  _priv_gst_pad_invalidate_cache (pad);
-  GST_OBJECT_UNLOCK (pad);
-
-  return sigid;
-}
-
-/**
- * gst_pad_add_event_probe:
- * @pad: pad to add the event probe handler to
- * @handler: function to call when events are passed over pad
- * @data: (closure): data to pass along with the handler
- *
- * Adds a probe that will be called for all events passing through a pad. See
- * gst_pad_add_data_probe() for more information.
- *
- * Returns: The handler id
- */
-gulong
-gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
-{
-  return gst_pad_add_event_probe_full (pad, handler, data, NULL);
-}
-
-/**
- * gst_pad_add_event_probe_full:
- * @pad: pad to add the event probe handler to
- * @handler: function to call when events are passed over pad
- * @data: (closure): data to pass along with the handler, or NULL
- * @notify: (allow-none): function to call when probe is disconnected, or NULL
- *
- * Adds a probe that will be called for all events passing through a pad. See
- * gst_pad_add_data_probe() for more information.
- *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
- *
- * Returns: The handler id
- *
- * Since: 0.10.20
+ * Returns: (transfer full): the caps of the pad with incremented ref-count.
  */
-gulong
-gst_pad_add_event_probe_full (GstPad * pad, GCallback handler,
-    gpointer data, GDestroyNotify notify)
+GstCaps *
+gst_pad_query_caps (GstPad * pad, GstCaps * filter)
 {
-  gulong sigid;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), 0);
-  g_return_val_if_fail (handler != NULL, 0);
-
-  GST_OBJECT_LOCK (pad);
+  GstCaps *result = NULL;
+  GstQuery *query;
 
-  /* we only expose a GDestroyNotify in our API because that's less confusing */
-  sigid = g_signal_connect_data (pad, "have-data::event", handler, data,
-      (GClosureNotify) notify, 0);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
 
-  GST_PAD_DO_EVENT_SIGNALS (pad)++;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes",
-      GST_PAD_DO_EVENT_SIGNALS (pad));
-  _priv_gst_pad_invalidate_cache (pad);
-  GST_OBJECT_UNLOCK (pad);
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
 
-  return sigid;
-}
+  query = gst_query_new_caps (filter);
+  if (gst_pad_query (pad, query)) {
+    gst_query_parse_caps_result (query, &result);
+    gst_caps_ref (result);
+    GST_DEBUG_OBJECT (pad, "query returned %" GST_PTR_FORMAT, result);
+  } else if (filter) {
+    result = gst_caps_ref (filter);
+  } else {
+    result = gst_caps_new_any ();
+  }
+  gst_query_unref (query);
 
-/**
- * gst_pad_add_buffer_probe:
- * @pad: pad to add the buffer probe handler to
- * @handler: function to call when buffers are passed over pad
- * @data: (closure): data to pass along with the handler
- *
- * Adds a probe that will be called for all buffers passing through a pad. See
- * gst_pad_add_data_probe() for more information.
- *
- * Returns: The handler id
- */
-gulong
-gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
-{
-  return gst_pad_add_buffer_probe_full (pad, handler, data, NULL);
+  return result;
 }
 
 /**
- * gst_pad_add_buffer_probe_full:
- * @pad: pad to add the buffer probe handler to
- * @handler: function to call when buffer are passed over pad
- * @data: (closure): data to pass along with the handler
- * @notify: (allow-none): function to call when the probe is disconnected,
- *     or NULL
+ * gst_pad_peer_query_caps:
+ * @pad: a  #GstPad to get the capabilities of.
+ * @filter: (allow-none): a #GstCaps filter, or NULL.
  *
- * Adds a probe that will be called for all buffers passing through a pad. See
- * gst_pad_add_data_probe() for more information.
+ * Gets the capabilities of the peer connected to this pad. Similar to
+ * gst_pad_query_caps().
  *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
+ * When called on srcpads @filter contains the caps that
+ * upstream could produce in the order preferred by upstream. When
+ * called on sinkpads @filter contains the caps accepted by
+ * downstream in the preffered order. @filter might be %NULL but
+ * if it is not %NULL the returned caps will be a subset of @filter.
  *
- * Returns: The handler id
- *
- * Since: 0.10.20
+ * Returns: the caps of the peer pad with incremented ref-count. This function
+ * returns %NULL when there is no peer pad.
  */
-gulong
-gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler,
-    gpointer data, GDestroyNotify notify)
+GstCaps *
+gst_pad_peer_query_caps (GstPad * pad, GstCaps * filter)
 {
-  gulong sigid;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), 0);
-  g_return_val_if_fail (handler != NULL, 0);
-
-  GST_OBJECT_LOCK (pad);
-
-  /* we only expose a GDestroyNotify in our API because that's less confusing */
-  sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data,
-      (GClosureNotify) notify, 0);
-
-  GST_PAD_DO_BUFFER_SIGNALS (pad)++;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes",
-      GST_PAD_DO_BUFFER_SIGNALS (pad));
-  _priv_gst_pad_invalidate_cache (pad);
-  GST_OBJECT_UNLOCK (pad);
-
-  return sigid;
-}
+  GstCaps *result = NULL;
+  GstQuery *query;
 
-/**
- * gst_pad_remove_data_probe:
- * @pad: pad to remove the data probe handler from
- * @handler_id: handler id returned from gst_pad_add_data_probe
- *
- * Removes a data probe from @pad.
- */
-void
-gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (handler_id > 0);
-
-  GST_OBJECT_LOCK (pad);
-  g_signal_handler_disconnect (pad, handler_id);
-  GST_PAD_DO_BUFFER_SIGNALS (pad)--;
-  GST_PAD_DO_EVENT_SIGNALS (pad)--;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-      "removed data probe, now %d event, %d buffer probes",
-      GST_PAD_DO_EVENT_SIGNALS (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
-  GST_OBJECT_UNLOCK (pad);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
+
+  query = gst_query_new_caps (filter);
+  if (gst_pad_peer_query (pad, query)) {
+    gst_query_parse_caps_result (query, &result);
+    gst_caps_ref (result);
+    GST_DEBUG_OBJECT (pad, "peer query returned %" GST_PTR_FORMAT, result);
+  } else if (filter) {
+    result = gst_caps_ref (filter);
+  } else {
+    result = gst_caps_new_any ();
+  }
+  gst_query_unref (query);
 
+  return result;
 }
 
 /**
- * gst_pad_remove_event_probe:
- * @pad: pad to remove the event probe handler from
- * @handler_id: handler id returned from gst_pad_add_event_probe
+ * gst_pad_query_accept_caps:
+ * @pad: a #GstPad to check
+ * @caps: a #GstCaps to check on the pad
  *
- * Removes an event probe from @pad.
- */
-void
-gst_pad_remove_event_probe (GstPad * pad, guint handler_id)
-{
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (handler_id > 0);
-
-  GST_OBJECT_LOCK (pad);
-  g_signal_handler_disconnect (pad, handler_id);
-  GST_PAD_DO_EVENT_SIGNALS (pad)--;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-      "removed event probe, now %d event probes",
-      GST_PAD_DO_EVENT_SIGNALS (pad));
-  GST_OBJECT_UNLOCK (pad);
-}
-
-/**
- * gst_pad_remove_buffer_probe:
- * @pad: pad to remove the buffer probe handler from
- * @handler_id: handler id returned from gst_pad_add_buffer_probe
+ * Check if the given pad accepts the caps.
  *
- * Removes a buffer probe from @pad.
+ * Returns: TRUE if the pad can accept the caps.
  */
-void
-gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id)
+gboolean
+gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps)
 {
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (handler_id > 0);
+  gboolean res = TRUE;
+  GstQuery *query;
 
-  GST_OBJECT_LOCK (pad);
-  g_signal_handler_disconnect (pad, handler_id);
-  GST_PAD_DO_BUFFER_SIGNALS (pad)--;
-  GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
-      "removed buffer probe, now %d buffer probes",
-      GST_PAD_DO_BUFFER_SIGNALS (pad));
-  GST_OBJECT_UNLOCK (pad);
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
 
-}
+  GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps);
 
-/**
- * gst_element_found_tags_for_pad:
- * @element: element for which to post taglist to bus.
- * @pad: (transfer none): pad on which to push tag-event
- * @list: (transfer full): the taglist to post on the bus and create event from
- *
- * Posts a message to the bus that new tags were found and pushes the
- * tags as event. Takes ownership of the @list.
- *
- * This is a utility method for elements. Applications should use the
- * #GstTagSetter interface.
- */
-void
-gst_element_found_tags_for_pad (GstElement * element,
-    GstPad * pad, GstTagList * list)
-{
-  g_return_if_fail (element != NULL);
-  g_return_if_fail (pad != NULL);
-  g_return_if_fail (list != NULL);
-
-  gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
-  /* FIXME 0.11: Set the pad as source. */
-  gst_element_post_message (element,
-      gst_message_new_tag_full (GST_OBJECT (element), pad, list));
-}
+  query = gst_query_new_accept_caps (caps);
+  if (gst_pad_query (pad, query)) {
+    gst_query_parse_accept_caps_result (query, &res);
+    GST_DEBUG_OBJECT (pad, "query returned %d", res);
+  }
+  gst_query_unref (query);
 
-static void
-push_and_ref (GstPad * pad, GstEvent * event)
-{
-  gst_pad_push_event (pad, gst_event_ref (event));
-  /* iterator refs pad, we unref when we are done with it */
-  gst_object_unref (pad);
+  return res;
 }
 
 /**
- * gst_element_found_tags:
- * @element: element for which we found the tags.
- * @list: (transfer full): list of tags.
+ * gst_pad_peer_query_accept_caps:
+ * @pad: a  #GstPad to check the peer of
+ * @caps: a #GstCaps to check on the pad
  *
- * Posts a message to the bus that new tags were found, and pushes an event
- * to all sourcepads. Takes ownership of the @list.
+ * Check if the peer of @pad accepts @caps. If @pad has no peer, this function
+ * returns TRUE.
  *
- * This is a utility method for elements. Applications should use the
- * #GstTagSetter interface.
+ * Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer.
  */
-void
-gst_element_found_tags (GstElement * element, GstTagList * list)
+gboolean
+gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps * caps)
 {
-  GstIterator *iter;
-  GstEvent *event;
+  gboolean res = TRUE;
+  GstQuery *query;
 
-  g_return_if_fail (element != NULL);
-  g_return_if_fail (list != NULL);
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
 
-  iter = gst_element_iterate_src_pads (element);
-  event = gst_event_new_tag (gst_tag_list_copy (list));
-  gst_iterator_foreach (iter, (GFunc) push_and_ref, event);
-  gst_iterator_free (iter);
-  gst_event_unref (event);
+  query = gst_query_new_accept_caps (caps);
+  if (gst_pad_peer_query (pad, query)) {
+    gst_query_parse_accept_caps_result (query, &res);
+    GST_DEBUG_OBJECT (pad, "query returned %d", res);
+  }
+  gst_query_unref (query);
 
-  gst_element_post_message (element,
-      gst_message_new_tag (GST_OBJECT (element), list));
+  return res;
 }
 
 static GstPad *
@@ -3608,6 +3164,7 @@ element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
   GstIterator *iter;
   GstPad *unlinked_pad = NULL;
   gboolean done;
+  GValue data = { 0, };
 
   switch (direction) {
     case GST_PAD_SRC:
@@ -3622,26 +3179,25 @@ element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
 
   done = FALSE;
   while (!done) {
-    gpointer pad;
-
-    switch (gst_iterator_next (iter, &pad)) {
+    switch (gst_iterator_next (iter, &data)) {
       case GST_ITERATOR_OK:{
         GstPad *peer;
+        GstPad *pad = g_value_get_object (&data);
 
         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
             GST_DEBUG_PAD_NAME (pad));
 
-        peer = gst_pad_get_peer (GST_PAD (pad));
+        peer = gst_pad_get_peer (pad);
         if (peer == NULL) {
-          unlinked_pad = pad;
+          unlinked_pad = gst_object_ref (pad);
           done = TRUE;
           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
               "found existing unlinked pad %s:%s",
               GST_DEBUG_PAD_NAME (unlinked_pad));
         } else {
-          gst_object_unref (pad);
           gst_object_unref (peer);
         }
+        g_value_reset (&data);
         break;
       }
       case GST_ITERATOR_DONE:
@@ -3655,7 +3211,7 @@ element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
         break;
     }
   }
-
+  g_value_unset (&data);
   gst_iterator_free (iter);
 
   return unlinked_pad;
@@ -3682,6 +3238,7 @@ gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
   GstIterator *iter;
   gboolean done;
   GstPad *pad = NULL;
+  GValue data = { 0, };
 
   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
@@ -3689,15 +3246,16 @@ gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
   done = FALSE;
   iter = gst_bin_iterate_recurse (bin);
   while (!done) {
-    gpointer element;
+    switch (gst_iterator_next (iter, &data)) {
+      case GST_ITERATOR_OK:{
+        GstElement *element = g_value_get_object (&data);
 
-    switch (gst_iterator_next (iter, &element)) {
-      case GST_ITERATOR_OK:
-        pad = element_find_unlinked_pad (GST_ELEMENT (element), direction);
-        gst_object_unref (element);
+        pad = element_find_unlinked_pad (element, direction);
         if (pad != NULL)
           done = TRUE;
+        g_value_reset (&data);
         break;
+      }
       case GST_ITERATOR_DONE:
         done = TRUE;
         break;
@@ -3709,41 +3267,13 @@ gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
         break;
     }
   }
-
+  g_value_unset (&data);
   gst_iterator_free (iter);
 
   return pad;
 }
 
 /**
- * gst_bin_find_unconnected_pad:
- * @bin: bin in which to look for elements with unlinked pads
- * @direction: whether to look for an unlinked source or sink pad
- *
- * Recursively looks for elements with an unlinked pad of the given
- * direction within the specified bin and returns an unlinked pad
- * if one is found, or NULL otherwise. If a pad is found, the caller
- * owns a reference to it and should use gst_object_unref() on the
- * pad when it is not needed any longer.
- *
- * Returns: (transfer full): unlinked pad of the given direction, or NULL.
- *
- * Since: 0.10.3
- *
- * Deprecated: use gst_bin_find_unlinked_pad() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-GstPad *gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction);
-#endif
-GstPad *
-gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
-{
-  return gst_bin_find_unlinked_pad (bin, direction);
-}
-#endif
-
-/**
  * gst_parse_bin_from_description:
  * @bin_description: command line describing the bin
  * @ghost_unlinked_pads: whether to automatically create ghost pads
@@ -3849,79 +3379,6 @@ gst_parse_bin_from_description_full (const gchar * bin_description,
 }
 
 /**
- * gst_type_register_static_full:
- * @parent_type: The GType of the parent type the newly registered type will
- *   derive from
- * @type_name: NULL-terminated string used as the name of the new type
- * @class_size: Size of the class structure.
- * @base_init: Location of the base initialization function (optional).
- * @base_finalize: Location of the base finalization function (optional).
- * @class_init: Location of the class initialization function for class types
- *   Location of the default vtable initialization function for interface
- *   types. (optional)
- * @class_finalize: Location of the class finalization function for class types.
- *   Location of the default vtable finalization function for interface types.
- *   (optional)
- * @class_data: User-supplied data passed to the class init/finalize functions.
- * @instance_size: Size of the instance (object) structure (required for
- *   instantiatable types only).
- * @n_preallocs: The number of pre-allocated (cached) instances to reserve
- *   memory for (0 indicates no caching). Ignored on recent GLib's.
- * @instance_init: Location of the instance initialization function (optional,
- *   for instantiatable types only).
- * @value_table: A GTypeValueTable function table for generic handling of
- *   GValues of this type (usually only useful for fundamental types).
- * @flags: #GTypeFlags for this GType. E.g: G_TYPE_FLAG_ABSTRACT
- *
- * Helper function which constructs a #GTypeInfo structure and registers a
- * GType, but which generates less linker overhead than a static const
- * #GTypeInfo structure. For further details of the parameters, please see
- * #GTypeInfo in the GLib documentation.
- *
- * Registers type_name as the name of a new static type derived from
- * parent_type. The value of flags determines the nature (e.g. abstract or
- * not) of the type. It works by filling a GTypeInfo struct and calling
- * g_type_register_static().
- *
- * Returns: A #GType for the newly-registered type.
- *
- * Since: 0.10.14
- */
-GType
-gst_type_register_static_full (GType parent_type,
-    const gchar * type_name,
-    guint class_size,
-    GBaseInitFunc base_init,
-    GBaseFinalizeFunc base_finalize,
-    GClassInitFunc class_init,
-    GClassFinalizeFunc class_finalize,
-    gconstpointer class_data,
-    guint instance_size,
-    guint16 n_preallocs,
-    GInstanceInitFunc instance_init,
-    const GTypeValueTable * value_table, GTypeFlags flags)
-{
-  GTypeInfo info;
-
-  g_return_val_if_fail (class_size <= G_MAXUINT16, G_TYPE_INVALID);
-  g_return_val_if_fail (instance_size <= G_MAXUINT16, G_TYPE_INVALID);
-
-  info.class_size = class_size;
-  info.base_init = base_init;
-  info.base_finalize = base_finalize;
-  info.class_init = class_init;
-  info.class_finalize = class_finalize;
-  info.class_data = class_data;
-  info.instance_size = instance_size;
-  info.n_preallocs = n_preallocs;
-  info.instance_init = instance_init;
-  info.value_table = value_table;
-
-  return g_type_register_static (parent_type, type_name, &info, flags);
-}
-
-
-/**
  * gst_util_get_timestamp:
  *
  * Get a timestamp as GstClockTime to be used for interval measurements.
@@ -4065,6 +3522,32 @@ gst_util_greatest_common_divisor (gint a, gint b)
 }
 
 /**
+ * gst_util_greatest_common_divisor_int64:
+ * @a: First value as #gint64
+ * @b: Second value as #gint64
+ *
+ * Calculates the greatest common divisor of @a
+ * and @b.
+ *
+ * Returns: Greatest common divisor of @a and @b
+ *
+ * Since: 0.11.0
+ */
+gint64
+gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b)
+{
+  while (b != 0) {
+    gint64 temp = a;
+
+    a = b;
+    b = temp % b;
+  }
+
+  return ABS (a);
+}
+
+
+/**
  * gst_util_fraction_to_double:
  * @src_n: Fraction numerator as #gint
  * @src_d: Fraction denominator #gint
index a746913..c3f8ec6 100644 (file)
@@ -31,9 +31,9 @@
 
 G_BEGIN_DECLS
 
-void           gst_util_set_value_from_string  (GValue *value, const gchar *value_str);
-void           gst_util_set_object_arg         (GObject *object, const gchar *name, const gchar *value);
-void           gst_util_dump_mem               (const guchar *mem, guint size);
+void            gst_util_set_value_from_string  (GValue *value, const gchar *value_str);
+void            gst_util_set_object_arg         (GObject *object, const gchar *name, const gchar *value);
+void            gst_util_dump_mem               (const guchar *mem, guint size);
 
 guint64         gst_util_gdouble_to_guint64     (gdouble value)  G_GNUC_CONST;
 gdouble         gst_util_guint64_to_gdouble     (guint64 value)  G_GNUC_CONST;
@@ -63,9 +63,9 @@ gdouble         gst_util_guint64_to_gdouble     (guint64 value)  G_GNUC_CONST;
 #define         gst_guint64_to_gdouble(value)   ((gdouble) (value))
 #endif
 
-guint64                gst_util_uint64_scale           (guint64 val, guint64 num, guint64 denom);
-guint64                gst_util_uint64_scale_round     (guint64 val, guint64 num, guint64 denom);
-guint64                gst_util_uint64_scale_ceil      (guint64 val, guint64 num, guint64 denom);
+guint64         gst_util_uint64_scale           (guint64 val, guint64 num, guint64 denom);
+guint64         gst_util_uint64_scale_round     (guint64 val, guint64 num, guint64 denom);
+guint64         gst_util_uint64_scale_ceil      (guint64 val, guint64 num, guint64 denom);
 
 guint64         gst_util_uint64_scale_int       (guint64 val, gint num, gint denom);
 guint64         gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom);
@@ -74,170 +74,10 @@ guint64         gst_util_uint64_scale_int_ceil  (guint64 val, gint num, gint den
 guint32         gst_util_seqnum_next            (void);
 gint32          gst_util_seqnum_compare         (guint32 s1, guint32 s2);
 
-void           gst_print_pad_caps              (GString *buf, gint indent, GstPad *pad);
-void           gst_print_element_args          (GString *buf, gint indent, GstElement *element);
+void            gst_print_pad_caps              (GString *buf, gint indent, GstPad *pad);
+void            gst_print_element_args          (GString *buf, gint indent, GstElement *element);
 
 
-GType gst_type_register_static_full (GType parent_type,
-                                          const gchar       *type_name,
-                               guint              class_size,
-                               GBaseInitFunc      base_init,
-                               GBaseFinalizeFunc  base_finalize,
-                               GClassInitFunc     class_init,
-                               GClassFinalizeFunc class_finalize,
-                               gconstpointer      class_data,
-                               guint              instance_size,
-                               guint16            n_preallocs,
-                               GInstanceInitFunc  instance_init,
-                               const GTypeValueTable *value_table,
-                               GTypeFlags       flags);
-
-
-/* Macros for defining classes.  Ideas taken from Bonobo, which took theirs
-   from Nautilus and GOB. */
-
-/**
- * GST_BOILERPLATE_FULL:
- * @type: the name of the type struct
- * @type_as_function: the prefix for the functions
- * @parent_type: the parent type struct name
- * @parent_type_macro: the parent type macro
- * @additional_initializations: function pointer in the form of
- * void additional_initializations (GType type) that can be used for
- * initializing interfaces and the like
- *
- * Define the boilerplate type stuff to reduce typos and code size.  Defines
- * the get_type method and the parent_class static variable.
- *
- * <informalexample>
- * <programlisting>
- *   GST_BOILERPLATE_FULL (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT, _do_init);
- * </programlisting>
- * </informalexample>
- */
-#define GST_BOILERPLATE_FULL(type, type_as_function, parent_type, parent_type_macro, additional_initializations)       \
-                                                                       \
-static void type_as_function ## _base_init     (gpointer      g_class);        \
-static void type_as_function ## _class_init    (type ## Class *g_class);\
-static void type_as_function ## _init         (type          *object,  \
-                                                type ## Class *g_class);\
-static parent_type ## Class *parent_class = NULL;                      \
-static void                                                            \
-type_as_function ## _class_init_trampoline (gpointer g_class)          \
-{                                                                      \
-  parent_class = (parent_type ## Class *)                              \
-      g_type_class_peek_parent (g_class);                              \
-  type_as_function ## _class_init ((type ## Class *)g_class);          \
-}                                                                      \
-                                                                       \
-GType                                                                  \
-type_as_function ## _get_type (void)                                   \
-{                                                                      \
-  /* The typedef for GType may be gulong or gsize, depending on the    \
-   * system and whether the compiler is c++ or not. The g_once_init_*  \
-   * functions always take a gsize * though ... */                     \
-  static volatile gsize gonce_data = 0;                                        \
-  if (g_once_init_enter (&gonce_data)) {                               \
-    GType _type;                                                       \
-    _type = gst_type_register_static_full (parent_type_macro,           \
-        g_intern_static_string (#type),                                        \
-       sizeof (type ## Class),                                         \
-        type_as_function ## _base_init,                                        \
-        NULL,            /* base_finalize */                           \
-        (GClassInitFunc) type_as_function ## _class_init_trampoline,    \
-        NULL,            /* class_finalize */                          \
-        NULL,               /* class_data */                           \
-        sizeof (type),                                                 \
-        0,                  /* n_preallocs */                          \
-        (GInstanceInitFunc) type_as_function ## _init,                  \
-        NULL,                                                           \
-        (GTypeFlags) 0);                                               \
-    additional_initializations (_type);                                        \
-    g_once_init_leave (&gonce_data, (gsize) _type);                    \
-  }                                                                    \
-  return (GType) gonce_data;                                           \
-}
-
-#define __GST_DO_NOTHING(type) /* NOP */
-
-/**
- * GST_BOILERPLATE:
- * @type: the name of the type struct
- * @type_as_function: the prefix for the functions
- * @parent_type: the parent type struct name
- * @parent_type_macro: the parent type macro
- *
- * Define the boilerplate type stuff to reduce typos and code size.  Defines
- * the get_type method and the parent_class static variable.
- *
- * <informalexample>
- * <programlisting>
- *   GST_BOILERPLATE (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT);
- * </programlisting>
- * </informalexample>
- */
-#define GST_BOILERPLATE(type,type_as_function,parent_type,parent_type_macro)   \
-  GST_BOILERPLATE_FULL (type, type_as_function, parent_type, parent_type_macro,        \
-      __GST_DO_NOTHING)
-
-/* Like GST_BOILERPLATE, but makes the type 1) implement an interface, and 2)
- * implement GstImplementsInterface for that type
- *
- * After this you will need to implement interface_as_function ## _supported
- * and interface_as_function ## _interface_init
- */
-/**
- * GST_BOILERPLATE_WITH_INTERFACE:
- * @type: the name of the type struct
- * @type_as_function: the prefix for the functions
- * @parent_type: the parent type struct name
- * @parent_type_as_macro: the parent type macro
- * @interface_type: the name of the interface type struct
- * @interface_type_as_macro: the interface type macro
- * @interface_as_function: the interface function name prefix
- *
- * Like GST_BOILERPLATE, but makes the type 1) implement an interface, and 2)
- * implement GstImplementsInterface for that type.
- *
- * After this you will need to implement interface_as_function ## _supported
- * and interface_as_function ## _interface_init
- */
-#define GST_BOILERPLATE_WITH_INTERFACE(type, type_as_function,         \
-    parent_type, parent_type_as_macro, interface_type,                 \
-    interface_type_as_macro, interface_as_function)                    \
-                                                                        \
-static void interface_as_function ## _interface_init (interface_type ## Class *klass);  \
-static gboolean interface_as_function ## _supported (type *object, GType iface_type);   \
-                                                                        \
-static void                                                             \
-type_as_function ## _implements_interface_init (GstImplementsInterfaceClass *klass)     \
-{                                                                       \
-  klass->supported = (gboolean (*)(GstImplementsInterface*, GType))interface_as_function ## _supported;     \
-}                                                                       \
-                                                                        \
-static void                                                             \
-type_as_function ## _init_interfaces (GType type_var)                   \
-{                                                                       \
-  static const GInterfaceInfo implements_iface_info = {                 \
-    (GInterfaceInitFunc) type_as_function ## _implements_interface_init,\
-    NULL,                                                               \
-    NULL,                                                               \
-  };                                                                    \
-  static const GInterfaceInfo iface_info = {                            \
-    (GInterfaceInitFunc) interface_as_function ## _interface_init,      \
-    NULL,                                                               \
-    NULL,                                                               \
-  };                                                                    \
-                                                                        \
-  g_type_add_interface_static (type_var, GST_TYPE_IMPLEMENTS_INTERFACE, \
-      &implements_iface_info);                                          \
-  g_type_add_interface_static (type_var, interface_type_as_macro,      \
-      &iface_info);                                                    \
-}                                                                       \
-                                                                        \
-GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
-    parent_type_as_macro, type_as_function ## _init_interfaces)
-
 /**
  * GST_CALL_PARENT:
  * @parent_class_cast: the name of the class cast macro for the parent type
@@ -249,9 +89,9 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  * this macro is not to be used with things that return something, use
  * the _WITH_DEFAULT version for that
  */
-#define GST_CALL_PARENT(parent_class_cast, name, args)                 \
-       ((parent_class_cast(parent_class)->name != NULL) ?              \
-        parent_class_cast(parent_class)->name args : (void) 0)
+#define GST_CALL_PARENT(parent_class_cast, name, args)                  \
+        ((parent_class_cast(parent_class)->name != NULL) ?              \
+         parent_class_cast(parent_class)->name args : (void) 0)
 
 /**
  * GST_CALL_PARENT_WITH_DEFAULT:
@@ -264,8 +104,8 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  * evaluates to @def_return.
  */
 #define GST_CALL_PARENT_WITH_DEFAULT(parent_class_cast, name, args, def_return)\
-       ((parent_class_cast(parent_class)->name != NULL) ?              \
-        parent_class_cast(parent_class)->name args : def_return)
+        ((parent_class_cast(parent_class)->name != NULL) ?              \
+         parent_class_cast(parent_class)->name args : def_return)
 
 /* Define PUT and GET functions for unaligned memory */
 #define _GST_GET(__data, __idx, __size, __shift) \
@@ -280,14 +120,14 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 64 bit unsigned integer value in big endian format from the memory buffer.
  */
-#define GST_READ_UINT64_BE(data)       (_GST_GET (data, 0, 64, 56) | \
-                                        _GST_GET (data, 1, 64, 48) | \
-                                        _GST_GET (data, 2, 64, 40) | \
-                                        _GST_GET (data, 3, 64, 32) | \
-                                        _GST_GET (data, 4, 64, 24) | \
-                                        _GST_GET (data, 5, 64, 16) | \
-                                        _GST_GET (data, 6, 64,  8) | \
-                                        _GST_GET (data, 7, 64,  0))
+#define GST_READ_UINT64_BE(data)        (_GST_GET (data, 0, 64, 56) | \
+                                         _GST_GET (data, 1, 64, 48) | \
+                                         _GST_GET (data, 2, 64, 40) | \
+                                         _GST_GET (data, 3, 64, 32) | \
+                                         _GST_GET (data, 4, 64, 24) | \
+                                         _GST_GET (data, 5, 64, 16) | \
+                                         _GST_GET (data, 6, 64,  8) | \
+                                         _GST_GET (data, 7, 64,  0))
 
 /**
  * GST_READ_UINT64_LE:
@@ -295,14 +135,14 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 64 bit unsigned integer value in little endian format from the memory buffer.
  */
-#define GST_READ_UINT64_LE(data)       (_GST_GET (data, 7, 64, 56) | \
-                                        _GST_GET (data, 6, 64, 48) | \
-                                        _GST_GET (data, 5, 64, 40) | \
-                                        _GST_GET (data, 4, 64, 32) | \
-                                        _GST_GET (data, 3, 64, 24) | \
-                                        _GST_GET (data, 2, 64, 16) | \
-                                        _GST_GET (data, 1, 64,  8) | \
-                                        _GST_GET (data, 0, 64,  0))
+#define GST_READ_UINT64_LE(data)        (_GST_GET (data, 7, 64, 56) | \
+                                         _GST_GET (data, 6, 64, 48) | \
+                                         _GST_GET (data, 5, 64, 40) | \
+                                         _GST_GET (data, 4, 64, 32) | \
+                                         _GST_GET (data, 3, 64, 24) | \
+                                         _GST_GET (data, 2, 64, 16) | \
+                                         _GST_GET (data, 1, 64,  8) | \
+                                         _GST_GET (data, 0, 64,  0))
 
 /**
  * GST_READ_UINT32_BE:
@@ -310,10 +150,10 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 32 bit unsigned integer value in big endian format from the memory buffer.
  */
-#define GST_READ_UINT32_BE(data)       (_GST_GET (data, 0, 32, 24) | \
-                                        _GST_GET (data, 1, 32, 16) | \
-                                        _GST_GET (data, 2, 32,  8) | \
-                                        _GST_GET (data, 3, 32,  0))
+#define GST_READ_UINT32_BE(data)        (_GST_GET (data, 0, 32, 24) | \
+                                         _GST_GET (data, 1, 32, 16) | \
+                                         _GST_GET (data, 2, 32,  8) | \
+                                         _GST_GET (data, 3, 32,  0))
 
 /**
  * GST_READ_UINT32_LE:
@@ -321,10 +161,10 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 32 bit unsigned integer value in little endian format from the memory buffer.
  */
-#define GST_READ_UINT32_LE(data)       (_GST_GET (data, 3, 32, 24) | \
-                                        _GST_GET (data, 2, 32, 16) | \
-                                        _GST_GET (data, 1, 32,  8) | \
-                                        _GST_GET (data, 0, 32,  0))
+#define GST_READ_UINT32_LE(data)        (_GST_GET (data, 3, 32, 24) | \
+                                         _GST_GET (data, 2, 32, 16) | \
+                                         _GST_GET (data, 1, 32,  8) | \
+                                         _GST_GET (data, 0, 32,  0))
 
 /**
  * GST_READ_UINT24_BE:
@@ -334,9 +174,9 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Since: 0.10.22
  */
-#define GST_READ_UINT24_BE(data)       (_GST_GET (data, 0, 32, 16) | \
-                                        _GST_GET (data, 1, 32,  8) | \
-                                        _GST_GET (data, 2, 32,  0))
+#define GST_READ_UINT24_BE(data)        (_GST_GET (data, 0, 32, 16) | \
+                                         _GST_GET (data, 1, 32,  8) | \
+                                         _GST_GET (data, 2, 32,  0))
 
 /**
  * GST_READ_UINT24_LE:
@@ -346,9 +186,9 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Since: 0.10.22
  */
-#define GST_READ_UINT24_LE(data)       (_GST_GET (data, 2, 32, 16) | \
-                                        _GST_GET (data, 1, 32,  8) | \
-                                        _GST_GET (data, 0, 32,  0))
+#define GST_READ_UINT24_LE(data)        (_GST_GET (data, 2, 32, 16) | \
+                                         _GST_GET (data, 1, 32,  8) | \
+                                         _GST_GET (data, 0, 32,  0))
 
 /**
  * GST_READ_UINT16_BE:
@@ -356,8 +196,8 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 16 bit unsigned integer value in big endian format from the memory buffer.
  */
-#define GST_READ_UINT16_BE(data)       (_GST_GET (data, 0, 16,  8) | \
-                                        _GST_GET (data, 1, 16,  0))
+#define GST_READ_UINT16_BE(data)        (_GST_GET (data, 0, 16,  8) | \
+                                         _GST_GET (data, 1, 16,  0))
 
 /**
  * GST_READ_UINT16_LE:
@@ -365,8 +205,8 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read a 16 bit unsigned integer value in little endian format from the memory buffer.
  */
-#define GST_READ_UINT16_LE(data)       (_GST_GET (data, 1, 16,  8) | \
-                                        _GST_GET (data, 0, 16,  0))
+#define GST_READ_UINT16_LE(data)        (_GST_GET (data, 1, 16,  8) | \
+                                         _GST_GET (data, 0, 16,  0))
 
 /**
  * GST_READ_UINT8:
@@ -374,7 +214,7 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Read an 8 bit unsigned integer value from the memory buffer.
  */
-#define GST_READ_UINT8(data)           (_GST_GET (data, 0,  8,  0))
+#define GST_READ_UINT8(data)            (_GST_GET (data, 0,  8,  0))
 
 /**
  * GST_WRITE_UINT64_BE:
@@ -383,16 +223,16 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 64 bit unsigned integer value in big endian format into the memory buffer.
  */
-#define GST_WRITE_UINT64_BE(data, num) do { \
-                                         _GST_PUT (data, 0, 64, 56, num); \
-                                         _GST_PUT (data, 1, 64, 48, num); \
-                                         _GST_PUT (data, 2, 64, 40, num); \
-                                         _GST_PUT (data, 3, 64, 32, num); \
-                                         _GST_PUT (data, 4, 64, 24, num); \
-                                         _GST_PUT (data, 5, 64, 16, num); \
-                                         _GST_PUT (data, 6, 64,  8, num); \
-                                         _GST_PUT (data, 7, 64,  0, num); \
-                                       } while (0)
+#define GST_WRITE_UINT64_BE(data, num)  do { \
+                                          _GST_PUT (data, 0, 64, 56, num); \
+                                          _GST_PUT (data, 1, 64, 48, num); \
+                                          _GST_PUT (data, 2, 64, 40, num); \
+                                          _GST_PUT (data, 3, 64, 32, num); \
+                                          _GST_PUT (data, 4, 64, 24, num); \
+                                          _GST_PUT (data, 5, 64, 16, num); \
+                                          _GST_PUT (data, 6, 64,  8, num); \
+                                          _GST_PUT (data, 7, 64,  0, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT64_LE:
@@ -401,16 +241,16 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 64 bit unsigned integer value in little endian format into the memory buffer.
  */
-#define GST_WRITE_UINT64_LE(data, num) do { \
-                                         _GST_PUT (data, 0, 64,  0, num); \
-                                         _GST_PUT (data, 1, 64,  8, num); \
-                                         _GST_PUT (data, 2, 64, 16, num); \
-                                         _GST_PUT (data, 3, 64, 24, num); \
-                                         _GST_PUT (data, 4, 64, 32, num); \
-                                         _GST_PUT (data, 5, 64, 40, num); \
-                                         _GST_PUT (data, 6, 64, 48, num); \
-                                         _GST_PUT (data, 7, 64, 56, num); \
-                                       } while (0)
+#define GST_WRITE_UINT64_LE(data, num)  do { \
+                                          _GST_PUT (data, 0, 64,  0, num); \
+                                          _GST_PUT (data, 1, 64,  8, num); \
+                                          _GST_PUT (data, 2, 64, 16, num); \
+                                          _GST_PUT (data, 3, 64, 24, num); \
+                                          _GST_PUT (data, 4, 64, 32, num); \
+                                          _GST_PUT (data, 5, 64, 40, num); \
+                                          _GST_PUT (data, 6, 64, 48, num); \
+                                          _GST_PUT (data, 7, 64, 56, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT32_BE:
@@ -419,12 +259,12 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 32 bit unsigned integer value in big endian format into the memory buffer.
  */
-#define GST_WRITE_UINT32_BE(data, num) do { \
-                                         _GST_PUT (data, 0, 32, 24, num); \
-                                         _GST_PUT (data, 1, 32, 16, num); \
-                                         _GST_PUT (data, 2, 32,  8, num); \
-                                         _GST_PUT (data, 3, 32,  0, num); \
-                                       } while (0)
+#define GST_WRITE_UINT32_BE(data, num)  do { \
+                                          _GST_PUT (data, 0, 32, 24, num); \
+                                          _GST_PUT (data, 1, 32, 16, num); \
+                                          _GST_PUT (data, 2, 32,  8, num); \
+                                          _GST_PUT (data, 3, 32,  0, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT32_LE:
@@ -433,12 +273,12 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 32 bit unsigned integer value in little endian format into the memory buffer.
  */
-#define GST_WRITE_UINT32_LE(data, num) do { \
-                                         _GST_PUT (data, 0, 32,  0, num); \
-                                         _GST_PUT (data, 1, 32,  8, num); \
-                                         _GST_PUT (data, 2, 32, 16, num); \
-                                         _GST_PUT (data, 3, 32, 24, num); \
-                                       } while (0)
+#define GST_WRITE_UINT32_LE(data, num)  do { \
+                                          _GST_PUT (data, 0, 32,  0, num); \
+                                          _GST_PUT (data, 1, 32,  8, num); \
+                                          _GST_PUT (data, 2, 32, 16, num); \
+                                          _GST_PUT (data, 3, 32, 24, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT24_BE:
@@ -449,11 +289,11 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Since: 0.10.22
  */
-#define GST_WRITE_UINT24_BE(data, num) do { \
-                                         _GST_PUT (data, 0, 32,  16, num); \
-                                         _GST_PUT (data, 1, 32,  8, num); \
-                                         _GST_PUT (data, 2, 32,  0, num); \
-                                       } while (0)
+#define GST_WRITE_UINT24_BE(data, num)  do { \
+                                          _GST_PUT (data, 0, 32,  16, num); \
+                                          _GST_PUT (data, 1, 32,  8, num); \
+                                          _GST_PUT (data, 2, 32,  0, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT24_LE:
@@ -464,11 +304,11 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Since: 0.10.22
  */
-#define GST_WRITE_UINT24_LE(data, num) do { \
-                                         _GST_PUT (data, 0, 32,  0, num); \
-                                         _GST_PUT (data, 1, 32,  8, num); \
-                                         _GST_PUT (data, 2, 32,  16, num); \
-                                       } while (0)
+#define GST_WRITE_UINT24_LE(data, num)  do { \
+                                          _GST_PUT (data, 0, 32,  0, num); \
+                                          _GST_PUT (data, 1, 32,  8, num); \
+                                          _GST_PUT (data, 2, 32,  16, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT16_BE:
@@ -477,10 +317,10 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 16 bit unsigned integer value in big endian format into the memory buffer.
  */
-#define GST_WRITE_UINT16_BE(data, num) do { \
-                                         _GST_PUT (data, 0, 16,  8, num); \
-                                         _GST_PUT (data, 1, 16,  0, num); \
-                                       } while (0)
+#define GST_WRITE_UINT16_BE(data, num)  do { \
+                                          _GST_PUT (data, 0, 16,  8, num); \
+                                          _GST_PUT (data, 1, 16,  0, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT16_LE:
@@ -489,10 +329,10 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store a 16 bit unsigned integer value in little endian format into the memory buffer.
  */
-#define GST_WRITE_UINT16_LE(data, num) do { \
-                                         _GST_PUT (data, 0, 16,  0, num); \
-                                         _GST_PUT (data, 1, 16,  8, num); \
-                                       } while (0)
+#define GST_WRITE_UINT16_LE(data, num)  do { \
+                                          _GST_PUT (data, 0, 16,  0, num); \
+                                          _GST_PUT (data, 1, 16,  8, num); \
+                                        } while (0)
 
 /**
  * GST_WRITE_UINT8:
@@ -501,9 +341,9 @@ GST_BOILERPLATE_FULL (type, type_as_function, parent_type,              \
  *
  * Store an 8 bit unsigned integer value into the memory buffer.
  */
-#define GST_WRITE_UINT8(data, num)     do { \
-                                         _GST_PUT (data, 0,  8,  0, num); \
-                                       } while (0)
+#define GST_WRITE_UINT8(data, num)      do { \
+                                          _GST_PUT (data, 0,  8,  0, num); \
+                                        } while (0)
 
 /* Float endianness conversion macros */
 
@@ -992,39 +832,39 @@ GST_WRITE_DOUBLE_BE(guint8 *data, gdouble num)
  */
 #define GST_ROUND_DOWN_64(num) ((num)&(~63))
 
-void                   gst_object_default_error        (GstObject    * source,
-                                                        const GError * error,
-                                                        const gchar  * debug);
+void                    gst_object_default_error        (GstObject    * source,
+                                                         const GError * error,
+                                                         const gchar  * debug);
 
 /* element functions */
 void                    gst_element_create_all_pads     (GstElement *element);
 GstPad*                 gst_element_get_compatible_pad  (GstElement *element, GstPad *pad,
-                                                        const GstCaps *caps);
+                                                         const GstCaps *caps);
 
 GstPadTemplate*         gst_element_get_compatible_pad_template (GstElement *element, GstPadTemplate *compattempl);
 
 const gchar*            gst_element_state_get_name      (GstState state);
 const gchar *           gst_element_state_change_return_get_name (GstStateChangeReturn state_ret);
 
-gboolean               gst_element_link                (GstElement *src, GstElement *dest);
-gboolean               gst_element_link_many           (GstElement *element_1,
-                                                        GstElement *element_2, ...) G_GNUC_NULL_TERMINATED;
-gboolean               gst_element_link_filtered       (GstElement * src,
+gboolean                gst_element_link                (GstElement *src, GstElement *dest);
+gboolean                gst_element_link_many           (GstElement *element_1,
+                                                         GstElement *element_2, ...) G_GNUC_NULL_TERMINATED;
+gboolean                gst_element_link_filtered       (GstElement * src,
                                                          GstElement * dest,
                                                          GstCaps *filter);
 void                    gst_element_unlink              (GstElement *src, GstElement *dest);
 void                    gst_element_unlink_many         (GstElement *element_1,
-                                                        GstElement *element_2, ...) G_GNUC_NULL_TERMINATED;
+                                                         GstElement *element_2, ...) G_GNUC_NULL_TERMINATED;
 
-gboolean               gst_element_link_pads           (GstElement *src, const gchar *srcpadname,
-                                                        GstElement *dest, const gchar *destpadname);
-gboolean               gst_element_link_pads_full      (GstElement *src, const gchar *srcpadname,
-                                                        GstElement *dest, const gchar *destpadname,
-                                                        GstPadLinkCheck flags);
+gboolean                gst_element_link_pads           (GstElement *src, const gchar *srcpadname,
+                                                         GstElement *dest, const gchar *destpadname);
+gboolean                gst_element_link_pads_full      (GstElement *src, const gchar *srcpadname,
+                                                         GstElement *dest, const gchar *destpadname,
+                                                         GstPadLinkCheck flags);
 void                    gst_element_unlink_pads         (GstElement *src, const gchar *srcpadname,
-                                                        GstElement *dest, const gchar *destpadname);
+                                                         GstElement *dest, const gchar *destpadname);
 
-gboolean               gst_element_link_pads_filtered  (GstElement * src, const gchar * srcpadname,
+gboolean                gst_element_link_pads_filtered  (GstElement * src, const gchar * srcpadname,
                                                          GstElement * dest, const gchar * destpadname,
                                                          GstCaps *filter);
 
@@ -1034,110 +874,52 @@ gboolean                gst_element_seek_simple         (GstElement   *element,
                                                          gint64        seek_pos);
 
 /* util elementfactory functions */
-#ifndef GST_DISABLE_DEPRECATED
-gboolean               gst_element_factory_can_src_caps    (GstElementFactory *factory, const GstCaps *caps);
-gboolean               gst_element_factory_can_sink_caps   (GstElementFactory *factory, const GstCaps *caps);
-#endif /* GST_DISABLE_DEPRECATED */
 gboolean gst_element_factory_can_sink_all_caps (GstElementFactory *factory, const GstCaps *caps);
 gboolean gst_element_factory_can_src_all_caps  (GstElementFactory *factory, const GstCaps *caps);
 gboolean gst_element_factory_can_sink_any_caps (GstElementFactory *factory, const GstCaps *caps);
 gboolean gst_element_factory_can_src_any_caps  (GstElementFactory *factory, const GstCaps *caps);
 
 /* util query functions */
-gboolean                gst_element_query_position      (GstElement *element, GstFormat *format,
-                                                        gint64 *cur);
-gboolean                gst_element_query_duration      (GstElement *element, GstFormat *format,
-                                                        gint64 *duration);
+gboolean                gst_element_query_position      (GstElement *element, GstFormat format, gint64 *cur);
+gboolean                gst_element_query_duration      (GstElement *element, GstFormat format, gint64 *duration);
 gboolean                gst_element_query_convert       (GstElement *element, GstFormat src_format, gint64 src_val,
-                                                        GstFormat *dest_format, gint64 *dest_val);
+                                                         GstFormat dest_format, gint64 *dest_val);
 
 /* element class functions */
-void                   gst_element_class_install_std_props (GstElementClass * klass,
-                                                        const gchar * first_name, ...) G_GNUC_NULL_TERMINATED;
+void                    gst_element_class_install_std_props (GstElementClass * klass,
+                                                         const gchar * first_name, ...) G_GNUC_NULL_TERMINATED;
 
 /* pad functions */
-void                   gst_pad_use_fixed_caps          (GstPad *pad);
-GstCaps*               gst_pad_get_fixed_caps_func     (GstPad *pad);
-GstCaps*               gst_pad_proxy_getcaps           (GstPad * pad);
-gboolean               gst_pad_proxy_setcaps           (GstPad * pad, GstCaps * caps);
-
-GstElement*            gst_pad_get_parent_element      (GstPad *pad);
+void                    gst_pad_use_fixed_caps          (GstPad *pad);
+GstElement*             gst_pad_get_parent_element      (GstPad *pad);
 
 /* util query functions */
-gboolean                gst_pad_query_position          (GstPad *pad, GstFormat *format,
-                                                        gint64 *cur);
-gboolean                gst_pad_query_duration          (GstPad *pad, GstFormat *format,
-                                                        gint64 *duration);
+gboolean                gst_pad_proxy_query_accept_caps (GstPad *pad, GstQuery *query);
+gboolean                gst_pad_proxy_query_caps        (GstPad *pad, GstQuery *query);
+
+gboolean                gst_pad_query_position          (GstPad *pad, GstFormat format, gint64 *cur);
+gboolean                gst_pad_query_duration          (GstPad *pad, GstFormat format, gint64 *duration);
 gboolean                gst_pad_query_convert           (GstPad *pad, GstFormat src_format, gint64 src_val,
-                                                        GstFormat *dest_format, gint64 *dest_val);
+                                                         GstFormat dest_format, gint64 *dest_val);
+GstCaps *               gst_pad_query_caps              (GstPad *pad, GstCaps *filter);
+gboolean                gst_pad_query_accept_caps       (GstPad *pad, GstCaps *caps);
+
 
-gboolean                gst_pad_query_peer_position     (GstPad *pad, GstFormat *format,
-                                                        gint64 *cur);
-gboolean                gst_pad_query_peer_duration     (GstPad *pad, GstFormat *format,
-                                                        gint64 *duration);
-gboolean                gst_pad_query_peer_convert      (GstPad *pad, GstFormat src_format, gint64 src_val,
-                                                        GstFormat *dest_format, gint64 *dest_val);
+gboolean                gst_pad_peer_query_position     (GstPad *pad, GstFormat format, gint64 *cur);
+gboolean                gst_pad_peer_query_duration     (GstPad *pad, GstFormat format, gint64 *duration);
+gboolean                gst_pad_peer_query_convert      (GstPad *pad, GstFormat src_format, gint64 src_val,
+                                                         GstFormat dest_format, gint64 *dest_val);
+GstCaps *               gst_pad_peer_query_caps         (GstPad * pad, GstCaps *filter);
+gboolean                gst_pad_peer_query_accept_caps  (GstPad * pad, GstCaps *caps);
 
 /* bin functions */
 void                    gst_bin_add_many                (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED;
 void                    gst_bin_remove_many             (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED;
 GstPad *                gst_bin_find_unlinked_pad       (GstBin *bin, GstPadDirection direction);
-#ifndef GST_DISABLE_DEPRECATED
-GstPad *                gst_bin_find_unconnected_pad    (GstBin *bin, GstPadDirection direction);
-#endif
 
 /* buffer functions */
-GstBuffer *            gst_buffer_merge                (GstBuffer * buf1, GstBuffer * buf2);
-GstBuffer *            gst_buffer_join                 (GstBuffer * buf1, GstBuffer * buf2);
-#ifndef GST_DISABLE_DEPRECATED
-void                   gst_buffer_stamp                (GstBuffer * dest, const GstBuffer * src);
-#endif /* GST_DISABLE_DEPRECATED */
-
-/* atomic functions */
-#ifndef GST_DISABLE_DEPRECATED
-void                    gst_atomic_int_set              (gint * atomic_int, gint value);
-#endif
-
-/* probes */
-gulong                 gst_pad_add_data_probe          (GstPad   * pad,
-                                                        GCallback  handler,
-                                                        gpointer   data);
-
-gulong                 gst_pad_add_data_probe_full     (GstPad       * pad,
-                                                        GCallback      handler,
-                                                        gpointer       data,
-                                                        GDestroyNotify notify);
-
-void                   gst_pad_remove_data_probe       (GstPad * pad, guint handler_id);
-
-gulong                 gst_pad_add_event_probe         (GstPad   * pad,
-                                                        GCallback  handler,
-                                                        gpointer   data);
-
-gulong                 gst_pad_add_event_probe_full    (GstPad       * pad,
-                                                        GCallback      handler,
-                                                        gpointer       data,
-                                                        GDestroyNotify notify);
-
-void                   gst_pad_remove_event_probe      (GstPad * pad, guint handler_id);
-
-gulong                 gst_pad_add_buffer_probe        (GstPad   * pad,
-                                                        GCallback  handler,
-                                                        gpointer   data);
-
-gulong                 gst_pad_add_buffer_probe_full   (GstPad       * pad,
-                                                        GCallback      handler,
-                                                        gpointer       data,
-                                                        GDestroyNotify notify);
-
-void                   gst_pad_remove_buffer_probe     (GstPad * pad, guint handler_id);
-
-/* tag emission utility functions */
-void                   gst_element_found_tags_for_pad  (GstElement * element,
-                                                        GstPad * pad,
-                                                        GstTagList * list);
-void                   gst_element_found_tags          (GstElement * element,
-                                                        GstTagList * list);
+GstBuffer *             gst_buffer_merge                (GstBuffer * buf1, GstBuffer * buf2);
+GstBuffer *             gst_buffer_join                 (GstBuffer * buf1, GstBuffer * buf2);
 
 /* parse utility functions */
 GstElement *            gst_parse_bin_from_description      (const gchar     * bin_description,
@@ -1168,29 +950,23 @@ typedef enum {
   GST_SEARCH_MODE_AFTER
 } GstSearchMode;
 
-gpointer                gst_util_array_binary_search      (gpointer array, guint num_elements,
-                                                           gsize element_size, GCompareDataFunc search_func,
-                                                          GstSearchMode mode, gconstpointer search_data,
-                                                          gpointer user_data);
+gpointer      gst_util_array_binary_search      (gpointer array, guint num_elements,
+                                                 gsize element_size, GCompareDataFunc search_func,
+                                                 GstSearchMode mode, gconstpointer search_data,
+                                                 gpointer user_data);
 
-gint gst_util_greatest_common_divisor (gint a, gint b);
-void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest);
-void gst_util_double_to_fraction (gdouble src, gint *dest_n, gint *dest_d);
-gboolean gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d);
-gboolean gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d);
-gint gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d);
+/* fraction operations */
+gint          gst_util_greatest_common_divisor  (gint a, gint b);
+gint64        gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b);
 
+void          gst_util_fraction_to_double       (gint src_n, gint src_d, gdouble *dest);
+void          gst_util_double_to_fraction       (gdouble src, gint *dest_n, gint *dest_d);
 
-/* sink message event
- *
- * FIXME: This should be in gstevent.h but can't because
- * it needs GstMessage and this would introduce circular
- * header includes. And forward declarations of typedefs
- * are unfortunately not possible. The implementation of
- * these functions is in gstevent.c.
- */
-GstEvent*       gst_event_new_sink_message      (GstMessage *msg);
-void            gst_event_parse_sink_message    (GstEvent *event, GstMessage **msg);
+gboolean      gst_util_fraction_multiply        (gint a_n, gint a_d, gint b_n, gint b_d,
+                                                 gint *res_n, gint *res_d);
+gboolean      gst_util_fraction_add             (gint a_n, gint a_d, gint b_n, gint b_d,
+                                                 gint *res_n, gint *res_d);
+gint          gst_util_fraction_compare         (gint a_n, gint a_d, gint b_n, gint b_d);
 
 
 G_END_DECLS
index bf9bb13..1b91ee6 100644 (file)
@@ -296,6 +296,58 @@ gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
   return NULL;
 }
 
+static gboolean
+gst_value_list_or_array_get_basic_type (const GValue * value, GType * type)
+{
+  if (GST_VALUE_HOLDS_LIST (value)) {
+    if (VALUE_LIST_SIZE (value) == 0)
+      return FALSE;
+    return gst_value_list_or_array_get_basic_type (VALUE_LIST_GET_VALUE (value,
+            0), type);
+  }
+  if (GST_VALUE_HOLDS_ARRAY (value)) {
+    const GArray *array = (const GArray *) value->data[0].v_pointer;
+    if (array->len == 0)
+      return FALSE;
+    return gst_value_list_or_array_get_basic_type (&g_array_index (array,
+            GValue, 0), type);
+  }
+  *type = G_VALUE_TYPE (value);
+  return TRUE;
+}
+
+#define IS_RANGE_COMPAT(type1,type2,t1,t2) \
+  (((t1) == (type1) && (t2) == (type2)) || ((t2) == (type1) && (t1) == (type2)))
+
+static gboolean
+gst_value_list_or_array_are_compatible (const GValue * value1,
+    const GValue * value2)
+{
+  GType basic_type1, basic_type2;
+
+  /* empty or same type is OK */
+  if (!gst_value_list_or_array_get_basic_type (value1, &basic_type1) ||
+      !gst_value_list_or_array_get_basic_type (value2, &basic_type2) ||
+      basic_type1 == basic_type2)
+    return TRUE;
+
+  /* ranges are distinct types for each bound type... */
+  if (IS_RANGE_COMPAT (G_TYPE_INT, GST_TYPE_INT_RANGE, basic_type1,
+          basic_type2))
+    return TRUE;
+  if (IS_RANGE_COMPAT (G_TYPE_INT64, GST_TYPE_INT64_RANGE, basic_type1,
+          basic_type2))
+    return TRUE;
+  if (IS_RANGE_COMPAT (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, basic_type1,
+          basic_type2))
+    return TRUE;
+  if (IS_RANGE_COMPAT (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, basic_type1,
+          basic_type2))
+    return TRUE;
+
+  return FALSE;
+}
+
 /**
  * gst_value_list_append_value:
  * @value: a #GValue of type #GST_TYPE_LIST
@@ -310,6 +362,8 @@ gst_value_list_append_value (GValue * value, const GValue * append_value)
 
   g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
   g_return_if_fail (G_IS_VALUE (append_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          append_value));
 
   gst_value_init_and_copy (&val, append_value);
   g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
@@ -329,6 +383,8 @@ gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
 
   g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
   g_return_if_fail (G_IS_VALUE (prepend_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          prepend_value));
 
   gst_value_init_and_copy (&val, prepend_value);
   g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
@@ -355,6 +411,7 @@ gst_value_list_concat (GValue * dest, const GValue * value1,
   g_return_if_fail (G_VALUE_TYPE (dest) == 0);
   g_return_if_fail (G_IS_VALUE (value1));
   g_return_if_fail (G_IS_VALUE (value2));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
 
   value1_length =
       (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
@@ -412,6 +469,7 @@ gst_value_list_merge (GValue * dest, const GValue * value1,
   g_return_if_fail (G_VALUE_TYPE (dest) == 0);
   g_return_if_fail (G_IS_VALUE (value1));
   g_return_if_fail (G_IS_VALUE (value2));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
 
   value1_length =
       (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
@@ -537,6 +595,8 @@ gst_value_array_append_value (GValue * value, const GValue * append_value)
 
   g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
   g_return_if_fail (G_IS_VALUE (append_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          append_value));
 
   gst_value_init_and_copy (&val, append_value);
   g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
@@ -556,6 +616,8 @@ gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
 
   g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
   g_return_if_fail (G_IS_VALUE (prepend_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          prepend_value));
 
   gst_value_init_and_copy (&val, prepend_value);
   g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
@@ -714,182 +776,58 @@ gst_value_deserialize_array (GValue * dest, const gchar * s)
   return FALSE;
 }
 
-/**********
- * fourcc *
- **********/
-
-static void
-gst_value_init_fourcc (GValue * value)
-{
-  value->data[0].v_int = 0;
-}
-
-static void
-gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
-{
-  dest_value->data[0].v_int = src_value->data[0].v_int;
-}
-
-static gchar *
-gst_value_collect_fourcc (GValue * value, guint n_collect_values,
-    GTypeCValue * collect_values, guint collect_flags)
-{
-  value->data[0].v_int = collect_values[0].v_int;
-
-  return NULL;
-}
-
-static gchar *
-gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
-    GTypeCValue * collect_values, guint collect_flags)
-{
-  guint32 *fourcc_p = collect_values[0].v_pointer;
-
-  if (!fourcc_p)
-    return g_strdup_printf ("value location for `%s' passed as NULL",
-        G_VALUE_TYPE_NAME (value));
-
-  *fourcc_p = value->data[0].v_int;
-
-  return NULL;
-}
-
-/**
- * gst_value_set_fourcc:
- * @value: a GValue initialized to #GST_TYPE_FOURCC
- * @fourcc: the #guint32 fourcc to set
- *
- * Sets @value to @fourcc.
- */
-void
-gst_value_set_fourcc (GValue * value, guint32 fourcc)
-{
-  g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
-
-  value->data[0].v_int = fourcc;
-}
-
-/**
- * gst_value_get_fourcc:
- * @value: a GValue initialized to #GST_TYPE_FOURCC
- *
- * Gets the #guint32 fourcc contained in @value.
+/*************
+ * int range *
  *
- * Returns: the #guint32 fourcc contained in @value.
- */
-guint32
-gst_value_get_fourcc (const GValue * value)
-{
-  g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
+ * Values in the range are defined as any value greater or equal
+ * to min*step, AND lesser or equal to max*step.
+ * For step == 1, this falls back to the traditional range semantics.
+ *************/
 
-  return value->data[0].v_int;
-}
+#define INT_RANGE_MIN(v) (((gint *)((v)->data[0].v_pointer))[0])
+#define INT_RANGE_MAX(v) (((gint *)((v)->data[0].v_pointer))[1])
+#define INT_RANGE_STEP(v) (((gint *)((v)->data[0].v_pointer))[2])
 
 static void
-gst_value_transform_fourcc_string (const GValue * src_value,
-    GValue * dest_value)
-{
-  guint32 fourcc = src_value->data[0].v_int;
-  gchar fourcc_char[4];
-
-  fourcc_char[0] = (fourcc >> 0) & 0xff;
-  fourcc_char[1] = (fourcc >> 8) & 0xff;
-  fourcc_char[2] = (fourcc >> 16) & 0xff;
-  fourcc_char[3] = (fourcc >> 24) & 0xff;
-
-  if ((g_ascii_isalnum (fourcc_char[0]) || fourcc_char[0] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[1]) || fourcc_char[1] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[2]) || fourcc_char[2] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[3]) || fourcc_char[3] == ' ')) {
-    dest_value->data[0].v_pointer =
-        g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-  } else {
-    dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
-  }
-}
-
-static gint
-gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
-{
-  if (value2->data[0].v_int == value1->data[0].v_int)
-    return GST_VALUE_EQUAL;
-  return GST_VALUE_UNORDERED;
-}
-
-static gchar *
-gst_value_serialize_fourcc (const GValue * value)
-{
-  guint32 fourcc = value->data[0].v_int;
-  gchar fourcc_char[4];
-
-  fourcc_char[0] = (fourcc >> 0) & 0xff;
-  fourcc_char[1] = (fourcc >> 8) & 0xff;
-  fourcc_char[2] = (fourcc >> 16) & 0xff;
-  fourcc_char[3] = (fourcc >> 24) & 0xff;
-
-  if ((g_ascii_isalnum (fourcc_char[0]) || fourcc_char[0] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[1]) || fourcc_char[1] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[2]) || fourcc_char[2] == ' ') &&
-      (g_ascii_isalnum (fourcc_char[3]) || fourcc_char[3] == ' ')) {
-    return g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-  } else {
-    return g_strdup_printf ("0x%08x", fourcc);
-  }
-}
-
-static gboolean
-gst_value_deserialize_fourcc (GValue * dest, const gchar * s)
+gst_value_init_int_range (GValue * value)
 {
-  gboolean ret = FALSE;
-  guint32 fourcc = 0;
-  gchar *end;
-  gint l = strlen (s);
-
-  if (l == 4) {
-    fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
-    ret = TRUE;
-  } else if (l == 3) {
-    fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], ' ');
-    ret = TRUE;
-  } else if (l == 2) {
-    fourcc = GST_MAKE_FOURCC (s[0], s[1], ' ', ' ');
-    ret = TRUE;
-  } else if (l == 1) {
-    fourcc = GST_MAKE_FOURCC (s[0], ' ', ' ', ' ');
-    ret = TRUE;
-  } else if (g_ascii_isdigit (*s)) {
-    fourcc = strtoul (s, &end, 0);
-    if (*end == 0) {
-      ret = TRUE;
-    }
-  }
-  gst_value_set_fourcc (dest, fourcc);
-
-  return ret;
+  gint *vals = g_slice_alloc0 (3 * sizeof (gint));
+  value->data[0].v_pointer = vals;
+  INT_RANGE_MIN (value) = 0;
+  INT_RANGE_MAX (value) = 0;
+  INT_RANGE_STEP (value) = 1;
 }
 
-/*************
- * int range *
- *************/
-
 static void
-gst_value_init_int_range (GValue * value)
+gst_value_free_int_range (GValue * value)
 {
-  value->data[0].v_int = 0;
-  value->data[1].v_int = 0;
+  g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
+  g_slice_free1 (3 * sizeof (gint), value->data[0].v_pointer);
+  value->data[0].v_pointer = NULL;
 }
 
 static void
 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
 {
-  dest_value->data[0].v_int = src_value->data[0].v_int;
-  dest_value->data[1].v_int = src_value->data[1].v_int;
+  gint *vals = (gint *) dest_value->data[0].v_pointer;
+  gint *src_vals = (gint *) src_value->data[0].v_pointer;
+
+  if (vals == NULL) {
+    gst_value_init_int_range (dest_value);
+  }
+  if (src_vals != NULL) {
+    INT_RANGE_MIN (dest_value) = INT_RANGE_MIN (src_value);
+    INT_RANGE_MAX (dest_value) = INT_RANGE_MAX (src_value);
+    INT_RANGE_STEP (dest_value) = INT_RANGE_STEP (src_value);
+  }
 }
 
 static gchar *
 gst_value_collect_int_range (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
+  gint *vals = value->data[0].v_pointer;
+
   if (n_collect_values != 2)
     return g_strdup_printf ("not enough value locations for `%s' passed",
         G_VALUE_TYPE_NAME (value));
@@ -897,8 +835,12 @@ gst_value_collect_int_range (GValue * value, guint n_collect_values,
     return g_strdup_printf ("range start is not smaller than end for `%s'",
         G_VALUE_TYPE_NAME (value));
 
-  value->data[0].v_int = collect_values[0].v_int;
-  value->data[1].v_int = collect_values[1].v_int;
+  if (vals == NULL) {
+    gst_value_init_int_range (value);
+  }
+
+  gst_value_set_int_range_step (value, collect_values[0].v_int,
+      collect_values[1].v_int, 1);
 
   return NULL;
 }
@@ -909,6 +851,8 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
 {
   guint32 *int_range_start = collect_values[0].v_pointer;
   guint32 *int_range_end = collect_values[1].v_pointer;
+  guint32 *int_range_step = collect_values[2].v_pointer;
+  gint *vals = (gint *) value->data[0].v_pointer;
 
   if (!int_range_start)
     return g_strdup_printf ("start value location for `%s' passed as NULL",
@@ -916,29 +860,57 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
   if (!int_range_end)
     return g_strdup_printf ("end value location for `%s' passed as NULL",
         G_VALUE_TYPE_NAME (value));
+  if (!int_range_step)
+    return g_strdup_printf ("step value location for `%s' passed as NULL",
+        G_VALUE_TYPE_NAME (value));
+
+  if (G_UNLIKELY (vals == NULL)) {
+    return g_strdup_printf ("Uninitialised `%s' passed",
+        G_VALUE_TYPE_NAME (value));
+  }
 
-  *int_range_start = value->data[0].v_int;
-  *int_range_end = value->data[1].v_int;
+  *int_range_start = INT_RANGE_MIN (value);
+  *int_range_end = INT_RANGE_MAX (value);
+  *int_range_step = INT_RANGE_STEP (value);
 
   return NULL;
 }
 
 /**
- * gst_value_set_int_range:
+ * gst_value_set_int_range_step:
  * @value: a GValue initialized to GST_TYPE_INT_RANGE
  * @start: the start of the range
  * @end: the end of the range
+ * @step: the step of the range
  *
- * Sets @value to the range specified by @start and @end.
+ * Sets @value to the range specified by @start, @end and @step.
  */
 void
-gst_value_set_int_range (GValue * value, gint start, gint end)
+gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step)
 {
   g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
   g_return_if_fail (start < end);
+  g_return_if_fail (step > 0);
+  g_return_if_fail (start % step == 0);
+  g_return_if_fail (end % step == 0);
+
+  INT_RANGE_MIN (value) = start / step;
+  INT_RANGE_MAX (value) = end / step;
+  INT_RANGE_STEP (value) = step;
+}
 
-  value->data[0].v_int = start;
-  value->data[1].v_int = end;
+/**
+ * gst_value_set_int_range:
+ * @value: a GValue initialized to GST_TYPE_INT_RANGE
+ * @start: the start of the range
+ * @end: the end of the range
+ *
+ * Sets @value to the range specified by @start and @end.
+ */
+void
+gst_value_set_int_range (GValue * value, gint start, gint end)
+{
+  gst_value_set_int_range_step (value, start, end, 1);
 }
 
 /**
@@ -954,7 +926,7 @@ gst_value_get_int_range_min (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
 
-  return value->data[0].v_int;
+  return INT_RANGE_MIN (value) * INT_RANGE_STEP (value);
 }
 
 /**
@@ -970,31 +942,81 @@ gst_value_get_int_range_max (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
 
-  return value->data[1].v_int;
+  return INT_RANGE_MAX (value) * INT_RANGE_STEP (value);
+}
+
+/**
+ * gst_value_get_int_range_step:
+ * @value: a GValue initialized to GST_TYPE_INT_RANGE
+ *
+ * Gets the step of the range specified by @value.
+ *
+ * Returns: the step of the range
+ */
+gint
+gst_value_get_int_range_step (const GValue * value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
+
+  return INT_RANGE_STEP (value);
 }
 
 static void
 gst_value_transform_int_range_string (const GValue * src_value,
     GValue * dest_value)
 {
-  dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
-      (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
+  if (INT_RANGE_STEP (src_value) == 1)
+    dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
+        INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value));
+  else
+    dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]",
+        INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value),
+        INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value),
+        INT_RANGE_STEP (src_value));
 }
 
 static gint
 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
 {
-  if (value2->data[0].v_int == value1->data[0].v_int &&
-      value2->data[1].v_int == value1->data[1].v_int)
+  /* calculate the number of values in each range */
+  gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1;
+  gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1;
+
+  /* they must be equal */
+  if (n1 != n2)
+    return GST_VALUE_UNORDERED;
+
+  /* if empty, equal */
+  if (n1 == 0)
     return GST_VALUE_EQUAL;
-  return GST_VALUE_UNORDERED;
+
+  /* if more than one value, then it is only equal if the step is equal
+     and bounds lie on the same value */
+  if (n1 > 1) {
+    if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
+        INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
+        INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2)) {
+      return GST_VALUE_EQUAL;
+    }
+    return GST_VALUE_UNORDERED;
+  } else {
+    /* if just one, only if the value is equal */
+    if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2))
+      return GST_VALUE_EQUAL;
+    return GST_VALUE_UNORDERED;
+  }
 }
 
 static gchar *
 gst_value_serialize_int_range (const GValue * value)
 {
-  return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
-      value->data[1].v_int);
+  if (INT_RANGE_STEP (value) == 1)
+    return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value),
+        INT_RANGE_MAX (value));
+  else
+    return g_strdup_printf ("[ %d, %d, %d ]",
+        INT_RANGE_MIN (value) * INT_RANGE_STEP (value),
+        INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value));
 }
 
 static gboolean
@@ -1006,26 +1028,57 @@ gst_value_deserialize_int_range (GValue * dest, const gchar * s)
 
 /***************
  * int64 range *
+ *
+ * Values in the range are defined as any value greater or equal
+ * to min*step, AND lesser or equal to max*step.
+ * For step == 1, this falls back to the traditional range semantics.
  ***************/
 
+#define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0])
+#define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1])
+#define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2])
+
 static void
 gst_value_init_int64_range (GValue * value)
 {
-  value->data[0].v_int64 = 0;
-  value->data[1].v_int64 = 0;
+  gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64));
+  value->data[0].v_pointer = vals;
+  INT64_RANGE_MIN (value) = 0;
+  INT64_RANGE_MAX (value) = 0;
+  INT64_RANGE_STEP (value) = 1;
+}
+
+static void
+gst_value_free_int64_range (GValue * value)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
+  g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer);
+  value->data[0].v_pointer = NULL;
 }
 
 static void
 gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value)
 {
-  dest_value->data[0].v_int64 = src_value->data[0].v_int64;
-  dest_value->data[1].v_int64 = src_value->data[1].v_int64;
+  gint64 *vals = (gint64 *) dest_value->data[0].v_pointer;
+  gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer;
+
+  if (vals == NULL) {
+    gst_value_init_int64_range (dest_value);
+    vals = (gint64 *) dest_value->data[0].v_pointer;
+  }
+  if (src_vals != NULL) {
+    INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value);
+    INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value);
+    INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value);
+  }
 }
 
 static gchar *
 gst_value_collect_int64_range (GValue * value, guint n_collect_values,
     GTypeCValue * collect_values, guint collect_flags)
 {
+  gint64 *vals = value->data[0].v_pointer;
+
   if (n_collect_values != 2)
     return g_strdup_printf ("not enough value locations for `%s' passed",
         G_VALUE_TYPE_NAME (value));
@@ -1033,8 +1086,12 @@ gst_value_collect_int64_range (GValue * value, guint n_collect_values,
     return g_strdup_printf ("range start is not smaller than end for `%s'",
         G_VALUE_TYPE_NAME (value));
 
-  value->data[0].v_int64 = collect_values[0].v_int64;
-  value->data[1].v_int64 = collect_values[1].v_int64;
+  if (vals == NULL) {
+    gst_value_init_int64_range (value);
+  }
+
+  gst_value_set_int64_range_step (value, collect_values[0].v_int64,
+      collect_values[1].v_int64, 1);
 
   return NULL;
 }
@@ -1045,6 +1102,8 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
 {
   guint64 *int_range_start = collect_values[0].v_pointer;
   guint64 *int_range_end = collect_values[1].v_pointer;
+  guint64 *int_range_step = collect_values[2].v_pointer;
+  gint64 *vals = (gint64 *) value->data[0].v_pointer;
 
   if (!int_range_start)
     return g_strdup_printf ("start value location for `%s' passed as NULL",
@@ -1052,14 +1111,49 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
   if (!int_range_end)
     return g_strdup_printf ("end value location for `%s' passed as NULL",
         G_VALUE_TYPE_NAME (value));
+  if (!int_range_step)
+    return g_strdup_printf ("step value location for `%s' passed as NULL",
+        G_VALUE_TYPE_NAME (value));
+
+  if (G_UNLIKELY (vals == NULL)) {
+    return g_strdup_printf ("Uninitialised `%s' passed",
+        G_VALUE_TYPE_NAME (value));
+  }
 
-  *int_range_start = value->data[0].v_int64;
-  *int_range_end = value->data[1].v_int64;
+  *int_range_start = INT64_RANGE_MIN (value);
+  *int_range_end = INT64_RANGE_MAX (value);
+  *int_range_step = INT64_RANGE_STEP (value);
 
   return NULL;
 }
 
 /**
+ * gst_value_set_int64_range_step:
+ * @value: a GValue initialized to GST_TYPE_INT64_RANGE
+ * @start: the start of the range
+ * @end: the end of the range
+ * @step: the step of the range
+ *
+ * Sets @value to the range specified by @start, @end and @step.
+ *
+ * Since: 0.11.0
+ */
+void
+gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end,
+    gint64 step)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
+  g_return_if_fail (start < end);
+  g_return_if_fail (step > 0);
+  g_return_if_fail (start % step == 0);
+  g_return_if_fail (end % step == 0);
+
+  INT64_RANGE_MIN (value) = start / step;
+  INT64_RANGE_MAX (value) = end / step;
+  INT64_RANGE_STEP (value) = step;
+}
+
+/**
  * gst_value_set_int64_range:
  * @value: a GValue initialized to GST_TYPE_INT64_RANGE
  * @start: the start of the range
@@ -1072,11 +1166,7 @@ gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
 void
 gst_value_set_int64_range (GValue * value, gint64 start, gint64 end)
 {
-  g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
-  g_return_if_fail (start < end);
-
-  value->data[0].v_int64 = start;
-  value->data[1].v_int64 = end;
+  gst_value_set_int64_range_step (value, start, end, 1);
 }
 
 /**
@@ -1094,7 +1184,7 @@ gst_value_get_int64_range_min (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
 
-  return value->data[0].v_int64;
+  return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value);
 }
 
 /**
@@ -1112,32 +1202,88 @@ gst_value_get_int64_range_max (const GValue * value)
 {
   g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
 
-  return value->data[1].v_int64;
+  return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value);
+}
+
+/**
+ * gst_value_get_int64_range_step:
+ * @value: a GValue initialized to GST_TYPE_INT64_RANGE
+ *
+ * Gets the step of the range specified by @value.
+ *
+ * Returns: the step of the range
+ *
+ * Since: 0.11.0
+ */
+gint64
+gst_value_get_int64_range_step (const GValue * value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
+
+  return INT64_RANGE_STEP (value);
 }
 
 static void
 gst_value_transform_int64_range_string (const GValue * src_value,
     GValue * dest_value)
 {
-  dest_value->data[0].v_pointer =
-      g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]",
-      src_value->data[0].v_int64, src_value->data[1].v_int64);
+  if (INT64_RANGE_STEP (src_value) == 1)
+    dest_value->data[0].v_pointer =
+        g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]",
+        INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value));
+  else
+    dest_value->data[0].v_pointer =
+        g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT
+        ",%" G_GINT64_FORMAT "]",
+        INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value),
+        INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value),
+        INT64_RANGE_STEP (src_value));
 }
 
 static gint
 gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
 {
-  if (value2->data[0].v_int64 == value1->data[0].v_int64 &&
-      value2->data[1].v_int64 == value1->data[1].v_int64)
+  /* calculate the number of values in each range */
+  gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1;
+  gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1;
+
+  /* they must be equal */
+  if (n1 != n2)
+    return GST_VALUE_UNORDERED;
+
+  /* if empty, equal */
+  if (n1 == 0)
     return GST_VALUE_EQUAL;
-  return GST_VALUE_UNORDERED;
+
+  /* if more than one value, then it is only equal if the step is equal
+     and bounds lie on the same value */
+  if (n1 > 1) {
+    if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
+        INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
+        INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2)) {
+      return GST_VALUE_EQUAL;
+    }
+    return GST_VALUE_UNORDERED;
+  } else {
+    /* if just one, only if the value is equal */
+    if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2))
+      return GST_VALUE_EQUAL;
+    return GST_VALUE_UNORDERED;
+  }
 }
 
 static gchar *
 gst_value_serialize_int64_range (const GValue * value)
 {
-  return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]",
-      value->data[0].v_int64, value->data[1].v_int64);
+  if (INT64_RANGE_STEP (value) == 1)
+    return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]",
+        INT64_RANGE_MIN (value), INT64_RANGE_MAX (value));
+  else
+    return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %"
+        G_GINT64_FORMAT " ]",
+        INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value),
+        INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value),
+        INT64_RANGE_STEP (value));
 }
 
 static gboolean
@@ -1722,20 +1868,33 @@ gst_value_deserialize_structure (GValue * dest, const gchar * s)
 static gint
 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
 {
-  GstBuffer *buf1 = GST_BUFFER (gst_value_get_mini_object (value1));
-  GstBuffer *buf2 = GST_BUFFER (gst_value_get_mini_object (value2));
+  GstBuffer *buf1 = gst_value_get_buffer (value1);
+  GstBuffer *buf2 = gst_value_get_buffer (value2);
+  gsize size1, size2;
+  gpointer data1, data2;
+  gint result = GST_VALUE_UNORDERED;
+
+  size1 = gst_buffer_get_size (buf1);
+  size2 = gst_buffer_get_size (buf2);
 
-  if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2))
+  if (size1 != size2)
     return GST_VALUE_UNORDERED;
-  if (GST_BUFFER_SIZE (buf1) == 0)
-    return GST_VALUE_EQUAL;
-  g_assert (GST_BUFFER_DATA (buf1));
-  g_assert (GST_BUFFER_DATA (buf2));
-  if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2),
-          GST_BUFFER_SIZE (buf1)) == 0)
+
+  if (size1 == 0)
     return GST_VALUE_EQUAL;
 
-  return GST_VALUE_UNORDERED;
+  data1 = gst_buffer_map (buf1, &size1, NULL, GST_MAP_READ);
+  data2 = gst_buffer_map (buf2, &size2, NULL, GST_MAP_READ);
+  g_assert (data1);
+  g_assert (data2);
+
+  if (memcmp (data1, data2, size1) == 0)
+    result = GST_VALUE_EQUAL;
+
+  gst_buffer_unmap (buf2, data2, size2);
+  gst_buffer_unmap (buf1, data1, size1);
+
+  return result;
 }
 
 static gchar *
@@ -1743,7 +1902,7 @@ gst_value_serialize_buffer (const GValue * value)
 {
   guint8 *data;
   gint i;
-  gint size;
+  gsize size;
   gchar *string;
   GstBuffer *buffer;
 
@@ -1751,8 +1910,7 @@ gst_value_serialize_buffer (const GValue * value)
   if (buffer == NULL)
     return NULL;
 
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 
   string = g_malloc (size * 2 + 1);
   for (i = 0; i < size; i++) {
@@ -1760,6 +1918,8 @@ gst_value_serialize_buffer (const GValue * value)
   }
   string[size * 2] = 0;
 
+  gst_buffer_unmap (buffer, data, size);
+
   return string;
 }
 
@@ -1771,13 +1931,15 @@ gst_value_deserialize_buffer (GValue * dest, const gchar * s)
   gchar ts[3];
   guint8 *data;
   gint i;
+  gsize size;
 
   len = strlen (s);
   if (len & 1)
     goto wrong_length;
 
-  buffer = gst_buffer_new_and_alloc (len / 2);
-  data = GST_BUFFER_DATA (buffer);
+  buffer = gst_buffer_new_allocate (NULL, len / 2, 0);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_WRITE);
+
   for (i = 0; i < len / 2; i++) {
     if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
       goto wrong_char;
@@ -1788,6 +1950,7 @@ gst_value_deserialize_buffer (GValue * dest, const gchar * s)
 
     data[i] = (guint8) strtoul (ts, NULL, 16);
   }
+  gst_buffer_unmap (buffer, data, size);
 
   gst_value_take_buffer (dest, buffer);
 
@@ -1801,6 +1964,7 @@ wrong_length:
 wrong_char:
   {
     gst_buffer_unref (buffer);
+    gst_buffer_unmap (buffer, data, size);
     return FALSE;
   }
 }
@@ -2400,9 +2564,12 @@ gst_value_serialize_enum (const GValue * value)
 }
 
 static gint
-gst_value_deserialize_enum_iter_cmp (const GstFormatDefinition * format_def,
+gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value,
     const gchar * s)
 {
+  const GstFormatDefinition *format_def =
+      g_value_get_pointer (format_def_value);
+
   if (g_ascii_strcasecmp (s, format_def->nick) == 0)
     return 0;
 
@@ -2430,16 +2597,21 @@ gst_value_deserialize_enum (GValue * dest, const gchar * s)
 
   /* might be one of the custom formats registered later */
   if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
+    GValue res = { 0, };
     const GstFormatDefinition *format_def;
     GstIterator *iter;
+    gboolean found;
 
     iter = gst_format_iterate_definitions ();
 
-    format_def = gst_iterator_find_custom (iter,
-        (GCompareFunc) gst_value_deserialize_enum_iter_cmp, (gpointer) s);
+    found = gst_iterator_find_custom (iter,
+        (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
 
+    g_return_val_if_fail (found, FALSE);
+    format_def = g_value_get_pointer (&res);
     g_return_val_if_fail (format_def != NULL, FALSE);
     g_value_set_enum (dest, (gint) format_def->value);
+    g_value_unset (&res);
     gst_iterator_free (iter);
     return TRUE;
   }
@@ -2557,6 +2729,114 @@ gst_value_deserialize_flags (GValue * dest, const gchar * s)
   return TRUE;
 }
 
+/****************
+ * subset *
+ ****************/
+
+static gboolean
+gst_value_is_subset_int_range_int_range (const GValue * value1,
+    const GValue * value2)
+{
+  gint gcd;
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE);
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE);
+
+  if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) <
+      INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2))
+    return FALSE;
+  if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) >
+      INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2))
+    return FALSE;
+
+  if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) {
+    if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) %
+        INT_RANGE_STEP (value1))
+      return FALSE;
+    return TRUE;
+  }
+
+  gcd =
+      gst_util_greatest_common_divisor (INT_RANGE_STEP (value1),
+      INT_RANGE_STEP (value2));
+  if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2)))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_is_subset_int64_range_int64_range (const GValue * value1,
+    const GValue * value2)
+{
+  gint64 gcd;
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE);
+  g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE);
+
+  if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2))
+    return FALSE;
+  if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2))
+    return FALSE;
+
+  if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) {
+    if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) %
+        INT64_RANGE_STEP (value1))
+      return FALSE;
+    return TRUE;
+  }
+
+  gcd =
+      gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1),
+      INT64_RANGE_STEP (value2));
+  if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2)))
+    return FALSE;
+
+  return TRUE;
+}
+
+gboolean
+gst_value_is_subset (const GValue * value1, const GValue * value2)
+{
+  /* special case for int/int64 ranges, since we cannot compute
+     the difference for those when they have different steps,
+     and it's actually a lot simpler to compute whether a range
+     is a subset of another. */
+  if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) {
+    return gst_value_is_subset_int_range_int_range (value1, value2);
+  } else if (GST_VALUE_HOLDS_INT64_RANGE (value1)
+      && GST_VALUE_HOLDS_INT64_RANGE (value2)) {
+    return gst_value_is_subset_int64_range_int64_range (value1, value2);
+  }
+
+  /*
+   * 1 - [1,2] = empty
+   * -> !subset
+   *
+   * [1,2] - 1 = 2
+   *  -> 1 - [1,2] = empty
+   *  -> subset
+   *
+   * [1,3] - [1,2] = 3
+   * -> [1,2] - [1,3] = empty
+   * -> subset
+   *
+   * {1,2} - {1,3} = 2
+   * -> {1,3} - {1,2} = 3
+   * -> !subset
+   *
+   *  First caps subtraction needs to return a non-empty set, second
+   *  subtractions needs to give en empty set.
+   *  Both substractions are switched below, as it's faster that way.
+   */
+  if (!gst_value_subtract (NULL, value1, value2)) {
+    if (gst_value_subtract (NULL, value2, value1)) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
 /*********
  * union *
  *********/
@@ -2565,11 +2845,33 @@ static gboolean
 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
     const GValue * src2)
 {
-  if (src2->data[0].v_int <= src1->data[0].v_int &&
-      src2->data[1].v_int >= src1->data[0].v_int) {
-    gst_value_init_and_copy (dest, src2);
+  gint v = src1->data[0].v_int;
+
+  /* check if it's already in the range */
+  if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v &&
+      INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v &&
+      v % INT_RANGE_STEP (src2) == 0) {
+    if (dest)
+      gst_value_init_and_copy (dest, src2);
+    return TRUE;
+  }
+
+  /* check if it extends the range */
+  if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) {
+    if (dest) {
+      gst_value_init_and_copy (dest, src2);
+      --INT_RANGE_MIN (src2);
+    }
+    return TRUE;
+  }
+  if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) {
+    if (dest) {
+      gst_value_init_and_copy (dest, src2);
+      ++INT_RANGE_MAX (src2);
+    }
     return TRUE;
   }
+
   return FALSE;
 }
 
@@ -2577,20 +2879,77 @@ static gboolean
 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
     const GValue * src2)
 {
-  gint min;
-  gint max;
+  /* We can union in several special cases:
+     1 - one is a subset of another
+     2 - same step and not disjoint
+     3 - different step, at least one with one value which matches a 'next' or 'previous'
+     - anything else ?
+   */
+
+  /* 1 - subset */
+  if (gst_value_is_subset_int_range_int_range (src1, src2)) {
+    if (dest)
+      gst_value_init_and_copy (dest, src2);
+    return TRUE;
+  }
+  if (gst_value_is_subset_int_range_int_range (src2, src1)) {
+    if (dest)
+      gst_value_init_and_copy (dest, src1);
+    return TRUE;
+  }
 
-  min = MAX (src1->data[0].v_int, src2->data[0].v_int);
-  max = MIN (src1->data[1].v_int, src2->data[1].v_int);
+  /* 2 - same step and not disjoint */
+  if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) {
+    if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 &&
+            INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) ||
+        (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 &&
+            INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) {
+      if (dest) {
+        gint step = INT_RANGE_STEP (src1);
+        gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2));
+        gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2));
+        g_value_init (dest, GST_TYPE_INT_RANGE);
+        gst_value_set_int_range_step (dest, min, max, step);
+      }
+      return TRUE;
+    }
+  }
 
-  if (min <= max) {
-    g_value_init (dest, GST_TYPE_INT_RANGE);
-    gst_value_set_int_range (dest,
-        MIN (src1->data[0].v_int, src2->data[0].v_int),
-        MAX (src1->data[1].v_int, src2->data[1].v_int));
-    return TRUE;
+  /* 3 - single value matches next or previous */
+  if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) {
+    gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1;
+    gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1;
+    if (n1 == 1 || n2 == 1) {
+      const GValue *range_value = NULL;
+      gint scalar = 0;
+      if (n1 == 1) {
+        range_value = src2;
+        scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1);
+      } else if (n2 == 1) {
+        range_value = src1;
+        scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2);
+      }
+
+      if (scalar ==
+          (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) {
+        if (dest) {
+          gst_value_init_and_copy (dest, range_value);
+          --INT_RANGE_MIN (range_value);
+        }
+        return TRUE;
+      } else if (scalar ==
+          (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) {
+        if (dest) {
+          gst_value_init_and_copy (dest, range_value);
+          ++INT_RANGE_MIN (range_value);
+        }
+        return TRUE;
+      }
+    }
   }
 
+  /* If we get there, we did not find a way to make a union that can be
+     represented with our simplistic model. */
   return FALSE;
 }
 
@@ -2602,8 +2961,9 @@ static gboolean
 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
     const GValue * src2)
 {
-  if (src2->data[0].v_int <= src1->data[0].v_int &&
-      src2->data[1].v_int >= src1->data[0].v_int) {
+  if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int &&
+      INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int &&
+      src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) {
     if (dest)
       gst_value_init_and_copy (dest, src1);
     return TRUE;
@@ -2618,14 +2978,29 @@ gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
 {
   gint min;
   gint max;
+  gint step;
 
-  min = MAX (src1->data[0].v_int, src2->data[0].v_int);
-  max = MIN (src1->data[1].v_int, src2->data[1].v_int);
+  step =
+      INT_RANGE_STEP (src1) /
+      gst_util_greatest_common_divisor (INT_RANGE_STEP (src1),
+      INT_RANGE_STEP (src2));
+  if (G_MAXINT32 / INT_RANGE_STEP (src2) < step)
+    return FALSE;
+  step *= INT_RANGE_STEP (src2);
+
+  min =
+      MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1),
+      INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
+  min = (min + step - 1) / step * step;
+  max =
+      MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1),
+      INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
+  max = max / step * step;
 
   if (min < max) {
     if (dest) {
       g_value_init (dest, GST_TYPE_INT_RANGE);
-      gst_value_set_int_range (dest, min, max);
+      gst_value_set_int_range_step (dest, min, max, step);
     }
     return TRUE;
   }
@@ -2644,8 +3019,9 @@ static gboolean
 gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1,
     const GValue * src2)
 {
-  if (src2->data[0].v_int64 <= src1->data[0].v_int64 &&
-      src2->data[1].v_int64 >= src1->data[0].v_int64) {
+  if (INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2) <= src1->data[0].v_int &&
+      INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2) >= src1->data[0].v_int &&
+      src1->data[0].v_int % INT64_RANGE_STEP (src2) == 0) {
     if (dest)
       gst_value_init_and_copy (dest, src1);
     return TRUE;
@@ -2660,14 +3036,29 @@ gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1,
 {
   gint64 min;
   gint64 max;
+  gint64 step;
+
+  step =
+      INT64_RANGE_STEP (src1) /
+      gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1),
+      INT64_RANGE_STEP (src2));
+  if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step)
+    return FALSE;
+  step *= INT64_RANGE_STEP (src2);
 
-  min = MAX (src1->data[0].v_int64, src2->data[0].v_int64);
-  max = MIN (src1->data[1].v_int64, src2->data[1].v_int64);
+  min =
+      MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1),
+      INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2));
+  min = (min + step - 1) / step * step;
+  max =
+      MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1),
+      INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2));
+  max = max / step * step;
 
   if (min < max) {
     if (dest) {
       g_value_init (dest, GST_TYPE_INT64_RANGE);
-      gst_value_set_int64_range (dest, min, max);
+      gst_value_set_int64_range_step (dest, min, max, step);
     }
     return TRUE;
   }
@@ -2896,11 +3287,12 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
 {
   gint min = gst_value_get_int_range_min (subtrahend);
   gint max = gst_value_get_int_range_max (subtrahend);
+  gint step = gst_value_get_int_range_step (subtrahend);
   gint val = g_value_get_int (minuend);
 
   /* subtracting a range from an int only works if the int is not in the
    * range */
-  if (val < min || val > max) {
+  if (val < min || val > max || val % step) {
     /* and the result is the int */
     if (dest)
       gst_value_init_and_copy (dest, minuend);
@@ -2913,12 +3305,18 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
  */
 static gboolean
 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
-    gint max2)
+    gint max2, gint step)
 {
   GValue v1 = { 0, };
   GValue v2 = { 0, };
   GValue *pv1, *pv2;            /* yeah, hungarian! */
 
+  g_return_val_if_fail (step > 0, FALSE);
+  g_return_val_if_fail (min1 % step == 0, FALSE);
+  g_return_val_if_fail (max1 % step == 0, FALSE);
+  g_return_val_if_fail (min2 % step == 0, FALSE);
+  g_return_val_if_fail (max2 % step == 0, FALSE);
+
   if (min1 <= max1 && min2 <= max2) {
     pv1 = &v1;
     pv2 = &v2;
@@ -2937,14 +3335,14 @@ gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
 
   if (min1 < max1) {
     g_value_init (pv1, GST_TYPE_INT_RANGE);
-    gst_value_set_int_range (pv1, min1, max1);
+    gst_value_set_int_range_step (pv1, min1, max1, step);
   } else if (min1 == max1) {
     g_value_init (pv1, G_TYPE_INT);
     g_value_set_int (pv1, min1);
   }
   if (min2 < max2) {
     g_value_init (pv2, GST_TYPE_INT_RANGE);
-    gst_value_set_int_range (pv2, min2, max2);
+    gst_value_set_int_range_step (pv2, min2, max2, step);
   } else if (min2 == max2) {
     g_value_init (pv2, G_TYPE_INT);
     g_value_set_int (pv2, min2);
@@ -2964,28 +3362,29 @@ gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
 {
   gint min = gst_value_get_int_range_min (minuend);
   gint max = gst_value_get_int_range_max (minuend);
+  gint step = gst_value_get_int_range_step (minuend);
   gint val = g_value_get_int (subtrahend);
 
   g_return_val_if_fail (min < max, FALSE);
 
   /* value is outside of the range, return range unchanged */
-  if (val < min || val > max) {
+  if (val < min || val > max || val % step) {
     if (dest)
       gst_value_init_and_copy (dest, minuend);
     return TRUE;
   } else {
     /* max must be MAXINT too as val <= max */
-    if (val == G_MAXINT) {
-      max--;
-      val--;
+    if (val >= G_MAXINT - step + 1) {
+      max -= step;
+      val -= step;
     }
     /* min must be MININT too as val >= max */
-    if (val == G_MININT) {
-      min++;
-      val++;
+    if (val <= G_MININT + step - 1) {
+      min += step;
+      val += step;
     }
     if (dest)
-      gst_value_create_new_range (dest, min, val - 1, val + 1, max);
+      gst_value_create_new_range (dest, min, val - step, val + step, max, step);
   }
   return TRUE;
 }
@@ -2996,18 +3395,30 @@ gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
 {
   gint min1 = gst_value_get_int_range_min (minuend);
   gint max1 = gst_value_get_int_range_max (minuend);
+  gint step1 = gst_value_get_int_range_step (minuend);
   gint min2 = gst_value_get_int_range_min (subtrahend);
   gint max2 = gst_value_get_int_range_max (subtrahend);
+  gint step2 = gst_value_get_int_range_step (subtrahend);
+  gint step;
+
+  if (step1 != step2) {
+    /* ENOIMPL */
+    g_assert (FALSE);
+    return FALSE;
+  }
+  step = step1;
 
-  if (max2 == G_MAXINT && min2 == G_MININT) {
+  if (max2 >= max1 && min2 <= min1) {
     return FALSE;
-  } else if (max2 == G_MAXINT) {
-    return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0);
-  } else if (min2 == G_MININT) {
-    return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0);
+  } else if (max2 >= max1) {
+    return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
+        step, 0, step);
+  } else if (min2 <= min1) {
+    return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1,
+        step, 0, step);
   } else {
-    return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
-        MAX (max2 + 1, min1), max1);
+    return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
+        MAX (max2 + step, min1), max1, step);
   }
 }
 
@@ -3017,11 +3428,12 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
 {
   gint64 min = gst_value_get_int64_range_min (subtrahend);
   gint64 max = gst_value_get_int64_range_max (subtrahend);
+  gint64 step = gst_value_get_int64_range_step (subtrahend);
   gint64 val = g_value_get_int64 (minuend);
 
   /* subtracting a range from an int64 only works if the int64 is not in the
    * range */
-  if (val < min || val > max) {
+  if (val < min || val > max || val % step) {
     /* and the result is the int64 */
     if (dest)
       gst_value_init_and_copy (dest, minuend);
@@ -3034,12 +3446,18 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
  */
 static gboolean
 gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
-    gint64 min2, gint64 max2)
+    gint64 min2, gint64 max2, gint64 step)
 {
   GValue v1 = { 0, };
   GValue v2 = { 0, };
   GValue *pv1, *pv2;            /* yeah, hungarian! */
 
+  g_return_val_if_fail (step > 0, FALSE);
+  g_return_val_if_fail (min1 % step == 0, FALSE);
+  g_return_val_if_fail (max1 % step == 0, FALSE);
+  g_return_val_if_fail (min2 % step == 0, FALSE);
+  g_return_val_if_fail (max2 % step == 0, FALSE);
+
   if (min1 <= max1 && min2 <= max2) {
     pv1 = &v1;
     pv2 = &v2;
@@ -3058,14 +3476,14 @@ gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
 
   if (min1 < max1) {
     g_value_init (pv1, GST_TYPE_INT64_RANGE);
-    gst_value_set_int64_range (pv1, min1, max1);
+    gst_value_set_int64_range_step (pv1, min1, max1, step);
   } else if (min1 == max1) {
     g_value_init (pv1, G_TYPE_INT64);
     g_value_set_int64 (pv1, min1);
   }
   if (min2 < max2) {
     g_value_init (pv2, GST_TYPE_INT64_RANGE);
-    gst_value_set_int64_range (pv2, min2, max2);
+    gst_value_set_int64_range_step (pv2, min2, max2, step);
   } else if (min2 == max2) {
     g_value_init (pv2, G_TYPE_INT64);
     g_value_set_int64 (pv2, min2);
@@ -3085,28 +3503,30 @@ gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
 {
   gint64 min = gst_value_get_int64_range_min (minuend);
   gint64 max = gst_value_get_int64_range_max (minuend);
+  gint64 step = gst_value_get_int64_range_step (minuend);
   gint64 val = g_value_get_int64 (subtrahend);
 
   g_return_val_if_fail (min < max, FALSE);
 
   /* value is outside of the range, return range unchanged */
-  if (val < min || val > max) {
+  if (val < min || val > max || val % step) {
     if (dest)
       gst_value_init_and_copy (dest, minuend);
     return TRUE;
   } else {
     /* max must be MAXINT64 too as val <= max */
-    if (val == G_MAXINT64) {
-      max--;
-      val--;
+    if (val >= G_MAXINT64 - step + 1) {
+      max -= step;
+      val -= step;
     }
     /* min must be MININT64 too as val >= max */
-    if (val == G_MININT64) {
-      min++;
-      val++;
+    if (val <= G_MININT64 + step - 1) {
+      min += step;
+      val += step;
     }
     if (dest)
-      gst_value_create_new_int64_range (dest, min, val - 1, val + 1, max);
+      gst_value_create_new_int64_range (dest, min, val - step, val + step, max,
+          step);
   }
   return TRUE;
 }
@@ -3117,20 +3537,30 @@ gst_value_subtract_int64_range_int64_range (GValue * dest,
 {
   gint64 min1 = gst_value_get_int64_range_min (minuend);
   gint64 max1 = gst_value_get_int64_range_max (minuend);
+  gint64 step1 = gst_value_get_int64_range_step (minuend);
   gint64 min2 = gst_value_get_int64_range_min (subtrahend);
   gint64 max2 = gst_value_get_int64_range_max (subtrahend);
+  gint64 step2 = gst_value_get_int64_range_step (subtrahend);
+  gint64 step;
+
+  if (step1 != step2) {
+    /* ENOIMPL */
+    g_assert (FALSE);
+    return FALSE;
+  }
+  step = step1;
 
-  if (max2 == G_MAXINT64 && min2 == G_MININT64) {
+  if (max2 >= max1 && min2 <= min1) {
     return FALSE;
-  } else if (max2 == G_MAXINT64) {
-    return gst_value_create_new_int64_range (dest, min1, MIN (min2 - 1, max1),
-        1, 0);
-  } else if (min2 == G_MININT64) {
-    return gst_value_create_new_int64_range (dest, MAX (max2 + 1, min1), max1,
-        1, 0);
+  } else if (max2 >= max1) {
+    return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
+            max1), step, 0, step);
+  } else if (min2 <= min1) {
+    return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1),
+        max1, step, 0, step);
   } else {
-    return gst_value_create_new_int64_range (dest, min1, MIN (min2 - 1, max1),
-        MAX (max2 + 1, min1), max1);
+    return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
+            max1), MAX (max2 + step, min1), max1, step);
   }
 }
 
@@ -3473,14 +3903,15 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
   if (CHECK_TYPES (INT, G)) {
     const gint rmin = gst_value_get_int_range_min (value);
     const gint rmax = gst_value_get_int_range_max (value);
+    const gint rstep = gst_value_get_int_range_step (value);
     /* note: this will overflow for min 0 and max INT_MAX, but this
        would only be equal to a list of INT_MAX elements, which seems
        very unlikely */
-    if (list_size != rmax - rmin + 1)
+    if (list_size != rmax / rstep - rmin / rstep + 1)
       return FALSE;
     for (n = 0; n < list_size; ++n) {
       gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n));
-      if (v < rmin || v > rmax) {
+      if (v < rmin || v > rmax || v % rstep) {
         return FALSE;
       }
     }
@@ -3488,12 +3919,13 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
   } else if (CHECK_TYPES (INT64, G)) {
     const gint64 rmin = gst_value_get_int64_range_min (value);
     const gint64 rmax = gst_value_get_int64_range_max (value);
+    const gint64 rstep = gst_value_get_int64_range_step (value);
     GST_DEBUG ("List/range of int64s");
-    if (list_size != rmax - rmin + 1)
+    if (list_size != rmax / rstep - rmin / rstep + 1)
       return FALSE;
     for (n = 0; n < list_size; ++n) {
       gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n));
-      if (v < rmin || v > rmax)
+      if (v < rmin || v > rmax || v % rstep)
         return FALSE;
     }
     return TRUE;
@@ -3637,34 +4069,32 @@ gst_value_can_union (const GValue * value1, const GValue * value2)
  *
  * Creates a GValue corresponding to the union of @value1 and @value2.
  *
- * Returns: always returns %TRUE
+ * Returns: TRUE if the union suceeded.
  */
-/* FIXME: change return type to 'void'? */
 gboolean
 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
 {
-  GstValueUnionInfo *union_info;
+  const GstValueUnionInfo *union_info;
   guint i, len;
+  GType type1, type2;
 
   g_return_val_if_fail (dest != NULL, FALSE);
   g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
   g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
+  g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2),
+      FALSE);
 
   len = gst_value_union_funcs->len;
+  type1 = G_VALUE_TYPE (value1);
+  type2 = G_VALUE_TYPE (value2);
 
   for (i = 0; i < len; i++) {
     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
-    if (union_info->type1 == G_VALUE_TYPE (value1) &&
-        union_info->type2 == G_VALUE_TYPE (value2)) {
-      if (union_info->func (dest, value1, value2)) {
-        return TRUE;
-      }
+    if (union_info->type1 == type1 && union_info->type2 == type2) {
+      return union_info->func (dest, value1, value2);
     }
-    if (union_info->type1 == G_VALUE_TYPE (value2) &&
-        union_info->type2 == G_VALUE_TYPE (value1)) {
-      if (union_info->func (dest, value2, value1)) {
-        return TRUE;
-      }
+    if (union_info->type1 == type2 && union_info->type2 == type1) {
+      return union_info->func (dest, value2, value1);
     }
   }
 
@@ -3673,7 +4103,7 @@ gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
 }
 
 /**
- * gst_value_register_union_func:
+ * gst_value_register_union_func: (skip)
  * @type1: a type to union
  * @type2: another type to union
  * @func: a function that implements creating a union between the two types
@@ -3750,7 +4180,7 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2)
 
 /**
  * gst_value_intersect:
- * @dest: (out caller-allocates): a uninitialized #GValue that will hold the calculated
+ * @dest: (out caller-allocates) (transfer full): a uninitialized #GValue that will hold the calculated
  * intersection value. May be NULL if the resulting set if not needed.
  * @value1: a value to intersect
  * @value2: another value to intersect
@@ -3807,7 +4237,7 @@ gst_value_intersect (GValue * dest, const GValue * value1,
 
 
 /**
- * gst_value_register_intersect_func:
+ * gst_value_register_intersect_func: (skip)
  * @type1: the first type to intersect
  * @type2: the second type to intersect
  * @func: the intersection function
@@ -3941,7 +4371,7 @@ gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
 }
 
 /**
- * gst_value_register_subtract_func:
+ * gst_value_register_subtract_func: (skip)
  * @minuend_type: type of the minuend
  * @subtrahend_type: type of the subtrahend
  * @func: function to use
@@ -3959,9 +4389,11 @@ gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
 {
   GstValueSubtractInfo info;
 
-  /* one type must be unfixed, other subtractions can be done as comparisons */
-  g_return_if_fail (!gst_type_is_fixed (minuend_type)
-      || !gst_type_is_fixed (subtrahend_type));
+  /* one type must be unfixed, other subtractions can be done as comparisons,
+   * special case: bitmasks */
+  if (minuend_type != GST_TYPE_BITMASK)
+    g_return_if_fail (!gst_type_is_fixed (minuend_type)
+        || !gst_type_is_fixed (subtrahend_type));
 
   info.minuend = minuend_type;
   info.subtrahend = subtrahend_type;
@@ -4147,6 +4579,73 @@ gst_value_is_fixed (const GValue * value)
   return gst_type_is_fixed (type);
 }
 
+/**
+ * gst_value_fixate:
+ * @dest: the #GValue destination
+ * @src: the #GValue to fixate
+ *
+ * Fixate @src into a new value @dest.
+ * For ranges, the first element is taken. For lists and arrays, the
+ * first item is fixated and returned.
+ * If @src is already fixed, this function returns FALSE.
+ *
+ * Returns: true if @dest contains a fixated version of @src.
+ */
+gboolean
+gst_value_fixate (GValue * dest, const GValue * src)
+{
+  g_return_val_if_fail (G_IS_VALUE (src), FALSE);
+  g_return_val_if_fail (dest != NULL, FALSE);
+
+  if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
+    g_value_init (dest, G_TYPE_INT);
+    g_value_set_int (dest, gst_value_get_int_range_min (src));
+  } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
+    g_value_init (dest, G_TYPE_DOUBLE);
+    g_value_set_double (dest, gst_value_get_double_range_min (src));
+  } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
+    gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
+  } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
+    GValue temp = { 0 };
+
+    /* list could be empty */
+    if (gst_value_list_get_size (src) <= 0)
+      return FALSE;
+
+    gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
+
+    if (!gst_value_fixate (dest, &temp))
+      gst_value_init_and_copy (dest, &temp);
+    g_value_unset (&temp);
+  } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
+    gboolean res = FALSE;
+    guint n, len;
+
+    len = gst_value_array_get_size (src);
+    g_value_init (dest, GST_TYPE_ARRAY);
+    for (n = 0; n < len; n++) {
+      GValue kid = { 0 };
+      const GValue *orig_kid = gst_value_array_get_value (src, n);
+
+      if (!gst_value_fixate (&kid, orig_kid))
+        gst_value_init_and_copy (&kid, orig_kid);
+      else
+        res = TRUE;
+      gst_value_array_append_value (dest, &kid);
+      g_value_unset (&kid);
+    }
+
+    if (!res)
+      g_value_unset (dest);
+
+    return res;
+  } else {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
 /************
  * fraction *
  ************/
@@ -4506,52 +5005,6 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2)
  * GDate *
  *********/
 
-/**
- * gst_value_set_date:
- * @value: a GValue initialized to GST_TYPE_DATE
- * @date: the date to set the value to
- *
- * Sets the contents of @value to correspond to @date.  The actual
- * #GDate structure is copied before it is used.
- */
-void
-gst_value_set_date (GValue * value, const GDate * date)
-{
-  g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE);
-  g_return_if_fail (g_date_valid (date));
-
-  g_value_set_boxed (value, date);
-}
-
-/**
- * gst_value_get_date:
- * @value: a GValue initialized to GST_TYPE_DATE
- *
- * Gets the contents of @value.
- *
- * Returns: (transfer none): the contents of @value
- */
-const GDate *
-gst_value_get_date (const GValue * value)
-{
-  g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE, NULL);
-
-  return (const GDate *) g_value_get_boxed (value);
-}
-
-static gpointer
-gst_date_copy (gpointer boxed)
-{
-  const GDate *date = (const GDate *) boxed;
-
-  if (!g_date_valid (date)) {
-    GST_WARNING ("invalid GDate");
-    return NULL;
-  }
-
-  return g_date_new_julian (g_date_get_julian (date));
-}
-
 static gint
 gst_value_compare_date (const GValue * value1, const GValue * value2)
 {
@@ -4708,6 +5161,209 @@ gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
   gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
 }
 
+
+/************
+ * bitmask *
+ ************/
+
+/* helper functions */
+static void
+gst_value_init_bitmask (GValue * value)
+{
+  value->data[0].v_uint64 = 0;
+}
+
+static void
+gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static gchar *
+gst_value_collect_bitmask (GValue * value, guint n_collect_values,
+    GTypeCValue * collect_values, guint collect_flags)
+{
+  if (n_collect_values != 1)
+    return g_strdup_printf ("not enough value locations for `%s' passed",
+        G_VALUE_TYPE_NAME (value));
+
+  gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
+
+  return NULL;
+}
+
+static gchar *
+gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
+    GTypeCValue * collect_values, guint collect_flags)
+{
+  guint64 *bitmask = collect_values[0].v_pointer;
+
+  if (!bitmask)
+    return g_strdup_printf ("value for `%s' passed as NULL",
+        G_VALUE_TYPE_NAME (value));
+
+  *bitmask = value->data[0].v_uint64;
+
+  return NULL;
+}
+
+/**
+ * gst_value_set_bitmask:
+ * @value: a GValue initialized to #GST_TYPE_FRACTION
+ * @bitmask: the bitmask
+ *
+ * Sets @value to the bitmask specified by @bitmask.
+ */
+void
+gst_value_set_bitmask (GValue * value, guint64 bitmask)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
+
+  value->data[0].v_uint64 = bitmask;
+}
+
+/**
+ * gst_value_get_bitmask:
+ * @value: a GValue initialized to #GST_TYPE_FRACTION
+ *
+ * Gets the bitmask specified by @value.
+ *
+ * Returns: the bitmask.
+ */
+guint64
+gst_value_get_bitmask (const GValue * value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
+
+  return value->data[0].v_uint64;
+}
+
+static gchar *
+gst_value_serialize_bitmask (const GValue * value)
+{
+  guint64 bitmask = value->data[0].v_uint64;
+
+  return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
+}
+
+static gboolean
+gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
+{
+  gchar *endptr = NULL;
+  guint64 val;
+
+  if (G_UNLIKELY (s == NULL))
+    return FALSE;
+
+  if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
+    return FALSE;
+
+  val = g_ascii_strtoull (s, &endptr, 16);
+  if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
+    return FALSE;
+  if (val == 0 && endptr == s)
+    return FALSE;
+
+  gst_value_set_bitmask (dest, val);
+
+  return TRUE;
+}
+
+static void
+gst_value_transform_bitmask_string (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
+}
+
+static void
+gst_value_transform_string_bitmask (const GValue * src_value,
+    GValue * dest_value)
+{
+  if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
+    gst_value_set_bitmask (dest_value, 0);
+}
+
+static void
+gst_value_transform_uint64_bitmask (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static void
+gst_value_transform_bitmask_uint64 (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static gboolean
+gst_value_intersect_bitmask_bitmask (GValue * dest, const GValue * src1,
+    const GValue * src2)
+{
+  guint64 s1, s2;
+
+  s1 = gst_value_get_bitmask (src1);
+  s2 = gst_value_get_bitmask (src2);
+
+  if (dest) {
+    g_value_init (dest, GST_TYPE_BITMASK);
+    gst_value_set_bitmask (dest, s1 & s2);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_union_bitmask_bitmask (GValue * dest, const GValue * src1,
+    const GValue * src2)
+{
+  guint64 s1, s2;
+
+  s1 = gst_value_get_bitmask (src1);
+  s2 = gst_value_get_bitmask (src2);
+
+  g_value_init (dest, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (dest, s1 | s2);
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_bitmask_bitmask (GValue * dest,
+    const GValue * minuend, const GValue * subtrahend)
+{
+  guint64 m, s, r;
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (minuend), FALSE);
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (subtrahend), FALSE);
+
+  m = minuend->data[0].v_uint64;
+  s = subtrahend->data[0].v_uint64;
+  r = m & (~s);
+
+  if (dest) {
+    g_value_init (dest, GST_TYPE_BITMASK);
+    gst_value_set_bitmask (dest, r);
+  }
+  return (r != 0);
+}
+
+static gint
+gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
+{
+  guint64 v1, v2;
+
+  v1 = value1->data[0].v_uint64;
+  v2 = value2->data[0].v_uint64;
+
+  if (v1 == v2)
+    return GST_VALUE_EQUAL;
+
+  return GST_VALUE_UNORDERED;
+}
+
 static void
 gst_value_transform_object_string (const GValue * src_value,
     GValue * dest_value)
@@ -4761,22 +5417,9 @@ GType gst_ ## type ## _get_type (void)                          \
   return gst_ ## type ## _type;                                 \
 }
 
-static const GTypeValueTable _gst_fourcc_value_table = {
-  gst_value_init_fourcc,
-  NULL,
-  gst_value_copy_fourcc,
-  NULL,
-  (char *) "i",
-  gst_value_collect_fourcc,
-  (char *) "p",
-  gst_value_lcopy_fourcc
-};
-
-FUNC_VALUE_GET_TYPE (fourcc, "GstFourcc");
-
 static const GTypeValueTable _gst_int_range_value_table = {
   gst_value_init_int_range,
-  NULL,
+  gst_value_free_int_range,
   gst_value_copy_int_range,
   NULL,
   (char *) "ii",
@@ -4789,7 +5432,7 @@ FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
 
 static const GTypeValueTable _gst_int64_range_value_table = {
   gst_value_init_int64_range,
-  NULL,
+  gst_value_free_int64_range,
   gst_value_copy_int64_range,
   NULL,
   (char *) "qq",
@@ -4865,25 +5508,6 @@ static const GTypeValueTable _gst_fraction_value_table = {
 
 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
 
-
-GType
-gst_date_get_type (void)
-{
-  static GType gst_date_type = 0;
-
-  if (G_UNLIKELY (gst_date_type == 0)) {
-    /* FIXME 0.11: we require GLib 2.8 already
-     * Not using G_TYPE_DATE here on purpose, even if we could
-     * if GLIB_CHECK_VERSION(2,8,0) was true: we don't want the
-     * serialised strings to have different type strings depending
-     * on what version is used, so FIXME when we require GLib-2.8 */
-    gst_date_type = g_boxed_type_register_static ("GstDate",
-        (GBoxedCopyFunc) gst_date_copy, (GBoxedFreeFunc) g_date_free);
-  }
-
-  return gst_date_type;
-}
-
 GType
 gst_date_time_get_type (void)
 {
@@ -4898,9 +5522,22 @@ gst_date_time_get_type (void)
   return gst_date_time_type;
 }
 
+static const GTypeValueTable _gst_bitmask_value_table = {
+  gst_value_init_bitmask,
+  NULL,
+  gst_value_copy_bitmask,
+  NULL,
+  (char *) "q",
+  gst_value_collect_bitmask,
+  (char *) "p",
+  gst_value_lcopy_bitmask
+};
+
+FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
+
 
 void
-_gst_value_initialize (void)
+_priv_gst_value_initialize (void)
 {
   gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
   gst_value_hash = g_hash_table_new (NULL, NULL);
@@ -4914,18 +5551,6 @@ _gst_value_initialize (void)
   {
     static GstValueTable gst_value = {
       0,
-      gst_value_compare_fourcc,
-      gst_value_serialize_fourcc,
-      gst_value_deserialize_fourcc,
-    };
-
-    gst_value.type = gst_fourcc_get_type ();
-    gst_value_register (&gst_value);
-  }
-
-  {
-    static GstValueTable gst_value = {
-      0,
       gst_value_compare_int_range,
       gst_value_serialize_int_range,
       gst_value_deserialize_int_range,
@@ -5059,7 +5684,7 @@ _gst_value_initialize (void)
       gst_value_deserialize_date,
     };
 
-    gst_value.type = gst_date_get_type ();
+    gst_value.type = G_TYPE_DATE;
     gst_value_register (&gst_value);
   }
   {
@@ -5074,6 +5699,18 @@ _gst_value_initialize (void)
     gst_value_register (&gst_value);
   }
 
+  {
+    static GstValueTable gst_value = {
+      0,
+      gst_value_compare_bitmask,
+      gst_value_serialize_bitmask,
+      gst_value_deserialize_bitmask,
+    };
+
+    gst_value.type = gst_bitmask_get_type ();
+    gst_value_register (&gst_value);
+  }
+
   REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
   REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
 
@@ -5094,8 +5731,6 @@ _gst_value_initialize (void)
 
   REGISTER_SERIALIZATION (G_TYPE_UCHAR, uchar);
 
-  g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
-      gst_value_transform_fourcc_string);
   g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
       gst_value_transform_int_range_string);
   g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING,
@@ -5120,12 +5755,20 @@ _gst_value_initialize (void)
       gst_value_transform_double_fraction);
   g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
       gst_value_transform_float_fraction);
-  g_value_register_transform_func (GST_TYPE_DATE, G_TYPE_STRING,
+  g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING,
       gst_value_transform_date_string);
-  g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_DATE,
+  g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE,
       gst_value_transform_string_date);
   g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
       gst_value_transform_object_string);
+  g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
+      gst_value_transform_bitmask_uint64);
+  g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
+      gst_value_transform_bitmask_string);
+  g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
+      gst_value_transform_uint64_bitmask);
+  g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
+      gst_value_transform_string_bitmask);
 
   gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_intersect_int_int_range);
@@ -5146,6 +5789,8 @@ _gst_value_initialize (void)
   gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_intersect_fraction_range_fraction_range);
+  gst_value_register_intersect_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_intersect_bitmask_bitmask);
 
   gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_subtract_int_int_range);
@@ -5165,7 +5810,6 @@ _gst_value_initialize (void)
       gst_value_subtract_double_range_double);
   gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
       GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
-
   gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_fraction_range);
   gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION,
@@ -5173,6 +5817,8 @@ _gst_value_initialize (void)
   gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_range_fraction_range);
+  gst_value_register_subtract_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_subtract_bitmask_bitmask);
 
   /* see bug #317246, #64994, #65041 */
   {
@@ -5185,6 +5831,8 @@ _gst_value_initialize (void)
       gst_value_union_int_int_range);
   gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
       gst_value_union_int_range_int_range);
+  gst_value_register_union_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_union_bitmask_bitmask);
 
 #if 0
   /* Implement these if needed */
index a07f9ba..1fe64c4 100644 (file)
@@ -86,14 +86,6 @@ G_BEGIN_DECLS
         ((gchar) (((fourcc)>>24)&0xff))
 
 /**
- * GST_VALUE_HOLDS_FOURCC:
- * @x: the #GValue to check
- *
- * Checks if the given #GValue contains a #GST_TYPE_FOURCC value.
- */
-#define GST_VALUE_HOLDS_FOURCC(x)       (G_VALUE_HOLDS((x), gst_fourcc_get_type ()))
-
-/**
  * GST_VALUE_HOLDS_INT_RANGE:
  * @x: the #GValue to check
  *
@@ -133,7 +125,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_LIST value.
  */
-#define GST_VALUE_HOLDS_LIST(x)                (G_VALUE_HOLDS((x), gst_value_list_get_type ()))
+#define GST_VALUE_HOLDS_LIST(x)         (G_VALUE_HOLDS((x), gst_value_list_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_ARRAY:
@@ -141,7 +133,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_ARRAY value.
  */
-#define GST_VALUE_HOLDS_ARRAY(x)       (G_VALUE_HOLDS((x), gst_value_array_get_type ()))
+#define GST_VALUE_HOLDS_ARRAY(x)        (G_VALUE_HOLDS((x), gst_value_array_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_CAPS:
@@ -149,7 +141,7 @@ G_BEGIN_DECLS
  *
  * Checks if the given #GValue contains a #GST_TYPE_CAPS value.
  */
-#define GST_VALUE_HOLDS_CAPS(x)                (G_VALUE_HOLDS((x), GST_TYPE_CAPS))
+#define GST_VALUE_HOLDS_CAPS(x)         (G_VALUE_HOLDS((x), GST_TYPE_CAPS))
 
 /**
  * GST_VALUE_HOLDS_STRUCTURE:
@@ -159,7 +151,7 @@ G_BEGIN_DECLS
  *
  * Since: 0.10.15
  */
-#define GST_VALUE_HOLDS_STRUCTURE(x)           (G_VALUE_HOLDS((x), GST_TYPE_STRUCTURE))
+#define GST_VALUE_HOLDS_STRUCTURE(x)            (G_VALUE_HOLDS((x), GST_TYPE_STRUCTURE))
 
 /**
  * GST_VALUE_HOLDS_BUFFER:
@@ -170,20 +162,20 @@ G_BEGIN_DECLS
 #define GST_VALUE_HOLDS_BUFFER(x)       (G_VALUE_HOLDS((x), GST_TYPE_BUFFER))
 
 /**
- * GST_VALUE_HOLDS_FRACTION:
+ * GST_VALUE_HOLDS_SAMPLE:
  * @x: the #GValue to check
  *
- * Checks if the given #GValue contains a #GST_TYPE_FRACTION value.
+ * Checks if the given #GValue contains a #GST_TYPE_SAMPLE value.
  */
-#define GST_VALUE_HOLDS_FRACTION(x)    (G_VALUE_HOLDS((x), gst_fraction_get_type ()))
+#define GST_VALUE_HOLDS_SAMPLE(x)       (G_VALUE_HOLDS((x), GST_TYPE_SAMPLE))
 
 /**
- * GST_VALUE_HOLDS_DATE:
+ * GST_VALUE_HOLDS_FRACTION:
  * @x: the #GValue to check
  *
- * Checks if the given #GValue contains a #GST_TYPE_DATE value.
+ * Checks if the given #GValue contains a #GST_TYPE_FRACTION value.
  */
-#define GST_VALUE_HOLDS_DATE(x)         (G_VALUE_HOLDS((x), gst_date_get_type ()))
+#define GST_VALUE_HOLDS_FRACTION(x)     (G_VALUE_HOLDS((x), gst_fraction_get_type ()))
 
 /**
  * GST_VALUE_HOLDS_DATE_TIME:
@@ -196,13 +188,12 @@ G_BEGIN_DECLS
 #define GST_VALUE_HOLDS_DATE_TIME(x)    (G_VALUE_HOLDS((x), gst_date_time_get_type ()))
 
 /**
- * GST_TYPE_FOURCC:
- *
- * a #GValue type that represents 4 byte identifier (e.g. used for codecs)
+ * GST_VALUE_HOLDS_BITMASK:
+ * @x: the #GValue to check
  *
- * Returns: the #GType of GstFourcc
+ * Checks if the given #GValue contains a #GST_TYPE_BITMASK value.
  */
-#define GST_TYPE_FOURCC                  gst_fourcc_get_type ()
+#define GST_VALUE_HOLDS_BITMASK(x)      (G_VALUE_HOLDS((x), gst_bitmask_get_type ()))
 
 /**
  * GST_TYPE_INT_RANGE:
@@ -267,7 +258,7 @@ G_BEGIN_DECLS
  *
  * Returns: the #GType of GstArrayList (which is not explicitly typed)
  */
-#define GST_TYPE_ARRAY                  gst_value_array_get_type ()
+#define GST_TYPE_ARRAY                   gst_value_array_get_type ()
 
 /**
  * GST_TYPE_FRACTION:
@@ -281,25 +272,25 @@ G_BEGIN_DECLS
 #define GST_TYPE_FRACTION                gst_fraction_get_type ()
 
 /**
- * GST_TYPE_DATE:
+ * GST_TYPE_DATE_TIME:
  *
- * a boxed #GValue type for #GDate that represents a date.
+ * a boxed #GValue type for #GstDateTime that represents a date and time.
  *
- * Returns: the #GType of GstDate
+ * Returns: the #GType of GstDateTime
+ * Since: 0.10.31
  */
 
-#define GST_TYPE_DATE                    gst_date_get_type ()
+#define GST_TYPE_DATE_TIME               gst_date_time_get_type ()
 
 /**
- * GST_TYPE_DATE_TIME:
+ * GST_TYPE_BITMASK:
  *
- * a boxed #GValue type for #GstDateTime that represents a date and time.
+ * a #GValue type that represents a 64-bit bitmask.
  *
- * Returns: the #GType of GstDateTime
- * Since: 0.10.31
+ * Returns: the #GType of GstBitmask (which is not explicitly typed)
  */
 
-#define GST_TYPE_DATE_TIME               gst_date_time_get_type ()
+#define GST_TYPE_BITMASK                 gst_bitmask_get_type ()
 
 /**
  * GST_VALUE_LESS_THAN:
@@ -344,7 +335,7 @@ G_BEGIN_DECLS
  * or GST_VALUE_UNORDERED
  */
 typedef gint     (* GstValueCompareFunc)     (const GValue *value1,
-                                             const GValue *value2);
+                                              const GValue *value2);
 
 /**
  * GstValueSerializeFunc:
@@ -368,7 +359,7 @@ typedef gchar *  (* GstValueSerializeFunc)   (const GValue *value1);
  * Returns: %TRUE for success
  */
 typedef gboolean (* GstValueDeserializeFunc) (GValue       *dest,
-                                             const gchar  *s);
+                                              const gchar  *s);
 
 /**
  * GstValueUnionFunc:
@@ -382,8 +373,8 @@ typedef gboolean (* GstValueDeserializeFunc) (GValue       *dest,
  * Returns: %TRUE if a union was successful
  */
 typedef gboolean (* GstValueUnionFunc)       (GValue       *dest,
-                                             const GValue *value1,
-                                             const GValue *value2);
+                                              const GValue *value1,
+                                              const GValue *value2);
 
 /**
  * GstValueIntersectFunc:
@@ -400,8 +391,8 @@ typedef gboolean (* GstValueUnionFunc)       (GValue       *dest,
  * Returns: %TRUE if the values can intersect
  */
 typedef gboolean (* GstValueIntersectFunc)   (GValue       *dest,
-                                             const GValue *value1,
-                                             const GValue *value2);
+                                              const GValue *value1,
+                                              const GValue *value2);
 
 /**
  * GstValueSubtractFunc:
@@ -415,8 +406,8 @@ typedef gboolean (* GstValueIntersectFunc)   (GValue       *dest,
  * Returns: %TRUE if the subtraction is not empty
  */
 typedef gboolean (* GstValueSubtractFunc)    (GValue       *dest,
-                                             const GValue *minuend,
-                                             const GValue *subtrahend);
+                                              const GValue *minuend,
+                                              const GValue *subtrahend);
 
 typedef struct _GstValueTable GstValueTable;
 /**
@@ -435,157 +426,166 @@ struct _GstValueTable {
   GstValueDeserializeFunc deserialize;
 
   /*< private >*/
-  void *_gst_reserved [GST_PADDING];
+  gpointer _gst_reserved [GST_PADDING];
 };
 
 GType gst_int_range_get_type (void);
 GType gst_int64_range_get_type (void);
 GType gst_double_range_get_type (void);
 GType gst_fraction_range_get_type (void);
-GType gst_fourcc_get_type (void);
 GType gst_fraction_get_type (void);
 GType gst_value_list_get_type (void);
 GType gst_value_array_get_type (void);
+GType gst_bitmask_get_type (void);
 
-GType gst_date_get_type (void);
 GType gst_date_time_get_type (void);
 
-void           gst_value_register              (const GstValueTable   *table);
-void           gst_value_init_and_copy         (GValue                *dest,
-                                                const GValue          *src);
+void            gst_value_register              (const GstValueTable   *table);
+void            gst_value_init_and_copy         (GValue                *dest,
+                                                 const GValue          *src);
 
-gchar *                gst_value_serialize             (const GValue          *value) G_GNUC_MALLOC;
-gboolean       gst_value_deserialize           (GValue                *dest,
-                                                const gchar           *src);
+gchar *         gst_value_serialize             (const GValue          *value) G_GNUC_MALLOC;
+gboolean        gst_value_deserialize           (GValue                *dest,
+                                                 const gchar           *src);
 
 /* list */
-void           gst_value_list_append_value     (GValue         *value,
-                                                const GValue   *append_value);
-void           gst_value_list_prepend_value    (GValue         *value,
-                                                const GValue   *prepend_value);
-void           gst_value_list_concat           (GValue         *dest,
-                                                const GValue   *value1,
-                                                const GValue   *value2);
-void           gst_value_list_merge            (GValue         *dest,
-                                                const GValue   *value1,
-                                                const GValue   *value2);
-guint          gst_value_list_get_size         (const GValue   *value);
-const GValue * gst_value_list_get_value        (const GValue   *value,
-                                                guint          index);
+void            gst_value_list_append_value     (GValue         *value,
+                                                 const GValue   *append_value);
+void            gst_value_list_prepend_value    (GValue         *value,
+                                                 const GValue   *prepend_value);
+void            gst_value_list_concat           (GValue         *dest,
+                                                 const GValue   *value1,
+                                                 const GValue   *value2);
+void            gst_value_list_merge            (GValue         *dest,
+                                                 const GValue   *value1,
+                                                 const GValue   *value2);
+guint           gst_value_list_get_size         (const GValue   *value);
+const GValue *  gst_value_list_get_value        (const GValue   *value,
+                                                 guint          index);
 
 /* array */
-void           gst_value_array_append_value    (GValue         *value,
-                                                const GValue   *append_value);
-void           gst_value_array_prepend_value   (GValue         *value,
-                                                const GValue   *prepend_value);
-guint          gst_value_array_get_size        (const GValue   *value);
-const GValue * gst_value_array_get_value       (const GValue   *value,
-                                                guint          index);
-
-/* fourcc */
-void           gst_value_set_fourcc            (GValue         *value,
-                                                guint32        fourcc);
-guint32                gst_value_get_fourcc            (const GValue   *value);
+void            gst_value_array_append_value    (GValue         *value,
+                                                 const GValue   *append_value);
+void            gst_value_array_prepend_value   (GValue         *value,
+                                                 const GValue   *prepend_value);
+guint           gst_value_array_get_size        (const GValue   *value);
+const GValue *  gst_value_array_get_value       (const GValue   *value,
+                                                 guint          index);
 
 /* int range */
-void           gst_value_set_int_range         (GValue         *value,
-                                                gint           start,
-                                                gint           end);
-gint           gst_value_get_int_range_min     (const GValue   *value);
-gint           gst_value_get_int_range_max     (const GValue   *value);
+void            gst_value_set_int_range         (GValue         *value,
+                                                 gint           start,
+                                                 gint           end);
+void            gst_value_set_int_range_step    (GValue         *value,
+                                                 gint           start,
+                                                 gint           end,
+                                                 gint           step);
+gint            gst_value_get_int_range_min     (const GValue   *value);
+gint            gst_value_get_int_range_max     (const GValue   *value);
+gint            gst_value_get_int_range_step    (const GValue   *value);
 
 /* int64 range */
-void           gst_value_set_int64_range       (GValue         *value,
-                                                gint64         start,
-                                                gint64         end);
-gint64         gst_value_get_int64_range_min   (const GValue   *value);
-gint64         gst_value_get_int64_range_max   (const GValue   *value);
+void            gst_value_set_int64_range       (GValue         *value,
+                                                 gint64         start,
+                                                 gint64         end);
+void            gst_value_set_int64_range_step  (GValue         *value,
+                                                 gint64         start,
+                                                 gint64         end,
+                                                 gint64         step);
+gint64          gst_value_get_int64_range_min   (const GValue   *value);
+gint64          gst_value_get_int64_range_max   (const GValue   *value);
+gint64          gst_value_get_int64_range_step  (const GValue   *value);
 
 /* double range */
-void           gst_value_set_double_range      (GValue         *value,
-                                                gdouble        start,
-                                                gdouble        end);
-gdouble                gst_value_get_double_range_min  (const GValue   *value);
-gdouble                gst_value_get_double_range_max  (const GValue   *value);
+void            gst_value_set_double_range      (GValue         *value,
+                                                 gdouble        start,
+                                                 gdouble        end);
+gdouble         gst_value_get_double_range_min  (const GValue   *value);
+gdouble         gst_value_get_double_range_max  (const GValue   *value);
 
 /* caps */
-const GstCaps *        gst_value_get_caps              (const GValue   *value);
-void           gst_value_set_caps              (GValue         *value,
-                                                const GstCaps  *caps);
+const GstCaps * gst_value_get_caps              (const GValue   *value);
+void            gst_value_set_caps              (GValue         *value,
+                                                 const GstCaps  *caps);
 
 /* structure */
 const GstStructure *
-               gst_value_get_structure         (const GValue   *value);
-void           gst_value_set_structure         (GValue         *value,
-                                                const GstStructure  *structure);
+                gst_value_get_structure         (const GValue   *value);
+void            gst_value_set_structure         (GValue         *value,
+                                                 const GstStructure  *structure);
 
 /* fraction */
-void           gst_value_set_fraction          (GValue         *value,
-                                                gint           numerator,
-                                                gint           denominator);
-gint           gst_value_get_fraction_numerator (const GValue  *value);
-gint           gst_value_get_fraction_denominator(const GValue *value);
-gboolean       gst_value_fraction_multiply     (GValue         *product,
-                                                const GValue   *factor1,
-                                                const GValue   *factor2);
-gboolean       gst_value_fraction_subtract (GValue * dest,
-                                            const GValue * minuend, 
-                                            const GValue * subtrahend);
+void            gst_value_set_fraction          (GValue         *value,
+                                                 gint           numerator,
+                                                 gint           denominator);
+gint            gst_value_get_fraction_numerator   (const GValue  *value);
+gint            gst_value_get_fraction_denominator (const GValue *value);
+gboolean        gst_value_fraction_multiply        (GValue         *product,
+                                                    const GValue   *factor1,
+                                                    const GValue   *factor2);
+gboolean        gst_value_fraction_subtract     (GValue * dest,
+                                                 const GValue * minuend,
+                                                 const GValue * subtrahend);
 
 /* fraction range */
-void           gst_value_set_fraction_range    (GValue         *value,
-                                                const GValue   *start,
-                                                const GValue   *end);
-void           gst_value_set_fraction_range_full (GValue       *value,
-                                                gint numerator_start, 
-                                                gint denominator_start,
-                                                gint numerator_end, 
-                                                gint denominator_end);
-const GValue   *gst_value_get_fraction_range_min (const GValue *value);
-const GValue   *gst_value_get_fraction_range_max (const GValue *value);
-
-/* date */
-const GDate *  gst_value_get_date              (const GValue   *value);
-void           gst_value_set_date              (GValue         *value,
-                                                const GDate    *date);
+void            gst_value_set_fraction_range    (GValue         *value,
+                                                 const GValue   *start,
+                                                 const GValue   *end);
+void            gst_value_set_fraction_range_full (GValue       *value,
+                                                 gint numerator_start,
+                                                 gint denominator_start,
+                                                 gint numerator_end,
+                                                 gint denominator_end);
+const GValue    *gst_value_get_fraction_range_min (const GValue *value);
+const GValue    *gst_value_get_fraction_range_max (const GValue *value);
+
+/* bitmask */
+guint64         gst_value_get_bitmask           (const GValue   *value);
+void            gst_value_set_bitmask           (GValue         *value,
+                                                 guint64         bitmask);
 
 /* compare */
-gint           gst_value_compare               (const GValue   *value1,
-                                                const GValue   *value2);
-gboolean       gst_value_can_compare           (const GValue   *value1,
-                                                const GValue   *value2);
+gint            gst_value_compare               (const GValue   *value1,
+                                                 const GValue   *value2);
+gboolean        gst_value_can_compare           (const GValue   *value1,
+                                                 const GValue   *value2);
+gboolean        gst_value_is_subset             (const GValue   *value1,
+                                                 const GValue   *value2);
+
 /* union */
-gboolean       gst_value_union                 (GValue         *dest,
-                                                const GValue   *value1,
-                                                const GValue   *value2);
-gboolean       gst_value_can_union             (const GValue   *value1,
-                                                const GValue   *value2);
-void           gst_value_register_union_func   (GType          type1,
-                                                GType          type2,
-                                                GstValueUnionFunc func);
+gboolean        gst_value_union                 (GValue         *dest,
+                                                 const GValue   *value1,
+                                                 const GValue   *value2);
+gboolean        gst_value_can_union             (const GValue   *value1,
+                                                 const GValue   *value2);
+void            gst_value_register_union_func   (GType          type1,
+                                                 GType          type2,
+                                                 GstValueUnionFunc func);
 
 /* intersection */
-gboolean       gst_value_intersect             (GValue         *dest,
-                                                const GValue   *value1,
-                                                const GValue   *value2);
-gboolean       gst_value_can_intersect         (const GValue   *value1,
-                                                const GValue   *value2);
-void           gst_value_register_intersect_func (GType        type1,
-                                               GType           type2,
-                                               GstValueIntersectFunc func);
+gboolean        gst_value_intersect             (GValue         *dest,
+                                                 const GValue   *value1,
+                                                 const GValue   *value2);
+gboolean        gst_value_can_intersect         (const GValue   *value1,
+                                                 const GValue   *value2);
+void            gst_value_register_intersect_func (GType        type1,
+                                                GType           type2,
+                                                GstValueIntersectFunc func);
 
 /* subtraction */
-gboolean       gst_value_subtract              (GValue         *dest,
-                                                const GValue   *minuend,
-                                                const GValue   *subtrahend);
-gboolean       gst_value_can_subtract          (const GValue   *minuend,
-                                                const GValue   *subtrahend);
-void           gst_value_register_subtract_func (GType         minuend_type,
-                                               GType           subtrahend_type,
-                                               GstValueSubtractFunc func);
+gboolean        gst_value_subtract              (GValue         *dest,
+                                                 const GValue   *minuend,
+                                                 const GValue   *subtrahend);
+gboolean        gst_value_can_subtract          (const GValue   *minuend,
+                                                 const GValue   *subtrahend);
+void            gst_value_register_subtract_func (GType         minuend_type,
+                                                GType           subtrahend_type,
+                                                GstValueSubtractFunc func);
 
 /* fixation */
-gboolean       gst_value_is_fixed              (const GValue   *value);
+gboolean        gst_value_is_fixed              (const GValue   *value);
+gboolean        gst_value_fixate                (GValue         *dest,
+                                                 const GValue   *src);
 
 G_END_DECLS
 
diff --git a/gst/gstxml.c b/gst/gstxml.c
deleted file mode 100644 (file)
index b37a4e2..0000000
+++ /dev/null
@@ -1,541 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
- *
- * gstxml.c: XML save/restore of pipelines
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstxml
- * @short_description: XML save/restore operations of pipelines
- *
- * GStreamer pipelines can be saved to xml files using gst_xml_write_file().
- * They can be loaded back using gst_xml_parse_doc() / gst_xml_parse_file() / 
- * gst_xml_parse_memory().
- * Additionally one can load saved pipelines into the gst-editor to inspect the
- * graph.
- *
- * #GstElement implementations need to override the #GstObjectClass.save_thyself()
- * and #GstObjectClass.restore_thyself() virtual functions of #GstObject.
- *
- * Deprecated: This feature is deprecated pipeline serialization to XML is
- * broken for all but the most simple pipelines. It will most likely be
- * removed in future. Don't use it.
- */
-
-#include "gst_private.h"
-
-#include "gstxml.h"
-#include "gstmarshal.h"
-#include "gstinfo.h"
-#include "gstbin.h"
-
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#include <libxml/parser.h>
-xmlNodePtr gst_object_save_thyself (const GstObject * object,
-    xmlNodePtr parent);
-GstObject *gst_object_load_thyself (xmlNodePtr parent);
-void gst_object_restore_thyself (GstObject * object, GstXmlNodePtr self);
-
-#define GST_TYPE_XML           (gst_xml_get_type ())
-#define GST_XML(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XML, GstXML))
-#define GST_IS_XML(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XML))
-#define GST_XML_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_XML, GstXMLClass))
-#define GST_IS_XML_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_XML))
-#define GST_XML_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XML, GstXMLClass))
-
-typedef struct _GstXML GstXML;
-typedef struct _GstXMLClass GstXMLClass;
-
-struct _GstXML
-{
-  GstObject object;
-
-  /*< public > */
-  GList *topelements;
-
-  xmlNsPtr ns;
-
-  /*< private > */
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstXMLClass
-{
-  GstObjectClass parent_class;
-
-  /* signal callbacks */
-  void (*object_loaded) (GstXML * xml, GstObject * object, xmlNodePtr self);
-  void (*object_saved) (GstXML * xml, GstObject * object, xmlNodePtr self);
-
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-GType gst_xml_get_type (void);
-xmlDocPtr gst_xml_write (GstElement * element);
-gint gst_xml_write_file (GstElement * element, FILE * out);
-GstXML *gst_xml_new (void);
-gboolean gst_xml_parse_doc (GstXML * xml, xmlDocPtr doc, const guchar * root);
-gboolean gst_xml_parse_file (GstXML * xml, const guchar * fname,
-    const guchar * root);
-gboolean gst_xml_parse_memory (GstXML * xml, guchar * buffer, guint size,
-    const gchar * root);
-GstElement *gst_xml_get_element (GstXML * xml, const guchar * name);
-GList *gst_xml_get_topelements (GstXML * xml);
-GstElement *gst_xml_make_element (xmlNodePtr cur, GstObject * parent);
-#endif
-#endif
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-
-enum
-{
-  OBJECT_LOADED,
-  LAST_SIGNAL
-};
-
-static void gst_xml_dispose (GObject * object);
-
-static void gst_xml_object_loaded (GstObject * private, GstObject * object,
-    xmlNodePtr self, gpointer data);
-
-static GstObjectClass *parent_class = NULL;
-static guint gst_xml_signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (GstXML, gst_xml, GST_TYPE_OBJECT);
-
-static void
-gst_xml_class_init (GstXMLClass * klass)
-{
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->dispose = gst_xml_dispose;
-
-  /* FIXME G_TYPE_POINTER should be GType of xmlNodePtr
-   * (ensonic) can't be fixed, as libxml does not use GObject (unfortunately)
-   */
-  /**
-   * GstXML::object-loaded:
-   * @xml: the xml persistence instance
-   * @object: the object that has been loaded
-   * @xml_node: the related xml_node pointer to the document tree
-   *
-   * Signals that a new object has been deserialized.
-   */
-  gst_xml_signals[OBJECT_LOADED] =
-      g_signal_new ("object-loaded", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstXMLClass, object_loaded), NULL,
-      NULL, gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, GST_TYPE_OBJECT,
-      G_TYPE_POINTER);
-
-}
-
-static void
-gst_xml_init (GstXML * xml)
-{
-  xml->topelements = NULL;
-}
-
-static void
-gst_xml_dispose (GObject * object)
-{
-  GstXML *xml = GST_XML (object);
-
-  g_list_foreach (xml->topelements, (GFunc) gst_object_unref, NULL);
-  g_list_free (xml->topelements);
-  xml->topelements = NULL;
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-/**
- * gst_xml_new:
- *
- * Create a new GstXML parser object.
- *
- * Returns: a pointer to a new GstXML object.
- */
-GstXML *
-gst_xml_new (void)
-{
-  return GST_XML (g_object_newv (GST_TYPE_XML, 0, NULL));
-}
-
-/**
- * gst_xml_write:
- * @element: The element to write out
- *
- * Converts the given element into an XML presentation.
- *
- * Returns: a pointer to an XML document
- */
-xmlDocPtr
-gst_xml_write (GstElement * element)
-{
-  xmlDocPtr doc;
-  xmlNodePtr elementnode;
-  xmlNsPtr gst_ns;
-
-  doc = xmlNewDoc ((xmlChar *) "1.0");
-
-  doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *) "gstreamer", NULL);
-
-  gst_ns =
-      xmlNewNs (doc->xmlRootNode,
-      (xmlChar *) "http://gstreamer.net/gst-core/1.0/", (xmlChar *) "gst");
-
-  elementnode = xmlNewChild (doc->xmlRootNode, gst_ns, (xmlChar *) "element",
-      NULL);
-
-  gst_object_save_thyself (GST_OBJECT (element), elementnode);
-
-  return doc;
-}
-
-/**
- * gst_xml_write_file:
- * @element: The element to write out
- * @out: an open file, like stdout
- *
- * Converts the given element into XML and writes the formatted XML to an open
- * file.
- *
- * Returns: number of bytes written on success, -1 otherwise.
- */
-gint
-gst_xml_write_file (GstElement * element, FILE * out)
-{
-  xmlDocPtr cur;
-
-#ifdef HAVE_LIBXML2
-  xmlOutputBufferPtr buf;
-#endif
-  const char *encoding;
-  xmlCharEncodingHandlerPtr handler = NULL;
-  int indent;
-  gboolean ret;
-
-  cur = gst_xml_write (element);
-  if (!cur)
-    return -1;
-
-#ifdef HAVE_LIBXML2
-  encoding = (const char *) cur->encoding;
-
-  if (encoding != NULL) {
-    xmlCharEncoding enc;
-
-    enc = xmlParseCharEncoding (encoding);
-
-    if (cur->charset != XML_CHAR_ENCODING_UTF8) {
-      xmlGenericError (xmlGenericErrorContext,
-          "xmlDocDump: document not in UTF8\n");
-      return -1;
-    }
-    if (enc != XML_CHAR_ENCODING_UTF8) {
-      handler = xmlFindCharEncodingHandler (encoding);
-      if (handler == NULL) {
-        xmlFree ((char *) cur->encoding);
-        cur->encoding = NULL;
-      }
-    }
-  }
-
-  buf = xmlOutputBufferCreateFile (out, handler);
-
-  indent = xmlIndentTreeOutput;
-  xmlIndentTreeOutput = 1;
-  ret = xmlSaveFormatFileTo (buf, cur, NULL, 1);
-  xmlIndentTreeOutput = indent;
-#else
-  /* apparently this doesn't return anything in libxml1 */
-  xmlDocDump (out, cur);
-  ret = 1;
-#endif
-
-  return ret;
-}
-
-/**
- * gst_xml_parse_doc:
- * @xml: a pointer to a GstXML object
- * @doc: a pointer to an xml document to parse
- * @root: The name of the root object to build
- *
- * Fills the GstXML object with the elements from the
- * xmlDocPtr.
- *
- * Returns: TRUE on success, FALSE otherwise
- */
-gboolean
-gst_xml_parse_doc (GstXML * xml, xmlDocPtr doc, const guchar * root)
-{
-  xmlNodePtr field, cur;
-  xmlNsPtr ns;
-
-  cur = xmlDocGetRootElement (doc);
-  if (cur == NULL) {
-    g_warning ("gstxml: empty document\n");
-    return FALSE;
-  }
-  ns = xmlSearchNsByHref (doc, cur,
-      (xmlChar *) "http://gstreamer.net/gst-core/1.0/");
-  if (ns == NULL) {
-    g_warning ("gstxml: document of wrong type, core namespace not found\n");
-    return FALSE;
-  }
-  if (strcmp ((char *) cur->name, "gstreamer")) {
-    g_warning ("gstxml: XML file is in wrong format\n");
-    return FALSE;
-  }
-
-  gst_class_signal_connect (GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (xml)),
-      "object_loaded", (gpointer) gst_xml_object_loaded, xml);
-
-  xml->ns = ns;
-
-  field = cur->xmlChildrenNode;
-
-  while (field) {
-    if (!strcmp ((char *) field->name, "element") && (field->ns == xml->ns)) {
-      GstElement *element;
-
-      element = gst_xml_make_element (field, NULL);
-
-      xml->topelements = g_list_prepend (xml->topelements, element);
-    }
-    field = field->next;
-  }
-
-  xml->topelements = g_list_reverse (xml->topelements);
-
-  return TRUE;
-}
-
-/* FIXME 0.9: Why guchar*? */
-/**
- * gst_xml_parse_file:
- * @xml: a pointer to a GstXML object
- * @fname: The filename with the xml description
- * @root: The name of the root object to build
- *
- * Fills the GstXML object with the corresponding elements from
- * the XML file fname. Optionally it will only build the element from
- * the element node root (if it is not NULL). This feature is useful
- * if you only want to build a specific element from an XML file
- * but not the pipeline it is embedded in.
- *
- * Pass "-" as fname to read from stdin. You can also pass a URI
- * of any format that libxml supports, including http.
- *
- * Returns: TRUE on success, FALSE otherwise
- */
-gboolean
-gst_xml_parse_file (GstXML * xml, const guchar * fname, const guchar * root)
-{
-  xmlDocPtr doc;
-  gboolean ret;
-
-  g_return_val_if_fail (fname != NULL, FALSE);
-
-  doc = xmlParseFile ((char *) fname);
-
-  if (!doc) {
-    g_warning ("gstxml: XML file \"%s\" could not be read\n", fname);
-    return FALSE;
-  }
-
-  ret = gst_xml_parse_doc (xml, doc, root);
-
-  xmlFreeDoc (doc);
-  return ret;
-}
-
-/* FIXME 0.9: guchar* */
-/**
- * gst_xml_parse_memory:
- * @xml: a pointer to a GstXML object
- * @buffer: a pointer to the in memory XML buffer
- * @size: the size of the buffer
- * @root: the name of the root objects to build
- *
- * Fills the GstXML object with the corresponding elements from
- * an in memory XML buffer.
- *
- * Returns: TRUE on success
- */
-gboolean
-gst_xml_parse_memory (GstXML * xml, guchar * buffer, guint size,
-    const gchar * root)
-{
-  xmlDocPtr doc;
-  gboolean ret;
-
-  g_return_val_if_fail (buffer != NULL, FALSE);
-
-  doc = xmlParseMemory ((char *) buffer, size);
-
-  ret = gst_xml_parse_doc (xml, doc, (const xmlChar *) root);
-
-  xmlFreeDoc (doc);
-  return ret;
-}
-
-static void
-gst_xml_object_loaded (GstObject * private, GstObject * object, xmlNodePtr self,
-    gpointer data)
-{
-  GstXML *xml = GST_XML (data);
-
-  /* FIXME check that this element was created from the same xmlDocPtr... */
-  g_signal_emit (xml, gst_xml_signals[OBJECT_LOADED], 0, object, self);
-}
-
-/**
- * gst_xml_get_topelements:
- * @xml: The GstXML to get the elements from
- *
- * Retrieve a list of toplevel elements.
- *
- * Returns: a GList of top-level elements. The caller does not own a copy
- * of the list and must not free or modify the list. The caller also does not
- * own a reference to any of the elements in the list and should obtain its own
- * reference using gst_object_ref() if necessary.
- */
-GList *
-gst_xml_get_topelements (GstXML * xml)
-{
-  g_return_val_if_fail (xml != NULL, NULL);
-
-  return xml->topelements;
-}
-
-/* FIXME 0.11: why is the arg guchar* instead of gchar*? */
-/**
- * gst_xml_get_element:
- * @xml: The GstXML to get the element from
- * @name: The name of element to retrieve
- *
- * This function is used to get a pointer to the GstElement corresponding
- * to name in the pipeline description. You would use this if you have
- * to do anything to the element after loading.
- *
- * Returns: a pointer to a new GstElement, caller owns returned reference.
- */
-GstElement *
-gst_xml_get_element (GstXML * xml, const guchar * name)
-{
-  GstElement *element;
-  GList *topelements;
-
-  g_return_val_if_fail (xml != NULL, NULL);
-  g_return_val_if_fail (name != NULL, NULL);
-
-  GST_DEBUG ("gstxml: getting element \"%s\"", name);
-
-  topelements = gst_xml_get_topelements (xml);
-
-  while (topelements) {
-    GstElement *top = GST_ELEMENT (topelements->data);
-
-    GST_DEBUG ("gstxml: getting element \"%s\"", name);
-    if (!strcmp (GST_ELEMENT_NAME (top), (char *) name)) {
-      return GST_ELEMENT_CAST (gst_object_ref (top));
-    } else {
-      if (GST_IS_BIN (top)) {
-        element = gst_bin_get_by_name (GST_BIN (top), (gchar *) name);
-
-        if (element)
-          return element;
-      }
-    }
-    topelements = g_list_next (topelements);
-  }
-  return NULL;
-}
-
-/**
- * gst_xml_make_element:
- * @cur: the xml node
- * @parent: the parent of this object when it's loaded
- *
- * Load the element from the XML description
- *
- * Returns: the new element
- */
-GstElement *
-gst_xml_make_element (xmlNodePtr cur, GstObject * parent)
-{
-  xmlNodePtr children = cur->xmlChildrenNode;
-  GstElement *element;
-  gchar *name = NULL;
-  gchar *type = NULL;
-
-  /* first get the needed tags to construct the element */
-  while (children) {
-    if (!strcmp ((char *) children->name, "name")) {
-      name = (gchar *) xmlNodeGetContent (children);
-    } else if (!strcmp ((char *) children->name, "type")) {
-      type = (gchar *) xmlNodeGetContent (children);
-    }
-    children = children->next;
-  }
-  g_return_val_if_fail (name != NULL, NULL);
-  g_return_val_if_fail (type != NULL, NULL);
-
-  GST_CAT_INFO (GST_CAT_XML, "loading \"%s\" of type \"%s\"", name, type);
-
-  element = gst_element_factory_make (type, name);
-
-  g_return_val_if_fail (element != NULL, NULL);
-
-  g_free (type);
-  g_free (name);
-
-  /* ne need to set the parent on this object bacause the pads */
-  /* will go through the hierarchy to link to their peers */
-  if (parent) {
-    if (GST_IS_BIN (parent)) {
-      gst_bin_add (GST_BIN (parent), element);
-    } else {
-      gst_object_set_parent (GST_OBJECT (element), parent);
-    }
-  }
-
-  gst_object_restore_thyself (GST_OBJECT (element), cur);
-
-  return element;
-}
-
-#else
-
-/* FIXME: keep this dummy _get_type function around for now, so
- * gobject-introspection doesn't fail in the GST_REMOVE_DEPRECATED and
- * GST_DISABLE_LOADSAVE case */
-GType gst_xml_get_type (void);
-
-GType
-gst_xml_get_type (void)
-{
-  return g_pointer_type_register_static ("GstXML");
-}
-
-#endif
diff --git a/gst/gstxml.h b/gst/gstxml.h
deleted file mode 100644 (file)
index 4f61a82..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wim.taymans@chello.be>
- *
- * gstxml.h: Header for XML save/restore operations of pipelines
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_XML_H__
-#define __GST_XML_H__
-
-#include <gst/gstconfig.h>
-
-#ifndef GST_DISABLE_DEPRECATED
-#ifndef GST_DISABLE_LOADSAVE
-
-#include <gst/gstelement.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_XML           (gst_xml_get_type ())
-#define GST_XML(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XML, GstXML))
-#define GST_IS_XML(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XML))
-#define GST_XML_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_XML, GstXMLClass))
-#define GST_IS_XML_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_XML))
-#define GST_XML_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XML, GstXMLClass))
-
-typedef struct _GstXML GstXML;
-typedef struct _GstXMLClass GstXMLClass;
-
-/**
- * GstXML:
- * @topelements: list of element nodes
- * @ns: name space
- *
- * XML parser object
- */
-struct _GstXML {
-  GstObject object;
-
-  /*< public >*/
-  GList      *topelements;
-
-  xmlNsPtr ns;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-struct _GstXMLClass {
-  GstObjectClass parent_class;
-
-  /* signal callbacks */
-  void (*object_loaded)         (GstXML *xml, GstObject *object, xmlNodePtr self);
-  void (*object_saved)          (GstXML *xml, GstObject *object, xmlNodePtr self);
-
-  gpointer _gst_reserved[GST_PADDING];
-};
-
-GType          gst_xml_get_type        (void);
-
-
-/* create an XML document out of a pipeline */
-xmlDocPtr      gst_xml_write           (GstElement *element);
-
-/* write a formatted representation of a pipeline to an open file */
-gint           gst_xml_write_file      (GstElement *element, FILE *out);
-
-GstXML*                gst_xml_new             (void);
-
-gboolean       gst_xml_parse_doc       (GstXML *xml, xmlDocPtr doc, const guchar *root);
-gboolean       gst_xml_parse_file      (GstXML *xml, const guchar *fname, const guchar *root);
-gboolean       gst_xml_parse_memory    (GstXML *xml, guchar *buffer, guint size, const gchar *root);
-
-
-GstElement*    gst_xml_get_element     (GstXML *xml, const guchar *name);
-GList*         gst_xml_get_topelements (GstXML *xml);
-
-GstElement*    gst_xml_make_element    (xmlNodePtr cur, GstObject *parent);
-
-G_END_DECLS
-
-#else /* GST_DISABLE_LOADSAVE */
-
-#if defined __GNUC__ && __GNUC__ >= 3
-#pragma GCC poison gst_xml_write
-#pragma GCC poison gst_xml_new
-#pragma GCC poison gst_xml_parse_doc
-#pragma GCC poison gst_xml_parse_file
-#pragma GCC poison gst_xml_parse_memory
-#pragma GCC poison gst_xml_get_element
-#pragma GCC poison gst_xml_get_topelements
-#endif
-
-#endif /* GST_DISABLE_LOADSAVE */
-
-#endif
-
-#endif /* __GST_XML_H__ */
index d9b368c..aa123db 100644 (file)
@@ -79,6 +79,21 @@ __gst_math_compat_rintf (float x)
 #define rintf(x) __gst_math_compat_rintf(x)
 #endif
 
+#ifndef NAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define __GST_NAN_BYTES        { 0x7f, 0xc0, 0, 0 }
+#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define __GST_NAN_BYTES        { 0, 0, 0xc0, 0x7f }
+#endif
+static union {
+  unsigned char __c[4];
+  float __d;
+} __gst_nan_union G_GNUC_UNUSED = {
+  __GST_NAN_BYTES
+};
+#define NAN    (__gst_nan_union.__d)
+#endif
+
 G_END_DECLS
 
 #endif /* __GST_MATH_COMPAT_H__ */
index 84736f6..edff324 100644 (file)
@@ -16,7 +16,7 @@ CLEANFILES += grammar.tab.c lex.priv_gst_parse_yy.c
 
 # can't use GST_ALL_CFLAGS here because that'd pull in -Werror
 libgstparse_la_CFLAGS = -I$(top_srcdir) -I$(top_builddir) \
-       $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_OPTION_CFLAGS)
+       $(GLIB_CFLAGS) $(GST_OPTION_CFLAGS)
 libgstparse_la_LIBADD = $(GST_ALL_LIBS)
 
 noinst_HEADERS = grammar.tab.h types.h
index d569497..613c409 100644 (file)
@@ -40,6 +40,28 @@ hierarchy, and a set of media-agnostic core elements.
 
  <release>
   <Version>
+   <revision>0.11.1</revision>
+   <branch>0.11</branch>
+   <name>Sweet New Blossom</name>
+   <created>2011-09-29</created>
+   <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-0.11.1.tar.bz2" />
+   <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-0.11.1.tar.gz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
+   <revision>0.11.0</revision>
+   <branch>0.11</branch>
+   <name>It's a boy</name>
+   <created>2011-08-02</created>
+   <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-0.11.0.tar.bz2" />
+   <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-0.11.0.tar.gz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
    <revision>0.10.35</revision>
    <branch>0.10</branch>
    <name>Nuclear Fission</name>
index 7a542fd..a8716aa 100644 (file)
@@ -1,8 +1,7 @@
-%define                gstreamer       gstreamer
+%define                gstreamer       gstreamer011
 %define                majorminor      @GST_MAJORMINOR@
 
 %define        _glib2          @GLIB_REQ@
-%define        _libxml2        @LIBXML2_REQ@
 
 Name:          %{gstreamer}
 Version:       @VERSION@
@@ -15,12 +14,7 @@ URL:         http://gstreamer.freedesktop.org/
 Source:        http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-%{version}.tar.bz2
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
-Requires:      gstreamer-tools >= %{version}
-# gst-feedback uses these
-Requires:      which, pkgconfig
-
 BuildRequires:         glib2-devel >= %{_glib2}
-BuildRequires:         libxml2-devel >= %{_libxml2}
 BuildRequires:         bison
 BuildRequires:         flex
 BuildRequires:         m4
@@ -60,7 +54,6 @@ Group:                Development/Libraries
 
 Requires:      %{name} = %{version}-%{release}
 Requires:      glib2-devel >= %{_glib2}
-Requires:      libxml2-devel >= %{_libxml2}
 Requires:      check-devel
 
 %description devel
@@ -75,28 +68,13 @@ This package contains the libraries and includes files necessary to develop
 applications and plugins for GStreamer, as well as general and API
 documentation.
 
-%package -n gstreamer-tools
-Summary:       common tools and files for GStreamer streaming media framework
-Group:                 Applications/Multimedia
-
-%description -n gstreamer-tools
-GStreamer is a streaming media framework, based on graphs of filters which
-operate on media data. Applications using this library can do anything
-from real-time sound processing to playing videos, and just about anything
-else media-related.  Its plugin-based architecture means that new data
-types or processing capabilities can be added simply by installing new   
-plugins.
-
-This package contains wrapper scripts for the command-line tools that work
-with different major/minor versions of GStreamer.
-
 %prep
 %setup -q -n gstreamer-%{version}
 
 %build
 # 0.10.0: manuals do not build due to an openjade error; disable for now
 %configure \
-  --with-package-name='CVS gstreamer package' \
+  --with-package-name='gstreamer package' \
   --with-package-origin='http://gstreamer.freedesktop.org' \
   --enable-debug \
   --enable-gtk-doc \
@@ -136,48 +114,31 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/libgstreamer-%{majorminor}.so.*
 %{_libdir}/libgstbase-%{majorminor}.so.*
 %{_libdir}/libgstcontroller-%{majorminor}.so.*
-%{_libdir}/libgstdataprotocol-%{majorminor}.so.*
 %{_libdir}/libgstnet-%{majorminor}.so.*
 
 %dir %{_libdir}/gstreamer-%{majorminor}
 %{_libdir}/gstreamer-%{majorminor}/libgstcoreelements.so
-%{_libdir}/gstreamer-%{majorminor}/libgstcoreindexers.so
 
-%{_bindir}/gst-feedback-%{majorminor}
 %{_bindir}/gst-inspect-%{majorminor}
 %{_bindir}/gst-launch-%{majorminor}
 %{_bindir}/gst-typefind-%{majorminor}
-%{_bindir}/gst-xmlinspect-%{majorminor}
-%{_bindir}/gst-xmllaunch-%{majorminor}
 %{_libexecdir}/gstreamer-%{majorminor}/gst-plugin-scanner
-%doc %{_mandir}/man1/gst-feedback-%{majorminor}.*
 %doc %{_mandir}/man1/gst-inspect-%{majorminor}.*
 %doc %{_mandir}/man1/gst-launch-%{majorminor}.*
 %doc %{_mandir}/man1/gst-typefind-%{majorminor}.*
-%doc %{_mandir}/man1/gst-xmlinspect-%{majorminor}.*
-%doc %{_mandir}/man1/gst-xmllaunch-%{majorminor}.*
 %doc %{_datadir}/doc/gstreamer-%{majorminor}/manual
 %doc %{_datadir}/doc/gstreamer-%{majorminor}/pwg
 %doc %{_datadir}/doc/gstreamer-%{majorminor}/faq/
-%{_libdir}/girepository-1.0/Gst-0.10.typelib
-%{_libdir}/girepository-1.0/GstBase-0.10.typelib
-%{_libdir}/girepository-1.0/GstCheck-0.10.typelib
-%{_libdir}/girepository-1.0/GstController-0.10.typelib
-%{_libdir}/girepository-1.0/GstNet-0.10.typelib
-%{_datadir}/gir-1.0/Gst-0.10.gir
-%{_datadir}/gir-1.0/GstBase-0.10.gir
-%{_datadir}/gir-1.0/GstCheck-0.10.gir
-%{_datadir}/gir-1.0/GstController-0.10.gir
-%{_datadir}/gir-1.0/GstNet-0.10.gir
-
-%files -n gstreamer-tools
-%defattr(-, root, root, -)
-%{_bindir}/gst-feedback
-%{_bindir}/gst-inspect
-%{_bindir}/gst-launch
-%{_bindir}/gst-typefind
-%{_bindir}/gst-xmlinspect
-%{_bindir}/gst-xmllaunch
+%{_libdir}/girepository-1.0/Gst-%{majorminor}.typelib
+%{_libdir}/girepository-1.0/GstBase-%{majorminor}.typelib
+%{_libdir}/girepository-1.0/GstCheck-%{majorminor}.typelib
+%{_libdir}/girepository-1.0/GstController-%{majorminor}.typelib
+%{_libdir}/girepository-1.0/GstNet-%{majorminor}.typelib
+%{_datadir}/gir-1.0/Gst-%{majorminor}.gir
+%{_datadir}/gir-1.0/GstBase-%{majorminor}.gir
+%{_datadir}/gir-1.0/GstCheck-%{majorminor}.gir
+%{_datadir}/gir-1.0/GstController-%{majorminor}.gir
+%{_datadir}/gir-1.0/GstNet-%{majorminor}.gir
 
 %files devel
 %defattr(-, root, root, -)
@@ -188,11 +149,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_includedir}/gstreamer-%{majorminor}/gst/base
 %{_includedir}/gstreamer-%{majorminor}/gst/check
 %{_includedir}/gstreamer-%{majorminor}/gst/controller
-%{_includedir}/gstreamer-%{majorminor}/gst/dataprotocol
 %{_includedir}/gstreamer-%{majorminor}/gst/net
 
 %{_libdir}/libgstreamer-%{majorminor}.so
-%{_libdir}/libgstdataprotocol-%{majorminor}.so
 %{_libdir}/libgstbase-%{majorminor}.so
 %{_libdir}/libgstcheck-%{majorminor}.so*
 %{_libdir}/libgstcontroller-%{majorminor}.so
@@ -203,7 +162,6 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/pkgconfig/gstreamer-base-%{majorminor}.pc
 %{_libdir}/pkgconfig/gstreamer-controller-%{majorminor}.pc
 %{_libdir}/pkgconfig/gstreamer-check-%{majorminor}.pc
-%{_libdir}/pkgconfig/gstreamer-dataprotocol-%{majorminor}.pc
 %{_libdir}/pkgconfig/gstreamer-net-%{majorminor}.pc
 
 %doc %{_datadir}/gtk-doc/html/gstreamer-%{majorminor}/*
@@ -211,6 +169,12 @@ rm -rf $RPM_BUILD_ROOT
 %doc %{_datadir}/gtk-doc/html/gstreamer-plugins-%{majorminor}/*
 
 %changelog
+* Sat Aug 06 2011 Thomas Vander Stichele <thomas at apestaart dot org>
+- Use majorminor correctly for .gir files
+- Remove gstreamer-tools completely since the unversioned tools have been
+  removed
+- Rename package to gstreamer011 to be parallel-installable
+
 * Thu Apr 3 2008 Christian Schaller <christian.schaller at collabora co uk>
 - Update spec file to make inclusion of all docs explicit
 
index 65a4499..d02c4c7 100644 (file)
@@ -4,29 +4,15 @@ else
 SUBDIRS_CHECK =
 endif
 
-if GST_DISABLE_NET
-SUBDIRS_NET =
-else
-if HAVE_SYS_SOCKET_H
-SUBDIRS_NET = net
-else
-if HAVE_WINSOCK2_H
-SUBDIRS_NET = net
-else
-SUBDIRS_NET =
-endif
-endif
-endif
-
 if GST_DISABLE_REGISTRY
 SUBDIRS_HELPERS =
 else
 SUBDIRS_HELPERS = helpers
 endif
 
-SUBDIRS_ALWAYS = base controller dataprotocol
+SUBDIRS_ALWAYS = base controller net
 
-SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_NET) $(SUBDIRS_HELPERS)
+SUBDIRS = $(SUBDIRS_ALWAYS) $(SUBDIRS_CHECK) $(SUBDIRS_HELPERS)
 DIST_SUBDIRS = $(SUBDIRS_ALWAYS) check net helpers
 
 Android.mk: Makefile.am
index 4c8bccf..4ff2ec4 100644 (file)
@@ -14,8 +14,7 @@ libgstbase_@GST_MAJORMINOR@_la_SOURCES = \
        gstcollectpads.c        \
        gstcollectpads2.c       \
        gstpushsrc.c            \
-       gsttypefindhelper.c     \
-       gstdataqueue.c
+       gsttypefindhelper.c
 
 libgstbase_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
 libgstbase_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS)
@@ -36,13 +35,15 @@ libgstbase_@GST_MAJORMINOR@include_HEADERS =        \
        gstcollectpads.h        \
        gstcollectpads2.h       \
        gstpushsrc.h            \
-       gsttypefindhelper.h     \
-       gstdataqueue.h
+       gsttypefindhelper.h
 
 noinst_HEADERS = \
        gstbytereader-docs.h \
        gstbytewriter-docs.h \
-       gstbitreader-docs.h
+       gstbitreader-docs.h \
+       gstindex.h
+
+EXTRA_DIST = gstindex.c gstmemindex.c
 
 CLEANFILES = *.gcno *.gcda *.gcov
 
@@ -75,7 +76,9 @@ GstBase-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_MAJORMINO
                GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
                $(INTROSPECTION_SCANNER) -v --namespace GstBase \
                --nsversion=@GST_MAJORMINOR@ \
+               --warn-all \
                --strip-prefix=Gst \
+               -DGST_USE_UNSTABLE_API \
                -I$(top_srcdir) \
                -I$(top_srcdir)/libs \
                -I$(top_builddir) \
@@ -83,12 +86,12 @@ GstBase-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_MAJORMINO
                $(gir_cincludes) \
                --add-include-path=$(top_builddir)/gst \
                --library-path=$(top_builddir)/gst \
-               --library=$(top_builddir)/gst/libgstreamer-0.10.la \
-               --library=libgstbase-0.10.la \
-               --include=Gst-0.10 \
+               --library=$(top_builddir)/gst/libgstreamer-0.11.la \
+               --library=libgstbase-0.11.la \
+               --include=Gst-0.11 \
                --libtool="$(top_builddir)/libtool" \
-               --pkg gstreamer-0.10 \
-               --pkg-export gstreamer-base-0.10 \
+               --pkg gstreamer-@GST_MAJORMINOR@ \
+               --pkg-export gstreamer-base-@GST_MAJORMINOR@ \
                --add-init-section="gst_init(NULL,NULL);" \
                --output $@ \
                $(gir_headers) \
index 0f8053d..b932f3a 100644 (file)
  *
  * The theory of operation is like this: All buffers received are put
  * into the adapter using gst_adapter_push() and the data is then read back
- * in chunks of the desired size using gst_adapter_peek(). After the data is
- * processed, it is freed using gst_adapter_flush().
+ * in chunks of the desired size using gst_adapter_map()/gst_adapter_unmap()
+ * and/or gst_adapter_copy(). After the data has been processed, it is freed
+ * using gst_adapter_unmap().
  *
  * Other methods such as gst_adapter_take() and gst_adapter_take_buffer()
- * combine gst_adapter_peek() and gst_adapter_flush() in one method and are
+ * combine gst_adapter_map() and gst_adapter_unmap() in one method and are
  * potentially more convenient for some use cases.
  *
  * For example, a sink pad's chain function that needs to pass data to a library
  *   gst_adapter_push (adapter, buffer);
  *   // while we can read out 512 bytes, process them
  *   while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) {
+ *     const guint8 *data = gst_adapter_map (adapter, 512);
  *     // use flowreturn as an error value
- *     ret = my_library_foo (gst_adapter_peek (adapter, 512));
+ *     ret = my_library_foo (data);
+ *     gst_adapter_unmap (adapter);
  *     gst_adapter_flush (adapter, 512);
  *   }
  *
 /* default size for the assembled data buffer */
 #define DEFAULT_SIZE 4096
 
+static void gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush);
+
 GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
 #define GST_CAT_DEFAULT gst_adapter_debug
 
@@ -124,28 +129,27 @@ GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
 
 struct _GstAdapterPrivate
 {
-  GstClockTime timestamp;
-  guint64 distance;
+  GstClockTime pts;
+  guint64 pts_distance;
+  GstClockTime dts;
+  guint64 dts_distance;
 
-  guint scan_offset;
+  gsize scan_offset;
   GSList *scan_entry;
+
+  gpointer cdata;
+  gsize csize;
 };
 
-#define _do_init(thing) \
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
-GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,
-    _do_init);
+#define gst_adapter_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstAdapter, gst_adapter, G_TYPE_OBJECT, _do_init);
 
 static void gst_adapter_dispose (GObject * object);
 static void gst_adapter_finalize (GObject * object);
 
 static void
-gst_adapter_base_init (gpointer g_class)
-{
-  /* nop */
-}
-
-static void
 gst_adapter_class_init (GstAdapterClass * klass)
 {
   GObjectClass *object = G_OBJECT_CLASS (klass);
@@ -157,13 +161,15 @@ gst_adapter_class_init (GstAdapterClass * klass)
 }
 
 static void
-gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class)
+gst_adapter_init (GstAdapter * adapter)
 {
   adapter->priv = GST_ADAPTER_GET_PRIVATE (adapter);
   adapter->assembled_data = g_malloc (DEFAULT_SIZE);
   adapter->assembled_size = DEFAULT_SIZE;
-  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
-  adapter->priv->distance = 0;
+  adapter->priv->pts = GST_CLOCK_TIME_NONE;
+  adapter->priv->pts_distance = 0;
+  adapter->priv->dts = GST_CLOCK_TIME_NONE;
+  adapter->priv->dts_distance = 0;
 }
 
 static void
@@ -210,6 +216,10 @@ gst_adapter_clear (GstAdapter * adapter)
 {
   g_return_if_fail (GST_IS_ADAPTER (adapter));
 
+  if (adapter->priv->cdata) {
+    gst_adapter_unmap (adapter);
+  }
+
   g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL);
   g_slist_free (adapter->buflist);
   adapter->buflist = NULL;
@@ -217,34 +227,41 @@ gst_adapter_clear (GstAdapter * adapter)
   adapter->size = 0;
   adapter->skip = 0;
   adapter->assembled_len = 0;
-  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
-  adapter->priv->distance = 0;
+  adapter->priv->pts = GST_CLOCK_TIME_NONE;
+  adapter->priv->pts_distance = 0;
+  adapter->priv->dts = GST_CLOCK_TIME_NONE;
+  adapter->priv->dts_distance = 0;
   adapter->priv->scan_offset = 0;
   adapter->priv->scan_entry = NULL;
 }
 
 static inline void
-update_timestamp (GstAdapter * adapter, GstBuffer * buf)
+update_timestamps (GstAdapter * adapter, GstBuffer * buf)
 {
-  GstClockTime timestamp;
-
-  timestamp = GST_BUFFER_TIMESTAMP (buf);
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-    GST_LOG_OBJECT (adapter, "new timestamp %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timestamp));
-    adapter->priv->timestamp = timestamp;
-    adapter->priv->distance = 0;
+  GstClockTime pts, dts;
+
+  pts = GST_BUFFER_PTS (buf);
+  if (GST_CLOCK_TIME_IS_VALID (pts)) {
+    GST_LOG_OBJECT (adapter, "new pts %" GST_TIME_FORMAT, GST_TIME_ARGS (pts));
+    adapter->priv->pts = pts;
+    adapter->priv->pts_distance = 0;
+  }
+  dts = GST_BUFFER_DTS (buf);
+  if (GST_CLOCK_TIME_IS_VALID (dts)) {
+    GST_LOG_OBJECT (adapter, "new dts %" GST_TIME_FORMAT, GST_TIME_ARGS (dts));
+    adapter->priv->dts = dts;
+    adapter->priv->dts_distance = 0;
   }
 }
 
 /* copy data into @dest, skipping @skip bytes from the head buffers */
 static void
-copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
-    guint size)
+copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip,
+    gsize size)
 {
   GSList *g;
   GstBuffer *buf;
-  guint bsize, csize;
+  gsize bsize, csize;
 
   /* first step, do skipping */
   /* we might well be copying where we were scanning */
@@ -255,16 +272,18 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
     g = adapter->buflist;
   }
   buf = g->data;
-  bsize = GST_BUFFER_SIZE (buf);
+  bsize = gst_buffer_get_size (buf);
   while (G_UNLIKELY (skip >= bsize)) {
     skip -= bsize;
     g = g_slist_next (g);
     buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
+    bsize = gst_buffer_get_size (buf);
   }
   /* copy partial buffer */
   csize = MIN (bsize - skip, size);
-  memcpy (dest, GST_BUFFER_DATA (buf) + skip, csize);
+  GST_DEBUG ("bsize %" G_GSIZE_FORMAT ", skip %" G_GSIZE_FORMAT ", csize %"
+      G_GSIZE_FORMAT, bsize, skip, csize);
+  gst_buffer_extract (buf, skip, dest, csize);
   size -= csize;
   dest += csize;
 
@@ -272,10 +291,10 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
   while (size > 0) {
     g = g_slist_next (g);
     buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
+    bsize = gst_buffer_get_size (buf);
     if (G_LIKELY (bsize > 0)) {
       csize = MIN (bsize, size);
-      memcpy (dest, GST_BUFFER_DATA (buf), csize);
+      gst_buffer_extract (buf, 0, dest, csize);
       size -= csize;
       dest += csize;
     }
@@ -293,23 +312,23 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
 void
 gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
 {
-  guint size;
+  gsize size;
 
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (GST_IS_BUFFER (buf));
 
-  size = GST_BUFFER_SIZE (buf);
+  size = gst_buffer_get_size (buf);
   adapter->size += size;
 
   /* Note: merging buffers at this point is premature. */
   if (G_UNLIKELY (adapter->buflist == NULL)) {
-    GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
+    GST_LOG_OBJECT (adapter, "pushing first %" G_GSIZE_FORMAT " bytes", size);
     adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
-    update_timestamp (adapter, buf);
+    update_timestamps (adapter, buf);
   } else {
     /* Otherwise append to the end, and advance our end pointer */
-    GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
-        adapter->size);
+    GST_LOG_OBJECT (adapter, "pushing %" G_GSIZE_FORMAT " bytes at end, "
+        "size now %" G_GSIZE_FORMAT, size, adapter->size);
     adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
     adapter->buflist_end = g_slist_next (adapter->buflist_end);
   }
@@ -322,11 +341,12 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
  * Returns TRUE if it managed to merge anything.
  */
 static gboolean
-gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size)
+gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size)
 {
   GstBuffer *cur, *head;
   GSList *g;
   gboolean ret = FALSE;
+  gsize hsize;
 
   g = adapter->buflist;
   if (g == NULL)
@@ -338,18 +358,20 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size)
   /* How large do we want our head buffer? The requested size, plus whatever's
    * been skipped already */
   size += adapter->skip;
+  hsize = gst_buffer_get_size (head);
 
-  while (g != NULL && GST_BUFFER_SIZE (head) < size) {
+  while (g != NULL && hsize < size) {
     cur = g->data;
     if (!gst_buffer_is_span_fast (head, cur))
       return ret;
 
     /* Merge the head buffer and the next in line */
-    GST_LOG_OBJECT (adapter,
-        "Merging buffers of size %u & %u in search of target %u",
-        GST_BUFFER_SIZE (head), GST_BUFFER_SIZE (cur), size);
+    GST_LOG_OBJECT (adapter, "Merging buffers of size %" G_GSIZE_FORMAT " & %"
+        G_GSIZE_FORMAT " in search of target %" G_GSIZE_FORMAT,
+        hsize, gst_buffer_get_size (cur), size);
 
     head = gst_buffer_join (head, cur);
+    hsize = gst_buffer_get_size (head);
     ret = TRUE;
 
     /* Delete the front list item, and store our new buffer in the 2nd list
@@ -368,9 +390,9 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size)
 }
 
 /**
- * gst_adapter_peek:
+ * gst_adapter_map:
  * @adapter: a #GstAdapter
- * @size: the number of bytes to peek
+ * @size: the number of bytes to map/peek
  *
  * Gets the first @size bytes stored in the @adapter. The returned pointer is
  * valid until the next function is called on the adapter.
@@ -389,17 +411,21 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size)
  * Returns: (transfer none) (array length=size): a pointer to the first
  *     @size bytes of data, or NULL
  */
-const guint8 *
-gst_adapter_peek (GstAdapter * adapter, guint size)
+gconstpointer
+gst_adapter_map (GstAdapter * adapter, gsize size)
 {
   GstBuffer *cur;
-  guint skip;
-  guint toreuse, tocopy;
+  gsize skip, csize;
+  gsize toreuse, tocopy;
   guint8 *data;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (size > 0, NULL);
 
+  if (adapter->priv->cdata) {
+    gst_adapter_unmap (adapter);
+  }
+
   /* we don't have enough data, return NULL. This is unlikely
    * as one usually does an _available() first instead of peeking a
    * random size. */
@@ -410,20 +436,20 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
   if (adapter->assembled_len >= size)
     return adapter->assembled_data;
 
-  /* our head buffer has enough data left, return it */
-  cur = adapter->buflist->data;
-  skip = adapter->skip;
-  if (GST_BUFFER_SIZE (cur) >= size + skip)
-    return GST_BUFFER_DATA (cur) + skip;
-
-  /* We may be able to efficiently merge buffers in our pool to
-   * gather a big enough chunk to return it from the head buffer directly */
-  if (gst_adapter_try_to_merge_up (adapter, size)) {
-    /* Merged something! Check if there's enough avail now */
+  do {
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= size + skip)
-      return GST_BUFFER_DATA (cur) + skip;
-  }
+    skip = adapter->skip;
+
+    csize = gst_buffer_get_size (cur);
+    if (csize >= size + skip) {
+      data = gst_buffer_map (cur, &csize, NULL, GST_MAP_READ);
+      adapter->priv->cdata = data;
+      adapter->priv->csize = csize;
+      return data + skip;
+    }
+    /* We may be able to efficiently merge buffers in our pool to
+     * gather a big enough chunk to return it from the head buffer directly */
+  } while (gst_adapter_try_to_merge_up (adapter, size));
 
   /* see how much data we can reuse from the assembled memory and how much
    * we need to copy */
@@ -433,7 +459,7 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
   /* Gonna need to copy stuff out */
   if (G_UNLIKELY (adapter->assembled_size < size)) {
     adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
-    GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %u",
+    GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %" G_GSIZE_FORMAT,
         adapter->assembled_size);
     if (toreuse == 0) {
       GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "alloc new buffer");
@@ -443,13 +469,14 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
       adapter->assembled_data = g_malloc (adapter->assembled_size);
     } else {
       /* we are going to reuse all data, realloc then */
-      GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "reusing %u bytes", toreuse);
+      GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "reusing %" G_GSIZE_FORMAT " bytes",
+          toreuse);
       adapter->assembled_data =
           g_realloc (adapter->assembled_data, adapter->assembled_size);
     }
   }
-  GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy remaining %u bytes from adapter",
-      tocopy);
+  GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy remaining %" G_GSIZE_FORMAT
+      " bytes from adapter", tocopy);
   data = adapter->assembled_data;
   copy_into_unchecked (adapter, data + toreuse, skip + toreuse, tocopy);
   adapter->assembled_len = size;
@@ -458,6 +485,24 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
 }
 
 /**
+ * gst_adapter_unmap:
+ * @adapter: a #GstAdapter
+ *
+ * Releases the memory obtained with the last gst_adapter_map().
+ */
+void
+gst_adapter_unmap (GstAdapter * adapter)
+{
+  g_return_if_fail (GST_IS_ADAPTER (adapter));
+
+  if (adapter->priv->cdata) {
+    GstBuffer *cur = adapter->buflist->data;
+    gst_buffer_unmap (cur, adapter->priv->cdata, adapter->priv->csize);
+    adapter->priv->cdata = NULL;
+  }
+}
+
+/**
  * gst_adapter_copy:
  * @adapter: a #GstAdapter
  * @dest: (out caller-allocates) (array length=size): the memory to copy into
@@ -474,7 +519,7 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
  * Since: 0.10.12
  */
 void
-gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
+gst_adapter_copy (GstAdapter * adapter, gpointer dest, gsize offset, gsize size)
 {
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (size > 0);
@@ -491,17 +536,21 @@ gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
  * Flushes the first @flush bytes in the @adapter. The caller must ensure that
  * at least this many bytes are available.
  *
- * See also: gst_adapter_peek().
+ * See also: gst_adapter_map(), gst_adapter_unmap()
  */
 static void
-gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush)
+gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
 {
   GstBuffer *cur;
-  guint size;
+  gsize size;
   GstAdapterPrivate *priv;
   GSList *g;
 
-  GST_LOG_OBJECT (adapter, "flushing %u bytes", flush);
+  GST_LOG_OBJECT (adapter, "flushing %" G_GSIZE_FORMAT " bytes", flush);
+
+  if (adapter->priv->cdata) {
+    gst_adapter_unmap (adapter);
+  }
 
   priv = adapter->priv;
 
@@ -512,15 +561,17 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush)
   /* take skip into account */
   flush += adapter->skip;
   /* distance is always at least the amount of skipped bytes */
-  priv->distance -= adapter->skip;
+  priv->pts_distance -= adapter->skip;
+  priv->dts_distance -= adapter->skip;
 
   g = adapter->buflist;
   cur = g->data;
-  size = GST_BUFFER_SIZE (cur);
+  size = gst_buffer_get_size (cur);
   while (flush >= size) {
     /* can skip whole buffer */
     GST_LOG_OBJECT (adapter, "flushing out head buffer");
-    priv->distance += size;
+    priv->pts_distance += size;
+    priv->dts_distance += size;
     flush -= size;
 
     gst_buffer_unref (cur);
@@ -531,22 +582,23 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush)
       adapter->buflist_end = NULL;
       break;
     }
-    /* there is a new head buffer, update the timestamp */
+    /* there is a new head buffer, update the timestamps */
     cur = g->data;
-    update_timestamp (adapter, cur);
-    size = GST_BUFFER_SIZE (cur);
+    update_timestamps (adapter, cur);
+    size = gst_buffer_get_size (cur);
   }
   adapter->buflist = g;
   /* account for the remaining bytes */
   adapter->skip = flush;
-  adapter->priv->distance += flush;
+  adapter->priv->pts_distance += flush;
+  adapter->priv->dts_distance += flush;
   /* invalidate scan position */
   priv->scan_offset = 0;
   priv->scan_entry = NULL;
 }
 
 void
-gst_adapter_flush (GstAdapter * adapter, guint flush)
+gst_adapter_flush (GstAdapter * adapter, gsize flush)
 {
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (flush <= adapter->size);
@@ -560,10 +612,10 @@ gst_adapter_flush (GstAdapter * adapter, guint flush)
 
 /* internal function, nbytes should be flushed after calling this function */
 static guint8 *
-gst_adapter_take_internal (GstAdapter * adapter, guint nbytes)
+gst_adapter_take_internal (GstAdapter * adapter, gsize nbytes)
 {
   guint8 *data;
-  guint toreuse, tocopy;
+  gsize toreuse, tocopy;
 
   /* see how much data we can reuse from the assembled memory and how much
    * we need to copy */
@@ -575,24 +627,24 @@ gst_adapter_take_internal (GstAdapter * adapter, guint nbytes)
     /* we reuse already allocated memory but only when we're going to reuse
      * something from it because else we are worse than the malloc and copy
      * case below */
-    GST_LOG_OBJECT (adapter, "reusing %u bytes of assembled data", toreuse);
+    GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes of assembled"
+        " data", toreuse);
     /* we have enough free space in the assembled array */
     data = adapter->assembled_data;
     /* flush after this function should set the assembled_size to 0 */
     adapter->assembled_data = g_malloc (adapter->assembled_size);
   } else {
-    GST_LOG_OBJECT (adapter, "allocating %u bytes", nbytes);
+    GST_LOG_OBJECT (adapter, "allocating %" G_GSIZE_FORMAT " bytes", nbytes);
     /* not enough bytes in the assembled array, just allocate new space */
     data = g_malloc (nbytes);
     /* reuse what we can from the already assembled data */
     if (toreuse) {
-      GST_LOG_OBJECT (adapter, "reusing %u bytes", toreuse);
+      GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes", toreuse);
       memcpy (data, adapter->assembled_data, toreuse);
     }
   }
   if (tocopy) {
     /* copy the remaining data */
-    GST_LOG_OBJECT (adapter, "copying %u bytes", tocopy);
     copy_into_unchecked (adapter, toreuse + data, toreuse + adapter->skip,
         tocopy);
   }
@@ -614,10 +666,10 @@ gst_adapter_take_internal (GstAdapter * adapter, guint nbytes)
  * Returns: (transfer full) (array length=nbytes): oven-fresh hot data, or
  *     #NULL if @nbytes bytes are not available
  */
-guint8 *
-gst_adapter_take (GstAdapter * adapter, guint nbytes)
+gpointer
+gst_adapter_take (GstAdapter * adapter, gsize nbytes)
 {
-  guint8 *data;
+  gpointer data;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (nbytes > 0, NULL);
@@ -656,17 +708,18 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
  * Since: 0.10.6
  */
 GstBuffer *
-gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
+gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes)
 {
   GstBuffer *buffer;
   GstBuffer *cur;
-  guint hsize, skip;
+  gsize hsize, skip;
   guint8 *data;
 
   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 %u bytes", nbytes);
+  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
@@ -676,28 +729,28 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
 
   cur = adapter->buflist->data;
   skip = adapter->skip;
-  hsize = GST_BUFFER_SIZE (cur);
+  hsize = gst_buffer_get_size (cur);
 
   /* our head buffer has enough data left, return it */
   if (skip == 0 && hsize == nbytes) {
-    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
-        nbytes);
+    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
+        " as head buffer", nbytes);
     buffer = gst_buffer_ref (cur);
     goto done;
   } else if (hsize >= nbytes + skip) {
-    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
-        nbytes);
-    buffer = gst_buffer_create_sub (cur, skip, nbytes);
+    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
+        " via region copy", nbytes);
+    buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
     goto done;
   }
 
   if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
     /* Merged something, let's try again for sub-buffering */
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
-      GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
-          nbytes);
-      buffer = gst_buffer_create_sub (cur, skip, nbytes);
+    if (gst_buffer_get_size (cur) >= nbytes + skip) {
+      GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
+          " via sub-buffer", nbytes);
+      buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
       goto done;
     }
   }
@@ -705,9 +758,8 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
   data = gst_adapter_take_internal (adapter, nbytes);
 
   buffer = gst_buffer_new ();
-  GST_BUFFER_SIZE (buffer) = nbytes;
-  GST_BUFFER_DATA (buffer) = data;
-  GST_BUFFER_MALLOCDATA (buffer) = data;
+  gst_buffer_take_memory (buffer, -1,
+      gst_memory_new_wrapped (0, data, g_free, nbytes, 0, nbytes));
 
 done:
   gst_adapter_flush_unchecked (adapter, nbytes);
@@ -735,21 +787,21 @@ done:
  * Since: 0.10.31
  */
 GList *
-gst_adapter_take_list (GstAdapter * adapter, guint nbytes)
+gst_adapter_take_list (GstAdapter * adapter, gsize nbytes)
 {
   GQueue queue = G_QUEUE_INIT;
   GstBuffer *cur;
-  guint hsize, skip;
+  gsize hsize, skip;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (nbytes <= adapter->size, NULL);
 
-  GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
+  GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes);
 
   while (nbytes > 0) {
     cur = adapter->buflist->data;
     skip = adapter->skip;
-    hsize = MIN (nbytes, GST_BUFFER_SIZE (cur) - skip);
+    hsize = MIN (nbytes, gst_buffer_get_size (cur) - skip);
 
     cur = gst_adapter_take_buffer (adapter, hsize);
 
@@ -765,12 +817,12 @@ gst_adapter_take_list (GstAdapter * adapter, guint nbytes)
  * @adapter: a #GstAdapter
  *
  * Gets the maximum amount of bytes available, that is it returns the maximum
- * value that can be supplied to gst_adapter_peek() without that function
+ * value that can be supplied to gst_adapter_map() without that function
  * returning NULL.
  *
  * Returns: number of bytes available in @adapter
  */
-guint
+gsize
 gst_adapter_available (GstAdapter * adapter)
 {
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
@@ -789,11 +841,11 @@ gst_adapter_available (GstAdapter * adapter)
  * Returns: number of bytes that are available in @adapter without expensive
  * operations
  */
-guint
+gsize
 gst_adapter_available_fast (GstAdapter * adapter)
 {
   GstBuffer *cur;
-  guint size;
+  gsize size;
   GSList *g;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
@@ -810,7 +862,7 @@ gst_adapter_available_fast (GstAdapter * adapter)
   g = adapter->buflist;
   while (TRUE) {
     cur = g->data;
-    size = GST_BUFFER_SIZE (cur);
+    size = gst_buffer_get_size (cur);
     if (size != 0)
       break;
     g = g_slist_next (g);
@@ -821,32 +873,57 @@ gst_adapter_available_fast (GstAdapter * adapter)
 }
 
 /**
- * gst_adapter_prev_timestamp:
+ * gst_adapter_prev_pts:
  * @adapter: a #GstAdapter
  * @distance: (out) (allow-none): pointer to location for distance, or NULL
  *
- * Get the timestamp that was before the current byte in the adapter. When
- * @distance is given, the amount of bytes between the timestamp and the current
+ * Get the pts that was before the current byte in the adapter. When
+ * @distance is given, the amount of bytes between the pts and the current
  * position is returned.
  *
- * The timestamp is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
+ * 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 timestamp is removed from the adapter, the timestamp
+ * the first byte with a pts is removed from the adapter, the pts
  * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
  *
- * Returns: The previously seen timestamp.
+ * Returns: The previously seen pts.
+ */
+GstClockTime
+gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance)
+{
+  g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+
+  if (distance)
+    *distance = adapter->priv->pts_distance;
+
+  return adapter->priv->pts;
+}
+
+/**
+ * gst_adapter_prev_dts:
+ * @adapter: a #GstAdapter
+ * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ *
+ * Get the dts that was before the current byte 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: 0.10.24
+ * Returns: The previously seen dts.
  */
 GstClockTime
-gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance)
+gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
 {
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
 
   if (distance)
-    *distance = adapter->priv->distance;
+    *distance = adapter->priv->dts_distance;
 
-  return adapter->priv->timestamp;
+  return adapter->priv->dts;
 }
 
 /**
@@ -874,14 +951,14 @@ gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance)
  *
  * Since: 0.10.30
  */
-guint
+gsize
 gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
-    guint32 pattern, guint offset, guint size, guint32 * value)
+    guint32 pattern, gsize offset, gsize size, guint32 * value)
 {
   GSList *g;
-  guint skip, bsize, i;
+  gsize skip, bsize, osize, i;
   guint32 state;
-  guint8 *bdata;
+  guint8 *bdata, *odata;
   GstBuffer *buf;
 
   g_return_val_if_fail (size > 0, -1);
@@ -905,18 +982,20 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
     adapter->priv->scan_entry = NULL;
   }
   buf = g->data;
-  bsize = GST_BUFFER_SIZE (buf);
+  bsize = gst_buffer_get_size (buf);
   while (G_UNLIKELY (skip >= bsize)) {
     skip -= bsize;
     g = g_slist_next (g);
     adapter->priv->scan_offset += bsize;
     adapter->priv->scan_entry = g;
     buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
+    bsize = gst_buffer_get_size (buf);
   }
   /* get the data now */
-  bsize -= skip;
-  bdata = GST_BUFFER_DATA (buf) + skip;
+  odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ);
+
+  bdata = odata + skip;
+  bsize = osize - skip;
   skip = 0;
 
   /* set the state to something that does not match */
@@ -933,6 +1012,7 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
         if (G_LIKELY (skip + i >= 3)) {
           if (G_LIKELY (value))
             *value = state;
+          gst_buffer_unmap (buf, odata, osize);
           return offset + skip + i - 3;
         }
       }
@@ -944,13 +1024,18 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
     /* nothing found yet, go to next buffer */
     skip += bsize;
     g = g_slist_next (g);
-    adapter->priv->scan_offset += GST_BUFFER_SIZE (buf);
+    adapter->priv->scan_offset += osize;
     adapter->priv->scan_entry = g;
+    gst_buffer_unmap (buf, odata, osize);
     buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
-    bdata = GST_BUFFER_DATA (buf);
+
+    odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ);
+    bsize = osize;
+    bdata = odata;
   } while (TRUE);
 
+  gst_buffer_unmap (buf, odata, osize);
+
   /* nothing found */
   return -1;
 }
@@ -1001,9 +1086,9 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
  *
  * Since: 0.10.24
  */
-guint
+gsize
 gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
-    guint32 pattern, guint offset, guint size)
+    guint32 pattern, gsize offset, gsize size)
 {
   return gst_adapter_masked_scan_uint32_peek (adapter, mask, pattern, offset,
       size, NULL);
index f4e2a06..17bf323 100644 (file)
@@ -52,22 +52,18 @@ struct _GstAdapter {
 
   /*< private >*/
   GSList *      buflist;
-  guint         size;
-  guint         skip;
+  GSList *      buflist_end;
+  gsize         size;
+  gsize         skip;
 
   /* we keep state of assembled pieces */
-  guint8 *      assembled_data;
-  guint         assembled_size;
-  guint         assembled_len;
-
-  /* ABI added */
-  /* Remember where the end of our buffer list is to
-   * speed up the push */
-  GSList *buflist_end;
+  gpointer      assembled_data;
+  gsize         assembled_size;
+  gsize         assembled_len;
 
   GstAdapterPrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING - 2];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstAdapterClass {
@@ -83,23 +79,25 @@ GstAdapter *            gst_adapter_new                 (void) G_GNUC_MALLOC;
 
 void                    gst_adapter_clear               (GstAdapter *adapter);
 void                    gst_adapter_push                (GstAdapter *adapter, GstBuffer* buf);
-const guint8 *          gst_adapter_peek                (GstAdapter *adapter, guint size);
-void                    gst_adapter_copy                (GstAdapter *adapter, guint8 *dest,
-                                                         guint offset, guint size);
-void                    gst_adapter_flush               (GstAdapter *adapter, guint flush);
-guint8*                 gst_adapter_take                (GstAdapter *adapter, guint nbytes);
-GstBuffer*              gst_adapter_take_buffer         (GstAdapter *adapter, guint nbytes);
-GList*                  gst_adapter_take_list           (GstAdapter *adapter, guint nbytes);
-guint                   gst_adapter_available           (GstAdapter *adapter);
-guint                   gst_adapter_available_fast      (GstAdapter *adapter);
-
-GstClockTime            gst_adapter_prev_timestamp      (GstAdapter *adapter, guint64 *distance);
-
-guint                   gst_adapter_masked_scan_uint32  (GstAdapter * adapter, guint32 mask,
-                                                         guint32 pattern, guint offset, guint size);
-
-guint                   gst_adapter_masked_scan_uint32_peek  (GstAdapter * adapter, guint32 mask,
-                                                         guint32 pattern, guint offset, guint size, guint32 * value);
+gconstpointer           gst_adapter_map                 (GstAdapter *adapter, gsize size);
+void                    gst_adapter_unmap               (GstAdapter *adapter);
+void                    gst_adapter_copy                (GstAdapter *adapter, gpointer dest,
+                                                         gsize offset, gsize size);
+void                    gst_adapter_flush               (GstAdapter *adapter, gsize flush);
+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);
+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);
+
+gsize                   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,
+                                                         guint32 pattern, gsize offset, gsize size, guint32 * value);
 
 G_END_DECLS
 
index 93f9173..82c8127 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <gst/base/gstadapter.h>
 
 #include "gstbaseparse.h"
 
+/* FIXME: get rid of old GstIndex code */
+#include "gstindex.h"
+#include "gstindex.c"
+#include "gstmemindex.c"
+
 #define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC  (1 << 0)
 
 #define MIN_FRAMES_TO_POST_BITRATE 10
@@ -229,7 +231,7 @@ static const GstFormat fmtlist[] = {
 
 struct _GstBaseParsePrivate
 {
-  GstActivateMode pad_mode;
+  GstPadMode pad_mode;
 
   GstAdapter *adapter;
 
@@ -287,11 +289,7 @@ struct _GstBaseParsePrivate
   GstIndex *index;
   gint index_id;
   gboolean own_index;
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  GStaticMutex index_lock;
-#else
   GMutex index_lock;
-#endif
 
   /* seek table entries only maintained if upstream is BYTE seekable */
   gboolean upstream_seekable;
@@ -340,17 +338,10 @@ typedef struct _GstBaseParseSeek
   GstClockTime start_ts;
 } GstBaseParseSeek;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-#define GST_BASE_PARSE_INDEX_LOCK(parse) \
-  g_static_mutex_lock (&parse->priv->index_lock);
-#define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
-  g_static_mutex_unlock (&parse->priv->index_lock);
-#else
 #define GST_BASE_PARSE_INDEX_LOCK(parse) \
   g_mutex_lock (&parse->priv->index_lock);
 #define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
   g_mutex_unlock (&parse->priv->index_lock);
-#endif
 
 static GstElementClass *parent_class = NULL;
 
@@ -390,26 +381,31 @@ static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
     GstStateChange transition);
 static void gst_base_parse_reset (GstBaseParse * parse);
 
+#if 0
 static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
 static GstIndex *gst_base_parse_get_index (GstElement * element);
+#endif
 
-static gboolean gst_base_parse_sink_activate (GstPad * sinkpad);
-static gboolean gst_base_parse_sink_activate_push (GstPad * pad,
-    gboolean active);
-static gboolean gst_base_parse_sink_activate_pull (GstPad * pad,
-    gboolean active);
+static gboolean gst_base_parse_sink_activate (GstPad * sinkpad,
+    GstObject * parent);
+static gboolean gst_base_parse_sink_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
 static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
     GstEvent * event);
 static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
 
-static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query);
-static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_base_parse_sink_getcaps (GstPad * pad);
-static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad);
+static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_base_parse_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_base_parse_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+
+static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
 static void gst_base_parse_loop (GstPad * pad);
 
 static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
@@ -493,11 +489,7 @@ gst_base_parse_finalize (GObject * object)
     gst_object_unref (parse->priv->index);
     parse->priv->index = NULL;
   }
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_static_mutex_free (&parse->priv->index_lock);
-#else
   g_mutex_clear (&parse->priv->index_lock);
-#endif
 
   gst_base_parse_clear_queues (parse);
 
@@ -518,8 +510,11 @@ gst_base_parse_class_init (GstBaseParseClass * klass)
   gstelement_class = (GstElementClass *) klass;
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
+
+#if 0
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
+#endif
 
   /* Default handlers */
   klass->check_valid_frame = gst_base_parse_check_frame;
@@ -546,18 +541,14 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
   parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
   gst_pad_set_event_function (parse->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
-  gst_pad_set_setcaps_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps));
-  gst_pad_set_getcaps_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_sink_getcaps));
+  gst_pad_set_query_function (parse->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_parse_sink_query));
   gst_pad_set_chain_function (parse->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_parse_chain));
   gst_pad_set_activate_function (parse->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
-  gst_pad_set_activatepush_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push));
-  gst_pad_set_activatepull_function (parse->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull));
+  gst_pad_set_activatemode_function (parse->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode));
   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
 
   GST_DEBUG_OBJECT (parse, "sinkpad created");
@@ -568,10 +559,8 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
   parse->srcpad = gst_pad_new_from_template (pad_template, "src");
   gst_pad_set_event_function (parse->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
-  gst_pad_set_query_type_function (parse->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes));
   gst_pad_set_query_function (parse->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_parse_query));
+      GST_DEBUG_FUNCPTR (gst_base_parse_src_query));
   gst_pad_use_fixed_caps (parse->srcpad);
   gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
   GST_DEBUG_OBJECT (parse, "src created");
@@ -580,17 +569,15 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
 
   parse->priv->adapter = gst_adapter_new ();
 
-  parse->priv->pad_mode = GST_ACTIVATE_NONE;
+  parse->priv->pad_mode = GST_PAD_MODE_NONE;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_static_mutex_init (&parse->priv->index_lock);
-#else
   g_mutex_init (&parse->priv->index_lock);
-#endif
 
   /* init state */
   gst_base_parse_reset (parse);
   GST_DEBUG_OBJECT (parse, "init ok");
+
+  GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
 }
 
 static GstBaseParseFrame *
@@ -806,7 +793,7 @@ static gboolean
 gst_base_parse_check_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
-  *framesize = GST_BUFFER_SIZE (frame->buffer);
+  *framesize = gst_buffer_get_size (frame->buffer);
   *skipsize = 0;
   return TRUE;
 }
@@ -897,25 +884,26 @@ gst_base_parse_convert (GstBaseParse * parse,
  * Returns: TRUE if the event was handled.
  */
 static gboolean
-gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
+gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstBaseParse *parse;
   GstBaseParseClass *bclass;
   gboolean handled = FALSE;
   gboolean ret = TRUE;
 
-  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+  parse = GST_BASE_PARSE (parent);
   bclass = GST_BASE_PARSE_GET_CLASS (parse);
 
   GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event),
       GST_EVENT_TYPE_NAME (event));
 
-  /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a
+  /* Cache all events except EOS, SEGMENT and FLUSH_STOP if we have a
    * pending segment */
   if (parse->priv->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS
-      && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT
+      && GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT
       && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START
-      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
+      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP
+      && GST_EVENT_TYPE (event) != GST_EVENT_CAPS) {
 
     if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
       /* See if any bitrate tags were posted */
@@ -938,11 +926,11 @@ gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
       handled = gst_base_parse_sink_eventfunc (parse, event);
 
     if (!handled)
-      ret = gst_pad_event_default (pad, event);
+      ret = gst_pad_event_default (pad, parent, event);
   }
 
-  gst_object_unref (parse);
   GST_DEBUG_OBJECT (parse, "event handled");
+
   return ret;
 }
 
@@ -965,36 +953,54 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
   GstEvent **eventp;
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+      GstBaseParseClass *klass;
+
+      klass = GST_BASE_PARSE_GET_CLASS (parse);
+
+      gst_event_parse_caps (event, &caps);
+      GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
+
+      if (klass->set_sink_caps)
+        klass->set_sink_caps (parse, caps);
+
+      /* will send our own caps downstream */
+      gst_event_unref (event);
+      handled = TRUE;
+      break;
+    }
+    case GST_EVENT_SEGMENT:
     {
+      const GstSegment *in_segment;
+      GstSegment out_segment;
+      gint64 offset = 0, next_ts;
+
+#if 0
       gdouble rate, applied_rate;
       GstFormat format;
-      gint64 start, stop, pos, next_ts, offset = 0;
+      gint64 start, stop, pos, next_ts;
       gboolean update;
+#endif
 
-      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-          &format, &start, &stop, &pos);
+      gst_event_parse_segment (event, &in_segment);
+      gst_segment_init (&out_segment, GST_FORMAT_TIME);
 
-      GST_DEBUG_OBJECT (parse, "newseg rate %g, applied rate %g, "
-          "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
-          ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format,
-          GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos));
+      GST_DEBUG_OBJECT (parse, "segment %" GST_SEGMENT_FORMAT, in_segment);
 
-      if (format == GST_FORMAT_BYTES) {
-        GstClockTime seg_start, seg_stop;
+      if (in_segment->format == GST_FORMAT_BYTES) {
         GstBaseParseSeek *seek = NULL;
         GSList *node;
 
         /* stop time is allowed to be open-ended, but not start & pos */
-        seg_stop = GST_CLOCK_TIME_NONE;
-        seg_start = 0;
-        offset = pos;
+        offset = in_segment->time;
 
         GST_OBJECT_LOCK (parse);
         for (node = parse->priv->pending_seeks; node; node = node->next) {
           GstBaseParseSeek *tmp = node->data;
 
-          if (tmp->offset == pos) {
+          if (tmp->offset == offset) {
             seek = tmp;
             break;
           }
@@ -1007,8 +1013,11 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
           GST_DEBUG_OBJECT (parse,
               "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT,
               seek->accurate ? " accurate" : "", &seek->segment);
-          seg_start = seek->segment.start;
-          seg_stop = seek->segment.stop;
+
+          out_segment.start = seek->segment.start;
+          out_segment.stop = seek->segment.stop;
+          out_segment.time = seek->segment.start;
+
           next_ts = seek->start_ts;
           parse->priv->exact_position = seek->accurate;
           g_free (seek);
@@ -1016,39 +1025,48 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
           /* best attempt convert */
           /* as these are only estimates, stop is kept open-ended to avoid
            * premature cutting */
-          gst_base_parse_convert (parse, GST_FORMAT_BYTES, start,
-              GST_FORMAT_TIME, (gint64 *) & seg_start);
-          parse->priv->exact_position = (start == 0);
-          next_ts = seg_start;
+          gst_base_parse_convert (parse, GST_FORMAT_BYTES, in_segment->start,
+              GST_FORMAT_TIME, (gint64 *) & next_ts);
+
+          out_segment.start = next_ts;
+          out_segment.stop = GST_CLOCK_TIME_NONE;
+          out_segment.time = next_ts;
+
+          parse->priv->exact_position = (in_segment->start == 0);
         }
 
         gst_event_unref (event);
-        event = gst_event_new_new_segment_full (update, rate, applied_rate,
-            GST_FORMAT_TIME, seg_start, seg_stop, seg_start);
-        format = GST_FORMAT_TIME;
-        start = seg_start;
-        stop = seg_stop;
-        GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. "
-            "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop));
-      } else if (format != GST_FORMAT_TIME) {
+
+        event = gst_event_new_segment (&out_segment);
+
+        GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. %"
+            GST_SEGMENT_FORMAT, in_segment);
+
+      } else if (in_segment->format != GST_FORMAT_TIME) {
         /* Unknown incoming segment format. Output a default open-ended
          * TIME segment */
         gst_event_unref (event);
-        event = gst_event_new_new_segment_full (update, rate, applied_rate,
-            GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
-        format = GST_FORMAT_TIME;
-        next_ts = start = 0;
-        stop = GST_CLOCK_TIME_NONE;
+
+        out_segment.start = 0;
+        out_segment.stop = GST_CLOCK_TIME_NONE;;
+        out_segment.time = 0;;
+
+        event = gst_event_new_segment (&out_segment);
+
+        next_ts = 0;
       } else {
         /* not considered BYTE seekable if it is talking to us in TIME,
          * whatever else it might claim */
         parse->priv->upstream_seekable = FALSE;
-        next_ts = start;
+        next_ts = in_segment->start;
       }
 
-      gst_segment_set_newsegment_full (&parse->segment, update, rate,
-          applied_rate, format, start, stop, start);
+      memcpy (&parse->segment, &out_segment, sizeof (GstSegment));
+
+      /*
+         gst_segment_set_newsegment (&parse->segment, update, rate,
+         applied_rate, format, start, stop, start);
+       */
 
       /* save the segment for later, right before we push a new buffer so that
        * the caps are fixed and the next linked element can receive
@@ -1060,11 +1078,12 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
 
       /* but finish the current segment */
       GST_DEBUG_OBJECT (parse, "draining current segment");
-      if (parse->segment.rate > 0.0)
+      if (in_segment->rate > 0.0)
         gst_base_parse_drain (parse);
       else
         gst_base_parse_process_fragment (parse, FALSE);
       gst_adapter_clear (parse->priv->adapter);
+
       parse->priv->offset = offset;
       parse->priv->sync_offset = offset;
       parse->priv->next_ts = next_ts;
@@ -1121,6 +1140,59 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
   return handled;
 }
 
+static gboolean
+gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  GstBaseParse *parse;
+  GstBaseParseClass *bclass;
+  gboolean res;
+
+  parse = GST_BASE_PARSE (parent);
+  bclass = GST_BASE_PARSE_GET_CLASS (parse);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+    {
+      if (bclass->get_sink_caps) {
+        GstCaps *caps, *filter;
+
+        gst_query_parse_caps (query, &filter);
+        caps = bclass->get_sink_caps (parse, filter);
+        GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT,
+            caps);
+        gst_query_set_caps_result (query, caps);
+        gst_caps_unref (caps);
+
+        res = TRUE;
+      } else {
+        GstCaps *caps, *template_caps, *filter;
+
+        gst_query_parse_caps (query, &filter);
+        template_caps = gst_pad_get_pad_template_caps (pad);
+        if (filter != NULL) {
+          caps =
+              gst_caps_intersect_full (filter, template_caps,
+              GST_CAPS_INTERSECT_FIRST);
+        } else {
+          caps = gst_caps_copy (template_caps);
+        }
+        gst_query_set_caps_result (query, caps);
+        gst_caps_unref (caps);
+
+        res = TRUE;
+      }
+      break;
+    }
+    default:
+    {
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+    }
+  }
+
+  return res;
+}
+
 
 /* gst_base_parse_src_event:
  * @pad: #GstPad that received the event.
@@ -1131,14 +1203,14 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
  * Returns: TRUE if the event was handled.
  */
 static gboolean
-gst_base_parse_src_event (GstPad * pad, GstEvent * event)
+gst_base_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstBaseParse *parse;
   GstBaseParseClass *bclass;
   gboolean handled = FALSE;
   gboolean ret = TRUE;
 
-  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+  parse = GST_BASE_PARSE (parent);
   bclass = GST_BASE_PARSE_GET_CLASS (parse);
 
   GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
@@ -1148,9 +1220,8 @@ gst_base_parse_src_event (GstPad * pad, GstEvent * event)
     handled = bclass->src_event (parse, event);
 
   if (!handled)
-    ret = gst_pad_event_default (pad, event);
+    ret = gst_pad_event_default (pad, parent, event);
 
-  gst_object_unref (parse);
   return ret;
 }
 
@@ -1282,14 +1353,13 @@ gst_base_parse_update_duration (GstBaseParse * baseparse)
 
   peer = gst_pad_get_peer (parse->sinkpad);
   if (peer) {
-    GstFormat pformat = GST_FORMAT_BYTES;
     gboolean qres = FALSE;
     gint64 ptot, dest_value;
 
-    qres = gst_pad_query_duration (peer, &pformat, &ptot);
+    qres = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &ptot);
     gst_object_unref (GST_OBJECT (peer));
     if (qres) {
-      if (gst_base_parse_convert (parse, pformat, ptot,
+      if (gst_base_parse_convert (parse, GST_FORMAT_BYTES, ptot,
               GST_FORMAT_TIME, &dest_value)) {
 
         /* inform if duration changed, but try to avoid spamming */
@@ -1318,7 +1388,7 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
   GstTagList *taglist = NULL;
 
   if (post_min && parse->priv->post_min_bitrate) {
-    taglist = gst_tag_list_new ();
+    taglist = gst_tag_list_new_empty ();
 
     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
         GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL);
@@ -1326,7 +1396,7 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
 
   if (post_avg && parse->priv->post_avg_bitrate) {
     if (taglist == NULL)
-      taglist = gst_tag_list_new ();
+      taglist = gst_tag_list_new_empty ();
 
     parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate;
     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
@@ -1335,7 +1405,7 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
 
   if (post_max && parse->priv->post_max_bitrate) {
     if (taglist == NULL)
-      taglist = gst_tag_list_new ();
+      taglist = gst_tag_list_new_empty ();
 
     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
         GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL);
@@ -1346,8 +1416,7 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
       parse->priv->max_bitrate);
 
   if (taglist != NULL) {
-    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), parse->srcpad,
-        taglist);
+    gst_pad_push_event (parse->srcpad, gst_event_new_tag (taglist));
   }
 }
 
@@ -1373,7 +1442,7 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
   if (overhead == -1)
     return;
 
-  data_len = GST_BUFFER_SIZE (buffer) - overhead;
+  data_len = gst_buffer_get_size (buffer) - overhead;
   parse->priv->data_bytecount += data_len;
 
   /* duration should be valid by now,
@@ -1519,8 +1588,9 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
   /* index might change on-the-fly, although that would be nutty app ... */
   GST_BASE_PARSE_INDEX_LOCK (parse);
   gst_index_add_associationv (parse->priv->index, parse->priv->index_id,
-      (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_DELTA_UNIT,
-      2, (const GstIndexAssociation *) &associations);
+      (key) ? GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT :
+      GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT, 2,
+      (const GstIndexAssociation *) &associations);
   GST_BASE_PARSE_INDEX_UNLOCK (parse);
 
   if (key) {
@@ -1553,10 +1623,8 @@ gst_base_parse_check_seekability (GstBaseParse * parse)
 
   /* try harder to query upstream size if we didn't get it the first time */
   if (seekable && stop == -1) {
-    GstFormat fmt = GST_FORMAT_BYTES;
-
     GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
-    gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
+    gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &stop);
   }
 
   /* if upstream doesn't know the size, it's likely that it's not seekable in
@@ -1592,10 +1660,9 @@ done:
 static void
 gst_base_parse_check_upstream (GstBaseParse * parse)
 {
-  GstFormat fmt = GST_FORMAT_TIME;
   gint64 stop;
 
-  if (gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop))
+  if (gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_TIME, &stop))
     if (GST_CLOCK_TIME_IS_VALID (stop) && stop) {
       /* upstream has one, accept it also, and no further updates */
       gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0);
@@ -1614,7 +1681,7 @@ gst_base_parse_check_media (GstBaseParse * parse)
   GstCaps *caps;
   GstStructure *s;
 
-  caps = GST_PAD_CAPS (parse->srcpad);
+  caps = gst_pad_get_current_caps (parse->srcpad);
   if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) {
     parse->priv->is_video =
         g_str_has_prefix (gst_structure_get_name (s), "video");
@@ -1622,6 +1689,8 @@ gst_base_parse_check_media (GstBaseParse * parse)
     /* historical default */
     parse->priv->is_video = FALSE;
   }
+  if (caps)
+    gst_caps_unref (caps);
 
   GST_DEBUG_OBJECT (parse, "media is video: %d", parse->priv->is_video);
 }
@@ -1683,9 +1752,9 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
 
   GST_LOG_OBJECT (parse,
       "parsing frame at offset %" G_GUINT64_FORMAT
-      " (%#" G_GINT64_MODIFIER "x) of size %d",
+      " (%#" G_GINT64_MODIFIER "x) of size %" G_GSIZE_FORMAT,
       GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer),
-      GST_BUFFER_SIZE (buffer));
+      gst_buffer_get_size (buffer));
 
   /* use default handler to provide initial (upstream) metadata */
   gst_base_parse_parse_frame (parse, frame);
@@ -1702,7 +1771,7 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
    * If so, that allows and enables extra seek and duration determining options */
   if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) {
     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && parse->priv->has_timing_info
-        && parse->priv->pad_mode == GST_ACTIVATE_PULL) {
+        && parse->priv->pad_mode == GST_PAD_MODE_PULL) {
       parse->priv->first_frame_offset = offset;
       parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer);
       GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT
@@ -1762,10 +1831,6 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
     GstBaseParseFrame *queued_frame;
 
     while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) {
-      queued_frame->buffer =
-          gst_buffer_make_metadata_writable (queued_frame->buffer);
-      gst_buffer_set_caps (queued_frame->buffer,
-          GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)));
       gst_base_parse_push_frame (parse, queued_frame);
     }
   }
@@ -1797,6 +1862,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
   GstBuffer *buffer;
+  gsize size;
 
   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
   g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
@@ -1806,13 +1872,14 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   buffer = frame->buffer;
 
   GST_LOG_OBJECT (parse,
-      "processing buffer of size %d with ts %" GST_TIME_FORMAT
-      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
+      "processing buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buffer),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
 
   /* update stats */
-  parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
+  size = gst_buffer_get_size (buffer);
+  parse->priv->bytecount += size;
   if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
     parse->priv->framecount++;
     if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
@@ -1833,11 +1900,12 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     last_stop = last_start + GST_BUFFER_DURATION (buffer);
 
   /* should have caps by now */
-  g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
+  if (!gst_pad_has_current_caps (parse->srcpad))
+    goto no_caps;
 
   /* segment adjustment magic; only if we are running the whole show */
   if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
-      (parse->priv->pad_mode == GST_ACTIVATE_PULL ||
+      (parse->priv->pad_mode == GST_PAD_MODE_PULL ||
           parse->priv->upstream_seekable)) {
     /* segment times are typically estimates,
      * actual frame data might lead subclass to different timestamps,
@@ -1847,60 +1915,46 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
       gst_event_unref (parse->priv->pending_segment);
       parse->segment.start =
           MIN ((guint64) last_start, (guint64) parse->segment.stop);
+
       GST_DEBUG_OBJECT (parse,
           "adjusting pending segment start to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (parse->segment.start));
-      parse->priv->pending_segment =
-          gst_event_new_new_segment (FALSE, parse->segment.rate,
-          parse->segment.format, parse->segment.start,
-          parse->segment.stop, parse->segment.start);
+
+      parse->priv->pending_segment = gst_event_new_segment (&parse->segment);
     }
     /* handle gaps, e.g. non-zero start-time, in as much not handled by above */
-    if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
+    if (GST_CLOCK_TIME_IS_VALID (parse->segment.position) &&
         GST_CLOCK_TIME_IS_VALID (last_start)) {
       GstClockTimeDiff diff;
 
       /* only send newsegments with increasing start times,
        * otherwise if these go back and forth downstream (sinks) increase
        * accumulated time and running_time */
-      diff = GST_CLOCK_DIFF (parse->segment.last_stop, last_start);
+      diff = GST_CLOCK_DIFF (parse->segment.position, last_start);
       if (G_UNLIKELY (diff > 2 * GST_SECOND
               && last_start > parse->segment.start
               && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop)
                   || last_start < parse->segment.stop))) {
+
         GST_DEBUG_OBJECT (parse,
             "Gap of %" G_GINT64_FORMAT " ns detected in stream " "(%"
             GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
             "Sending updated NEWSEGMENT events", diff,
-            GST_TIME_ARGS (parse->segment.last_stop),
+            GST_TIME_ARGS (parse->segment.position),
             GST_TIME_ARGS (last_start));
+
         if (G_UNLIKELY (parse->priv->pending_segment)) {
           gst_event_unref (parse->priv->pending_segment);
           parse->segment.start = last_start;
+          parse->segment.time = last_start;
           parse->priv->pending_segment =
-              gst_event_new_new_segment (FALSE, parse->segment.rate,
-              parse->segment.format, parse->segment.start,
-              parse->segment.stop, parse->segment.start);
+              gst_event_new_segment (&parse->segment);
         } else {
-          /* send newsegment events such that the gap is not accounted in
-           * accum time, hence running_time */
-          /* close ahead of gap */
+          /* skip gap FIXME */
           gst_pad_push_event (parse->srcpad,
-              gst_event_new_new_segment (TRUE, parse->segment.rate,
-                  parse->segment.format, parse->segment.last_stop,
-                  parse->segment.last_stop, parse->segment.last_stop));
-          /* skip gap */
-          gst_pad_push_event (parse->srcpad,
-              gst_event_new_new_segment (FALSE, parse->segment.rate,
-                  parse->segment.format, last_start,
-                  parse->segment.stop, last_start));
+              gst_event_new_segment (&parse->segment));
         }
-        /* align segment view with downstream,
-         * prevents double-counting accum when closing segment */
-        gst_segment_set_newsegment (&parse->segment, FALSE,
-            parse->segment.rate, parse->segment.format, last_start,
-            parse->segment.stop, last_start);
-        parse->segment.last_stop = last_start;
+        parse->segment.position = last_start;
       }
     }
   }
@@ -1919,7 +1973,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     parse->priv->pending_segment = NULL;
 
     GST_DEBUG_OBJECT (parse, "%s push pending segment",
-        parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain");
+        parse->priv->pad_mode == GST_PAD_MODE_PULL ? "loop" : "chain");
     gst_pad_push_event (parse->srcpad, pending_segment);
 
     /* have caps; check identity */
@@ -1953,10 +2007,6 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   /* subclass must play nice */
   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
-  /* decorate */
-  buffer = gst_buffer_make_metadata_writable (buffer);
-  gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
-
   parse->priv->seen_keyframe |= parse->priv->is_video &&
       !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
@@ -1966,7 +2016,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
         GST_BUFFER_TIMESTAMP (buffer) >
         parse->segment.stop + parse->priv->lead_out_ts) {
       GST_LOG_OBJECT (parse, "Dropped frame, after segment");
-      ret = GST_FLOW_UNEXPECTED;
+      ret = GST_FLOW_EOS;
     } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
         GST_BUFFER_DURATION_IS_VALID (buffer) &&
         GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
@@ -1985,43 +2035,49 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   }
 
   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
-    GST_LOG_OBJECT (parse, "frame (%d bytes) dropped",
-        GST_BUFFER_SIZE (buffer));
+    GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) dropped", size);
     gst_buffer_unref (buffer);
     ret = GST_FLOW_OK;
   } else if (ret == GST_FLOW_OK) {
     if (parse->segment.rate > 0.0) {
-      GST_LOG_OBJECT (parse, "pushing frame (%d bytes) now..",
-          GST_BUFFER_SIZE (buffer));
+      GST_LOG_OBJECT (parse, "pushing frame (%" G_GSIZE_FORMAT " bytes) now..",
+          size);
       ret = gst_pad_push (parse->srcpad, buffer);
       GST_LOG_OBJECT (parse, "frame pushed, flow %s", gst_flow_get_name (ret));
     } else {
-      GST_LOG_OBJECT (parse, "frame (%d bytes) queued for now",
-          GST_BUFFER_SIZE (buffer));
+      GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) queued for now",
+          size);
       parse->priv->buffers_queued =
           g_slist_prepend (parse->priv->buffers_queued, buffer);
       ret = GST_FLOW_OK;
     }
   } else {
-    GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s",
-        GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
+    GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s",
+        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_UNEXPECTED &&
+    if (ret == GST_FLOW_EOS &&
         (parse->priv->passthrough ||
-            (parse->priv->pad_mode == GST_ACTIVATE_PUSH &&
+            (parse->priv->pad_mode == GST_PAD_MODE_PUSH &&
                 !parse->priv->upstream_seekable)))
       ret = GST_FLOW_OK;
   }
 
   /* Update current running segment position */
   if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE &&
-      parse->segment.last_stop < last_stop)
-    gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
+      parse->segment.position < last_stop)
+    parse->segment.position = last_stop;
 
   gst_base_parse_frame_free (frame);
 
   return ret;
+
+  /* ERRORS */
+no_caps:
+  {
+    GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("No caps set"), (NULL));
+    return GST_FLOW_ERROR;
+  }
 }
 
 
@@ -2044,7 +2100,8 @@ gst_base_parse_drain (GstBaseParse * parse)
     if (!avail)
       break;
 
-    if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) {
+    if (gst_base_parse_chain (parse->sinkpad, GST_OBJECT_CAST (parse),
+            NULL) != GST_FLOW_OK) {
       break;
     }
 
@@ -2122,8 +2179,8 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only)
   parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending);
   while (parse->priv->buffers_pending) {
     buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data);
-    GST_LOG_OBJECT (parse, "adding pending buffer (size %d)",
-        GST_BUFFER_SIZE (buf));
+    GST_LOG_OBJECT (parse, "adding pending buffer (size %" G_GSIZE_FORMAT ")",
+        gst_buffer_get_size (buf));
     gst_adapter_push (parse->priv->adapter, buf);
     parse->priv->buffers_pending =
         g_slist_delete_link (parse->priv->buffers_pending,
@@ -2134,7 +2191,7 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only)
    * ok if taken from subclass or upstream */
   parse->priv->next_ts = GST_CLOCK_TIME_NONE;
   /* prevent it hanging around stop all the time */
-  parse->segment.last_stop = GST_CLOCK_TIME_NONE;
+  parse->segment.position = GST_CLOCK_TIME_NONE;
   /* mark next run */
   parse->priv->discont = TRUE;
 
@@ -2208,7 +2265,7 @@ push:
 
   /* any trailing unused no longer usable (ideally none) */
   if (G_UNLIKELY (gst_adapter_available (parse->priv->adapter))) {
-    GST_DEBUG_OBJECT (parse, "discarding %d trailing bytes",
+    GST_DEBUG_OBJECT (parse, "discarding %" G_GSIZE_FORMAT " trailing bytes",
         gst_adapter_available (parse->priv->adapter));
     gst_adapter_clear (parse->priv->adapter);
   }
@@ -2231,7 +2288,7 @@ gst_base_parse_check_sync (GstBaseParse * parse)
 }
 
 static GstFlowReturn
-gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
+gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstBaseParseClass *bclass;
   GstBaseParse *parse;
@@ -2245,7 +2302,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
   GstClockTime timestamp;
   GstBaseParseFrame *frame;
 
-  parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
+  parse = GST_BASE_PARSE (parent);
   bclass = GST_BASE_PARSE_GET_CLASS (parse);
 
   if (parse->priv->detecting) {
@@ -2257,17 +2314,18 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       GList *l;
       guint offset = 0;
 
-      detect_buf =
-          gst_buffer_new_and_alloc (parse->priv->detect_buffers_size +
-          (buffer ? GST_BUFFER_SIZE (buffer) : 0));
+      detect_buf = gst_buffer_new ();
+
       for (l = parse->priv->detect_buffers; l; l = l->next) {
-        memcpy (GST_BUFFER_DATA (detect_buf) + offset,
-            GST_BUFFER_DATA (l->data), GST_BUFFER_SIZE (l->data));
-        offset += GST_BUFFER_SIZE (l->data);
+        gsize tmpsize = gst_buffer_get_size (l->data);
+
+        gst_buffer_copy_into (detect_buf, GST_BUFFER_CAST (l->data),
+            GST_BUFFER_COPY_MEMORY, offset, tmpsize);
+        offset += tmpsize;
       }
       if (buffer)
-        memcpy (GST_BUFFER_DATA (detect_buf) + offset, GST_BUFFER_DATA (buffer),
-            GST_BUFFER_SIZE (buffer));
+        gst_buffer_copy_into (detect_buf, buffer, GST_BUFFER_COPY_MEMORY,
+            offset, gst_buffer_get_size (buffer));
     }
 
     ret = bclass->detect (parse, detect_buf);
@@ -2283,7 +2341,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
         if (ret == GST_FLOW_OK && !parse->priv->flushing)
           ret =
               gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
-              GST_BUFFER_CAST (l->data));
+              parent, GST_BUFFER_CAST (l->data));
         else
           gst_buffer_unref (GST_BUFFER_CAST (l->data));
       }
@@ -2311,7 +2369,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       } else {
         parse->priv->detect_buffers =
             g_list_append (parse->priv->detect_buffers, buffer);
-        parse->priv->detect_buffers_size += GST_BUFFER_SIZE (buffer);
+        parse->priv->detect_buffers_size += gst_buffer_get_size (buffer);
         return GST_FLOW_OK;
       }
     } else {
@@ -2325,11 +2383,12 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
   frame = &parse->priv->frame;
 
   if (G_LIKELY (buffer)) {
-    GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
-        GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
+    GST_LOG_OBJECT (parse,
+        "buffer size: %" G_GSIZE_FORMAT ", offset = %" G_GINT64_FORMAT,
+        gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer));
     if (G_UNLIKELY (parse->priv->passthrough)) {
       gst_base_parse_frame_init (frame);
-      frame->buffer = gst_buffer_make_metadata_writable (buffer);
+      frame->buffer = gst_buffer_make_writable (buffer);
       return gst_base_parse_push_frame (parse, frame);
     }
     /* upstream feeding us in reverse playback;
@@ -2394,11 +2453,11 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       }
 
       /* always pass all available data */
-      data = gst_adapter_peek (parse->priv->adapter, av);
-      GST_BUFFER_DATA (tmpbuf) = (guint8 *) data;
-      GST_BUFFER_SIZE (tmpbuf) = av;
+      data = gst_adapter_map (parse->priv->adapter, av);
+      gst_buffer_take_memory (tmpbuf, -1,
+          gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+              (gpointer) data, NULL, av, 0, av));
       GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset;
-      GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY);
 
       if (parse->priv->discont) {
         GST_DEBUG_OBJECT (parse, "marking DISCONT");
@@ -2408,11 +2467,13 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       skip = -1;
       gst_base_parse_frame_update (parse, frame, tmpbuf);
       res = bclass->check_valid_frame (parse, frame, &fsize, &skip);
+      gst_adapter_unmap (parse->priv->adapter);
       gst_buffer_replace (&frame->buffer, NULL);
+      gst_buffer_remove_memory_range (tmpbuf, 0, -1);
       if (res) {
         if (gst_adapter_available (parse->priv->adapter) < fsize) {
-          GST_DEBUG_OBJECT (parse,
-              "found valid frame but not enough data available (only %d bytes)",
+          GST_DEBUG_OBJECT (parse, "found valid frame but not enough data"
+              " available (only %" G_GSIZE_FORMAT " bytes)",
               gst_adapter_available (parse->priv->adapter));
           gst_buffer_unref (tmpbuf);
           goto done;
@@ -2432,7 +2493,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
            * fragment coming later, hopefully subclass skips efficiently ... */
           timestamp = gst_adapter_prev_timestamp (parse->priv->adapter, NULL);
           outbuf = gst_adapter_take_buffer (parse->priv->adapter, skip);
-          outbuf = gst_buffer_make_metadata_writable (outbuf);
+          outbuf = gst_buffer_make_writable (outbuf);
           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
           parse->priv->buffers_pending =
               g_slist_prepend (parse->priv->buffers_pending, outbuf);
@@ -2484,7 +2545,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
 
     /* FIXME: Would it be more efficient to make a subbuffer instead? */
     outbuf = gst_adapter_take_buffer (parse->priv->adapter, fsize);
-    outbuf = gst_buffer_make_metadata_writable (outbuf);
+    outbuf = gst_buffer_make_writable (outbuf);
 
     /* Subclass may want to know the data offset */
     GST_BUFFER_OFFSET (outbuf) = parse->priv->offset;
@@ -2530,11 +2591,11 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
    * We do it mainly to avoid pulling buffers of 1 byte all the time */
   if (parse->priv->cache) {
     gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
-    gint cache_size = GST_BUFFER_SIZE (parse->priv->cache);
+    gint cache_size = gst_buffer_get_size (parse->priv->cache);
 
     if (cache_offset <= parse->priv->offset &&
         (parse->priv->offset + size) <= (cache_offset + cache_size)) {
-      *buffer = gst_buffer_create_sub (parse->priv->cache,
+      *buffer = gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL,
           parse->priv->offset - cache_offset, size);
       GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
       return GST_FLOW_OK;
@@ -2553,8 +2614,10 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
     return ret;
   }
 
-  if (GST_BUFFER_SIZE (parse->priv->cache) >= size) {
-    *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
+  if (gst_buffer_get_size (parse->priv->cache) >= size) {
+    *buffer =
+        gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0,
+        size);
     GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
     return GST_FLOW_OK;
   }
@@ -2573,10 +2636,10 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
     return ret;
   }
 
-  if (GST_BUFFER_SIZE (parse->priv->cache) < size) {
+  if (gst_buffer_get_size (parse->priv->cache) < size) {
     GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %"
-        G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->priv->offset,
-        size, GST_BUFFER_SIZE (parse->priv->cache));
+        G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
+        parse->priv->offset, size, gst_buffer_get_size (parse->priv->cache));
 
     *buffer = parse->priv->cache;
     parse->priv->cache = NULL;
@@ -2584,7 +2647,8 @@ gst_base_parse_pull_range (GstBaseParse * parse, guint size,
     return GST_FLOW_OK;
   }
 
-  *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
+  *buffer =
+      gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, size);
   GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
 
   return GST_FLOW_OK;
@@ -2605,7 +2669,7 @@ gst_base_parse_handle_previous_fragment (GstBaseParse * parse)
   if (!parse->priv->last_offset || parse->priv->last_ts <= parse->segment.start) {
     GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT,
         GST_TIME_ARGS (parse->segment.start));
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_EOS;
     goto exit;
   }
 
@@ -2617,10 +2681,8 @@ gst_base_parse_handle_previous_fragment (GstBaseParse * parse)
   if (parse->priv->exact_position) {
     offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL);
   } else {
-    GstFormat dstformat = GST_FORMAT_BYTES;
-
     if (!gst_pad_query_convert (parse->srcpad, GST_FORMAT_TIME, ts,
-            &dstformat, &offset)) {
+            GST_FORMAT_BYTES, &offset)) {
       GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based");
     }
   }
@@ -2695,7 +2757,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
 
     /* if we got a short read, inform subclass we are draining leftover
      * and no more is to be expected */
-    if (GST_BUFFER_SIZE (buffer) < min_size)
+    if (gst_buffer_get_size (buffer) < min_size)
       parse->priv->drain = TRUE;
 
     if (parse->priv->detecting) {
@@ -2740,7 +2802,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
         /* reverse playback, and no frames found yet, so we are skipping
          * the leading part of a fragment, which may form the tail of
          * fragment coming later, hopefully subclass skips efficiently ... */
-        outbuf = gst_buffer_create_sub (buffer, 0, skip);
+        outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, skip);
         parse->priv->buffers_pending =
             g_slist_prepend (parse->priv->buffers_pending, outbuf);
         outbuf = NULL;
@@ -2769,8 +2831,8 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
   else if (skip < 0)
     skip = 0;
 
-  if (fsize + skip <= GST_BUFFER_SIZE (buffer)) {
-    outbuf = gst_buffer_create_sub (buffer, skip, fsize);
+  if (fsize + skip <= gst_buffer_get_size (buffer)) {
+    outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, skip, fsize);
     GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + skip;
     GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
     gst_buffer_unref (buffer);
@@ -2779,9 +2841,9 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
     ret = gst_base_parse_pull_range (parse, fsize, &outbuf);
     if (ret != GST_FLOW_OK)
       goto done;
-    if (GST_BUFFER_SIZE (outbuf) < fsize) {
+    if (gst_buffer_get_size (outbuf) < fsize) {
       gst_buffer_unref (outbuf);
-      ret = GST_FLOW_UNEXPECTED;
+      ret = GST_FLOW_EOS;
     }
   }
 
@@ -2835,8 +2897,8 @@ gst_base_parse_loop (GstPad * pad)
   ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame);
 
   /* eat expected eos signalling past segment in reverse playback */
-  if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
-      parse->segment.last_stop >= parse->segment.stop) {
+  if (parse->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
+      parse->segment.position >= parse->segment.stop) {
     GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
     /* push what was accumulated during loop run */
     gst_base_parse_process_fragment (parse, TRUE);
@@ -2846,7 +2908,7 @@ gst_base_parse_loop (GstPad * pad)
   }
 
 done:
-  if (ret == GST_FLOW_UNEXPECTED)
+  if (ret == GST_FLOW_EOS)
     goto eos;
   else if (ret != GST_FLOW_OK)
     goto pause;
@@ -2857,7 +2919,7 @@ done:
   /* ERRORS */
 eos:
   {
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_EOS;
     GST_DEBUG_OBJECT (parse, "eos");
     /* fall-through */
   }
@@ -2869,7 +2931,7 @@ pause:
         gst_flow_get_name (ret));
     gst_pad_pause_task (parse->sinkpad);
 
-    if (ret == GST_FLOW_UNEXPECTED) {
+    if (ret == GST_FLOW_EOS) {
       /* handle end-of-stream/segment */
       if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
         gint64 stop;
@@ -2891,7 +2953,7 @@ pause:
         }
         push_eos = TRUE;
       }
-    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
+    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
       /* for fatal errors we post an error message, wrong-state is
        * not fatal because it happens due to flushes and only means
        * that we should stop now. */
@@ -2912,25 +2974,35 @@ pause:
 }
 
 static gboolean
-gst_base_parse_sink_activate (GstPad * sinkpad)
+gst_base_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
 {
   GstBaseParse *parse;
   gboolean result = TRUE;
+  GstQuery *query;
+  gboolean pull_mode;
 
-  parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
+  parse = GST_BASE_PARSE (parent);
 
   GST_DEBUG_OBJECT (parse, "sink activate");
 
-  if (gst_pad_check_pull_range (sinkpad)) {
+  query = gst_query_new_scheduling ();
+  result = gst_pad_peer_query (sinkpad, query);
+  if (result) {
+    pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
+  } else {
+    pull_mode = FALSE;
+  }
+  gst_query_unref (query);
+
+  if (pull_mode) {
     GST_DEBUG_OBJECT (parse, "trying to activate in pull mode");
-    result = gst_pad_activate_pull (sinkpad, TRUE);
+    result = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
   } else {
     GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
-    result = gst_pad_activate_push (sinkpad, TRUE);
+    result = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
   }
 
   GST_DEBUG_OBJECT (parse, "sink activate return %d", result);
-  gst_object_unref (parse);
   return result;
 }
 
@@ -2945,7 +3017,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active)
   klass = GST_BASE_PARSE_GET_CLASS (parse);
 
   if (active) {
-    if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start)
+    if (parse->priv->pad_mode == GST_PAD_MODE_NONE && klass->start)
       result = klass->start (parse);
 
     /* If the subclass implements ::detect we want to
@@ -2957,71 +3029,53 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active)
     GST_PAD_STREAM_LOCK (parse->sinkpad);
     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
 
-    if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop)
+    if (parse->priv->pad_mode != GST_PAD_MODE_NONE && klass->stop)
       result = klass->stop (parse);
 
-    parse->priv->pad_mode = GST_ACTIVATE_NONE;
+    parse->priv->pad_mode = GST_PAD_MODE_NONE;
   }
   GST_DEBUG_OBJECT (parse, "activate return: %d", result);
   return result;
 }
 
 static gboolean
-gst_base_parse_sink_activate_push (GstPad * pad, gboolean active)
+gst_base_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
   gboolean result = TRUE;
   GstBaseParse *parse;
 
-  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
-
-  GST_DEBUG_OBJECT (parse, "sink activate push %d", active);
-
-  result = gst_base_parse_activate (parse, active);
-
-  if (result)
-    parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
-
-  GST_DEBUG_OBJECT (parse, "sink activate push return: %d", result);
-
-  gst_object_unref (parse);
-  return result;
-}
+  parse = GST_BASE_PARSE (parent);
 
-static gboolean
-gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
-{
-  gboolean result = FALSE;
-  GstBaseParse *parse;
-
-  parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
-
-  GST_DEBUG_OBJECT (parse, "activate pull %d", active);
+  GST_DEBUG_OBJECT (parse, "sink activate mode %d, %d", mode, active);
 
   result = gst_base_parse_activate (parse, active);
 
   if (result) {
-    if (active) {
-      parse->priv->pending_segment = gst_event_new_new_segment (FALSE,
-          parse->segment.rate, parse->segment.format,
-          parse->segment.start, parse->segment.stop, parse->segment.last_stop);
-      result &=
-          gst_pad_start_task (sinkpad, (GstTaskFunction) gst_base_parse_loop,
-          sinkpad);
-    } else {
-      result &= gst_pad_stop_task (sinkpad);
+    switch (mode) {
+      case GST_PAD_MODE_PULL:
+        if (active) {
+          parse->priv->pending_segment =
+              gst_event_new_segment (&parse->segment);
+          result &=
+              gst_pad_start_task (pad, (GstTaskFunction) gst_base_parse_loop,
+              pad);
+        } else {
+          result &= gst_pad_stop_task (pad);
+        }
+        break;
+      default:
+        break;
     }
   }
-
   if (result)
-    parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
+    parse->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
 
-  GST_DEBUG_OBJECT (parse, "sink activate pull return: %d", result);
+  GST_DEBUG_OBJECT (parse, "sink activate return: %d", result);
 
-  gst_object_unref (parse);
   return result;
 }
 
-
 /**
  * gst_base_parse_set_duration:
  * @parse: #GstBaseParse.
@@ -3279,28 +3333,13 @@ gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
   return res;
 }
 
-static const GstQueryType *
-gst_base_parse_get_querytypes (GstPad * pad)
-{
-  static const GstQueryType list[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_FORMATS,
-    GST_QUERY_SEEKING,
-    GST_QUERY_CONVERT,
-    GST_QUERY_NONE
-  };
-
-  return list;
-}
-
 static gboolean
-gst_base_parse_query (GstPad * pad, GstQuery * query)
+gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstBaseParse *parse;
   gboolean res = FALSE;
 
-  parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
+  parse = GST_BASE_PARSE (parent);
 
   GST_LOG_OBJECT (parse, "handling query: %" GST_PTR_FORMAT, query);
 
@@ -3314,7 +3353,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
       gst_query_parse_position (query, &format, NULL);
 
       /* try upstream first */
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
       if (!res) {
         /* Fall back on interpreting segment */
         GST_OBJECT_LOCK (parse);
@@ -3322,9 +3361,9 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
           dest_value = parse->priv->offset;
           res = TRUE;
         } else if (format == parse->segment.format &&
-            GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)) {
+            GST_CLOCK_TIME_IS_VALID (parse->segment.position)) {
           dest_value = gst_segment_to_stream_time (&parse->segment,
-              parse->segment.format, parse->segment.last_stop);
+              parse->segment.format, parse->segment.position);
           res = TRUE;
         }
         GST_OBJECT_UNLOCK (parse);
@@ -3348,7 +3387,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
       gst_query_parse_duration (query, &format, NULL);
 
       /* consult upstream */
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
 
       /* otherwise best estimate from us */
       if (!res) {
@@ -3368,7 +3407,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
 
       /* consult upstream */
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
 
       /* we may be able to help if in TIME */
       if (fmt == GST_FORMAT_TIME && gst_base_parse_is_seekable (parse)) {
@@ -3437,7 +3476,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
       break;
     }
     default:
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
       break;
   }
   return res;
@@ -3484,8 +3523,9 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
   buf = frame.buffer;
   GST_LOG_OBJECT (parse,
       "peek parsing frame at offset %" G_GUINT64_FORMAT
-      " (%#" G_GINT64_MODIFIER "x) of size %d",
-      GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf));
+      " (%#" G_GINT64_MODIFIER "x) of size %" G_GSIZE_FORMAT,
+      GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf),
+      gst_buffer_get_size (buf));
 
   /* get offset first, subclass parsing might dump other stuff in there */
   *pos = GST_BUFFER_OFFSET (buf);
@@ -3567,7 +3607,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time,
   /* check preconditions are satisfied;
    * start and end are needed, except for special case where we scan for
    * last frame to determine duration */
-  if (parse->priv->pad_mode != GST_ACTIVATE_PULL || !hpos ||
+  if (parse->priv->pad_mode != GST_PAD_MODE_PULL || !hpos ||
       !GST_CLOCK_TIME_IS_VALID (ltime) ||
       (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) {
     return GST_FLOW_OK;
@@ -3613,7 +3653,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time,
         GST_TIME_ARGS (time), newpos);
 
     ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur);
-    if (ret == GST_FLOW_UNEXPECTED) {
+    if (ret == GST_FLOW_EOS) {
       /* heuristic HACK */
       hpos = MAX (lpos, hpos - chunk);
       continue;
@@ -3678,7 +3718,7 @@ gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time,
     entry = gst_index_get_assoc_entry (parse->priv->index,
         parse->priv->index_id,
         before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER,
-        GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
+        GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
   }
 
   if (entry) {
@@ -3716,7 +3756,6 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
   gboolean flush, update, res = TRUE, accurate;
   gint64 cur, stop, seekpos, seekstop;
   GstSegment seeksegment = { 0, };
-  GstFormat dstformat;
   GstClockTime start_ts;
 
   gst_event_parse_seek (event, &rate, &format, &flags,
@@ -3728,7 +3767,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
       cur_type, GST_TIME_ARGS (cur), stop_type, GST_TIME_ARGS (stop));
 
   /* no negative rates in push mode */
-  if (rate < 0.0 && parse->priv->pad_mode == GST_ACTIVATE_PUSH)
+  if (rate < 0.0 && parse->priv->pad_mode == GST_PAD_MODE_PUSH)
     goto negative_rate;
 
   if (cur_type != GST_SEEK_TYPE_SET ||
@@ -3754,10 +3793,10 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
 
   /* copy segment, we need this because we still need the old
    * segment when we close the current segment. */
-  memcpy (&seeksegment, &parse->segment, sizeof (GstSegment));
+  gst_segment_copy_into (&parse->segment, &seeksegment);
 
   GST_DEBUG_OBJECT (parse, "configuring seek");
-  gst_segment_set_seek (&seeksegment, rate, format, flags,
+  gst_segment_do_seek (&seeksegment, rate, format, flags,
       cur_type, cur, stop_type, stop, &update);
 
   /* accurate seeking implies seek tables are used to obtain position,
@@ -3765,13 +3804,13 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
   accurate = flags & GST_SEEK_FLAG_ACCURATE;
 
   /* maybe we can be accurate for (almost) free */
-  gst_base_parse_find_offset (parse, seeksegment.last_stop, TRUE, &start_ts);
-  if (seeksegment.last_stop <= start_ts + TARGET_DIFFERENCE) {
+  gst_base_parse_find_offset (parse, seeksegment.position, TRUE, &start_ts);
+  if (seeksegment.position <= start_ts + TARGET_DIFFERENCE) {
     GST_DEBUG_OBJECT (parse, "accurate seek possible");
     accurate = TRUE;
   }
   if (accurate) {
-    GstClockTime startpos = seeksegment.last_stop;
+    GstClockTime startpos = seeksegment.position;
 
     /* accurate requested, so ... seek a bit before target */
     if (startpos < parse->priv->lead_in_ts)
@@ -3782,13 +3821,12 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
     seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE,
         NULL);
   } else {
-    start_ts = seeksegment.last_stop;
-    dstformat = GST_FORMAT_BYTES;
-    if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.last_stop,
-            &dstformat, &seekpos))
+    start_ts = seeksegment.position;
+    if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.position,
+            GST_FORMAT_BYTES, &seekpos))
       goto convert_failed;
     if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.stop,
-            &dstformat, &seekstop))
+            GST_FORMAT_BYTES, &seekstop))
       goto convert_failed;
   }
 
@@ -3799,7 +3837,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
       "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT,
       seeksegment.stop, seekstop);
 
-  if (parse->priv->pad_mode == GST_ACTIVATE_PULL) {
+  if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
     gint64 last_stop;
 
     GST_DEBUG_OBJECT (parse, "seek in PULL mode");
@@ -3820,7 +3858,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
     GST_PAD_STREAM_LOCK (parse->sinkpad);
 
     /* save current position */
-    last_stop = parse->segment.last_stop;
+    last_stop = parse->segment.position;
     GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT,
         last_stop);
 
@@ -3829,26 +3867,13 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
     /* prepare for streaming again */
     if (flush) {
       GST_DEBUG_OBJECT (parse, "sending flush stop");
-      gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop ());
-      gst_pad_push_event (parse->sinkpad, gst_event_new_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_base_parse_clear_queues (parse);
     } else {
-      if (parse->priv->close_segment)
-        gst_event_unref (parse->priv->close_segment);
-
-      parse->priv->close_segment = gst_event_new_new_segment (TRUE,
-          parse->segment.rate, parse->segment.format,
-          parse->segment.accum, parse->segment.last_stop, parse->segment.accum);
-
-      /* keep track of our last_stop */
-      seeksegment.accum = parse->segment.last_stop;
-
-      GST_DEBUG_OBJECT (parse, "Created close seg format %d, "
-          "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
-          ", pos = %" GST_TIME_FORMAT, format,
-          GST_TIME_ARGS (parse->segment.accum),
-          GST_TIME_ARGS (parse->segment.last_stop),
-          GST_TIME_ARGS (parse->segment.accum));
+      /* keep track of our position */
+      seeksegment.base = gst_segment_to_running_time (&seeksegment,
+          seeksegment.format, parse->segment.position);
     }
 
     memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
@@ -3858,10 +3883,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
       gst_event_unref (parse->priv->pending_segment);
 
     /* This will be sent later in _loop() */
-    parse->priv->pending_segment =
-        gst_event_new_new_segment (FALSE, parse->segment.rate,
-        parse->segment.format, parse->segment.start,
-        parse->segment.stop, parse->segment.start);
+    parse->priv->pending_segment = gst_event_new_segment (&parse->segment);
 
     GST_DEBUG_OBJECT (parse, "Created newseg format %d, "
         "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
@@ -3874,7 +3896,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
      * maybe scan and subclass can find where to go */
     if (!accurate) {
       gint64 scanpos;
-      GstClockTime ts = seeksegment.last_stop;
+      GstClockTime ts = seeksegment.position;
 
       gst_base_parse_locate_time (parse, &ts, &scanpos);
       if (scanpos >= 0) {
@@ -3919,7 +3941,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
        seek event (in bytes) to upstream. Segment / flush handling happens
        in corresponding src event handlers */
     GST_DEBUG_OBJECT (parse, "seek in PUSH mode");
-    if (seekstop >= 0 && seekpos <= seekpos)
+    if (seekstop >= 0 && seekstop <= seekpos)
       seekstop = seekpos;
     new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
         GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop);
@@ -4002,46 +4024,7 @@ gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event)
   }
 }
 
-static gboolean
-gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
-  GstBaseParse *parse;
-  GstBaseParseClass *klass;
-  gboolean res = TRUE;
-
-  parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
-  klass = GST_BASE_PARSE_GET_CLASS (parse);
-
-  GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
-
-  if (klass->set_sink_caps)
-    res = klass->set_sink_caps (parse, caps);
-
-  return res;
-}
-
-static GstCaps *
-gst_base_parse_sink_getcaps (GstPad * pad)
-{
-  GstBaseParse *parse;
-  GstBaseParseClass *klass;
-  GstCaps *caps;
-
-  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
-  klass = GST_BASE_PARSE_GET_CLASS (parse);
-  g_assert (pad == GST_BASE_PARSE_SINK_PAD (parse));
-
-  if (klass->get_sink_caps)
-    caps = klass->get_sink_caps (parse);
-  else
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-  gst_object_unref (parse);
-
-  GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT, caps);
-
-  return caps;
-}
-
+#if 0
 static void
 gst_base_parse_set_index (GstElement * element, GstIndex * index)
 {
@@ -4074,6 +4057,7 @@ gst_base_parse_get_index (GstElement * element)
 
   return result;
 }
+#endif
 
 static GstStateChangeReturn
 gst_base_parse_change_state (GstElement * element, GstStateChange transition)
@@ -4098,7 +4082,7 @@ gst_base_parse_change_state (GstElement * element, GstStateChange transition)
       if (G_UNLIKELY (!parse->priv->index)) {
         GST_DEBUG_OBJECT (parse, "no index provided creating our own");
 
-        parse->priv->index = gst_index_factory_make ("memindex");
+        parse->priv->index = g_object_new (gst_mem_index_get_type (), NULL);
         gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse),
             &parse->priv->index_id);
         parse->priv->own_index = TRUE;
index fff4d85..fcdb391 100644 (file)
@@ -192,7 +192,6 @@ struct _GstBaseParse {
  *                  Allows closing external resources.
  * @set_sink_caps:  allows the subclass to be notified of the actual caps set.
  * @get_sink_caps:  allows the subclass to do its own sink get caps if needed.
- *                  Since: 0.10.36
  * @check_valid_frame:  Check if the given piece of data contains a valid
  *                      frame.
  * @parse_frame:    Parse the already checked frame. Subclass need to
@@ -258,13 +257,14 @@ struct _GstBaseParseClass {
   gboolean      (*src_event)          (GstBaseParse * parse,
                                        GstEvent     * event);
 
-  GstCaps *     (*get_sink_caps)      (GstBaseParse * parse);
+  GstCaps *     (*get_sink_caps)      (GstBaseParse * parse,
+                                       GstCaps      * filter);
 
   GstFlowReturn (*detect)             (GstBaseParse * parse,
                                        GstBuffer    * buffer);
 
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE - 2];
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 GType           gst_base_parse_get_type (void);
index a610e2e..b56f8af 100644 (file)
  *
  * #GstBaseSink provides support for exactly one sink pad, which should be
  * named "sink". A sink implementation (subclass of #GstBaseSink) should
- * install a pad template in its base_init function, like so:
+ * install a pad template in its class_init function, like so:
  * |[
  * static void
- * my_element_base_init (gpointer g_class)
+ * my_element_class_init (GstMyElementClass *klass)
  * {
- *   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ *   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
  *
  *   // sinktemplate should be a #GstStaticPadTemplate with direction
  *   // #GST_PAD_SINK and name "sink"
  * very specific elements (such as file sinks) which need to handle the
  * newsegment event specially.
  *
- * #GstBaseSink provides an overridable #GstBaseSinkClass.buffer_alloc()
- * function that can be used by sinks that want to do reverse negotiation or to
- * provide custom buffers (hardware buffers for example) to upstream elements.
- *
  * The #GstBaseSinkClass.unlock() method is called when the elements should
  * unblock any blocking operations they perform in the
  * #GstBaseSinkClass.render() method. This is mostly useful when the
 #  include "config.h"
 #endif
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <gst/gst_private.h>
 
 #include "gstbasesink.h"
@@ -181,9 +174,6 @@ typedef struct
   gboolean need_preroll;        /* if we need preroll after this step */
 } GstStepInfo;
 
-/* FIXME, some stuff in ABI.data and other in Private...
- * Make up your mind please.
- */
 struct _GstBaseSinkPrivate
 {
   gint qos_enabled;             /* ATOMIC */
@@ -244,11 +234,12 @@ struct _GstBaseSinkPrivate
   gboolean have_latency;
 
   /* the last buffer we prerolled or rendered. Useful for making snapshots */
-  gint enable_last_buffer;      /* atomic */
+  gint enable_last_sample;      /* atomic */
   GstBuffer *last_buffer;
+  GstCaps *last_caps;
 
-  /* caps for pull based scheduling */
-  GstCaps *pull_caps;
+  /* negotiated caps */
+  GstCaps *caps;
 
   /* blocksize for pulling */
   guint blocksize;
@@ -271,6 +262,8 @@ struct _GstBaseSinkPrivate
   /* for throttling and QoS */
   GstClockTime earliest_in_time;
   GstClockTime throttle_time;
+
+  gboolean reset_time;
 };
 
 #define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
@@ -284,25 +277,11 @@ struct _GstBaseSinkPrivate
 #define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
 #define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
 
-enum
-{
-  _PR_IS_NOTHING = 1 << 0,
-  _PR_IS_BUFFER = 1 << 1,
-  _PR_IS_BUFFERLIST = 1 << 2,
-  _PR_IS_EVENT = 1 << 3
-} PrivateObjectType;
-
-#define OBJ_IS_BUFFER(a) ((a) & _PR_IS_BUFFER)
-#define OBJ_IS_BUFFERLIST(a) ((a) & _PR_IS_BUFFERLIST)
-#define OBJ_IS_EVENT(a) ((a) & _PR_IS_EVENT)
-#define OBJ_IS_BUFFERFULL(a) ((a) & (_PR_IS_BUFFER | _PR_IS_BUFFERLIST))
-
 /* BaseSink properties */
 
 #define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */
 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
 
-#define DEFAULT_PREROLL_QUEUE_LEN   0
 #define DEFAULT_SYNC                TRUE
 #define DEFAULT_MAX_LATENESS        -1
 #define DEFAULT_QOS                 FALSE
@@ -310,20 +289,19 @@ enum
 #define DEFAULT_TS_OFFSET           0
 #define DEFAULT_BLOCKSIZE           4096
 #define DEFAULT_RENDER_DELAY        0
-#define DEFAULT_ENABLE_LAST_BUFFER  TRUE
+#define DEFAULT_ENABLE_LAST_SAMPLE  TRUE
 #define DEFAULT_THROTTLE_TIME       0
 
 enum
 {
   PROP_0,
-  PROP_PREROLL_QUEUE_LEN,
   PROP_SYNC,
   PROP_MAX_LATENESS,
   PROP_QOS,
   PROP_ASYNC,
   PROP_TS_OFFSET,
-  PROP_ENABLE_LAST_BUFFER,
-  PROP_LAST_BUFFER,
+  PROP_ENABLE_LAST_SAMPLE,
+  PROP_LAST_SAMPLE,
   PROP_BLOCKSIZE,
   PROP_RENDER_DELAY,
   PROP_THROTTLE_TIME,
@@ -370,14 +348,13 @@ static void gst_base_sink_get_property (GObject * object, guint prop_id,
 static gboolean gst_base_sink_send_event (GstElement * element,
     GstEvent * event);
 static gboolean default_element_query (GstElement * element, GstQuery * query);
-static const GstQueryType *gst_base_sink_get_query_types (GstElement * element);
-
-static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink);
-static gboolean gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps);
-static GstFlowReturn gst_base_sink_buffer_alloc (GstBaseSink * sink,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
-static void gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
-    GstClockTime * start, GstClockTime * end);
+
+static GstCaps *gst_base_sink_default_get_caps (GstBaseSink * sink,
+    GstCaps * caps);
+static gboolean gst_base_sink_default_set_caps (GstBaseSink * sink,
+    GstCaps * caps);
+static void gst_base_sink_default_get_times (GstBaseSink * basesink,
+    GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
 static gboolean gst_base_sink_set_flushing (GstBaseSink * basesink,
     GstPad * pad, gboolean flushing);
 static gboolean gst_base_sink_default_activate_pull (GstBaseSink * basesink,
@@ -390,33 +367,35 @@ static gboolean gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
 static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,
     GstStateChange transition);
 
-static gboolean gst_base_sink_sink_query (GstPad * pad, GstQuery * query);
-static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_base_sink_chain_list (GstPad * pad,
+static gboolean gst_base_sink_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static GstFlowReturn gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
     GstBufferList * list);
 
 static void gst_base_sink_loop (GstPad * pad);
-static gboolean gst_base_sink_pad_activate (GstPad * pad);
-static gboolean gst_base_sink_pad_activate_push (GstPad * pad, gboolean active);
-static gboolean gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active);
-static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_sink_pad_activate (GstPad * pad, GstObject * parent);
+static gboolean gst_base_sink_pad_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
+static gboolean gst_base_sink_default_event (GstBaseSink * basesink,
+    GstEvent * event);
+static GstFlowReturn gst_base_sink_default_wait_eos (GstBaseSink * basesink,
+    GstEvent * event);
+static gboolean gst_base_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
-static gboolean default_sink_query (GstBaseSink * sink, GstQuery * query);
+static gboolean gst_base_sink_default_query (GstBaseSink * sink,
+    GstQuery * query);
 
 static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
-static GstCaps *gst_base_sink_pad_getcaps (GstPad * pad);
-static gboolean gst_base_sink_pad_setcaps (GstPad * pad, GstCaps * caps);
-static void gst_base_sink_pad_fixate (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_base_sink_pad_buffer_alloc (GstPad * pad,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
-
+static void gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps);
+static void 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);
-static GstFlowReturn gst_base_sink_preroll_object (GstBaseSink * basesink,
-    guint8 obj_type, GstMiniObject * obj);
 
 static void
 gst_base_sink_class_init (GstBaseSinkClass * klass)
@@ -438,14 +417,6 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
   gobject_class->set_property = gst_base_sink_set_property;
   gobject_class->get_property = gst_base_sink_get_property;
 
-  /* FIXME, this next value should be configured using an event from the
-   * upstream element, ie, the BUFFER_SIZE event. */
-  g_object_class_install_property (gobject_class, PROP_PREROLL_QUEUE_LEN,
-      g_param_spec_uint ("preroll-queue-len", "Preroll queue length",
-          "Number of buffers to queue during preroll", 0, G_MAXUINT,
-          DEFAULT_PREROLL_QUEUE_LEN,
-          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
-
   g_object_class_install_property (gobject_class, PROP_SYNC,
       g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
@@ -489,22 +460,22 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
           DEFAULT_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstBaseSink:enable-last-buffer
+   * GstBaseSink:enable-last-sample
    *
-   * Enable the last-buffer property. If FALSE, basesink doesn't keep a
-   * reference to the last buffer arrived and the last-buffer property is always
+   * Enable the last-sample property. If FALSE, basesink doesn't keep a
+   * reference to the last buffer arrived and the last-sample property is always
    * set to NULL. This can be useful if you need buffers to be released as soon
    * as possible, eg. if you're using a buffer pool.
    *
    * Since: 0.10.30
    */
-  g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_BUFFER,
-      g_param_spec_boolean ("enable-last-buffer", "Enable Last Buffer",
-          "Enable the last-buffer property", DEFAULT_ENABLE_LAST_BUFFER,
+  g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE,
+      g_param_spec_boolean ("enable-last-sample", "Enable Last Buffer",
+          "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstBaseSink:last-buffer
+   * GstBaseSink:last-sample
    *
    * The last buffer that arrived in the sink and was used for preroll or for
    * rendering. This property can be used to generate thumbnails. This property
@@ -512,9 +483,9 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
    *
    * Since: 0.10.15
    */
-  g_object_class_install_property (gobject_class, PROP_LAST_BUFFER,
-      gst_param_spec_mini_object ("last-buffer", "Last Buffer",
-          "The last buffer received in the sink", GST_TYPE_BUFFER,
+  g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE,
+      g_param_spec_boxed ("last-sample", "Last Sample",
+          "The last sample received in the sink", GST_TYPE_SAMPLE,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   /**
    * GstBaseSink:blocksize
@@ -559,25 +530,21 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
       GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
   gstelement_class->query = GST_DEBUG_FUNCPTR (default_element_query);
-  gstelement_class->get_query_types =
-      GST_DEBUG_FUNCPTR (gst_base_sink_get_query_types);
 
-  klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_get_caps);
-  klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_set_caps);
-  klass->buffer_alloc = GST_DEBUG_FUNCPTR (gst_base_sink_buffer_alloc);
-  klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_get_times);
+  klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_caps);
+  klass->set_caps = GST_DEBUG_FUNCPTR (gst_base_sink_default_set_caps);
+  klass->fixate = GST_DEBUG_FUNCPTR (gst_base_sink_default_fixate);
   klass->activate_pull =
       GST_DEBUG_FUNCPTR (gst_base_sink_default_activate_pull);
-  klass->query = GST_DEBUG_FUNCPTR (default_sink_query);
+  klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_default_get_times);
+  klass->query = GST_DEBUG_FUNCPTR (gst_base_sink_default_query);
+  klass->event = GST_DEBUG_FUNCPTR (gst_base_sink_default_event);
+  klass->wait_eos = GST_DEBUG_FUNCPTR (gst_base_sink_default_wait_eos);
 
   /* Registering debug symbols for function pointers */
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_getcaps);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_setcaps);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_fixate);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_buffer_alloc);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_fixate);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_push);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_pull);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_mode);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_event);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain_list);
@@ -585,25 +552,23 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
 }
 
 static GstCaps *
-gst_base_sink_pad_getcaps (GstPad * pad)
+gst_base_sink_query_caps (GstBaseSink * bsink, GstPad * pad, GstCaps * filter)
 {
   GstBaseSinkClass *bclass;
-  GstBaseSink *bsink;
   GstCaps *caps = NULL;
+  gboolean fixed;
 
-  bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
   bclass = GST_BASE_SINK_GET_CLASS (bsink);
+  fixed = GST_PAD_IS_FIXED_CAPS (pad);
 
-  if (bsink->pad_mode == GST_ACTIVATE_PULL) {
-    /* if we are operating in pull mode we only accept the negotiated caps */
-    GST_OBJECT_LOCK (pad);
-    if ((caps = GST_PAD_CAPS (pad)))
-      gst_caps_ref (caps);
-    GST_OBJECT_UNLOCK (pad);
+  if (fixed || bsink->pad_mode == GST_PAD_MODE_PULL) {
+    /* if we are operating in pull mode or fixed caps, we only accept the
+     * currently negotiated caps */
+    caps = gst_pad_get_current_caps (pad);
   }
   if (caps == NULL) {
     if (bclass->get_caps)
-      caps = bclass->get_caps (bsink);
+      caps = bclass->get_caps (bsink, filter);
 
     if (caps == NULL) {
       GstPadTemplate *pad_template;
@@ -612,69 +577,39 @@ gst_base_sink_pad_getcaps (GstPad * pad)
           gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass),
           "sink");
       if (pad_template != NULL) {
-        caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
+        caps = gst_pad_template_get_caps (pad_template);
+
+        if (filter) {
+          GstCaps *intersection;
+
+          intersection =
+              gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+          gst_caps_unref (caps);
+          caps = intersection;
+        }
       }
     }
   }
-  gst_object_unref (bsink);
 
   return caps;
 }
 
-static gboolean
-gst_base_sink_pad_setcaps (GstPad * pad, GstCaps * caps)
+static void
+gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps)
 {
-  GstBaseSinkClass *bclass;
-  GstBaseSink *bsink;
-  gboolean res = TRUE;
-
-  bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
-  bclass = GST_BASE_SINK_GET_CLASS (bsink);
-
-  if (res && bclass->set_caps)
-    res = bclass->set_caps (bsink, caps);
-
-  gst_object_unref (bsink);
-
-  return res;
+  GST_DEBUG_OBJECT (bsink, "using default caps fixate function");
+  gst_caps_fixate (caps);
 }
 
 static void
-gst_base_sink_pad_fixate (GstPad * pad, GstCaps * caps)
+gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
 {
   GstBaseSinkClass *bclass;
-  GstBaseSink *bsink;
 
-  bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
   bclass = GST_BASE_SINK_GET_CLASS (bsink);
 
   if (bclass->fixate)
     bclass->fixate (bsink, caps);
-
-  gst_object_unref (bsink);
-}
-
-static GstFlowReturn
-gst_base_sink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstBaseSinkClass *bclass;
-  GstBaseSink *bsink;
-  GstFlowReturn result = GST_FLOW_OK;
-
-  bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (bsink == NULL))
-    return GST_FLOW_WRONG_STATE;
-  bclass = GST_BASE_SINK_GET_CLASS (bsink);
-
-  if (bclass->buffer_alloc)
-    result = bclass->buffer_alloc (bsink, offset, size, caps, buf);
-  else
-    *buf = NULL;                /* fallback in gstpad.c will allocate generic buffer */
-
-  gst_object_unref (bsink);
-
-  return result;
 }
 
 static void
@@ -691,42 +626,35 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
 
   basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink");
 
-  gst_pad_set_getcaps_function (basesink->sinkpad, gst_base_sink_pad_getcaps);
-  gst_pad_set_setcaps_function (basesink->sinkpad, gst_base_sink_pad_setcaps);
-  gst_pad_set_fixatecaps_function (basesink->sinkpad, gst_base_sink_pad_fixate);
-  gst_pad_set_bufferalloc_function (basesink->sinkpad,
-      gst_base_sink_pad_buffer_alloc);
   gst_pad_set_activate_function (basesink->sinkpad, gst_base_sink_pad_activate);
-  gst_pad_set_activatepush_function (basesink->sinkpad,
-      gst_base_sink_pad_activate_push);
-  gst_pad_set_activatepull_function (basesink->sinkpad,
-      gst_base_sink_pad_activate_pull);
+  gst_pad_set_activatemode_function (basesink->sinkpad,
+      gst_base_sink_pad_activate_mode);
   gst_pad_set_query_function (basesink->sinkpad, gst_base_sink_sink_query);
   gst_pad_set_event_function (basesink->sinkpad, gst_base_sink_event);
   gst_pad_set_chain_function (basesink->sinkpad, gst_base_sink_chain);
   gst_pad_set_chain_list_function (basesink->sinkpad, gst_base_sink_chain_list);
   gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad);
 
-  basesink->pad_mode = GST_ACTIVATE_NONE;
-  basesink->preroll_queue = g_queue_new ();
-  basesink->abidata.ABI.clip_segment = gst_segment_new ();
+  basesink->pad_mode = GST_PAD_MODE_NONE;
+  g_mutex_init (&basesink->preroll_lock);
+  g_cond_init (&basesink->preroll_cond);
   priv->have_latency = FALSE;
 
   basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH;
   basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
 
   basesink->sync = DEFAULT_SYNC;
-  basesink->abidata.ABI.max_lateness = DEFAULT_MAX_LATENESS;
+  basesink->max_lateness = DEFAULT_MAX_LATENESS;
   g_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS);
   priv->async_enabled = DEFAULT_ASYNC;
   priv->ts_offset = DEFAULT_TS_OFFSET;
   priv->render_delay = DEFAULT_RENDER_DELAY;
   priv->blocksize = DEFAULT_BLOCKSIZE;
   priv->cached_clock_id = NULL;
-  g_atomic_int_set (&priv->enable_last_buffer, DEFAULT_ENABLE_LAST_BUFFER);
+  g_atomic_int_set (&priv->enable_last_sample, DEFAULT_ENABLE_LAST_SAMPLE);
   priv->throttle_time = DEFAULT_THROTTLE_TIME;
 
-  GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
+  GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_SINK);
 }
 
 static void
@@ -736,8 +664,8 @@ gst_base_sink_finalize (GObject * object)
 
   basesink = GST_BASE_SINK (object);
 
-  g_queue_free (basesink->preroll_queue);
-  gst_segment_free (basesink->abidata.ABI.clip_segment);
+  g_mutex_clear (&basesink->preroll_lock);
+  g_cond_clear (&basesink->preroll_cond);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -808,7 +736,7 @@ gst_base_sink_set_max_lateness (GstBaseSink * sink, gint64 max_lateness)
   g_return_if_fail (GST_IS_BASE_SINK (sink));
 
   GST_OBJECT_LOCK (sink);
-  sink->abidata.ABI.max_lateness = max_lateness;
+  sink->max_lateness = max_lateness;
   GST_OBJECT_UNLOCK (sink);
 }
 
@@ -833,7 +761,7 @@ gst_base_sink_get_max_lateness (GstBaseSink * sink)
   g_return_val_if_fail (GST_IS_BASE_SINK (sink), -1);
 
   GST_OBJECT_LOCK (sink);
-  res = sink->abidata.ABI.max_lateness;
+  res = sink->max_lateness;
   GST_OBJECT_UNLOCK (sink);
 
   return res;
@@ -896,10 +824,10 @@ gst_base_sink_set_async_enabled (GstBaseSink * sink, gboolean enabled)
 {
   g_return_if_fail (GST_IS_BASE_SINK (sink));
 
-  GST_PAD_PREROLL_LOCK (sink->sinkpad);
+  GST_BASE_SINK_PREROLL_LOCK (sink);
   g_atomic_int_set (&sink->priv->async_enabled, enabled);
   GST_LOG_OBJECT (sink, "set async enabled to %d", enabled);
-  GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
+  GST_BASE_SINK_PREROLL_UNLOCK (sink);
 }
 
 /**
@@ -974,32 +902,34 @@ gst_base_sink_get_ts_offset (GstBaseSink * sink)
 }
 
 /**
- * gst_base_sink_get_last_buffer:
+ * gst_base_sink_get_last_sample:
  * @sink: the sink
  *
- * Get the last buffer that arrived in the sink and was used for preroll or for
+ * Get the last sample that arrived in the sink and was used for preroll or for
  * rendering. This property can be used to generate thumbnails.
  *
- * The #GstCaps on the buffer can be used to determine the type of the buffer.
+ * The #GstCaps on the sample can be used to determine the type of the buffer.
  *
- * Free-function: gst_buffer_unref
+ * Free-function: gst_sample_unref
  *
- * Returns: (transfer full): a #GstBuffer. gst_buffer_unref() after usage.
+ * Returns: (transfer full): a #GstSample. gst_sample_unref() after usage.
  *     This function returns NULL when no buffer has arrived in the sink yet
  *     or when the sink is not in PAUSED or PLAYING.
  *
  * Since: 0.10.15
  */
-GstBuffer *
-gst_base_sink_get_last_buffer (GstBaseSink * sink)
+GstSample *
+gst_base_sink_get_last_sample (GstBaseSink * sink)
 {
-  GstBuffer *res;
+  GstSample *res = NULL;
 
   g_return_val_if_fail (GST_IS_BASE_SINK (sink), NULL);
 
   GST_OBJECT_LOCK (sink);
-  if ((res = sink->priv->last_buffer))
-    gst_buffer_ref (res);
+  if (sink->priv->last_buffer) {
+    res = gst_sample_new (sink->priv->last_buffer,
+        sink->priv->last_caps, &sink->segment, NULL);
+  }
   GST_OBJECT_UNLOCK (sink);
 
   return res;
@@ -1017,6 +947,11 @@ gst_base_sink_set_last_buffer_unlocked (GstBaseSink * sink, GstBuffer * buffer)
     if (G_LIKELY (buffer))
       gst_buffer_ref (buffer);
     sink->priv->last_buffer = buffer;
+    if (buffer)
+      /* copy over the caps */
+      gst_caps_replace (&sink->priv->last_caps, sink->priv->caps);
+    else
+      gst_caps_replace (&sink->priv->last_caps, NULL);
   } else {
     old = NULL;
   }
@@ -1032,7 +967,7 @@ gst_base_sink_set_last_buffer_unlocked (GstBaseSink * sink, GstBuffer * buffer)
 static void
 gst_base_sink_set_last_buffer (GstBaseSink * sink, GstBuffer * buffer)
 {
-  if (!g_atomic_int_get (&sink->priv->enable_last_buffer))
+  if (!g_atomic_int_get (&sink->priv->enable_last_sample))
     return;
 
   GST_OBJECT_LOCK (sink);
@@ -1041,22 +976,22 @@ gst_base_sink_set_last_buffer (GstBaseSink * sink, GstBuffer * buffer)
 }
 
 /**
- * gst_base_sink_set_last_buffer_enabled:
+ * gst_base_sink_set_last_sample_enabled:
  * @sink: the sink
- * @enabled: the new enable-last-buffer value.
+ * @enabled: the new enable-last-sample value.
  *
- * Configures @sink to store the last received buffer in the last-buffer
+ * Configures @sink to store the last received sample in the last-sample
  * property.
  *
  * Since: 0.10.30
  */
 void
-gst_base_sink_set_last_buffer_enabled (GstBaseSink * sink, gboolean enabled)
+gst_base_sink_set_last_sample_enabled (GstBaseSink * sink, gboolean enabled)
 {
   g_return_if_fail (GST_IS_BASE_SINK (sink));
 
   /* Only take lock if we change the value */
-  if (g_atomic_int_compare_and_exchange (&sink->priv->enable_last_buffer,
+  if (g_atomic_int_compare_and_exchange (&sink->priv->enable_last_sample,
           !enabled, enabled) && !enabled) {
     GST_OBJECT_LOCK (sink);
     gst_base_sink_set_last_buffer_unlocked (sink, NULL);
@@ -1065,22 +1000,22 @@ gst_base_sink_set_last_buffer_enabled (GstBaseSink * sink, gboolean enabled)
 }
 
 /**
- * gst_base_sink_is_last_buffer_enabled:
+ * gst_base_sink_is_last_sample_enabled:
  * @sink: the sink
  *
- * Checks if @sink is currently configured to store the last received buffer in
- * the last-buffer property.
+ * Checks if @sink is currently configured to store the last received sample in
+ * the last-sample property.
  *
- * Returns: TRUE if the sink is configured to store the last received buffer.
+ * Returns: TRUE if the sink is configured to store the last received sample.
  *
  * Since: 0.10.30
  */
 gboolean
-gst_base_sink_is_last_buffer_enabled (GstBaseSink * sink)
+gst_base_sink_is_last_sample_enabled (GstBaseSink * sink)
 {
   g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
 
-  return g_atomic_int_get (&sink->priv->enable_last_buffer);
+  return g_atomic_int_get (&sink->priv->enable_last_sample);
 }
 
 /**
@@ -1373,12 +1308,6 @@ gst_base_sink_set_property (GObject * object, guint prop_id,
   GstBaseSink *sink = GST_BASE_SINK (object);
 
   switch (prop_id) {
-    case PROP_PREROLL_QUEUE_LEN:
-      /* preroll lock necessary to serialize with finish_preroll */
-      GST_PAD_PREROLL_LOCK (sink->sinkpad);
-      g_atomic_int_set (&sink->preroll_queue_max_len, g_value_get_uint (value));
-      GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
-      break;
     case PROP_SYNC:
       gst_base_sink_set_sync (sink, g_value_get_boolean (value));
       break;
@@ -1400,8 +1329,8 @@ gst_base_sink_set_property (GObject * object, guint prop_id,
     case PROP_RENDER_DELAY:
       gst_base_sink_set_render_delay (sink, g_value_get_uint64 (value));
       break;
-    case PROP_ENABLE_LAST_BUFFER:
-      gst_base_sink_set_last_buffer_enabled (sink, g_value_get_boolean (value));
+    case PROP_ENABLE_LAST_SAMPLE:
+      gst_base_sink_set_last_sample_enabled (sink, g_value_get_boolean (value));
       break;
     case PROP_THROTTLE_TIME:
       gst_base_sink_set_throttle_time (sink, g_value_get_uint64 (value));
@@ -1419,9 +1348,6 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
   GstBaseSink *sink = GST_BASE_SINK (object);
 
   switch (prop_id) {
-    case PROP_PREROLL_QUEUE_LEN:
-      g_value_set_uint (value, g_atomic_int_get (&sink->preroll_queue_max_len));
-      break;
     case PROP_SYNC:
       g_value_set_boolean (value, gst_base_sink_get_sync (sink));
       break;
@@ -1437,11 +1363,11 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_TS_OFFSET:
       g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink));
       break;
-    case PROP_LAST_BUFFER:
-      gst_value_take_buffer (value, gst_base_sink_get_last_buffer (sink));
+    case PROP_LAST_SAMPLE:
+      gst_value_take_buffer (value, gst_base_sink_get_last_sample (sink));
       break;
-    case PROP_ENABLE_LAST_BUFFER:
-      g_value_set_boolean (value, gst_base_sink_is_last_buffer_enabled (sink));
+    case PROP_ENABLE_LAST_SAMPLE:
+      g_value_set_boolean (value, gst_base_sink_is_last_sample_enabled (sink));
       break;
     case PROP_BLOCKSIZE:
       g_value_set_uint (value, gst_base_sink_get_blocksize (sink));
@@ -1460,100 +1386,17 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
 
 
 static GstCaps *
-gst_base_sink_get_caps (GstBaseSink * sink)
+gst_base_sink_default_get_caps (GstBaseSink * sink, GstCaps * filter)
 {
   return NULL;
 }
 
 static gboolean
-gst_base_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
+gst_base_sink_default_set_caps (GstBaseSink * sink, GstCaps * caps)
 {
   return TRUE;
 }
 
-static GstFlowReturn
-gst_base_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  *buf = NULL;
-  return GST_FLOW_OK;
-}
-
-/* with PREROLL_LOCK, STREAM_LOCK */
-static void
-gst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad)
-{
-  GstMiniObject *obj;
-
-  GST_DEBUG_OBJECT (basesink, "flushing queue %p", basesink);
-  while ((obj = g_queue_pop_head (basesink->preroll_queue))) {
-    GST_DEBUG_OBJECT (basesink, "popped %p", obj);
-    gst_mini_object_unref (obj);
-  }
-  /* we can't have EOS anymore now */
-  basesink->eos = FALSE;
-  basesink->priv->received_eos = FALSE;
-  basesink->have_preroll = FALSE;
-  basesink->priv->step_unlock = FALSE;
-  basesink->eos_queued = FALSE;
-  basesink->preroll_queued = 0;
-  basesink->buffers_queued = 0;
-  basesink->events_queued = 0;
-  /* can't report latency anymore until we preroll again */
-  if (basesink->priv->async_enabled) {
-    GST_OBJECT_LOCK (basesink);
-    basesink->priv->have_latency = FALSE;
-    GST_OBJECT_UNLOCK (basesink);
-  }
-  /* and signal any waiters now */
-  GST_PAD_PREROLL_SIGNAL (pad);
-}
-
-/* with STREAM_LOCK, configures given segment with the event information. */
-static void
-gst_base_sink_configure_segment (GstBaseSink * basesink, GstPad * pad,
-    GstEvent * event, GstSegment * segment)
-{
-  gboolean update;
-  gdouble rate, arate;
-  GstFormat format;
-  gint64 start;
-  gint64 stop;
-  gint64 time;
-
-  /* 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_parse_new_segment_full (event, &update, &rate, &arate, &format,
-      &start, &stop, &time);
-
-  /* The segment is protected with both the STREAM_LOCK and the OBJECT_LOCK.
-   * We protect with the OBJECT_LOCK so that we can use the values to
-   * safely answer a POSITION query. */
-  GST_OBJECT_LOCK (basesink);
-  gst_segment_set_newsegment_full (segment, update, rate, arate, format, start,
-      stop, time);
-
-  if (format == GST_FORMAT_TIME) {
-    GST_DEBUG_OBJECT (basesink,
-        "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-        "format GST_FORMAT_TIME, "
-        "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
-        ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
-        update, rate, arate, GST_TIME_ARGS (segment->start),
-        GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
-        GST_TIME_ARGS (segment->accum));
-  } else {
-    GST_DEBUG_OBJECT (basesink,
-        "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-        "format %d, "
-        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-        G_GINT64_FORMAT ", accum %" G_GINT64_FORMAT, update, rate, arate,
-        segment->format, segment->start, segment->stop, segment->time,
-        segment->accum);
-  }
-  GST_OBJECT_UNLOCK (basesink);
-}
-
 /* with PREROLL_LOCK, STREAM_LOCK */
 static gboolean
 gst_base_sink_commit_state (GstBaseSink * basesink)
@@ -1563,6 +1406,7 @@ gst_base_sink_commit_state (GstBaseSink * basesink)
   gboolean post_paused = FALSE;
   gboolean post_async_done = FALSE;
   gboolean post_playing = FALSE;
+  gboolean reset_time;
 
   /* we are certainly not playing async anymore now */
   basesink->playing_async = FALSE;
@@ -1572,15 +1416,12 @@ gst_base_sink_commit_state (GstBaseSink * basesink)
   next = GST_STATE_NEXT (basesink);
   pending = GST_STATE_PENDING (basesink);
   post_pending = pending;
+  reset_time = basesink->priv->reset_time;
+  basesink->priv->reset_time = FALSE;
 
   switch (pending) {
     case GST_STATE_PLAYING:
     {
-      GstBaseSinkClass *bclass;
-      GstStateChangeReturn ret;
-
-      bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
       GST_DEBUG_OBJECT (basesink, "commiting state to PLAYING");
 
       basesink->need_preroll = FALSE;
@@ -1591,14 +1432,6 @@ gst_base_sink_commit_state (GstBaseSink * basesink)
       if (current == GST_STATE_READY) {
         post_paused = TRUE;
       }
-
-      /* make sure we notify the subclass of async playing */
-      if (bclass->async_play) {
-        GST_WARNING_OBJECT (basesink, "deprecated async_play");
-        ret = bclass->async_play (basesink);
-        if (ret == GST_STATE_CHANGE_FAILURE)
-          goto async_failed;
-      }
       break;
     }
     case GST_STATE_PAUSED:
@@ -1635,7 +1468,7 @@ gst_base_sink_commit_state (GstBaseSink * basesink)
   if (post_async_done) {
     GST_DEBUG_OBJECT (basesink, "posting async-done message");
     gst_element_post_message (GST_ELEMENT_CAST (basesink),
-        gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
+        gst_message_new_async_done (GST_OBJECT_CAST (basesink), reset_time));
   }
   if (post_playing) {
     GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message");
@@ -1683,13 +1516,6 @@ stopping:
     GST_OBJECT_UNLOCK (basesink);
     return FALSE;
   }
-async_failed:
-  {
-    GST_DEBUG_OBJECT (basesink, "async commit failed");
-    GST_STATE_RETURN (basesink) = GST_STATE_CHANGE_FAILURE;
-    GST_OBJECT_UNLOCK (basesink);
-    return FALSE;
-  }
 }
 
 static void
@@ -1720,7 +1546,6 @@ start_stepping (GstBaseSink * sink, GstSegment * segment,
   /* set the new rate for the remainder of the segment */
   current->start_rate = segment->rate;
   segment->rate *= current->rate;
-  segment->abs_rate = ABS (segment->rate);
 
   /* save values */
   if (segment->rate > 0.0)
@@ -1734,27 +1559,19 @@ start_stepping (GstBaseSink * sink, GstSegment * segment,
       /* update the segment clipping regions for non-flushing seeks */
       if (segment->rate > 0.0) {
         segment->stop = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
-        segment->last_stop = segment->stop;
+        segment->position = segment->stop;
       } else {
         gint64 position;
 
         position = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
         segment->time = position;
         segment->start = position;
-        segment->last_stop = position;
+        segment->position = position;
       }
     }
   }
 
-  GST_DEBUG_OBJECT (sink,
-      "segment now rate %lf, applied rate %lf, "
-      "format GST_FORMAT_TIME, "
-      "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
-      ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
-      segment->rate, segment->applied_rate, GST_TIME_ARGS (segment->start),
-      GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
-      GST_TIME_ARGS (segment->accum));
-
+  GST_DEBUG_OBJECT (sink, "segment now %" GST_SEGMENT_FORMAT, segment);
   GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT,
       GST_TIME_ARGS (current->start));
 
@@ -1799,8 +1616,8 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment,
   gst_segment_set_running_time (segment, GST_FORMAT_TIME, position);
 
   if (current->flush) {
-    /* and remove the accumulated time we flushed, start time did not change */
-    segment->accum = current->start;
+    /* and remove the time we flushed, start time did not change */
+    segment->base = current->start;
   } else {
     /* start time is now the stepped position */
     gst_element_set_start_time (GST_ELEMENT_CAST (sink), position);
@@ -1808,16 +1625,12 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment,
 
   /* restore the previous rate */
   segment->rate = current->start_rate;
-  segment->abs_rate = ABS (segment->rate);
 
   if (segment->rate > 0.0)
     segment->stop = current->start_stop;
   else
     segment->start = current->start_start;
 
-  /* the clip segment is used for position report in paused... */
-  memcpy (sink->abidata.ABI.clip_segment, segment, sizeof (GstSegment));
-
   /* post the step done when we know the stepped duration in TIME */
   message =
       gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format,
@@ -1835,8 +1648,8 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment,
 
 static gboolean
 handle_stepping (GstBaseSink * sink, GstSegment * segment,
-    GstStepInfo * current, gint64 * cstart, gint64 * cstop, gint64 * rstart,
-    gint64 * rstop)
+    GstStepInfo * current, guint64 * cstart, guint64 * cstop, guint64 * rstart,
+    guint64 * rstop)
 {
   gboolean step_end = FALSE;
 
@@ -1845,7 +1658,8 @@ handle_stepping (GstBaseSink * sink, GstSegment * segment,
     case GST_FORMAT_TIME:
     {
       guint64 end;
-      gint64 first, last;
+      guint64 first, last;
+      gdouble abs_rate;
 
       if (segment->rate > 0.0) {
         if (segment->stop == *cstop)
@@ -1864,8 +1678,9 @@ handle_stepping (GstBaseSink * sink, GstSegment * segment,
       end = current->start + current->amount;
       current->position = first - current->start;
 
-      if (G_UNLIKELY (segment->abs_rate != 1.0))
-        current->position /= segment->abs_rate;
+      abs_rate = ABS (segment->rate);
+      if (G_UNLIKELY (abs_rate != 1.0))
+        current->position /= abs_rate;
 
       GST_DEBUG_OBJECT (sink,
           "buffer: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
@@ -1929,44 +1744,45 @@ static gboolean
 gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
     GstClockTime * rsstart, GstClockTime * rsstop,
     GstClockTime * rrstart, GstClockTime * rrstop, gboolean * do_sync,
-    gboolean * stepped, GstSegment * segment, GstStepInfo * step,
-    gboolean * step_end, guint8 obj_type)
+    gboolean * stepped, GstStepInfo * step, gboolean * step_end)
 {
   GstBaseSinkClass *bclass;
   GstBuffer *buffer;
   GstClockTime start, stop;     /* raw start/stop timestamps */
-  gint64 cstart, cstop;         /* clipped raw timestamps */
-  gint64 rstart, rstop;         /* clipped timestamps converted to running time */
+  guint64 cstart, cstop;        /* clipped raw timestamps */
+  guint64 rstart, rstop;        /* clipped timestamps converted to running time */
   GstClockTime sstart, sstop;   /* clipped timestamps converted to stream time */
   GstFormat format;
   GstBaseSinkPrivate *priv;
+  GstSegment *segment;
   gboolean eos;
 
   priv = basesink->priv;
+  segment = &basesink->segment;
 
   /* start with nothing */
   start = stop = GST_CLOCK_TIME_NONE;
 
-  if (G_UNLIKELY (OBJ_IS_EVENT (obj_type))) {
+  if (G_UNLIKELY (GST_IS_EVENT (obj))) {
     GstEvent *event = GST_EVENT_CAST (obj);
 
     switch (GST_EVENT_TYPE (event)) {
         /* EOS event needs syncing */
       case GST_EVENT_EOS:
       {
-        if (basesink->segment.rate >= 0.0) {
+        if (segment->rate >= 0.0) {
           sstart = sstop = priv->current_sstop;
           if (!GST_CLOCK_TIME_IS_VALID (sstart)) {
             /* we have not seen a buffer yet, use the segment values */
-            sstart = sstop = gst_segment_to_stream_time (&basesink->segment,
-                basesink->segment.format, basesink->segment.stop);
+            sstart = sstop = gst_segment_to_stream_time (segment,
+                segment->format, segment->stop);
           }
         } else {
           sstart = sstop = priv->current_sstart;
           if (!GST_CLOCK_TIME_IS_VALID (sstart)) {
             /* we have not seen a buffer yet, use the segment values */
-            sstart = sstop = gst_segment_to_stream_time (&basesink->segment,
-                basesink->segment.format, basesink->segment.start);
+            sstart = sstop = gst_segment_to_stream_time (segment,
+                segment->format, segment->start);
           }
         }
 
@@ -1981,11 +1797,6 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
       }
       default:
         /* other events do not need syncing */
-        /* FIXME, maybe NEWSEGMENT might need synchronisation
-         * since the POSITION query depends on accumulated times and
-         * we cannot accumulate the current segment before the previous
-         * one completed.
-         */
         return FALSE;
     }
   }
@@ -2006,7 +1817,7 @@ again:
   if (!GST_CLOCK_TIME_IS_VALID (start)) {
     /* we don't need to sync but we still want to get the timestamps for
      * tracking the position */
-    gst_base_sink_get_times (basesink, buffer, &start, &stop);
+    gst_base_sink_default_get_times (basesink, buffer, &start, &stop);
     *do_sync = FALSE;
   } else {
     *do_sync = TRUE;
@@ -2019,19 +1830,9 @@ again:
   /* collect segment and format for code clarity */
   format = segment->format;
 
-  /* no timestamp clipping if we did not get a TIME segment format */
-  if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
-    cstart = start;
-    cstop = stop;
-    /* do running and stream time in TIME format */
-    format = GST_FORMAT_TIME;
-    GST_LOG_OBJECT (basesink, "not time format, don't clip");
-    goto do_times;
-  }
-
-  /* clip, only when we know about time */
-  if (G_UNLIKELY (!gst_segment_clip (segment, GST_FORMAT_TIME,
-              (gint64) start, (gint64) stop, &cstart, &cstop))) {
+  /* clip */
+  if (G_UNLIKELY (!gst_segment_clip (segment, format,
+              start, stop, &cstart, &cstop))) {
     if (step->valid) {
       GST_DEBUG_OBJECT (basesink, "step out of segment");
       /* when we are stepping, pretend we're at the end of the segment */
@@ -2055,9 +1856,9 @@ again:
 
   /* set last stop position */
   if (G_LIKELY (stop != GST_CLOCK_TIME_NONE && cstop != GST_CLOCK_TIME_NONE))
-    gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstop);
+    segment->position = cstop;
   else
-    gst_segment_set_last_stop (segment, GST_FORMAT_TIME, cstart);
+    segment->position = cstart;
 
 do_times:
   rstart = gst_segment_to_running_time (segment, format, cstart);
@@ -2200,8 +2001,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);
@@ -2220,11 +2021,11 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
    * entry. */
   sink->clock_id = sink->priv->cached_clock_id;
   /* release the preroll lock while waiting */
-  GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
+  GST_BASE_SINK_PREROLL_UNLOCK (sink);
 
   ret = gst_clock_id_wait (sink->priv->cached_clock_id, jitter);
 
-  GST_PAD_PREROLL_LOCK (sink->sinkpad);
+  GST_BASE_SINK_PREROLL_LOCK (sink);
   sink->clock_id = NULL;
 
   return ret;
@@ -2276,7 +2077,7 @@ gst_base_sink_wait_preroll (GstBaseSink * sink)
   sink->have_preroll = TRUE;
   GST_DEBUG_OBJECT (sink, "waiting in preroll for flush or PLAYING");
   /* block until the state changes, or we get a flush, or something */
-  GST_PAD_PREROLL_WAIT (sink->sinkpad);
+  GST_BASE_SINK_PREROLL_WAIT (sink);
   sink->have_preroll = FALSE;
   if (G_UNLIKELY (sink->flushing))
     goto stopping;
@@ -2300,23 +2101,6 @@ step_unlocked:
   }
 }
 
-static inline guint8
-get_object_type (GstMiniObject * obj)
-{
-  guint8 obj_type;
-
-  if (G_LIKELY (GST_IS_BUFFER (obj)))
-    obj_type = _PR_IS_BUFFER;
-  else if (GST_IS_EVENT (obj))
-    obj_type = _PR_IS_EVENT;
-  else if (GST_IS_BUFFER_LIST (obj))
-    obj_type = _PR_IS_BUFFERLIST;
-  else
-    obj_type = _PR_IS_NOTHING;
-
-  return obj_type;
-}
-
 /**
  * gst_base_sink_do_preroll:
  * @sink: the sink
@@ -2340,14 +2124,41 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
   GstFlowReturn ret;
 
   while (G_UNLIKELY (sink->need_preroll)) {
-    guint8 obj_type;
     GST_DEBUG_OBJECT (sink, "prerolling object %p", obj);
 
-    obj_type = get_object_type (obj);
+    /* if it's a buffer, we need to call the preroll method */
+    if (sink->priv->call_preroll) {
+      GstBaseSinkClass *bclass;
+      GstBuffer *buf;
+
+      if (GST_IS_BUFFER_LIST (obj)) {
+        buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0);
+        g_assert (NULL != buf);
+      } else if (GST_IS_BUFFER (obj)) {
+        buf = GST_BUFFER_CAST (obj);
+        /* For buffer lists do not set last buffer for now */
+        gst_base_sink_set_last_buffer (sink, buf);
+      } else
+        buf = NULL;
+
+      if (buf) {
+        GST_DEBUG_OBJECT (sink, "preroll buffer %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+
+        bclass = GST_BASE_SINK_GET_CLASS (sink);
+        if (bclass->preroll)
+          if ((ret = bclass->preroll (sink, buf)) != GST_FLOW_OK)
+            goto preroll_canceled;
 
-    ret = gst_base_sink_preroll_object (sink, obj_type, obj);
-    if (ret != GST_FLOW_OK)
-      goto preroll_failed;
+        sink->priv->call_preroll = FALSE;
+      }
+    }
+
+    /* commit state */
+    if (G_LIKELY (sink->playing_async)) {
+      if (G_UNLIKELY (!gst_base_sink_commit_state (sink)))
+        goto stopping;
+    }
 
     /* need to recheck here because the commit state could have
      * made us not need the preroll anymore */
@@ -2361,6 +2172,17 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
   return GST_FLOW_OK;
 
   /* ERRORS */
+preroll_canceled:
+  {
+    GST_DEBUG_OBJECT (sink, "preroll failed, abort state");
+    gst_element_abort_state (GST_ELEMENT_CAST (sink));
+    return ret;
+  }
+stopping:
+  {
+    GST_DEBUG_OBJECT (sink, "stopping while commiting state");
+    return GST_FLOW_WRONG_STATE;
+  }
 preroll_failed:
   {
     GST_DEBUG_OBJECT (sink, "preroll failed: %s", gst_flow_get_name (ret));
@@ -2467,8 +2289,8 @@ flushing:
  * does not take ownership of obj.
  */
 static GstFlowReturn
-gst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad,
-    GstMiniObject * obj, gboolean * late, gboolean * step_end, guint8 obj_type)
+gst_base_sink_do_sync (GstBaseSink * basesink,
+    GstMiniObject * obj, gboolean * late, gboolean * step_end)
 {
   GstClockTimeDiff jitter = 0;
   gboolean syncable;
@@ -2495,8 +2317,7 @@ do_step:
 
   /* get timing information for this object against the render segment */
   syncable = gst_base_sink_get_sync_times (basesink, obj,
-      &sstart, &sstop, &rstart, &rstop, &do_sync, &stepped, &basesink->segment,
-      current, step_end, obj_type);
+      &sstart, &sstop, &rstart, &rstop, &do_sync, &stepped, current, step_end);
 
   if (G_UNLIKELY (stepped))
     goto step_skipped;
@@ -2643,7 +2464,7 @@ gst_base_sink_send_qos (GstBaseSink * basesink, GstQOSType type,
       "qos: type %d, proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
       GST_TIME_FORMAT, type, proportion, diff, GST_TIME_ARGS (time));
 
-  event = gst_event_new_qos_full (type, proportion, diff, time);
+  event = gst_event_new_qos (type, proportion, diff, time);
 
   /* send upstream */
   res = gst_pad_push_event (basesink->sinkpad, event);
@@ -2824,7 +2645,7 @@ gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
     GstClockReturn status, GstClockTimeDiff jitter)
 {
   gboolean late;
-  gint64 max_lateness;
+  guint64 max_lateness;
   GstBaseSinkPrivate *priv;
 
   priv = basesink->priv;
@@ -2835,7 +2656,7 @@ gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
   if (G_LIKELY (status != GST_CLOCK_EARLY))
     goto in_time;
 
-  max_lateness = basesink->abidata.ABI.max_lateness;
+  max_lateness = basesink->max_lateness;
 
   /* check if frame dropping is enabled */
   if (max_lateness == -1)
@@ -2940,616 +2761,254 @@ gst_base_sink_do_render_stats (GstBaseSink * basesink, gboolean start)
   }
 }
 
-/* with STREAM_LOCK, PREROLL_LOCK,
- *
- * Synchronize the object on the clock and then render it.
- *
- * takes ownership of obj.
- */
-static GstFlowReturn
-gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
-    guint8 obj_type, gpointer obj)
+static void
+gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
 {
-  GstFlowReturn ret;
-  GstBaseSinkClass *bclass;
-  gboolean late, step_end;
-  gpointer sync_obj;
-  GstBaseSinkPrivate *priv;
-
-  priv = basesink->priv;
+  /* make sure we are not blocked on the clock also clear any pending
+   * eos state. */
+  gst_base_sink_set_flushing (basesink, pad, TRUE);
 
-  if (OBJ_IS_BUFFERLIST (obj_type)) {
-    /*
-     * If buffer list, use the first group buffer within the list
-     * for syncing
-     */
-    sync_obj = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
-    g_assert (NULL != sync_obj);
+  /* we grab the stream lock but that is not needed since setting the
+   * sink to flushing would make sure no state commit is being done
+   * anymore */
+  GST_PAD_STREAM_LOCK (pad);
+  gst_base_sink_reset_qos (basesink);
+  /* and we need to commit our state again on the next
+   * prerolled buffer */
+  basesink->playing_async = TRUE;
+  if (basesink->priv->async_enabled) {
+    gst_element_lost_state (GST_ELEMENT_CAST (basesink));
   } else {
-    sync_obj = obj;
+    /* start time reset in above case as well;
+     * arranges for a.o. proper position reporting when flushing in PAUSED */
+    gst_element_set_start_time (GST_ELEMENT_CAST (basesink), 0);
+    basesink->priv->have_latency = TRUE;
   }
+  gst_base_sink_set_last_buffer (basesink, NULL);
+  GST_PAD_STREAM_UNLOCK (pad);
+}
 
-again:
-  late = FALSE;
-  step_end = FALSE;
-
-  /* synchronize this object, non syncable objects return OK
-   * immediately. */
-  ret =
-      gst_base_sink_do_sync (basesink, pad, sync_obj, &late, &step_end,
-      obj_type);
-  if (G_UNLIKELY (ret != GST_FLOW_OK))
-    goto sync_failed;
+static void
+gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad,
+    gboolean reset_time)
+{
+  /* unset flushing so we can accept new data, this also flushes out any EOS
+   * event. */
+  gst_base_sink_set_flushing (basesink, pad, FALSE);
 
-  /* and now render, event or buffer/buffer list. */
-  if (G_LIKELY (OBJ_IS_BUFFERFULL (obj_type))) {
-    /* drop late buffers unconditionally, let's hope it's unlikely */
-    if (G_UNLIKELY (late))
-      goto dropped;
+  /* for position reporting */
+  GST_OBJECT_LOCK (basesink);
+  basesink->priv->current_sstart = GST_CLOCK_TIME_NONE;
+  basesink->priv->current_sstop = GST_CLOCK_TIME_NONE;
+  basesink->priv->eos_rtime = GST_CLOCK_TIME_NONE;
+  basesink->priv->call_preroll = TRUE;
+  basesink->priv->current_step.valid = FALSE;
+  basesink->priv->pending_step.valid = FALSE;
+  if (basesink->pad_mode == GST_PAD_MODE_PUSH) {
+    /* we need new segment info after the flush. */
+    basesink->have_newsegment = FALSE;
+    if (reset_time) {
+      gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
+    }
+  }
+  basesink->priv->reset_time = reset_time;
+  GST_OBJECT_UNLOCK (basesink);
+}
 
-    bclass = GST_BASE_SINK_GET_CLASS (basesink);
+static GstFlowReturn
+gst_base_sink_default_wait_eos (GstBaseSink * basesink, GstEvent * event)
+{
+  GstFlowReturn ret;
+  gboolean late, step_end;
 
-    if (G_LIKELY ((OBJ_IS_BUFFERLIST (obj_type) && bclass->render_list) ||
-            (!OBJ_IS_BUFFERLIST (obj_type) && bclass->render))) {
-      gint do_qos;
+  ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (event),
+      &late, &step_end);
 
-      /* read once, to get same value before and after */
-      do_qos = g_atomic_int_get (&priv->qos_enabled);
+  return ret;
+}
 
-      GST_DEBUG_OBJECT (basesink, "rendering object %p", obj);
+static gboolean
+gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
+{
+  gboolean result = TRUE;
+  GstBaseSinkClass *bclass;
 
-      /* record rendering time for QoS and stats */
-      if (do_qos)
-        gst_base_sink_do_render_stats (basesink, TRUE);
+  bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
-      if (!OBJ_IS_BUFFERLIST (obj_type)) {
-        GstBuffer *buf;
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_START:
+    {
+      GST_DEBUG_OBJECT (basesink, "flush-start %p", event);
+      gst_base_sink_flush_start (basesink, basesink->sinkpad);
+      break;
+    }
+    case GST_EVENT_FLUSH_STOP:
+    {
+      gboolean reset_time;
 
-        /* For buffer lists do not set last buffer. Creating buffer
-         * with meaningful data can be done only with memcpy which will
-         * significantly affect performance */
-        buf = GST_BUFFER_CAST (obj);
-        gst_base_sink_set_last_buffer (basesink, buf);
+      gst_event_parse_flush_stop (event, &reset_time);
+      GST_DEBUG_OBJECT (basesink, "flush-stop %p, reset_time: %d", event,
+          reset_time);
+      gst_base_sink_flush_stop (basesink, basesink->sinkpad, reset_time);
+      break;
+    }
+    case GST_EVENT_EOS:
+    {
+      GstMessage *message;
+      guint32 seqnum;
 
-        ret = bclass->render (basesink, buf);
-      } else {
-        GstBufferList *buflist;
+      /* we set the received EOS flag here so that we can use it when testing if
+       * we are prerolled and to refuse more buffers. */
+      basesink->priv->received_eos = TRUE;
 
-        buflist = GST_BUFFER_LIST_CAST (obj);
+      /* wait for EOS */
+      if (G_LIKELY (bclass->wait_eos)) {
+        GstFlowReturn ret;
 
-        ret = bclass->render_list (basesink, buflist);
+        ret = bclass->wait_eos (basesink, event);
+        if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+          result = FALSE;
+          goto done;
+        }
       }
 
-      if (do_qos)
-        gst_base_sink_do_render_stats (basesink, FALSE);
+      /* the EOS event is completely handled so we mark
+       * ourselves as being in the EOS state. eos is also
+       * protected by the object lock so we can read it when
+       * answering the POSITION query. */
+      GST_OBJECT_LOCK (basesink);
+      basesink->eos = TRUE;
+      GST_OBJECT_UNLOCK (basesink);
 
-      if (ret == GST_FLOW_STEP)
-        goto again;
+      /* ok, now we can post the message */
+      GST_DEBUG_OBJECT (basesink, "Now posting EOS");
 
-      if (G_UNLIKELY (basesink->flushing))
-        goto flushing;
+      seqnum = basesink->priv->seqnum = gst_event_get_seqnum (event);
+      GST_DEBUG_OBJECT (basesink, "Got seqnum #%" G_GUINT32_FORMAT, seqnum);
 
-      priv->rendered++;
+      message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
+      gst_message_set_seqnum (message, seqnum);
+      gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
+      break;
     }
-  } else if (G_LIKELY (OBJ_IS_EVENT (obj_type))) {
-    GstEvent *event = GST_EVENT_CAST (obj);
-    gboolean event_res = TRUE;
-    GstEventType type;
-
-    bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
-    type = GST_EVENT_TYPE (event);
-
-    GST_DEBUG_OBJECT (basesink, "rendering event %p, type %s", obj,
-        gst_event_type_get_name (type));
-
-    if (bclass->event)
-      event_res = bclass->event (basesink, event);
-
-    /* when we get here we could be flushing again when the event handler calls
-     * _wait_eos(). We have to ignore this object in that case. */
-    if (G_UNLIKELY (basesink->flushing))
-      goto flushing;
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
 
-    if (G_LIKELY (event_res)) {
-      guint32 seqnum;
+      GST_DEBUG_OBJECT (basesink, "caps %p", event);
 
-      seqnum = basesink->priv->seqnum = gst_event_get_seqnum (event);
-      GST_DEBUG_OBJECT (basesink, "Got seqnum #%" G_GUINT32_FORMAT, seqnum);
+      gst_event_parse_caps (event, &caps);
+      if (bclass->set_caps)
+        result = bclass->set_caps (basesink, caps);
 
-      switch (type) {
-        case GST_EVENT_EOS:
-        {
-          GstMessage *message;
+      if (result) {
+        GST_OBJECT_LOCK (basesink);
+        gst_caps_replace (&basesink->priv->caps, caps);
+        GST_OBJECT_UNLOCK (basesink);
+      }
+      break;
+    }
+    case GST_EVENT_SEGMENT:
+      /* configure the segment */
+      /* The segment is protected with both the STREAM_LOCK and the OBJECT_LOCK.
+       * We protect with the OBJECT_LOCK so that we can use the values to
+       * safely answer a POSITION query. */
+      GST_OBJECT_LOCK (basesink);
+      /* 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,
+          &basesink->segment);
+      basesink->have_newsegment = TRUE;
+      GST_OBJECT_UNLOCK (basesink);
+      break;
+    case GST_EVENT_TAG:
+    {
+      GstTagList *taglist;
 
-          /* the EOS event is completely handled so we mark
-           * ourselves as being in the EOS state. eos is also
-           * protected by the object lock so we can read it when
-           * answering the POSITION query. */
-          GST_OBJECT_LOCK (basesink);
-          basesink->eos = TRUE;
-          GST_OBJECT_UNLOCK (basesink);
+      gst_event_parse_tag (event, &taglist);
 
-          /* ok, now we can post the message */
-          GST_DEBUG_OBJECT (basesink, "Now posting EOS");
+      gst_element_post_message (GST_ELEMENT_CAST (basesink),
+          gst_message_new_tag (GST_OBJECT_CAST (basesink),
+              gst_tag_list_copy (taglist)));
+      break;
+    }
+    case GST_EVENT_SINK_MESSAGE:
+    {
+      GstMessage *msg = NULL;
 
-          message = gst_message_new_eos (GST_OBJECT_CAST (basesink));
-          gst_message_set_seqnum (message, seqnum);
-          gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
-          break;
-        }
-        case GST_EVENT_NEWSEGMENT:
-          /* configure the segment */
-          gst_base_sink_configure_segment (basesink, pad, event,
-              &basesink->segment);
-          break;
-        case GST_EVENT_SINK_MESSAGE:{
-          GstMessage *msg = NULL;
-
-          gst_event_parse_sink_message (event, &msg);
-
-          if (msg)
-            gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
-        }
-        default:
-          break;
-      }
+      gst_event_parse_sink_message (event, &msg);
+      if (msg)
+        gst_element_post_message (GST_ELEMENT_CAST (basesink), msg);
+      break;
     }
-  } else {
-    g_return_val_if_reached (GST_FLOW_ERROR);
+    default:
+      break;
   }
-
 done:
-  if (step_end) {
-    /* the step ended, check if we need to activate a new step */
-    GST_DEBUG_OBJECT (basesink, "step ended");
-    stop_stepping (basesink, &basesink->segment, &priv->current_step,
-        priv->current_rstart, priv->current_rstop, basesink->eos);
-    goto again;
-  }
+  gst_event_unref (event);
 
-  gst_base_sink_perform_qos (basesink, late);
+  return result;
+}
 
-  GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);
-  gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
-  return ret;
-
-  /* ERRORS */
-sync_failed:
-  {
-    GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret));
-    goto done;
-  }
-dropped:
-  {
-    priv->dropped++;
-    GST_DEBUG_OBJECT (basesink, "buffer late, dropping");
-
-    if (g_atomic_int_get (&priv->qos_enabled)) {
-      GstMessage *qos_msg;
-      GstClockTime timestamp, duration;
-
-      timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (sync_obj));
-      duration = GST_BUFFER_DURATION (GST_BUFFER_CAST (sync_obj));
-
-      GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
-          "qos: dropped buffer rt %" GST_TIME_FORMAT ", st %" GST_TIME_FORMAT
-          ", ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (priv->current_rstart),
-          GST_TIME_ARGS (priv->current_sstart), GST_TIME_ARGS (timestamp),
-          GST_TIME_ARGS (duration));
-      GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
-          "qos: rendered %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT,
-          priv->rendered, priv->dropped);
-
-      qos_msg =
-          gst_message_new_qos (GST_OBJECT_CAST (basesink), basesink->sync,
-          priv->current_rstart, priv->current_sstart, timestamp, duration);
-      gst_message_set_qos_values (qos_msg, priv->current_jitter, priv->avg_rate,
-          1000000);
-      gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, priv->rendered,
-          priv->dropped);
-      gst_element_post_message (GST_ELEMENT_CAST (basesink), qos_msg);
-    }
-    goto done;
-  }
-flushing:
-  {
-    GST_DEBUG_OBJECT (basesink, "we are flushing, ignore object");
-    gst_mini_object_unref (obj);
-    return GST_FLOW_WRONG_STATE;
-  }
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Perform preroll on the given object. For buffers this means
- * calling the preroll subclass method.
- * If that succeeds, the state will be commited.
- *
- * function does not take ownership of obj.
- */
-static GstFlowReturn
-gst_base_sink_preroll_object (GstBaseSink * basesink, guint8 obj_type,
-    GstMiniObject * obj)
-{
-  GstFlowReturn ret;
-
-  GST_DEBUG_OBJECT (basesink, "prerolling object %p", obj);
-
-  /* if it's a buffer, we need to call the preroll method */
-  if (G_LIKELY (OBJ_IS_BUFFERFULL (obj_type) && basesink->priv->call_preroll)) {
-    GstBaseSinkClass *bclass;
-    GstBuffer *buf;
-    GstClockTime timestamp;
-
-    if (OBJ_IS_BUFFERLIST (obj_type)) {
-      buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
-      g_assert (NULL != buf);
-    } else {
-      buf = GST_BUFFER_CAST (obj);
-    }
-
-    timestamp = GST_BUFFER_TIMESTAMP (buf);
-
-    GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timestamp));
-
-    /*
-     * For buffer lists do not set last buffer. Creating buffer
-     * with meaningful data can be done only with memcpy which will
-     * significantly affect performance
-     */
-    if (!OBJ_IS_BUFFERLIST (obj_type)) {
-      gst_base_sink_set_last_buffer (basesink, buf);
-    }
-
-    bclass = GST_BASE_SINK_GET_CLASS (basesink);
-    if (bclass->preroll)
-      if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)
-        goto preroll_failed;
-
-    basesink->priv->call_preroll = FALSE;
-  }
-
-  /* commit state */
-  if (G_LIKELY (basesink->playing_async)) {
-    if (G_UNLIKELY (!gst_base_sink_commit_state (basesink)))
-      goto stopping;
-  }
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-preroll_failed:
-  {
-    GST_DEBUG_OBJECT (basesink, "preroll failed, abort state");
-    gst_element_abort_state (GST_ELEMENT_CAST (basesink));
-    return ret;
-  }
-stopping:
-  {
-    GST_DEBUG_OBJECT (basesink, "stopping while commiting state");
-    return GST_FLOW_WRONG_STATE;
-  }
-}
-
-/* with STREAM_LOCK, PREROLL_LOCK
- *
- * Queue an object for rendering.
- * The first prerollable object queued will complete the preroll. If the
- * preroll queue is filled, we render all the objects in the queue.
- *
- * This function takes ownership of the object.
- */
-static GstFlowReturn
-gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
-    guint8 obj_type, gpointer obj, gboolean prerollable)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  gint length;
-  GQueue *q;
-
-  if (G_UNLIKELY (basesink->need_preroll)) {
-    if (G_LIKELY (prerollable))
-      basesink->preroll_queued++;
-
-    length = basesink->preroll_queued;
-
-    GST_DEBUG_OBJECT (basesink, "now %d prerolled items", length);
-
-    /* first prerollable item needs to finish the preroll */
-    if (length == 1) {
-      ret = gst_base_sink_preroll_object (basesink, obj_type, obj);
-      if (G_UNLIKELY (ret != GST_FLOW_OK))
-        goto preroll_failed;
-    }
-    /* need to recheck if we need preroll, commit state during preroll
-     * could have made us not need more preroll. */
-    if (G_UNLIKELY (basesink->need_preroll)) {
-      /* see if we can render now, if we can't add the object to the preroll
-       * queue. */
-      if (G_UNLIKELY (length <= basesink->preroll_queue_max_len))
-        goto more_preroll;
-    }
-  }
-  /* we can start rendering (or blocking) the queued object
-   * if any. */
-  q = basesink->preroll_queue;
-  while (G_UNLIKELY (!g_queue_is_empty (q))) {
-    GstMiniObject *o;
-    guint8 ot;
-
-    o = g_queue_pop_head (q);
-    GST_DEBUG_OBJECT (basesink, "rendering queued object %p", o);
-
-    ot = get_object_type (o);
-
-    /* do something with the return value */
-    ret = gst_base_sink_render_object (basesink, pad, ot, o);
-    if (ret != GST_FLOW_OK)
-      goto dequeue_failed;
-  }
-
-  /* now render the object */
-  ret = gst_base_sink_render_object (basesink, pad, obj_type, obj);
-  basesink->preroll_queued = 0;
-
-  return ret;
-
-  /* special cases */
-preroll_failed:
-  {
-    GST_DEBUG_OBJECT (basesink, "preroll failed, reason %s",
-        gst_flow_get_name (ret));
-    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
-    return ret;
-  }
-more_preroll:
-  {
-    /* add object to the queue and return */
-    GST_DEBUG_OBJECT (basesink, "need more preroll data %d <= %d",
-        length, basesink->preroll_queue_max_len);
-    g_queue_push_tail (basesink->preroll_queue, obj);
-    return GST_FLOW_OK;
-  }
-dequeue_failed:
-  {
-    GST_DEBUG_OBJECT (basesink, "rendering queued objects failed, reason %s",
-        gst_flow_get_name (ret));
-    gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
-    return ret;
-  }
-}
-
-/* with STREAM_LOCK
- *
- * This function grabs the PREROLL_LOCK and adds the object to
- * the queue.
- *
- * This function takes ownership of obj.
- *
- * Note: Only GstEvent seem to be passed to this private method
- */
-static GstFlowReturn
-gst_base_sink_queue_object (GstBaseSink * basesink, GstPad * pad,
-    GstMiniObject * obj, gboolean prerollable)
-{
-  GstFlowReturn ret;
-
-  GST_PAD_PREROLL_LOCK (pad);
-  if (G_UNLIKELY (basesink->flushing))
-    goto flushing;
-
-  if (G_UNLIKELY (basesink->priv->received_eos))
-    goto was_eos;
-
-  ret =
-      gst_base_sink_queue_object_unlocked (basesink, pad, _PR_IS_EVENT, obj,
-      prerollable);
-  GST_PAD_PREROLL_UNLOCK (pad);
-
-  return ret;
-
-  /* ERRORS */
-flushing:
-  {
-    GST_DEBUG_OBJECT (basesink, "sink is flushing");
-    GST_PAD_PREROLL_UNLOCK (pad);
-    gst_mini_object_unref (obj);
-    return GST_FLOW_WRONG_STATE;
-  }
-was_eos:
-  {
-    GST_DEBUG_OBJECT (basesink,
-        "we are EOS, dropping object, return UNEXPECTED");
-    GST_PAD_PREROLL_UNLOCK (pad);
-    gst_mini_object_unref (obj);
-    return GST_FLOW_UNEXPECTED;
-  }
-}
-
-static void
-gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
-{
-  /* make sure we are not blocked on the clock also clear any pending
-   * eos state. */
-  gst_base_sink_set_flushing (basesink, pad, TRUE);
-
-  /* we grab the stream lock but that is not needed since setting the
-   * sink to flushing would make sure no state commit is being done
-   * anymore */
-  GST_PAD_STREAM_LOCK (pad);
-  gst_base_sink_reset_qos (basesink);
-  /* and we need to commit our state again on the next
-   * prerolled buffer */
-  basesink->playing_async = TRUE;
-  if (basesink->priv->async_enabled) {
-    gst_element_lost_state (GST_ELEMENT_CAST (basesink));
-  } else {
-    /* start time reset in above case as well;
-     * arranges for a.o. proper position reporting when flushing in PAUSED */
-    gst_element_set_start_time (GST_ELEMENT_CAST (basesink), 0);
-    basesink->priv->have_latency = TRUE;
-  }
-  gst_base_sink_set_last_buffer (basesink, NULL);
-  GST_PAD_STREAM_UNLOCK (pad);
-}
-
-static void
-gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad)
-{
-  /* unset flushing so we can accept new data, this also flushes out any EOS
-   * event. */
-  gst_base_sink_set_flushing (basesink, pad, FALSE);
-
-  /* for position reporting */
-  GST_OBJECT_LOCK (basesink);
-  basesink->priv->current_sstart = GST_CLOCK_TIME_NONE;
-  basesink->priv->current_sstop = GST_CLOCK_TIME_NONE;
-  basesink->priv->eos_rtime = GST_CLOCK_TIME_NONE;
-  basesink->priv->call_preroll = TRUE;
-  basesink->priv->current_step.valid = FALSE;
-  basesink->priv->pending_step.valid = FALSE;
-  if (basesink->pad_mode == GST_ACTIVATE_PUSH) {
-    /* we need new segment info after the flush. */
-    basesink->have_newsegment = FALSE;
-    gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
-    gst_segment_init (basesink->abidata.ABI.clip_segment, GST_FORMAT_UNDEFINED);
-  }
-  GST_OBJECT_UNLOCK (basesink);
-}
-
-static gboolean
-gst_base_sink_event (GstPad * pad, GstEvent * event)
-{
-  GstBaseSink *basesink;
-  gboolean result = TRUE;
-  GstBaseSinkClass *bclass;
-
-  basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (basesink == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+static gboolean
+gst_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+  GstBaseSink *basesink;
+  gboolean result = TRUE;
+  GstBaseSinkClass *bclass;
 
+  basesink = GST_BASE_SINK_CAST (parent);
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
   GST_DEBUG_OBJECT (basesink, "received event %p %" GST_PTR_FORMAT, event,
       event);
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-    {
-      GstFlowReturn ret;
-
-      GST_PAD_PREROLL_LOCK (pad);
-      if (G_UNLIKELY (basesink->flushing))
-        goto flushing;
-
-      if (G_UNLIKELY (basesink->priv->received_eos)) {
-        /* we can't accept anything when we are EOS */
-        result = FALSE;
-        gst_event_unref (event);
-      } else {
-        /* we set the received EOS flag here so that we can use it when testing if
-         * we are prerolled and to refuse more buffers. */
-        basesink->priv->received_eos = TRUE;
-
-        /* EOS is a prerollable object, we call the unlocked version because it
-         * does not check the received_eos flag. */
-        ret = gst_base_sink_queue_object_unlocked (basesink, pad,
-            _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), TRUE);
-        if (G_UNLIKELY (ret != GST_FLOW_OK))
-          result = FALSE;
-      }
-      GST_PAD_PREROLL_UNLOCK (pad);
-      break;
-    }
-    case GST_EVENT_NEWSEGMENT:
-    {
-      GstFlowReturn ret;
-      gboolean update;
-
-      GST_DEBUG_OBJECT (basesink, "newsegment %p", event);
-
-      GST_PAD_PREROLL_LOCK (pad);
-      if (G_UNLIKELY (basesink->flushing))
-        goto flushing;
-
-      gst_event_parse_new_segment_full (event, &update, NULL, NULL, NULL, NULL,
-          NULL, NULL);
-
-      if (G_UNLIKELY (basesink->priv->received_eos && !update)) {
-        /* we can't accept anything when we are EOS */
-        result = FALSE;
-        gst_event_unref (event);
-      } else {
-        /* the new segment is a non prerollable item and does not block anything,
-         * we need to configure the current clipping segment and insert the event
-         * in the queue to serialize it with the buffers for rendering. */
-        gst_base_sink_configure_segment (basesink, pad, event,
-            basesink->abidata.ABI.clip_segment);
-
-        ret =
-            gst_base_sink_queue_object_unlocked (basesink, pad,
-            _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), FALSE);
-        if (G_UNLIKELY (ret != GST_FLOW_OK))
-          result = FALSE;
-        else {
-          GST_OBJECT_LOCK (basesink);
-          basesink->have_newsegment = TRUE;
-          GST_OBJECT_UNLOCK (basesink);
-        }
-      }
-      GST_PAD_PREROLL_UNLOCK (pad);
-      break;
-    }
-    case GST_EVENT_FLUSH_START:
-      if (bclass->event)
-        bclass->event (basesink, event);
-
-      GST_DEBUG_OBJECT (basesink, "flush-start %p", event);
-
-      gst_base_sink_flush_start (basesink, pad);
-
-      gst_event_unref (event);
-      break;
     case GST_EVENT_FLUSH_STOP:
+      /* special case for this serialized event because we don't want to grab
+       * the PREROLL lock or check if we were flushing */
       if (bclass->event)
-        bclass->event (basesink, event);
-
-      GST_DEBUG_OBJECT (basesink, "flush-stop %p", event);
-
-      gst_base_sink_flush_stop (basesink, pad);
-
-      gst_event_unref (event);
+        result = bclass->event (basesink, event);
       break;
     default:
-      /* other events are sent to queue or subclass depending on if they
-       * are serialized. */
       if (GST_EVENT_IS_SERIALIZED (event)) {
-        gst_base_sink_queue_object (basesink, pad,
-            GST_MINI_OBJECT_CAST (event), FALSE);
+        GST_BASE_SINK_PREROLL_LOCK (basesink);
+        if (G_UNLIKELY (basesink->flushing))
+          goto flushing;
+
+        if (G_UNLIKELY (basesink->priv->received_eos))
+          goto after_eos;
+
+        if (bclass->event)
+          result = bclass->event (basesink, event);
+
+        GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       } else {
         if (bclass->event)
-          bclass->event (basesink, event);
-        gst_event_unref (event);
+          result = bclass->event (basesink, event);
       }
       break;
   }
 done:
-  gst_object_unref (basesink);
-
   return result;
 
   /* ERRORS */
 flushing:
   {
     GST_DEBUG_OBJECT (basesink, "we are flushing");
-    GST_PAD_PREROLL_UNLOCK (pad);
+    GST_BASE_SINK_PREROLL_UNLOCK (basesink);
+    gst_event_unref (event);
     result = FALSE;
+    goto done;
+  }
+
+after_eos:
+  {
+    GST_DEBUG_OBJECT (basesink, "Event received after EOS, dropping");
+    GST_BASE_SINK_PREROLL_UNLOCK (basesink);
     gst_event_unref (event);
+    result = FALSE;
     goto done;
   }
 }
@@ -3558,14 +3017,17 @@ flushing:
  * timestamps on a buffer, subclasses can override
  */
 static void
-gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
+gst_base_sink_default_get_times (GstBaseSink * basesink, GstBuffer * buffer,
     GstClockTime * start, GstClockTime * end)
 {
   GstClockTime timestamp, duration;
 
-  timestamp = GST_BUFFER_TIMESTAMP (buffer);
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+  /* first sync on DTS, else use PTS */
+  timestamp = GST_BUFFER_DTS (buffer);
+  if (!GST_CLOCK_TIME_IS_VALID (timestamp))
+    timestamp = GST_BUFFER_PTS (buffer);
 
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
     /* get duration to calculate end time */
     duration = GST_BUFFER_DURATION (buffer);
     if (GST_CLOCK_TIME_IS_VALID (duration)) {
@@ -3598,35 +3060,38 @@ gst_base_sink_needs_preroll (GstBaseSink * basesink)
  *
  * Takes a buffer and compare the timestamps with the last segment.
  * If the buffer falls outside of the segment boundaries, drop it.
- * Else queue the buffer for preroll and rendering.
+ * Else send the buffer for preroll and rendering.
  *
  * This function takes ownership of the buffer.
  */
 static GstFlowReturn
 gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
-    guint8 obj_type, gpointer obj)
+    gpointer obj)
 {
   GstBaseSinkClass *bclass;
-  GstFlowReturn result;
+  GstBaseSinkPrivate *priv = basesink->priv;
+  GstFlowReturn ret;
   GstClockTime start = GST_CLOCK_TIME_NONE, end = GST_CLOCK_TIME_NONE;
-  GstSegment *clip_segment;
-  GstBuffer *time_buf;
+  GstSegment *segment;
+  GstBuffer *sync_buf;
+  gint do_qos;
+  gboolean late, step_end;
 
   if (G_UNLIKELY (basesink->flushing))
     goto flushing;
 
-  if (G_UNLIKELY (basesink->priv->received_eos))
+  if (G_UNLIKELY (priv->received_eos))
     goto was_eos;
 
-  if (OBJ_IS_BUFFERLIST (obj_type)) {
-    time_buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
-    g_assert (NULL != time_buf);
+  if (GST_IS_BUFFER_LIST (obj)) {
+    sync_buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0);
+    g_assert (NULL != sync_buf);
   } else {
-    time_buf = GST_BUFFER_CAST (obj);
+    sync_buf = GST_BUFFER_CAST (obj);
   }
 
   /* for code clarity */
-  clip_segment = basesink->abidata.ABI.clip_segment;
+  segment = &basesink->segment;
 
   if (G_UNLIKELY (!basesink->have_newsegment)) {
     gboolean sync;
@@ -3640,8 +3105,8 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
 
     /* this means this sink will assume timestamps start from 0 */
     GST_OBJECT_LOCK (basesink);
-    clip_segment->start = 0;
-    clip_segment->stop = -1;
+    segment->start = 0;
+    segment->stop = -1;
     basesink->segment.start = 0;
     basesink->segment.stop = -1;
     basesink->have_newsegment = TRUE;
@@ -3653,30 +3118,85 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
   /* check if the buffer needs to be dropped, we first ask the subclass for the
    * start and end */
   if (bclass->get_times)
-    bclass->get_times (basesink, time_buf, &start, &end);
+    bclass->get_times (basesink, sync_buf, &start, &end);
 
   if (!GST_CLOCK_TIME_IS_VALID (start)) {
     /* if the subclass does not want sync, we use our own values so that we at
      * least clip the buffer to the segment */
-    gst_base_sink_get_times (basesink, time_buf, &start, &end);
+    gst_base_sink_default_get_times (basesink, sync_buf, &start, &end);
   }
 
   GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
       ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
 
   /* a dropped buffer does not participate in anything */
-  if (GST_CLOCK_TIME_IS_VALID (start) &&
-      (clip_segment->format == GST_FORMAT_TIME)) {
-    if (G_UNLIKELY (!gst_segment_clip (clip_segment,
-                GST_FORMAT_TIME, (gint64) start, (gint64) end, NULL, NULL)))
+  if (GST_CLOCK_TIME_IS_VALID (start) && (segment->format == GST_FORMAT_TIME)) {
+    if (G_UNLIKELY (!gst_segment_clip (segment,
+                GST_FORMAT_TIME, start, end, NULL, NULL)))
       goto out_of_segment;
   }
 
-  /* now we can process the buffer in the queue, this function takes ownership
-   * of the buffer */
-  result = gst_base_sink_queue_object_unlocked (basesink, pad,
-      obj_type, obj, TRUE);
-  return result;
+again:
+  late = FALSE;
+  step_end = FALSE;
+
+  /* synchronize this object, non syncable objects return OK
+   * immediately. */
+  ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (sync_buf),
+      &late, &step_end);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto sync_failed;
+
+  /* drop late buffers unconditionally, let's hope it's unlikely */
+  if (G_UNLIKELY (late))
+    goto dropped;
+
+  /* read once, to get same value before and after */
+  do_qos = g_atomic_int_get (&priv->qos_enabled);
+
+  GST_DEBUG_OBJECT (basesink, "rendering object %p", obj);
+
+  /* record rendering time for QoS and stats */
+  if (do_qos)
+    gst_base_sink_do_render_stats (basesink, TRUE);
+
+  if (!GST_IS_BUFFER_LIST (obj)) {
+    /* For buffer lists do not set last buffer for now. */
+    gst_base_sink_set_last_buffer (basesink, GST_BUFFER_CAST (obj));
+
+    if (bclass->render)
+      ret = bclass->render (basesink, GST_BUFFER_CAST (obj));
+  } else {
+    if (bclass->render_list)
+      ret = bclass->render_list (basesink, GST_BUFFER_LIST_CAST (obj));
+  }
+
+  if (do_qos)
+    gst_base_sink_do_render_stats (basesink, FALSE);
+
+  if (ret == GST_FLOW_STEP)
+    goto again;
+
+  if (G_UNLIKELY (basesink->flushing))
+    goto flushing;
+
+  priv->rendered++;
+
+done:
+  if (step_end) {
+    /* the step ended, check if we need to activate a new step */
+    GST_DEBUG_OBJECT (basesink, "step ended");
+    stop_stepping (basesink, &basesink->segment, &priv->current_step,
+        priv->current_rstart, priv->current_rstop, basesink->eos);
+    goto again;
+  }
+
+  gst_base_sink_perform_qos (basesink, late);
+
+  GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+
+  return ret;
 
   /* ERRORS */
 flushing:
@@ -3687,10 +3207,9 @@ flushing:
   }
 was_eos:
   {
-    GST_DEBUG_OBJECT (basesink,
-        "we are EOS, dropping object, return UNEXPECTED");
+    GST_DEBUG_OBJECT (basesink, "we are EOS, dropping object, return EOS");
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 out_of_segment:
   {
@@ -3698,22 +3217,59 @@ out_of_segment:
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     return GST_FLOW_OK;
   }
+sync_failed:
+  {
+    GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret));
+    goto done;
+  }
+dropped:
+  {
+    priv->dropped++;
+    GST_DEBUG_OBJECT (basesink, "buffer late, dropping");
+
+    if (g_atomic_int_get (&priv->qos_enabled)) {
+      GstMessage *qos_msg;
+      GstClockTime timestamp, duration;
+
+      timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (sync_buf));
+      duration = GST_BUFFER_DURATION (GST_BUFFER_CAST (sync_buf));
+
+      GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
+          "qos: dropped buffer rt %" GST_TIME_FORMAT ", st %" GST_TIME_FORMAT
+          ", ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (priv->current_rstart),
+          GST_TIME_ARGS (priv->current_sstart), GST_TIME_ARGS (timestamp),
+          GST_TIME_ARGS (duration));
+      GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
+          "qos: rendered %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT,
+          priv->rendered, priv->dropped);
+
+      qos_msg =
+          gst_message_new_qos (GST_OBJECT_CAST (basesink), basesink->sync,
+          priv->current_rstart, priv->current_sstart, timestamp, duration);
+      gst_message_set_qos_values (qos_msg, priv->current_jitter, priv->avg_rate,
+          1000000);
+      gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, priv->rendered,
+          priv->dropped);
+      gst_element_post_message (GST_ELEMENT_CAST (basesink), qos_msg);
+    }
+    goto done;
+  }
 }
 
 /* with STREAM_LOCK
  */
 static GstFlowReturn
-gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad,
-    guint8 obj_type, gpointer obj)
+gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj)
 {
   GstFlowReturn result;
 
-  if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PUSH))
+  if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH))
     goto wrong_mode;
 
-  GST_PAD_PREROLL_LOCK (pad);
-  result = gst_base_sink_chain_unlocked (basesink, pad, obj_type, obj);
-  GST_PAD_PREROLL_UNLOCK (pad);
+  GST_BASE_SINK_PREROLL_LOCK (basesink);
+  result = gst_base_sink_chain_unlocked (basesink, pad, obj);
+  GST_BASE_SINK_PREROLL_UNLOCK (basesink);
 
 done:
   return result;
@@ -3729,60 +3285,50 @@ wrong_mode:
     gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
     /* we don't post an error message this will signal to the peer
      * pushing that EOS is reached. */
-    result = GST_FLOW_UNEXPECTED;
+    result = GST_FLOW_EOS;
     goto done;
   }
 }
 
 static GstFlowReturn
-gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
+gst_base_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
   GstBaseSink *basesink;
 
-  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
+  basesink = GST_BASE_SINK (parent);
 
-  return gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER, buf);
+  return gst_base_sink_chain_main (basesink, pad, buf);
 }
 
 static GstFlowReturn
-gst_base_sink_chain_list (GstPad * pad, GstBufferList * list)
+gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * list)
 {
   GstBaseSink *basesink;
   GstBaseSinkClass *bclass;
   GstFlowReturn result;
 
-  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
+  basesink = GST_BASE_SINK (parent);
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
   if (G_LIKELY (bclass->render_list)) {
-    result = gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFERLIST, list);
+    result = gst_base_sink_chain_main (basesink, pad, list);
   } else {
-    GstBufferListIterator *it;
-    GstBuffer *group;
+    guint i, len;
+    GstBuffer *buffer;
 
     GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
 
-    it = gst_buffer_list_iterate (list);
+    len = gst_buffer_list_length (list);
 
-    if (gst_buffer_list_iterator_next_group (it)) {
-      do {
-        group = gst_buffer_list_iterator_merge_group (it);
-        if (group == NULL) {
-          group = gst_buffer_new ();
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
-        } else {
-          GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
-        }
-        result = gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER, group);
-      } while (result == GST_FLOW_OK
-          && gst_buffer_list_iterator_next_group (it));
-    } else {
-      GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
-      result =
-          gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER,
-          gst_buffer_new ());
+    result = GST_FLOW_OK;
+    for (i = 0; i < len; i++) {
+      buffer = gst_buffer_list_get (list, i);
+      result = gst_base_sink_chain_main (basesink, pad,
+          gst_buffer_ref (buffer));
+      if (result != GST_FLOW_OK)
+        break;
     }
-    gst_buffer_list_iterator_free (it);
     gst_buffer_list_unref (list);
   }
   return result;
@@ -3824,17 +3370,16 @@ gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
   GstSeekType cur_type, stop_type;
   gint64 cur, stop;
   GstSeekFlags flags;
-  GstFormat seek_format, dest_format;
+  GstFormat seek_format;
   gdouble rate;
   gboolean update;
   gboolean res = TRUE;
 
   gst_event_parse_seek (event, &rate, &seek_format, &flags,
       &cur_type, &cur, &stop_type, &stop);
-  dest_format = segment->format;
 
-  if (seek_format == dest_format) {
-    gst_segment_set_seek (segment, rate, seek_format, flags,
+  if (seek_format == segment->format) {
+    gst_segment_do_seek (segment, rate, seek_format, flags,
         cur_type, cur, stop_type, stop, &update);
     return TRUE;
   }
@@ -3842,7 +3387,7 @@ gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
   if (cur_type != GST_SEEK_TYPE_NONE) {
     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
     res =
-        gst_pad_query_convert (sink->sinkpad, seek_format, cur, &dest_format,
+        gst_pad_query_convert (sink->sinkpad, seek_format, cur, segment->format,
         &cur);
     cur_type = GST_SEEK_TYPE_SET;
   }
@@ -3850,13 +3395,13 @@ gst_base_sink_default_prepare_seek_segment (GstBaseSink * sink,
   if (res && stop_type != GST_SEEK_TYPE_NONE) {
     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
     res =
-        gst_pad_query_convert (sink->sinkpad, seek_format, stop, &dest_format,
-        &stop);
+        gst_pad_query_convert (sink->sinkpad, seek_format, stop,
+        segment->format, &stop);
     stop_type = GST_SEEK_TYPE_SET;
   }
 
   /* And finally, configure our output segment in the desired format */
-  gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,
+  gst_segment_do_seek (segment, rate, segment->format, flags, cur_type, cur,
       stop_type, stop, &update);
 
   if (!res)
@@ -3929,7 +3474,7 @@ gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
       } else {
         /* The seek format matches our processing format, no need to ask the
          * the subclass to configure the segment. */
-        gst_segment_set_seek (&seeksegment, rate, seek_format, flags,
+        gst_segment_do_seek (&seeksegment, rate, seek_format, flags,
             cur_type, cur, stop_type, stop, &update);
       }
     }
@@ -3940,22 +3485,22 @@ gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
   if (res) {
     GST_DEBUG_OBJECT (sink, "segment configured from %" G_GINT64_FORMAT
         " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
-        seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+        seeksegment.start, seeksegment.stop, seeksegment.position);
 
-    /* do the seek, segment.last_stop contains the new position. */
+    /* do the seek, segment.position contains the new position. */
     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 ());
-    gst_base_sink_flush_stop (sink, pad);
-  } else if (res && sink->abidata.ABI.running) {
+    gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
+    gst_base_sink_flush_stop (sink, pad, TRUE);
+  } else if (res && sink->running) {
     /* we are running the current segment and doing a non-flushing seek,
-     * close the segment first based on the last_stop. */
+     * close the segment first based on the position. */
     GST_DEBUG_OBJECT (sink, "closing running segment %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, sink->segment.start, sink->segment.last_stop);
+        " to %" G_GINT64_FORMAT, sink->segment.start, sink->segment.position);
   }
 
   /* The subclass must have converted the segment to the processing format
@@ -3969,17 +3514,17 @@ gst_base_sink_perform_seek (GstBaseSink * sink, GstPad * pad, GstEvent * event)
   /* if successful seek, we update our real segment and push
    * out the new segment. */
   if (res) {
-    memcpy (&sink->segment, &seeksegment, sizeof (GstSegment));
+    gst_segment_copy_into (&seeksegment, &sink->segment);
 
     if (sink->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       gst_element_post_message (GST_ELEMENT (sink),
           gst_message_new_segment_start (GST_OBJECT (sink),
-              sink->segment.format, sink->segment.last_stop));
+              sink->segment.format, sink->segment.position));
     }
   }
 
   sink->priv->discont = TRUE;
-  sink->abidata.ABI.running = TRUE;
+  sink->running = TRUE;
 
   GST_PAD_STREAM_UNLOCK (pad);
 
@@ -4042,7 +3587,7 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
     if (bclass->unlock)
       bclass->unlock (sink);
 
-    GST_PAD_PREROLL_LOCK (sink->sinkpad);
+    GST_BASE_SINK_PREROLL_LOCK (sink);
     /* now that we have the PREROLL lock, clear our unlock request */
     if (bclass->unlock_stop)
       bclass->unlock_stop (sink);
@@ -4057,7 +3602,7 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
       sink->playing_async = TRUE;
       priv->pending_step.need_preroll = TRUE;
       sink->need_preroll = FALSE;
-      gst_element_lost_state_full (GST_ELEMENT_CAST (sink), FALSE);
+      gst_element_lost_state (GST_ELEMENT_CAST (sink));
     } else {
       sink->priv->have_latency = TRUE;
       sink->need_preroll = FALSE;
@@ -4076,9 +3621,9 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
     if (sink->have_preroll) {
       GST_DEBUG_OBJECT (sink, "signal waiter");
       priv->step_unlock = TRUE;
-      GST_PAD_PREROLL_SIGNAL (sink->sinkpad);
+      GST_BASE_SINK_PREROLL_SIGNAL (sink);
     }
-    GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
+    GST_BASE_SINK_PREROLL_UNLOCK (sink);
   } else {
     /* update the stepinfo and make it valid */
     set_step_info (sink, current, pending, seqnum, format, amount, rate, flush,
@@ -4093,20 +3638,22 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
 static void
 gst_base_sink_loop (GstPad * pad)
 {
+  GstObject *parent;
   GstBaseSink *basesink;
   GstBuffer *buf = NULL;
   GstFlowReturn result;
   guint blocksize;
   guint64 offset;
 
-  basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
+  parent = GST_OBJECT_PARENT (pad);
+  basesink = GST_BASE_SINK (parent);
 
-  g_assert (basesink->pad_mode == GST_ACTIVATE_PULL);
+  g_assert (basesink->pad_mode == GST_PAD_MODE_PULL);
 
   if ((blocksize = basesink->priv->blocksize) == 0)
     blocksize = -1;
 
-  offset = basesink->segment.last_stop;
+  offset = basesink->segment.position;
 
   GST_DEBUG_OBJECT (basesink, "pulling %" G_GUINT64_FORMAT ", %u",
       offset, blocksize);
@@ -4118,13 +3665,13 @@ gst_base_sink_loop (GstPad * pad)
   if (G_UNLIKELY (buf == NULL))
     goto no_buffer;
 
-  offset += GST_BUFFER_SIZE (buf);
+  offset += gst_buffer_get_size (buf);
 
-  gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_BYTES, offset);
+  basesink->segment.position = offset;
 
-  GST_PAD_PREROLL_LOCK (pad);
-  result = gst_base_sink_chain_unlocked (basesink, pad, _PR_IS_BUFFER, buf);
-  GST_PAD_PREROLL_UNLOCK (pad);
+  GST_BASE_SINK_PREROLL_LOCK (basesink);
+  result = gst_base_sink_chain_unlocked (basesink, pad, buf);
+  GST_BASE_SINK_PREROLL_UNLOCK (basesink);
   if (G_UNLIKELY (result != GST_FLOW_OK))
     goto paused;
 
@@ -4136,16 +3683,16 @@ paused:
     GST_LOG_OBJECT (basesink, "pausing task, reason %s",
         gst_flow_get_name (result));
     gst_pad_pause_task (pad);
-    if (result == GST_FLOW_UNEXPECTED) {
+    if (result == GST_FLOW_EOS) {
       /* perform EOS logic */
       if (basesink->segment.flags & GST_SEEK_FLAG_SEGMENT) {
         gst_element_post_message (GST_ELEMENT_CAST (basesink),
             gst_message_new_segment_done (GST_OBJECT_CAST (basesink),
-                basesink->segment.format, basesink->segment.last_stop));
+                basesink->segment.format, basesink->segment.position));
       } else {
-        gst_base_sink_event (pad, gst_event_new_eos ());
+        gst_base_sink_event (pad, parent, gst_event_new_eos ());
       }
-    } else if (result == GST_FLOW_NOT_LINKED || result <= GST_FLOW_UNEXPECTED) {
+    } else if (result == GST_FLOW_NOT_LINKED || result <= GST_FLOW_EOS) {
       /* for fatal errors we post an error message, post the error
        * first so the app knows about the error first. 
        * wrong-state is not a fatal error because it happens due to
@@ -4155,7 +3702,7 @@ paused:
       GST_ELEMENT_ERROR (basesink, STREAM, FAILED,
           (_("Internal data stream error.")),
           ("stream stopped, reason %s", gst_flow_get_name (result)));
-      gst_base_sink_event (pad, gst_event_new_eos ());
+      gst_base_sink_event (pad, parent, gst_event_new_eos ());
     }
     return;
   }
@@ -4184,7 +3731,7 @@ gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad,
       bclass->unlock (basesink);
   }
 
-  GST_PAD_PREROLL_LOCK (pad);
+  GST_BASE_SINK_PREROLL_LOCK (basesink);
   basesink->flushing = flushing;
   if (flushing) {
     /* step 1, now that we have the PREROLL lock, clear our unlock request */
@@ -4204,9 +3751,22 @@ gst_base_sink_set_flushing (GstBaseSink * basesink, GstPad * pad,
      * also flush out the EOS state */
     GST_DEBUG_OBJECT (basesink,
         "flushing out data thread, need preroll to TRUE");
-    gst_base_sink_preroll_queue_flush (basesink, pad);
+
+    /* we can't have EOS anymore now */
+    basesink->eos = FALSE;
+    basesink->priv->received_eos = FALSE;
+    basesink->have_preroll = FALSE;
+    basesink->priv->step_unlock = FALSE;
+    /* can't report latency anymore until we preroll again */
+    if (basesink->priv->async_enabled) {
+      GST_OBJECT_LOCK (basesink);
+      basesink->priv->have_latency = FALSE;
+      GST_OBJECT_UNLOCK (basesink);
+    }
+    /* and signal any waiters now */
+    GST_BASE_SINK_PREROLL_SIGNAL (basesink);
   }
-  GST_PAD_PREROLL_UNLOCK (pad);
+  GST_BASE_SINK_PREROLL_UNLOCK (basesink);
 
   return TRUE;
 }
@@ -4229,12 +3789,14 @@ gst_base_sink_default_activate_pull (GstBaseSink * basesink, gboolean active)
 }
 
 static gboolean
-gst_base_sink_pad_activate (GstPad * pad)
+gst_base_sink_pad_activate (GstPad * pad, GstObject * parent)
 {
   gboolean result = FALSE;
   GstBaseSink *basesink;
+  GstQuery *query;
+  gboolean pull_mode;
 
-  basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
+  basesink = GST_BASE_SINK (parent);
 
   GST_DEBUG_OBJECT (basesink, "Trying pull mode first");
 
@@ -4247,7 +3809,19 @@ gst_base_sink_pad_activate (GstPad * pad)
   }
 
   /* check if downstreams supports pull mode at all */
-  if (!gst_pad_check_pull_range (pad)) {
+  query = gst_query_new_scheduling ();
+
+  if (!gst_pad_peer_query (pad, query)) {
+    gst_query_unref (query);
+    GST_DEBUG_OBJECT (basesink, "peer query faild, no pull mode");
+    goto fallback;
+  }
+
+  /* parse result of the query */
+  pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
+  gst_query_unref (query);
+
+  if (!pull_mode) {
     GST_DEBUG_OBJECT (basesink, "pull mode not supported");
     goto fallback;
   }
@@ -4255,7 +3829,7 @@ gst_base_sink_pad_activate (GstPad * pad)
   /* set the pad mode before starting the task so that it's in the
    * correct state for the new thread. also the sink set_caps and get_caps
    * function checks this */
-  basesink->pad_mode = GST_ACTIVATE_PULL;
+  basesink->pad_mode = GST_PAD_MODE_PULL;
 
   /* we first try to negotiate a format so that when we try to activate
    * downstream, it knows about our format */
@@ -4265,10 +3839,10 @@ gst_base_sink_pad_activate (GstPad * pad)
   }
 
   /* ok activate now */
-  if (!gst_pad_activate_pull (pad, TRUE)) {
+  if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) {
     /* clear any pending caps */
     GST_OBJECT_LOCK (basesink);
-    gst_caps_replace (&basesink->priv->pull_caps, NULL);
+    gst_caps_replace (&basesink->priv->caps, NULL);
     GST_OBJECT_UNLOCK (basesink);
     GST_DEBUG_OBJECT (basesink, "failed to activate in pull mode");
     goto fallback;
@@ -4281,7 +3855,7 @@ gst_base_sink_pad_activate (GstPad * pad)
   /* push mode fallback */
 fallback:
   GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
-  if ((result = gst_pad_activate_push (pad, TRUE))) {
+  if ((result = gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE))) {
     GST_DEBUG_OBJECT (basesink, "Success activating push mode");
   }
 
@@ -4291,40 +3865,37 @@ done:
     gst_base_sink_set_flushing (basesink, pad, TRUE);
   }
 
-  gst_object_unref (basesink);
-
   return result;
 }
 
 static gboolean
-gst_base_sink_pad_activate_push (GstPad * pad, gboolean active)
+gst_base_sink_pad_activate_push (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean result;
   GstBaseSink *basesink;
 
-  basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
+  basesink = GST_BASE_SINK (parent);
 
   if (active) {
     if (!basesink->can_activate_push) {
       result = FALSE;
-      basesink->pad_mode = GST_ACTIVATE_NONE;
+      basesink->pad_mode = GST_PAD_MODE_NONE;
     } else {
       result = TRUE;
-      basesink->pad_mode = GST_ACTIVATE_PUSH;
+      basesink->pad_mode = GST_PAD_MODE_PUSH;
     }
   } else {
-    if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PUSH)) {
+    if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PUSH)) {
       g_warning ("Internal GStreamer activation error!!!");
       result = FALSE;
     } else {
       gst_base_sink_set_flushing (basesink, pad, TRUE);
       result = TRUE;
-      basesink->pad_mode = GST_ACTIVATE_NONE;
+      basesink->pad_mode = GST_PAD_MODE_NONE;
     }
   }
 
-  gst_object_unref (basesink);
-
   return result;
 }
 
@@ -4345,29 +3916,25 @@ gst_base_sink_negotiate_pull (GstBaseSink * basesink)
 
   GST_DEBUG_OBJECT (basesink, "allowed caps: %" GST_PTR_FORMAT, caps);
 
-  caps = gst_caps_make_writable (caps);
-  /* get the first (preferred) format */
-  gst_caps_truncate (caps);
-  /* try to fixate */
-  gst_pad_fixate_caps (GST_BASE_SINK_PAD (basesink), caps);
-
-  GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
-
   if (gst_caps_is_any (caps)) {
     GST_DEBUG_OBJECT (basesink, "caps were ANY after fixating, "
         "allowing pull()");
     /* neither side has template caps in this case, so they are prepared for
        pull() without setcaps() */
     result = TRUE;
-  } else if (gst_caps_is_fixed (caps)) {
-    if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps))
-      goto could_not_set_caps;
+  } else {
+    caps = gst_caps_make_writable (caps);
+    /* try to fixate */
+    gst_base_sink_fixate (basesink, caps);
+    GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
 
-    GST_OBJECT_LOCK (basesink);
-    gst_caps_replace (&basesink->priv->pull_caps, caps);
-    GST_OBJECT_UNLOCK (basesink);
+    if (gst_caps_is_fixed (caps)) {
+      if (!gst_pad_send_event (GST_BASE_SINK_PAD (basesink),
+              gst_event_new_caps (caps)))
+        goto could_not_set_caps;
 
-    result = TRUE;
+      result = TRUE;
+    }
   }
 
   gst_caps_unref (caps);
@@ -4392,38 +3959,33 @@ could_not_set_caps:
 
 /* this won't get called until we implement an activate function */
 static gboolean
-gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active)
+gst_base_sink_pad_activate_pull (GstPad * pad, GstObject * parent,
+    gboolean active)
 {
   gboolean result = FALSE;
   GstBaseSink *basesink;
   GstBaseSinkClass *bclass;
 
-  basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
+  basesink = GST_BASE_SINK (parent);
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
   if (active) {
-    GstFormat format;
     gint64 duration;
 
     /* we mark we have a newsegment here because pull based
      * mode works just fine without having a newsegment before the
      * first buffer */
-    format = GST_FORMAT_BYTES;
-
-    gst_segment_init (&basesink->segment, format);
-    gst_segment_init (basesink->abidata.ABI.clip_segment, format);
+    gst_segment_init (&basesink->segment, GST_FORMAT_BYTES);
     GST_OBJECT_LOCK (basesink);
     basesink->have_newsegment = TRUE;
     GST_OBJECT_UNLOCK (basesink);
 
     /* get the peer duration in bytes */
-    result = gst_pad_query_peer_duration (pad, &format, &duration);
+    result = gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &duration);
     if (result) {
       GST_DEBUG_OBJECT (basesink,
           "setting duration in bytes to %" G_GINT64_FORMAT, duration);
-      gst_segment_set_duration (basesink->abidata.ABI.clip_segment, format,
-          duration);
-      gst_segment_set_duration (&basesink->segment, format, duration);
+      basesink->segment.duration = duration;
     } else {
       GST_DEBUG_OBJECT (basesink, "unknown duration");
     }
@@ -4437,21 +3999,16 @@ gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active)
       goto activate_failed;
 
   } else {
-    if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PULL)) {
+    if (G_UNLIKELY (basesink->pad_mode != GST_PAD_MODE_PULL)) {
       g_warning ("Internal GStreamer activation error!!!");
       result = FALSE;
     } else {
       result = gst_base_sink_set_flushing (basesink, pad, TRUE);
       if (bclass->activate_pull)
         result &= bclass->activate_pull (basesink, FALSE);
-      basesink->pad_mode = GST_ACTIVATE_NONE;
-      /* clear any pending caps */
-      GST_OBJECT_LOCK (basesink);
-      gst_caps_replace (&basesink->priv->pull_caps, NULL);
-      GST_OBJECT_UNLOCK (basesink);
+      basesink->pad_mode = GST_PAD_MODE_NONE;
     }
   }
-  gst_object_unref (basesink);
 
   return result;
 
@@ -4459,13 +4016,34 @@ gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active)
 activate_failed:
   {
     /* reset, as starting the thread failed */
-    basesink->pad_mode = GST_ACTIVATE_NONE;
+    basesink->pad_mode = GST_PAD_MODE_NONE;
 
     GST_ERROR_OBJECT (basesink, "subclass failed to activate in pull mode");
     return FALSE;
   }
 }
 
+static gboolean
+gst_base_sink_pad_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
+{
+  gboolean res;
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_base_sink_pad_activate_pull (pad, parent, active);
+      break;
+    case GST_PAD_MODE_PUSH:
+      res = gst_base_sink_pad_activate_push (pad, parent, active);
+      break;
+    default:
+      GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
 /* send an event to our sinkpad peer. */
 static gboolean
 gst_base_sink_send_event (GstElement * element, GstEvent * event)
@@ -4473,7 +4051,7 @@ gst_base_sink_send_event (GstElement * element, GstEvent * event)
   GstPad *pad;
   GstBaseSink *basesink = GST_BASE_SINK (element);
   gboolean forward, result = TRUE;
-  GstActivateMode mode;
+  GstPadMode mode;
 
   GST_OBJECT_LOCK (element);
   /* get the pad and the scheduling mode */
@@ -4511,7 +4089,7 @@ gst_base_sink_send_event (GstElement * element, GstEvent * event)
     }
     case GST_EVENT_SEEK:
       /* in pull mode we will execute the seek */
-      if (mode == GST_ACTIVATE_PULL)
+      if (mode == GST_PAD_MODE_PULL)
         result = gst_base_sink_perform_seek (basesink, pad, event);
       break;
     case GST_EVENT_STEP:
@@ -4543,11 +4121,11 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
 {
   GstClock *clock = NULL;
   gboolean res = FALSE;
-  GstFormat oformat, tformat;
+  GstFormat oformat;
   GstSegment *segment;
   GstClockTime now, latency;
-  GstClockTimeDiff base;
-  gint64 time, accum, duration;
+  GstClockTimeDiff base_time;
+  gint64 time, base, duration;
   gdouble rate;
   gint64 last;
   gboolean last_seen, with_clock, in_paused;
@@ -4566,16 +4144,8 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
     in_paused = TRUE;
   }
 
-  /* we don't use the clip segment in pull mode, when seeking we update the
-   * main segment directly with the new segment values without it having to be
-   * activated by the rendering after preroll */
-  if (basesink->pad_mode == GST_ACTIVATE_PUSH)
-    segment = basesink->abidata.ABI.clip_segment;
-  else
-    segment = &basesink->segment;
+  segment = &basesink->segment;
 
-  /* our intermediate time format */
-  tformat = GST_FORMAT_TIME;
   /* get the format in the segment */
   oformat = segment->format;
 
@@ -4612,7 +4182,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
   else
     duration = 0;
 
-  accum = segment->accum;
+  base = segment->base;
   rate = segment->rate * segment->applied_rate;
   latency = basesink->priv->latency;
 
@@ -4637,28 +4207,28 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
     }
   } else {
     /* convert last stop to stream time */
-    last = gst_segment_to_stream_time (segment, oformat, segment->last_stop);
+    last = gst_segment_to_stream_time (segment, oformat, segment->position);
   }
 
   if (in_paused) {
     /* in paused, use start_time */
-    base = GST_ELEMENT_START_TIME (basesink);
+    base_time = GST_ELEMENT_START_TIME (basesink);
     GST_DEBUG_OBJECT (basesink, "in paused, using start time %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (base));
+        GST_TIME_ARGS (base_time));
   } else if (with_clock) {
     /* else use clock when needed */
-    base = GST_ELEMENT_CAST (basesink)->base_time;
+    base_time = GST_ELEMENT_CAST (basesink)->base_time;
     GST_DEBUG_OBJECT (basesink, "using clock and base time %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (base));
+        GST_TIME_ARGS (base_time));
   } else {
     /* else, no sync or clock -> no base time */
     GST_DEBUG_OBJECT (basesink, "no sync or no clock");
-    base = -1;
+    base_time = -1;
   }
 
-  /* no base, we can't calculate running_time, use last seem timestamp to report
+  /* no base_time, we can't calculate running_time, use last seem timestamp to report
    * time */
-  if (base == -1)
+  if (base_time == -1)
     last_seen = TRUE;
 
   /* need to release the object lock before we can get the time,
@@ -4680,47 +4250,47 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
         GST_TIME_ARGS (last));
     *cur = last;
   } else {
-    if (oformat != tformat) {
-      /* convert accum, time and duration to time */
-      if (!gst_pad_query_convert (basesink->sinkpad, oformat, accum, &tformat,
-              &accum))
+    if (oformat != GST_FORMAT_TIME) {
+      /* convert base, time and duration to time */
+      if (!gst_pad_query_convert (basesink->sinkpad, oformat, base,
+              GST_FORMAT_TIME, &base))
         goto convert_failed;
       if (!gst_pad_query_convert (basesink->sinkpad, oformat, duration,
-              &tformat, &duration))
+              GST_FORMAT_TIME, &duration))
         goto convert_failed;
-      if (!gst_pad_query_convert (basesink->sinkpad, oformat, time, &tformat,
-              &time))
+      if (!gst_pad_query_convert (basesink->sinkpad, oformat, time,
+              GST_FORMAT_TIME, &time))
         goto convert_failed;
-      if (!gst_pad_query_convert (basesink->sinkpad, oformat, last, &tformat,
-              &last))
+      if (!gst_pad_query_convert (basesink->sinkpad, oformat, last,
+              GST_FORMAT_TIME, &last))
         goto convert_failed;
 
       /* assume time format from now on */
-      oformat = tformat;
+      oformat = GST_FORMAT_TIME;
     }
 
     if (!in_paused && with_clock) {
       now = gst_clock_get_time (clock);
     } else {
-      now = base;
-      base = 0;
+      now = base_time;
+      base_time = 0;
     }
 
-    /* subtract base time and accumulated time from the clock time.
+    /* subtract base time and base time from the clock time.
      * Make sure we don't go negative. This is the current time in
      * the segment which we need to scale with the combined
      * rate and applied rate. */
-    base += accum;
-    base += latency;
-    if (GST_CLOCK_DIFF (base, now) < 0)
-      base = now;
+    base_time += base;
+    base_time += latency;
+    if (GST_CLOCK_DIFF (base_time, now) < 0)
+      base_time = now;
 
     /* for negative rates we need to count back from the segment
      * duration. */
     if (rate < 0.0)
       time += duration;
 
-    *cur = time + gst_guint64_to_gdouble (now - base) * rate;
+    *cur = time + gst_guint64_to_gdouble (now - base_time) * rate;
 
     if (in_paused) {
       /* never report less than segment values in paused */
@@ -4733,15 +4303,15 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
     }
 
     GST_DEBUG_OBJECT (basesink,
-        "now %" GST_TIME_FORMAT " - base %" GST_TIME_FORMAT " - accum %"
+        "now %" GST_TIME_FORMAT " - base_time %" GST_TIME_FORMAT " - base %"
         GST_TIME_FORMAT " + time %" GST_TIME_FORMAT "  last %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (now), GST_TIME_ARGS (base), GST_TIME_ARGS (accum),
+        GST_TIME_ARGS (now), GST_TIME_ARGS (base_time), GST_TIME_ARGS (base),
         GST_TIME_ARGS (time), GST_TIME_ARGS (last));
   }
 
   if (oformat != format) {
     /* convert to final format */
-    if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, &format, cur))
+    if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, format, cur))
       goto convert_failed;
   }
 
@@ -4781,21 +4351,23 @@ gst_base_sink_get_duration (GstBaseSink * basesink, GstFormat format,
 {
   gboolean res = FALSE;
 
-  if (basesink->pad_mode == GST_ACTIVATE_PULL) {
-    GstFormat uformat = GST_FORMAT_BYTES;
+  if (basesink->pad_mode == GST_PAD_MODE_PULL) {
     gint64 uduration;
 
     /* get the duration in bytes, in pull mode that's all we are sure to
      * know. We have to explicitly get this value from upstream instead of
      * using our cached value because it might change. Duration caching
      * should be done at a higher level. */
-    res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat, &uduration);
+    res =
+        gst_pad_peer_query_duration (basesink->sinkpad, GST_FORMAT_BYTES,
+        &uduration);
     if (res) {
-      gst_segment_set_duration (&basesink->segment, uformat, uduration);
-      if (format != uformat) {
+      basesink->segment.duration = uduration;
+      if (format != GST_FORMAT_BYTES) {
         /* convert to the requested format */
-        res = gst_pad_query_convert (basesink->sinkpad, uformat, uduration,
-            &format, dur);
+        res =
+            gst_pad_query_convert (basesink->sinkpad, GST_FORMAT_BYTES,
+            uduration, format, dur);
       } else {
         *dur = uduration;
       }
@@ -4808,20 +4380,6 @@ gst_base_sink_get_duration (GstBaseSink * basesink, GstFormat format,
   return res;
 }
 
-static const GstQueryType *
-gst_base_sink_get_query_types (GstElement * element)
-{
-  static const GstQueryType query_types[] = {
-    GST_QUERY_DURATION,
-    GST_QUERY_POSITION,
-    GST_QUERY_SEGMENT,
-    GST_QUERY_LATENCY,
-    0
-  };
-
-  return query_types;
-}
-
 static gboolean
 default_element_query (GstElement * element, GstQuery * query)
 {
@@ -4853,20 +4411,21 @@ default_element_query (GstElement * element, GstQuery * query)
         /* we can handle a few things if upstream failed */
         if (format == GST_FORMAT_PERCENT) {
           gint64 dur = 0;
-          GstFormat uformat = GST_FORMAT_TIME;
 
           res = gst_base_sink_get_position (basesink, GST_FORMAT_TIME, &cur,
               &upstream);
           if (!res && upstream) {
-            res = gst_pad_query_peer_position (basesink->sinkpad, &uformat,
+            res =
+                gst_pad_peer_query_position (basesink->sinkpad, GST_FORMAT_TIME,
                 &cur);
           }
           if (res) {
             res = gst_base_sink_get_duration (basesink, GST_FORMAT_TIME, &dur,
                 &upstream);
             if (!res && upstream) {
-              res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat,
-                  &dur);
+              res =
+                  gst_pad_peer_query_duration (basesink->sinkpad,
+                  GST_FORMAT_TIME, &dur);
             }
           }
           if (res) {
@@ -4927,7 +4486,7 @@ default_element_query (GstElement * element, GstQuery * query)
       break;
     case GST_QUERY_SEGMENT:
     {
-      if (basesink->pad_mode == GST_ACTIVATE_PULL) {
+      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);
         res = TRUE;
@@ -4948,25 +4507,52 @@ default_element_query (GstElement * element, GstQuery * query)
   return res;
 }
 
+
 static gboolean
-default_sink_query (GstBaseSink * basesink, GstQuery * query)
+gst_base_sink_default_query (GstBaseSink * basesink, GstQuery * query)
 {
-  return gst_pad_query_default (basesink->sinkpad, query);
+  gboolean res;
+  GstBaseSinkClass *bclass;
+
+  bclass = GST_BASE_SINK_GET_CLASS (basesink);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ALLOCATION:
+    {
+      if (bclass->propose_allocation)
+        res = bclass->propose_allocation (basesink, query);
+      else
+        res = FALSE;
+      break;
+    }
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *caps, *filter;
+
+      gst_query_parse_caps (query, &filter);
+      caps = gst_base_sink_query_caps (basesink, basesink->sinkpad, filter);
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      res = TRUE;
+      break;
+    }
+    default:
+      res =
+          gst_pad_query_default (basesink->sinkpad, GST_OBJECT_CAST (basesink),
+          query);
+      break;
+  }
+  return res;
 }
 
 static gboolean
-gst_base_sink_sink_query (GstPad * pad, GstQuery * query)
+gst_base_sink_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstBaseSink *basesink;
   GstBaseSinkClass *bclass;
   gboolean res;
 
-  basesink = GST_BASE_SINK_CAST (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (basesink == NULL)) {
-    gst_query_unref (query);
-    return FALSE;
-  }
-
+  basesink = GST_BASE_SINK_CAST (parent);
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
   if (bclass->query)
@@ -4974,8 +4560,6 @@ gst_base_sink_sink_query (GstPad * pad, GstQuery * query)
   else
     res = FALSE;
 
-  gst_object_unref (basesink);
-
   return res;
 }
 
@@ -5000,17 +4584,16 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       /* need to complete preroll before this state change completes, there
        * is no data flow in READY so we can safely assume we need to preroll. */
-      GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_LOCK (basesink);
       GST_DEBUG_OBJECT (basesink, "READY to PAUSED");
       basesink->have_newsegment = FALSE;
       gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
-      gst_segment_init (basesink->abidata.ABI.clip_segment,
-          GST_FORMAT_UNDEFINED);
       basesink->offset = 0;
       basesink->have_preroll = FALSE;
       priv->step_unlock = FALSE;
       basesink->need_preroll = TRUE;
       basesink->playing_async = TRUE;
+      basesink->priv->reset_time = FALSE;
       priv->current_sstart = GST_CLOCK_TIME_NONE;
       priv->current_sstop = GST_CLOCK_TIME_NONE;
       priv->eos_rtime = GST_CLOCK_TIME_NONE;
@@ -5028,14 +4611,14 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
          * the state change function */
         ret = GST_STATE_CHANGE_ASYNC;
         gst_element_post_message (GST_ELEMENT_CAST (basesink),
-            gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
+            gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
       } else {
         priv->have_latency = TRUE;
       }
-      GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_LOCK (basesink);
       g_atomic_int_set (&basesink->priv->to_playing, TRUE);
       if (!gst_base_sink_needs_preroll (basesink)) {
         GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, don't need preroll");
@@ -5052,7 +4635,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
           gst_element_post_message (GST_ELEMENT_CAST (basesink), message);
         } else {
           GST_DEBUG_OBJECT (basesink, "signal preroll");
-          GST_PAD_PREROLL_SIGNAL (basesink->sinkpad);
+          GST_BASE_SINK_PREROLL_SIGNAL (basesink);
         }
       } else {
         GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, we are not prerolled");
@@ -5064,10 +4647,10 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
           GST_DEBUG_OBJECT (basesink, "doing async state change");
           ret = GST_STATE_CHANGE_ASYNC;
           gst_element_post_message (GST_ELEMENT_CAST (basesink),
-              gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
+              gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
         }
       }
-      GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       break;
     default:
       break;
@@ -5098,7 +4681,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       if (bclass->unlock)
         bclass->unlock (basesink);
 
-      GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_LOCK (basesink);
       GST_DEBUG_OBJECT (basesink, "got preroll lock");
       /* now that we have the PREROLL lock, clear our unlock request */
       if (bclass->unlock_stop)
@@ -5133,8 +4716,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
             GST_DEBUG_OBJECT (basesink, "doing async state change");
             ret = GST_STATE_CHANGE_ASYNC;
             gst_element_post_message (GST_ELEMENT_CAST (basesink),
-                gst_message_new_async_start (GST_OBJECT_CAST (basesink),
-                    FALSE));
+                gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
           }
         }
       }
@@ -5142,10 +4724,10 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
           ", dropped: %" G_GUINT64_FORMAT, priv->rendered, priv->dropped);
 
       gst_base_sink_reset_qos (basesink);
-      GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_LOCK (basesink);
       /* start by resetting our position state with the object lock so that the
        * position query gets the right idea. We do this before we post the
        * messages so that the message handlers pick this up. */
@@ -5158,6 +4740,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
         gst_clock_id_unref (priv->cached_clock_id);
         priv->cached_clock_id = NULL;
       }
+      gst_caps_replace (&basesink->priv->caps, NULL);
       GST_OBJECT_UNLOCK (basesink);
 
       gst_base_sink_set_last_buffer (basesink, NULL);
@@ -5172,13 +4755,13 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
                   GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY));
 
           gst_element_post_message (GST_ELEMENT_CAST (basesink),
-              gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
+              gst_message_new_async_done (GST_OBJECT_CAST (basesink), FALSE));
         }
         priv->commited = TRUE;
       } else {
         GST_DEBUG_OBJECT (basesink, "PAUSED to READY, don't need_preroll");
       }
-      GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+      GST_BASE_SINK_PREROLL_UNLOCK (basesink);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
       if (bclass->stop) {
index ec68ca3..5c4755c 100644 (file)
@@ -44,6 +44,19 @@ G_BEGIN_DECLS
  */
 #define GST_BASE_SINK_PAD(obj)          (GST_BASE_SINK_CAST (obj)->sinkpad)
 
+#define GST_BASE_SINK_GET_PREROLL_LOCK(pad)   (&GST_BASE_SINK_CAST(pad)->preroll_lock)
+#define GST_BASE_SINK_PREROLL_LOCK(pad)       (g_mutex_lock(GST_BASE_SINK_GET_PREROLL_LOCK(pad)))
+#define GST_BASE_SINK_PREROLL_TRYLOCK(pad)    (g_mutex_trylock(GST_BASE_SINK_GET_PREROLL_LOCK(pad)))
+#define GST_BASE_SINK_PREROLL_UNLOCK(pad)     (g_mutex_unlock(GST_BASE_SINK_GET_PREROLL_LOCK(pad)))
+
+#define GST_BASE_SINK_GET_PREROLL_COND(pad)   (&GST_BASE_SINK_CAST(pad)->preroll_cond)
+#define GST_BASE_SINK_PREROLL_WAIT(pad)       \
+      g_cond_wait (GST_BASE_SINK_GET_PREROLL_COND (pad), GST_BASE_SINK_GET_PREROLL_LOCK (pad))
+#define GST_BASE_SINK_PREROLL_WAIT_UNTIL(pad, end_time) \
+      g_cond_wait_until (GST_BASE_SINK_GET_PREROLL_COND (pad), GST_BASE_SINK_GET_PREROLL_LOCK (pad), end_time)
+#define GST_BASE_SINK_PREROLL_SIGNAL(pad)     g_cond_signal (GST_BASE_SINK_GET_PREROLL_COND (pad));
+#define GST_BASE_SINK_PREROLL_BROADCAST(pad)  g_cond_broadcast (GST_BASE_SINK_GET_PREROLL_COND (pad));
+
 typedef struct _GstBaseSink GstBaseSink;
 typedef struct _GstBaseSinkClass GstBaseSinkClass;
 typedef struct _GstBaseSinkPrivate GstBaseSinkPrivate;
@@ -58,7 +71,7 @@ struct _GstBaseSink {
 
   /*< protected >*/
   GstPad        *sinkpad;
-  GstActivateMode       pad_mode;
+  GstPadMode     pad_mode;
 
   /*< protected >*/ /* with LOCK */
   guint64        offset;
@@ -66,13 +79,9 @@ struct _GstBaseSink {
   gboolean       can_activate_push;
 
   /*< protected >*/ /* with PREROLL_LOCK */
-  GQueue        *preroll_queue;
-  gint           preroll_queue_max_len; /* FIXME-0.11: the property is guint */
-  gint           preroll_queued;
-  gint           buffers_queued;
-  gint           events_queued;
+  GMutex         preroll_lock;
+  GCond          preroll_cond;
   gboolean       eos;
-  gboolean       eos_queued;
   gboolean       need_preroll;
   gboolean       have_preroll;
   gboolean       playing_async;
@@ -83,23 +92,16 @@ struct _GstBaseSink {
 
   /*< private >*/ /* with LOCK */
   GstClockID     clock_id;
-  GstClockTime   end_time;
   gboolean       sync;
   gboolean       flushing;
+  gboolean       running;
 
-  /*< private >*/
-  union {
-    struct {
-      /* segment used for clipping incoming buffers */
-      GstSegment    *clip_segment;
-      /* max amount of time a buffer can be late, -1 no limit. */
-      gint64         max_lateness;
-      gboolean       running;
-    } ABI;
-    gpointer _gst_reserved[GST_PADDING_LARGE - 1];
-  } abidata;
+  gint64         max_lateness;
 
+  /*< private >*/
   GstBaseSinkPrivate *priv;
+
+  gpointer _gst_reserved[GST_PADDING_LARGE];
 };
 
 /**
@@ -107,9 +109,17 @@ struct _GstBaseSink {
  * @parent_class: Element parent class
  * @get_caps: Called to get sink pad caps from the subclass
  * @set_caps: Notify subclass of changed caps
- * @buffer_alloc: Subclasses can override to perform custom buffer allocations
+ * @fixate: Only useful in pull mode, this vmethod will be called in response to
+ *     gst_pad_fixate_caps() being called on the sink pad. Implement if you have
+ *     ideas about what should be the default values for the caps you support.
+ * @activate_pull: Subclasses should override this when they can provide an
+ *     alternate method of spawning a thread to drive the pipeline in pull mode.
+ *     Should start or stop the pulling thread, depending on the value of the
+ *     "active" argument. Called after actually activating the sink pad in pull
+ *     mode. The default implementation starts a task on the sink pad.
  * @get_times: Called to get the start and end times for synchronising
  *     the passed buffer to the clock
+ * @propose_allocation: configure the allocation query
  * @start: Start processing. Ideal for opening resources in the subclass
  * @stop: Stop processing. Subclasses should use this to close resources.
  * @unlock: Unlock any pending access to the resource. Subclasses should
@@ -117,22 +127,13 @@ struct _GstBaseSink {
  * @unlock_stop: Clear the previous unlock request. Subclasses should clear
  *     any state they set during unlock(), such as clearing command queues.
  * @event: Override this to handle events arriving on the sink pad
+ * @wait_eos: Override this to implement custom logic to wait for the EOS time.
+ *     subclasses should always first chain up to the default implementation.
  * @preroll: Called to present the preroll buffer if desired
  * @render: Called when a buffer should be presented or output, at the
  *     correct moment if the #GstBaseSink has been set to sync to the clock.
  * @render_list: Same as @render but used whith buffer lists instead of
  *     buffers. Since: 0.10.24
- * @async_play: Subclasses should override this when they need to perform
- *     special processing when changing to the PLAYING state asynchronously.
- *     Called with the OBJECT_LOCK held.
- * @activate_pull: Subclasses should override this when they can provide an
- *     alternate method of spawning a thread to drive the pipeline in pull mode.
- *     Should start or stop the pulling thread, depending on the value of the
- *     "active" argument. Called after actually activating the sink pad in pull
- *     mode. The default implementation starts a task on the sink pad.
- * @fixate: Only useful in pull mode, this vmethod will be called in response to
- *     gst_pad_fixate_caps() being called on the sink pad. Implement if you have
- *     ideas about what should be the default values for the caps you support.
  * @query: perform a #GstQuery on the element. Since: 0.10.36
  *
  * Subclasses can override any of the available virtual methods or not, as
@@ -143,18 +144,22 @@ struct _GstBaseSinkClass {
   GstElementClass parent_class;
 
   /* get caps from subclass */
-  GstCaps*      (*get_caps)     (GstBaseSink *sink);
+  GstCaps*      (*get_caps)     (GstBaseSink *sink, GstCaps *filter);
   /* notify subclass of new caps */
   gboolean      (*set_caps)     (GstBaseSink *sink, GstCaps *caps);
 
-  /* allocate a new buffer with given caps */
-  GstFlowReturn (*buffer_alloc) (GstBaseSink *sink, guint64 offset, guint size,
-                                 GstCaps *caps, GstBuffer **buf);
+  /* fixate sink caps during pull-mode negotiation */
+  void          (*fixate)       (GstBaseSink *sink, GstCaps *caps);
+  /* start or stop a pulling thread */
+  gboolean      (*activate_pull)(GstBaseSink *sink, gboolean active);
 
   /* get the start and end times for syncing on this buffer */
   void          (*get_times)    (GstBaseSink *sink, GstBuffer *buffer,
                                  GstClockTime *start, GstClockTime *end);
 
+  /* propose allocation parameters for upstream */
+  gboolean      (*propose_allocation)   (GstBaseSink *sink, GstQuery *query);
+
   /* start and stop processing, ideal for opening/closing the resource */
   gboolean      (*start)        (GstBaseSink *sink);
   gboolean      (*stop)         (GstBaseSink *sink);
@@ -162,36 +167,27 @@ struct _GstBaseSinkClass {
   /* unlock any pending access to the resource. subclasses should unlock
    * any function ASAP. */
   gboolean      (*unlock)       (GstBaseSink *sink);
-
-  /* notify subclass of event, preroll buffer or real buffer */
-  gboolean      (*event)        (GstBaseSink *sink, GstEvent *event);
-  GstFlowReturn (*preroll)      (GstBaseSink *sink, GstBuffer *buffer);
-  GstFlowReturn (*render)       (GstBaseSink *sink, GstBuffer *buffer);
-
-  /* ABI additions */
-
-  /* when an ASYNC state change to PLAYING happens */ /* with LOCK */
-  GstStateChangeReturn (*async_play)   (GstBaseSink *sink);
-
-  /* start or stop a pulling thread */
-  gboolean      (*activate_pull)(GstBaseSink *sink, gboolean active);
-
-  /* fixate sink caps during pull-mode negotiation */
-  void          (*fixate)       (GstBaseSink *sink, GstCaps *caps);
-
   /* Clear a previously indicated unlock request not that unlocking is
    * complete. Sub-classes should clear any command queue or indicator they
    * set during unlock */
   gboolean      (*unlock_stop)  (GstBaseSink *sink);
 
-  /* Render a BufferList */
-  GstFlowReturn (*render_list)  (GstBaseSink *sink, GstBufferList *buffer_list);
-
   /* notify subclass of query */
   gboolean      (*query)        (GstBaseSink *sink, GstQuery *query);
 
+  /* notify subclass of event */
+  gboolean      (*event)        (GstBaseSink *sink, GstEvent *event);
+  /* wait for eos, subclasses should chain up to parent first */
+  GstFlowReturn (*wait_eos)     (GstBaseSink *sink, GstEvent *event);
+
+  /* notify subclass of preroll buffer or real buffer */
+  GstFlowReturn (*preroll)      (GstBaseSink *sink, GstBuffer *buffer);
+  GstFlowReturn (*render)       (GstBaseSink *sink, GstBuffer *buffer);
+  /* Render a BufferList */
+  GstFlowReturn (*render_list)  (GstBaseSink *sink, GstBufferList *buffer_list);
+
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE-6];
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 GType gst_base_sink_get_type(void);
@@ -219,10 +215,10 @@ gboolean        gst_base_sink_is_async_enabled  (GstBaseSink *sink);
 void            gst_base_sink_set_ts_offset     (GstBaseSink *sink, GstClockTimeDiff offset);
 GstClockTimeDiff gst_base_sink_get_ts_offset    (GstBaseSink *sink);
 
-/* last buffer */
-GstBuffer *     gst_base_sink_get_last_buffer   (GstBaseSink *sink);
-void            gst_base_sink_set_last_buffer_enabled (GstBaseSink *sink, gboolean enabled);
-gboolean        gst_base_sink_is_last_buffer_enabled (GstBaseSink *sink);
+/* last sample */
+GstSample *     gst_base_sink_get_last_sample   (GstBaseSink *sink);
+void            gst_base_sink_set_last_sample_enabled (GstBaseSink *sink, gboolean enabled);
+gboolean        gst_base_sink_is_last_sample_enabled (GstBaseSink *sink);
 
 /* latency */
 gboolean        gst_base_sink_query_latency     (GstBaseSink *sink, gboolean *live, gboolean *upstream_live,
index 0f352d4..a127f4e 100644 (file)
@@ -47,9 +47,6 @@
  *   </listitem>
  * </itemizedlist>
  *
- * Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any time
- * by overriding #GstBaseSrcClass.check_get_range() so that it returns %TRUE.
- *
  * If all the conditions are met for operating in pull mode, #GstBaseSrc is
  * automatically seekable in push mode as well. The following conditions must
  * be met to make the element seekable in push mode when the format is not
  * an EOS message to be posted on the pipeline's bus. Once this EOS message is
  * received, it may safely shut down the entire pipeline.
  *
- * The old behaviour for controlled shutdown introduced since GStreamer 0.10.3
- * is still available but deprecated as it is dangerous and less flexible.
- *
  * Last reviewed on 2007-12-19 (0.10.16)
  * </para>
  * </refsect2>
 #include <stdlib.h>
 #include <string.h>
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <gst/gst_private.h>
 #include <gst/glib-compat-private.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
 #define GST_CAT_DEFAULT gst_base_src_debug
 
-#define GST_LIVE_GET_LOCK(elem)               (GST_BASE_SRC_CAST(elem)->live_lock)
+#define GST_LIVE_GET_LOCK(elem)               (&GST_BASE_SRC_CAST(elem)->live_lock)
 #define GST_LIVE_LOCK(elem)                   g_mutex_lock(GST_LIVE_GET_LOCK(elem))
 #define GST_LIVE_TRYLOCK(elem)                g_mutex_trylock(GST_LIVE_GET_LOCK(elem))
 #define GST_LIVE_UNLOCK(elem)                 g_mutex_unlock(GST_LIVE_GET_LOCK(elem))
-#define GST_LIVE_GET_COND(elem)               (GST_BASE_SRC_CAST(elem)->live_cond)
+#define GST_LIVE_GET_COND(elem)               (&GST_BASE_SRC_CAST(elem)->live_cond)
 #define GST_LIVE_WAIT(elem)                   g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))
-#define GST_LIVE_TIMED_WAIT(elem, timeval)    g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem),\
-                                                                                timeval)
+#define GST_LIVE_WAIT_UNTIL(elem, end_time)   g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem), end_time)
 #define GST_LIVE_SIGNAL(elem)                 g_cond_signal (GST_LIVE_GET_COND (elem));
 #define GST_LIVE_BROADCAST(elem)              g_cond_broadcast (GST_LIVE_GET_COND (elem));
 
@@ -216,15 +206,14 @@ enum
 
 struct _GstBaseSrcPrivate
 {
-  gboolean last_sent_eos;       /* last thing we did was send an EOS (we set this
-                                 * to avoid the sending of two EOS in some cases) */
   gboolean discont;
   gboolean flushing;
 
-  /* two segments to be sent in the streaming thread with STREAM_LOCK */
-  GstEvent *close_segment;
-  GstEvent *start_segment;
-  gboolean newsegment_pending;
+  GstFlowReturn start_result;
+  gboolean async;
+
+  /* if segment should be sent */
+  gboolean segment_pending;
 
   /* if EOS is pending (atomic) */
   gint pending_eos;
@@ -252,11 +241,15 @@ struct _GstBaseSrcPrivate
   gboolean qos_enabled;
   gdouble proportion;
   GstClockTime earliest_time;
+
+  GstBufferPool *pool;
+  const GstAllocator *allocator;
+  guint prefix;
+  guint alignment;
 };
 
 static GstElementClass *parent_class = NULL;
 
-static void gst_base_src_base_init (gpointer g_class);
 static void gst_base_src_class_init (GstBaseSrcClass * klass);
 static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
 static void gst_base_src_finalize (GObject * object);
@@ -271,7 +264,7 @@ gst_base_src_get_type (void)
     GType _type;
     static const GTypeInfo base_src_info = {
       sizeof (GstBaseSrcClass),
-      (GBaseInitFunc) gst_base_src_base_init,
+      NULL,
       NULL,
       (GClassInitFunc) gst_base_src_class_init,
       NULL,
@@ -288,32 +281,42 @@ gst_base_src_get_type (void)
   return base_src_type;
 }
 
-static GstCaps *gst_base_src_getcaps (GstPad * pad);
-static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
-static void gst_base_src_fixate (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc,
+    GstCaps * filter);
+static void gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps);
+static void gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps);
 
-static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
-static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
+static gboolean gst_base_src_is_random_access (GstBaseSrc * src);
+static gboolean gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
 static void gst_base_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_base_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);
+static gboolean gst_base_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);
 static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event);
-static const GstQueryType *gst_base_src_get_query_types (GstElement * element);
 
-static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_base_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
+static gboolean gst_base_src_activate_pool (GstBaseSrc * basesrc,
+    gboolean active);
 static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
 static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,
     GstSegment * segment);
 static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);
 static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src,
     GstEvent * event, GstSegment * segment);
+static GstFlowReturn gst_base_src_default_create (GstBaseSrc * basesrc,
+    guint64 offset, guint size, GstBuffer ** buf);
+static GstFlowReturn gst_base_src_default_alloc (GstBaseSrc * basesrc,
+    guint64 offset, guint size, GstBuffer ** buf);
 
 static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc,
     gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing);
+
 static gboolean gst_base_src_start (GstBaseSrc * basesrc);
 static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
 
@@ -321,23 +324,16 @@ static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
     GstStateChange transition);
 
 static void gst_base_src_loop (GstPad * pad);
-static gboolean gst_base_src_pad_check_get_range (GstPad * pad);
-static gboolean gst_base_src_default_check_get_range (GstBaseSrc * bsrc);
-static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,
-    guint length, GstBuffer ** buf);
+static GstFlowReturn gst_base_src_getrange (GstPad * pad, GstObject * parent,
+    guint64 offset, guint length, GstBuffer ** buf);
 static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
     guint length, GstBuffer ** buf);
 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);
 
 static void
-gst_base_src_base_init (gpointer g_class)
-{
-  GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
-}
-
-static void
 gst_base_src_class_init (GstBaseSrcClass * klass)
 {
   GObjectClass *gobject_class;
@@ -346,6 +342,8 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gstelement_class = GST_ELEMENT_CLASS (klass);
 
+  GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
+
   g_type_class_add_private (klass, sizeof (GstBaseSrcPrivate));
 
   parent_class = g_type_class_peek_parent (klass);
@@ -354,10 +352,9 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
   gobject_class->set_property = gst_base_src_set_property;
   gobject_class->get_property = gst_base_src_get_property;
 
-/* FIXME 0.11: blocksize property should be int, not ulong (min is >max here) */
   g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
-      g_param_spec_ulong ("blocksize", "Block size",
-          "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
+      g_param_spec_uint ("blocksize", "Block size",
+          "Size in bytes to read per buffer (-1 = default)", 0, G_MAXUINT,
           DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
       g_param_spec_int ("num-buffers", "num-buffers",
@@ -376,27 +373,23 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_src_change_state);
   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);
-  gstelement_class->get_query_types =
-      GST_DEBUG_FUNCPTR (gst_base_src_get_query_types);
 
+  klass->get_caps = GST_DEBUG_FUNCPTR (gst_base_src_default_get_caps);
   klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate);
-  klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);
-  klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);
-  klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);
-  klass->check_get_range =
-      GST_DEBUG_FUNCPTR (gst_base_src_default_check_get_range);
+  klass->fixate = GST_DEBUG_FUNCPTR (gst_base_src_default_fixate);
   klass->prepare_seek_segment =
       GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment);
+  klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);
+  klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);
+  klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);
+  klass->create = GST_DEBUG_FUNCPTR (gst_base_src_default_create);
+  klass->alloc = GST_DEBUG_FUNCPTR (gst_base_src_default_alloc);
 
   /* Registering debug symbols for function pointers */
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_push);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_pull);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event_handler);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_mode);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_get_range);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_check_get_range);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getcaps);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_setcaps);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getrange);
   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate);
 }
 
@@ -409,13 +402,12 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc);
 
   basesrc->is_live = FALSE;
-  basesrc->live_lock = g_mutex_new ();
-  basesrc->live_cond = g_cond_new ();
+  g_mutex_init (&basesrc->live_lock);
+  g_cond_init (&basesrc->live_cond);
   basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
   basesrc->num_buffers_left = -1;
 
   basesrc->can_activate_push = TRUE;
-  basesrc->pad_mode = GST_ACTIVATE_NONE;
 
   pad_template =
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
@@ -425,15 +417,10 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   pad = gst_pad_new_from_template (pad_template, "src");
 
   GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
-  gst_pad_set_activatepush_function (pad, gst_base_src_activate_push);
-  gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
-  gst_pad_set_event_function (pad, gst_base_src_event_handler);
+  gst_pad_set_activatemode_function (pad, gst_base_src_activate_mode);
+  gst_pad_set_event_function (pad, gst_base_src_event);
   gst_pad_set_query_function (pad, gst_base_src_query);
-  gst_pad_set_checkgetrange_function (pad, gst_base_src_pad_check_get_range);
-  gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range);
-  gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
-  gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
-  gst_pad_set_fixatecaps_function (pad, gst_base_src_fixate);
+  gst_pad_set_getrange_function (pad, gst_base_src_getrange);
 
   /* hold pointer to pad */
   basesrc->srcpad = pad;
@@ -444,12 +431,14 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
   basesrc->clock_id = NULL;
   /* we operate in BYTES by default */
   gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
-  basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
+  basesrc->typefind = DEFAULT_TYPEFIND;
   basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
   g_atomic_int_set (&basesrc->priv->have_events, FALSE);
 
-  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
-  GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_IS_SOURCE);
+  basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
+  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
+  GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_FLAG_SOURCE);
 
   GST_DEBUG_OBJECT (basesrc, "init done");
 }
@@ -462,10 +451,10 @@ gst_base_src_finalize (GObject * object)
 
   basesrc = GST_BASE_SRC (object);
 
-  g_mutex_free (basesrc->live_lock);
-  g_cond_free (basesrc->live_cond);
+  g_mutex_clear (&basesrc->live_lock);
+  g_cond_clear (&basesrc->live_cond);
 
-  event_p = &basesrc->data.ABI.pending_seek;
+  event_p = &basesrc->pending_seek;
   gst_event_replace (event_p, NULL);
 
   if (basesrc->priv->pending_events) {
@@ -611,6 +600,49 @@ gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic)
 }
 
 /**
+ * gst_base_src_set_async:
+ * @src: base source instance
+ * @async: new async mode
+ *
+ * Configure async behaviour in @src, no state change will block. The open,
+ * close, start, stop, play and pause virtual methods will be executed in a
+ * different thread and are thus allowed to perform blocking operations. Any
+ * blocking operation should be unblocked with the unlock vmethod.
+ */
+void
+gst_base_src_set_async (GstBaseSrc * src, gboolean async)
+{
+  g_return_if_fail (GST_IS_BASE_SRC (src));
+
+  GST_OBJECT_LOCK (src);
+  src->priv->async = async;
+  GST_OBJECT_UNLOCK (src);
+}
+
+/**
+ * gst_base_src_is_async:
+ * @src: base source instance
+ *
+ * Get the current async behaviour of @src. See also gst_base_src_set_async().
+ *
+ * Returns: %TRUE if @src is operating in async mode.
+ */
+gboolean
+gst_base_src_is_async (GstBaseSrc * src)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
+
+  GST_OBJECT_LOCK (src);
+  res = src->priv->async;
+  GST_OBJECT_UNLOCK (src);
+
+  return res;
+}
+
+
+/**
  * gst_base_src_query_latency:
  * @src: the source
  * @live: (out) (allow-none): if the source is live
@@ -671,9 +703,8 @@ gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
  *
  * Since: 0.10.22
  */
-/* FIXME 0.11: blocksize property should be int, not ulong */
 void
-gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize)
+gst_base_src_set_blocksize (GstBaseSrc * src, guint blocksize)
 {
   g_return_if_fail (GST_IS_BASE_SRC (src));
 
@@ -692,11 +723,10 @@ gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize)
  *
  * Since: 0.10.22
  */
-/* FIXME 0.11: blocksize property should be int, not ulong */
-gulong
+guint
 gst_base_src_get_blocksize (GstBaseSrc * src)
 {
-  gulong res;
+  gint res;
 
   g_return_val_if_fail (GST_IS_BASE_SRC (src), 0);
 
@@ -783,94 +813,91 @@ gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
       GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
 
   GST_OBJECT_LOCK (src);
-  if (src->data.ABI.running && !src->priv->newsegment_pending) {
-    if (src->priv->close_segment)
-      gst_event_unref (src->priv->close_segment);
-    src->priv->close_segment =
-        gst_event_new_new_segment_full (TRUE,
-        src->segment.rate, src->segment.applied_rate, src->segment.format,
-        src->segment.start, src->segment.last_stop, src->segment.time);
-  }
-
-  gst_segment_set_newsegment_full (&src->segment, FALSE, src->segment.rate,
-      src->segment.applied_rate, src->segment.format, start, stop, position);
-
-  if (src->priv->start_segment)
-    gst_event_unref (src->priv->start_segment);
-  if (src->segment.rate >= 0.0) {
-    /* forward, we send data from last_stop to stop */
-    src->priv->start_segment =
-        gst_event_new_new_segment_full (FALSE,
-        src->segment.rate, src->segment.applied_rate, src->segment.format,
-        src->segment.last_stop, stop, src->segment.time);
-  } else {
-    /* reverse, we send data from last_stop to start */
-    src->priv->start_segment =
-        gst_event_new_new_segment_full (FALSE,
-        src->segment.rate, src->segment.applied_rate, src->segment.format,
-        src->segment.start, src->segment.last_stop, src->segment.time);
-  }
+
+  src->segment.base = gst_segment_to_running_time (&src->segment,
+      src->segment.format, src->segment.position);
+  src->segment.start = start;
+  src->segment.stop = stop;
+  src->segment.position = position;
+
+  /* forward, we send data from position to stop */
+  src->priv->segment_pending = TRUE;
   GST_OBJECT_UNLOCK (src);
 
   src->priv->discont = TRUE;
-  src->data.ABI.running = TRUE;
+  src->running = TRUE;
 
   return res;
 }
 
-static gboolean
-gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_base_src_set_caps:
+ * @src: a #GstBaseSrc
+ * @caps: a #GstCaps
+ *
+ * Set new caps on the basesrc source pad.
+ *
+ * Returns: %TRUE if the caps could be set
+ */
+gboolean
+gst_base_src_set_caps (GstBaseSrc * src, GstCaps * caps)
 {
   GstBaseSrcClass *bclass;
-  GstBaseSrc *bsrc;
   gboolean res = TRUE;
 
-  bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
-  bclass = GST_BASE_SRC_GET_CLASS (bsrc);
+  bclass = GST_BASE_SRC_GET_CLASS (src);
+
+  gst_pad_push_event (src->srcpad, gst_event_new_caps (caps));
 
   if (bclass->set_caps)
-    res = bclass->set_caps (bsrc, caps);
+    res = bclass->set_caps (src, caps);
 
   return res;
 }
 
 static GstCaps *
-gst_base_src_getcaps (GstPad * pad)
+gst_base_src_default_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
 {
-  GstBaseSrcClass *bclass;
-  GstBaseSrc *bsrc;
   GstCaps *caps = NULL;
+  GstPadTemplate *pad_template;
+  GstBaseSrcClass *bclass;
 
-  bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
-  if (bclass->get_caps)
-    caps = bclass->get_caps (bsrc);
 
-  if (caps == NULL) {
-    GstPadTemplate *pad_template;
+  pad_template =
+      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
 
-    pad_template =
-        gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
-    if (pad_template != NULL) {
-      caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
+  if (pad_template != NULL) {
+    caps = gst_pad_template_get_caps (pad_template);
+
+    if (filter) {
+      GstCaps *intersection;
+
+      intersection =
+          gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+      gst_caps_unref (caps);
+      caps = intersection;
     }
   }
   return caps;
 }
 
 static void
-gst_base_src_fixate (GstPad * pad, GstCaps * caps)
+gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps)
+{
+  GST_DEBUG_OBJECT (bsrc, "using default caps fixate function");
+  gst_caps_fixate (caps);
+}
+
+static void
+gst_base_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
 {
   GstBaseSrcClass *bclass;
-  GstBaseSrc *bsrc;
 
-  bsrc = GST_BASE_SRC (gst_pad_get_parent (pad));
   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
 
   if (bclass->fixate)
     bclass->fixate (bsrc, caps);
-
-  gst_object_unref (bsrc);
 }
 
 static gboolean
@@ -896,7 +923,7 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
           gint64 duration;
 
           GST_OBJECT_LOCK (src);
-          position = src->segment.last_stop;
+          position = src->segment.position;
           duration = src->segment.duration;
           GST_OBJECT_UNLOCK (src);
 
@@ -921,7 +948,7 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
           GST_OBJECT_LOCK (src);
           position =
               gst_segment_to_stream_time (&src->segment, src->segment.format,
-              src->segment.last_stop);
+              src->segment.position);
           seg_format = src->segment.format;
           GST_OBJECT_UNLOCK (src);
 
@@ -929,7 +956,7 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
             /* convert to requested format */
             res =
                 gst_pad_query_convert (src->srcpad, seg_format,
-                position, &format, &position);
+                position, format, &position);
           } else
             res = TRUE;
 
@@ -978,7 +1005,7 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
              * but we cannot answer the query, we must return FALSE. */
             res =
                 gst_pad_query_convert (src->srcpad, seg_format,
-                duration, &format, &duration);
+                duration, format, &duration);
           } else {
             /* The subclass did not configure a duration, we assume that the
              * media has an unknown duration then and we return TRUE to report
@@ -1115,45 +1142,75 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
        * but report TRUE. */
       if (format != GST_FORMAT_PERCENT && stop != -1) {
         res = gst_pad_query_convert (src->srcpad, seg_format,
-            stop, &format, &stop);
+            stop, format, &stop);
       } else {
         res = TRUE;
       }
       if (res && format != GST_FORMAT_PERCENT && start != -1)
         res = gst_pad_query_convert (src->srcpad, seg_format,
-            start, &format, &start);
+            start, format, &start);
 
       gst_query_set_buffering_range (query, format, start, stop, estimated);
       break;
     }
+    case GST_QUERY_SCHEDULING:
+    {
+      gboolean random_access;
+
+      random_access = gst_base_src_is_random_access (src);
+
+      /* we can operate in getrange mode if the native format is bytes
+       * and we are seekable, this condition is set in the random_access
+       * flag and is set in the _start() method. */
+      gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
+      if (random_access)
+        gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
+      gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
+
+      res = TRUE;
+      break;
+    }
+    case GST_QUERY_CAPS:
+    {
+      GstBaseSrcClass *bclass;
+      GstCaps *caps, *filter;
+
+      bclass = GST_BASE_SRC_GET_CLASS (src);
+      if (bclass->get_caps) {
+        gst_query_parse_caps (query, &filter);
+        if ((caps = bclass->get_caps (src, filter))) {
+          gst_query_set_caps_result (query, caps);
+          gst_caps_unref (caps);
+          res = TRUE;
+        } else {
+          res = FALSE;
+        }
+      } else
+        res = FALSE;
+      break;
+    }
     default:
       res = FALSE;
       break;
   }
   GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),
       res);
+
   return res;
 }
 
 static gboolean
-gst_base_src_query (GstPad * pad, GstQuery * query)
+gst_base_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstBaseSrc *src;
   GstBaseSrcClass *bclass;
   gboolean result = FALSE;
 
-  src = GST_BASE_SRC (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (src == NULL))
-    return FALSE;
-
+  src = GST_BASE_SRC (parent);
   bclass = GST_BASE_SRC_GET_CLASS (src);
 
   if (bclass->query)
     result = bclass->query (src, query);
-  else
-    result = gst_pad_query_default (pad, query);
-
-  gst_object_unref (src);
 
   return result;
 }
@@ -1217,7 +1274,7 @@ gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
   dest_format = segment->format;
 
   if (seek_format == dest_format) {
-    gst_segment_set_seek (segment, rate, seek_format, flags,
+    gst_segment_do_seek (segment, rate, seek_format, flags,
         cur_type, cur, stop_type, stop, &update);
     return TRUE;
   }
@@ -1225,7 +1282,7 @@ gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
   if (cur_type != GST_SEEK_TYPE_NONE) {
     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
     res =
-        gst_pad_query_convert (src->srcpad, seek_format, cur, &dest_format,
+        gst_pad_query_convert (src->srcpad, seek_format, cur, dest_format,
         &cur);
     cur_type = GST_SEEK_TYPE_SET;
   }
@@ -1233,13 +1290,13 @@ gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
   if (res && stop_type != GST_SEEK_TYPE_NONE) {
     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
     res =
-        gst_pad_query_convert (src->srcpad, seek_format, stop, &dest_format,
+        gst_pad_query_convert (src->srcpad, seek_format, stop, dest_format,
         &stop);
     stop_type = GST_SEEK_TYPE_SET;
   }
 
   /* And finally, configure our output segment in the desired format */
-  gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,
+  gst_segment_do_seek (segment, rate, dest_format, flags, cur_type, cur,
       stop_type, stop, &update);
 
   if (!res)
@@ -1269,6 +1326,83 @@ gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
   return result;
 }
 
+static GstFlowReturn
+gst_base_src_default_alloc (GstBaseSrc * src, guint64 offset,
+    guint size, GstBuffer ** buffer)
+{
+  GstFlowReturn ret;
+  GstBaseSrcPrivate *priv = src->priv;
+
+  if (priv->pool) {
+    ret = gst_buffer_pool_acquire_buffer (priv->pool, buffer, NULL);
+  } else if (size != -1) {
+    *buffer = gst_buffer_new_allocate (priv->allocator, size, priv->alignment);
+    if (G_UNLIKELY (*buffer == NULL))
+      goto alloc_failed;
+
+    ret = GST_FLOW_OK;
+  } else {
+    GST_WARNING_OBJECT (src, "Not trying to alloc %u bytes. Blocksize not set?",
+        size);
+    goto alloc_failed;
+  }
+  return ret;
+
+  /* ERRORS */
+alloc_failed:
+  {
+    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_base_src_default_create (GstBaseSrc * src, guint64 offset,
+    guint size, GstBuffer ** buffer)
+{
+  GstBaseSrcClass *bclass;
+  GstFlowReturn ret;
+
+  bclass = GST_BASE_SRC_GET_CLASS (src);
+
+  if (G_UNLIKELY (!bclass->alloc))
+    goto no_function;
+  if (G_UNLIKELY (!bclass->fill))
+    goto no_function;
+
+  ret = bclass->alloc (src, offset, size, buffer);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto alloc_failed;
+
+  if (G_LIKELY (size > 0)) {
+    /* only call fill when there is a size */
+    ret = bclass->fill (src, offset, size, *buffer);
+    if (G_UNLIKELY (ret != GST_FLOW_OK))
+      goto not_ok;
+  }
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+no_function:
+  {
+    GST_DEBUG_OBJECT (src, "no fill or alloc function");
+    return GST_FLOW_NOT_SUPPORTED;
+  }
+alloc_failed:
+  {
+    GST_DEBUG_OBJECT (src, "Failed to allocate buffer of %u bytes", size);
+    return ret;
+  }
+not_ok:
+  {
+    GST_DEBUG_OBJECT (src, "fill returned %d (%s)", ret,
+        gst_flow_get_name (ret));
+    gst_buffer_unref (*buffer);
+    return ret;
+  }
+}
+
 /* this code implements the seeking. It is a good example
  * handling all cases.
  *
@@ -1420,7 +1554,7 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
       } else {
         /* The seek format matches our processing format, no need to ask the
          * the subclass to configure the segment. */
-        gst_segment_set_seek (&seeksegment, rate, seek_format, flags,
+        gst_segment_do_seek (&seeksegment, rate, seek_format, flags,
             cur_type, cur, stop_type, stop, &update);
       }
     }
@@ -1431,36 +1565,19 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
   if (res) {
     GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
         " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
-        seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+        seeksegment.start, seeksegment.stop, seeksegment.position);
 
-    /* do the seek, segment.last_stop contains the new position. */
+    /* do the seek, segment.position contains the new position. */
     res = gst_base_src_do_seek (src, &seeksegment);
   }
 
   /* and prepare to continue streaming */
   if (flush) {
-    tevent = gst_event_new_flush_stop ();
+    tevent = gst_event_new_flush_stop (TRUE);
     gst_event_set_seqnum (tevent, seqnum);
     /* send flush stop, peer will accept data and events again. We
      * are not yet providing data as we still have the STREAM_LOCK. */
     gst_pad_push_event (src->srcpad, tevent);
-  } else if (res && src->data.ABI.running) {
-    /* we are running the current segment and doing a non-flushing seek,
-     * close the segment first based on the last_stop. */
-    GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, src->segment.start, src->segment.last_stop);
-
-    /* queue the segment for sending in the stream thread */
-    if (src->priv->close_segment)
-      gst_event_unref (src->priv->close_segment);
-    src->priv->close_segment =
-        gst_event_new_new_segment_full (TRUE,
-        src->segment.rate, src->segment.applied_rate, src->segment.format,
-        src->segment.start, src->segment.last_stop, src->segment.time);
-    seeksegment.time = gst_segment_to_stream_time (&src->segment,
-        src->segment.format, src->segment.last_stop);
-    seeksegment.start = src->segment.last_stop;
-    gst_event_set_seqnum (src->priv->close_segment, seqnum);
   }
 
   /* The subclass must have converted the segment to the processing format
@@ -1482,7 +1599,7 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
       GstMessage *message;
 
       message = gst_message_new_segment_start (GST_OBJECT (src),
-          seeksegment.format, seeksegment.last_stop);
+          seeksegment.format, seeksegment.position);
       gst_message_set_seqnum (message, seqnum);
 
       gst_element_post_message (GST_ELEMENT (src), message);
@@ -1493,32 +1610,11 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
     if ((stop = seeksegment.stop) == -1)
       stop = seeksegment.duration;
 
-    GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, seeksegment.start, stop);
-
-    /* now replace the old segment so that we send it in the stream thread the
-     * next time it is scheduled. */
-    if (src->priv->start_segment)
-      gst_event_unref (src->priv->start_segment);
-    if (seeksegment.rate >= 0.0) {
-      /* forward, we send data from last_stop to stop */
-      src->priv->start_segment =
-          gst_event_new_new_segment_full (FALSE,
-          seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
-          seeksegment.last_stop, stop, seeksegment.time);
-    } else {
-      /* reverse, we send data from last_stop to start */
-      src->priv->start_segment =
-          gst_event_new_new_segment_full (FALSE,
-          seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
-          seeksegment.start, seeksegment.last_stop, seeksegment.time);
-    }
-    gst_event_set_seqnum (src->priv->start_segment, seqnum);
-    src->priv->newsegment_pending = TRUE;
+    src->priv->segment_pending = TRUE;
   }
 
   src->priv->discont = TRUE;
-  src->data.ABI.running = TRUE;
+  src->running = TRUE;
   /* and restart the task in case it got paused explicitly or by
    * the FLUSH_START event we pushed out. */
   tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
@@ -1538,25 +1634,6 @@ prepare_failed:
   return FALSE;
 }
 
-static const GstQueryType *
-gst_base_src_get_query_types (GstElement * element)
-{
-  static const GstQueryType query_types[] = {
-    GST_QUERY_DURATION,
-    GST_QUERY_POSITION,
-    GST_QUERY_SEEKING,
-    GST_QUERY_SEGMENT,
-    GST_QUERY_FORMATS,
-    GST_QUERY_LATENCY,
-    GST_QUERY_JITTER,
-    GST_QUERY_RATE,
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return query_types;
-}
-
 /* all events send to this element directly. This is mainly done from the
  * application.
  */
@@ -1600,10 +1677,12 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
       g_atomic_int_set (&src->priv->pending_eos, TRUE);
       GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
 
+
       /* unlock the _create function so that we can check the pending_eos flag
        * and we can do EOS. This will eventually release the LIVE_LOCK again so
        * that we can grab it and stop the unlock again. We don't take the stream
        * lock so that this operation is guaranteed to never block. */
+      gst_base_src_activate_pool (src, FALSE);
       if (bclass->unlock)
         bclass->unlock (src);
 
@@ -1615,13 +1694,14 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
        * lock is enough because that protects the create function. */
       if (bclass->unlock_stop)
         bclass->unlock_stop (src);
+      gst_base_src_activate_pool (src, TRUE);
       GST_LIVE_UNLOCK (src);
 
       result = TRUE;
       break;
     }
-    case GST_EVENT_NEWSEGMENT:
-      /* sending random NEWSEGMENT downstream can break sync. */
+    case GST_EVENT_SEGMENT:
+      /* sending random SEGMENT downstream can break sync. */
       break;
     case GST_EVENT_TAG:
     case GST_EVENT_CUSTOM_DOWNSTREAM:
@@ -1648,9 +1728,9 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
       gboolean started;
 
       GST_OBJECT_LOCK (src->srcpad);
-      if (GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PULL)
+      if (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PULL)
         goto wrong_mode;
-      started = GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PUSH;
+      started = GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH;
       GST_OBJECT_UNLOCK (src->srcpad);
 
       if (started) {
@@ -1665,7 +1745,7 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
          * get activated */
         GST_OBJECT_LOCK (src);
         GST_DEBUG_OBJECT (src, "queueing seek");
-        event_p = &src->data.ABI.pending_seek;
+        event_p = &src->pending_seek;
         gst_event_replace ((GstEvent **) event_p, event);
         GST_OBJECT_UNLOCK (src);
         /* assume the seek will work */
@@ -1768,11 +1848,17 @@ gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
       GstClockTimeDiff diff;
       GstClockTime timestamp;
 
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+      gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
       gst_base_src_update_qos (src, proportion, diff, timestamp);
       result = TRUE;
       break;
     }
+    case GST_EVENT_RECONFIGURE:
+      result = TRUE;
+      break;
+    case GST_EVENT_LATENCY:
+      result = TRUE;
+      break;
     default:
       result = FALSE;
       break;
@@ -1788,18 +1874,13 @@ not_seekable:
 }
 
 static gboolean
-gst_base_src_event_handler (GstPad * pad, GstEvent * event)
+gst_base_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstBaseSrc *src;
   GstBaseSrcClass *bclass;
   gboolean result = FALSE;
 
-  src = GST_BASE_SRC (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (src == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
-
+  src = GST_BASE_SRC (parent);
   bclass = GST_BASE_SRC_GET_CLASS (src);
 
   if (bclass->event) {
@@ -1809,7 +1890,6 @@ gst_base_src_event_handler (GstPad * pad, GstEvent * event)
 
 done:
   gst_event_unref (event);
-  gst_object_unref (src);
 
   return result;
 
@@ -1831,13 +1911,13 @@ gst_base_src_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_BLOCKSIZE:
-      gst_base_src_set_blocksize (src, g_value_get_ulong (value));
+      gst_base_src_set_blocksize (src, g_value_get_uint (value));
       break;
     case PROP_NUM_BUFFERS:
       src->num_buffers = g_value_get_int (value);
       break;
     case PROP_TYPEFIND:
-      src->data.ABI.typefind = g_value_get_boolean (value);
+      src->typefind = g_value_get_boolean (value);
       break;
     case PROP_DO_TIMESTAMP:
       gst_base_src_set_do_timestamp (src, g_value_get_boolean (value));
@@ -1858,13 +1938,13 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
 
   switch (prop_id) {
     case PROP_BLOCKSIZE:
-      g_value_set_ulong (value, gst_base_src_get_blocksize (src));
+      g_value_set_uint (value, gst_base_src_get_blocksize (src));
       break;
     case PROP_NUM_BUFFERS:
       g_value_set_int (value, src->num_buffers);
       break;
     case PROP_TYPEFIND:
-      g_value_set_boolean (value, src->data.ABI.typefind);
+      g_value_set_boolean (value, src->typefind);
       break;
     case PROP_DO_TIMESTAMP:
       g_value_set_boolean (value, gst_base_src_get_do_timestamp (src));
@@ -2069,7 +2149,7 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
   format = src->segment.format;
   stop = src->segment.stop;
   /* get total file size */
-  size = (guint64) src->segment.duration;
+  size = src->segment.duration;
 
   /* only operate if we are working with bytes */
   if (format != GST_FORMAT_BYTES)
@@ -2118,10 +2198,10 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
     }
   }
 
-  /* keep track of current position and update duration.
+  /* keep track of current duration.
    * segment is in bytes, we checked that above. */
   GST_OBJECT_LOCK (src);
-  gst_segment_set_duration (&src->segment, GST_FORMAT_BYTES, size);
+  src->segment.duration = size;
   GST_OBJECT_UNLOCK (src);
 
   return TRUE;
@@ -2153,7 +2233,7 @@ again:
     }
   }
 
-  if (G_UNLIKELY (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)))
+  if (G_UNLIKELY (!GST_BASE_SRC_IS_STARTED (src)))
     goto not_started;
 
   if (G_UNLIKELY (!bclass->create))
@@ -2165,7 +2245,7 @@ again:
   /* track position */
   GST_OBJECT_LOCK (src);
   if (src->segment.format == GST_FORMAT_BYTES)
-    gst_segment_set_last_stop (&src->segment, GST_FORMAT_BYTES, offset);
+    src->segment.position = offset;
   GST_OBJECT_UNLOCK (src);
 
   /* normally we don't count buffers */
@@ -2204,16 +2284,11 @@ again:
   /* no timestamp set and we are at offset 0, we can timestamp with 0 */
   if (offset == 0 && src->segment.time == 0
       && GST_BUFFER_TIMESTAMP (*buf) == -1 && !src->is_live) {
-    *buf = gst_buffer_make_metadata_writable (*buf);
+    GST_DEBUG_OBJECT (src, "setting first timestamp to 0");
+    *buf = gst_buffer_make_writable (*buf);
     GST_BUFFER_TIMESTAMP (*buf) = 0;
   }
 
-  /* set pad caps on the buffer if the buffer had no caps */
-  if (GST_BUFFER_CAPS (*buf) == NULL) {
-    *buf = gst_buffer_make_metadata_writable (*buf);
-    gst_buffer_set_caps (*buf, GST_PAD_CAPS (src->srcpad));
-  }
-
   /* now sync before pushing the buffer */
   status = gst_base_src_do_sync (src, *buf);
 
@@ -2283,18 +2358,18 @@ not_started:
 no_function:
   {
     GST_DEBUG_OBJECT (src, "no create function");
-    return GST_FLOW_ERROR;
+    return GST_FLOW_NOT_SUPPORTED;
   }
 unexpected_length:
   {
     GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT
         ", size=%" G_GINT64_FORMAT ")", length, offset, src->segment.duration);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 reached_num_buffers:
   {
     GST_DEBUG_OBJECT (src, "sent all buffers");
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 flushing:
   {
@@ -2306,18 +2381,18 @@ flushing:
 eos:
   {
     GST_DEBUG_OBJECT (src, "we are EOS");
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
 static GstFlowReturn
-gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length,
-    GstBuffer ** buf)
+gst_base_src_getrange (GstPad * pad, GstObject * parent, guint64 offset,
+    guint length, GstBuffer ** buf)
 {
   GstBaseSrc *src;
   GstFlowReturn res;
 
-  src = GST_BASE_SRC_CAST (gst_object_ref (GST_OBJECT_PARENT (pad)));
+  src = GST_BASE_SRC_CAST (parent);
 
   GST_LIVE_LOCK (src);
   if (G_UNLIKELY (src->priv->flushing))
@@ -2328,8 +2403,6 @@ gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length,
 done:
   GST_LIVE_UNLOCK (src);
 
-  gst_object_unref (src);
-
   return res;
 
   /* ERRORS */
@@ -2342,62 +2415,28 @@ flushing:
 }
 
 static gboolean
-gst_base_src_default_check_get_range (GstBaseSrc * src)
+gst_base_src_is_random_access (GstBaseSrc * src)
 {
-  gboolean res;
-
-  if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
+  /* we need to start the basesrc to check random access */
+  if (!GST_BASE_SRC_IS_STARTED (src)) {
     GST_LOG_OBJECT (src, "doing start/stop to check get_range support");
-    if (G_LIKELY (gst_base_src_start (src)))
+    if (G_LIKELY (gst_base_src_start (src))) {
+      if (gst_base_src_start_wait (src) != GST_FLOW_OK)
+        goto start_failed;
       gst_base_src_stop (src);
+    }
   }
 
-  /* we can operate in getrange mode if the native format is bytes
-   * and we are seekable, this condition is set in the random_access
-   * flag and is set in the _start() method. */
-  res = src->random_access;
-
-  return res;
-}
-
-static gboolean
-gst_base_src_check_get_range (GstBaseSrc * src)
-{
-  GstBaseSrcClass *bclass;
-  gboolean res;
-
-  bclass = GST_BASE_SRC_GET_CLASS (src);
-
-  if (bclass->check_get_range == NULL)
-    goto no_function;
-
-  res = bclass->check_get_range (src);
-  GST_LOG_OBJECT (src, "%s() returned %d",
-      GST_DEBUG_FUNCPTR_NAME (bclass->check_get_range), (gint) res);
-
-  return res;
+  return src->random_access;
 
   /* ERRORS */
-no_function:
+start_failed:
   {
-    GST_WARNING_OBJECT (src, "no check_get_range function set");
+    GST_DEBUG_OBJECT (src, "failed to start");
     return FALSE;
   }
 }
 
-static gboolean
-gst_base_src_pad_check_get_range (GstPad * pad)
-{
-  GstBaseSrc *src;
-  gboolean res;
-
-  src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
-
-  res = gst_base_src_check_get_range (src);
-
-  return res;
-}
-
 static void
 gst_base_src_loop (GstPad * pad)
 {
@@ -2406,25 +2445,29 @@ gst_base_src_loop (GstPad * pad)
   GstFlowReturn ret;
   gint64 position;
   gboolean eos;
-  gulong blocksize;
+  guint blocksize;
   GList *pending_events = NULL, *tmp;
 
   eos = FALSE;
 
   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
 
+  /* check if we need to renegotiate */
+  if (gst_pad_check_reconfigure (pad)) {
+    if (!gst_base_src_negotiate (src))
+      goto not_negotiated;
+  }
+
   GST_LIVE_LOCK (src);
 
   if (G_UNLIKELY (src->priv->flushing))
     goto flushing;
 
-  src->priv->last_sent_eos = FALSE;
-
   blocksize = src->blocksize;
 
   /* if we operate in bytes, we can calculate an offset */
   if (src->segment.format == GST_FORMAT_BYTES) {
-    position = src->segment.last_stop;
+    position = src->segment.position;
     /* for negative rates, start with subtracting the blocksize */
     if (src->segment.rate < 0.0) {
       /* we cannot go below segment.start */
@@ -2439,7 +2482,7 @@ gst_base_src_loop (GstPad * pad)
   } else
     position = -1;
 
-  GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %lu",
+  GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %u",
       GST_TIME_ARGS (position), blocksize);
 
   ret = gst_base_src_get_range (src, position, blocksize, &buf);
@@ -2454,15 +2497,10 @@ gst_base_src_loop (GstPad * pad)
     goto null_buffer;
 
   /* push events to close/start our segment before we push the buffer. */
-  if (G_UNLIKELY (src->priv->close_segment)) {
-    gst_pad_push_event (pad, src->priv->close_segment);
-    src->priv->close_segment = NULL;
-  }
-  if (G_UNLIKELY (src->priv->start_segment)) {
-    gst_pad_push_event (pad, src->priv->start_segment);
-    src->priv->start_segment = NULL;
+  if (G_UNLIKELY (src->priv->segment_pending)) {
+    gst_pad_push_event (pad, gst_event_new_segment (&src->segment));
+    src->priv->segment_pending = FALSE;
   }
-  src->priv->newsegment_pending = FALSE;
 
   if (g_atomic_int_get (&src->priv->have_events)) {
     GST_OBJECT_LOCK (src);
@@ -2486,7 +2524,7 @@ gst_base_src_loop (GstPad * pad)
   switch (src->segment.format) {
     case GST_FORMAT_BYTES:
     {
-      guint bufsize = GST_BUFFER_SIZE (buf);
+      guint bufsize = gst_buffer_get_size (buf);
 
       /* we subtracted above for negative rates */
       if (src->segment.rate >= 0.0)
@@ -2503,7 +2541,7 @@ gst_base_src_loop (GstPad * pad)
       if (GST_CLOCK_TIME_IS_VALID (start))
         position = start;
       else
-        position = src->segment.last_stop;
+        position = src->segment.position;
 
       if (GST_CLOCK_TIME_IS_VALID (duration)) {
         if (src->segment.rate >= 0.0)
@@ -2545,12 +2583,13 @@ gst_base_src_loop (GstPad * pad)
       src->priv->discont = TRUE;
     }
     GST_OBJECT_LOCK (src);
-    gst_segment_set_last_stop (&src->segment, src->segment.format, position);
+    src->segment.position = position;
     GST_OBJECT_UNLOCK (src);
   }
 
   if (G_UNLIKELY (src->priv->discont)) {
-    buf = gst_buffer_make_metadata_writable (buf);
+    GST_INFO_OBJECT (src, "marking pending DISCONT");
+    buf = gst_buffer_make_writable (buf);
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
     src->priv->discont = FALSE;
   }
@@ -2565,7 +2604,7 @@ gst_base_src_loop (GstPad * pad)
 
   if (G_UNLIKELY (eos)) {
     GST_INFO_OBJECT (src, "pausing after end of segment");
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_EOS;
     goto pause;
   }
 
@@ -2573,6 +2612,12 @@ done:
   return;
 
   /* special cases */
+not_negotiated:
+  {
+    GST_DEBUG_OBJECT (src, "Failed to renegotiate");
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto pause;
+  }
 flushing:
   {
     GST_DEBUG_OBJECT (src, "we are flushing");
@@ -2586,32 +2631,31 @@ pause:
     GstEvent *event;
 
     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
-    src->data.ABI.running = FALSE;
+    src->running = FALSE;
     gst_pad_pause_task (pad);
-    if (ret == GST_FLOW_UNEXPECTED) {
+    if (ret == GST_FLOW_EOS) {
       gboolean flag_segment;
       GstFormat format;
-      gint64 last_stop;
+      gint64 position;
 
       /* perform EOS logic */
       flag_segment = (src->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0;
       format = src->segment.format;
-      last_stop = src->segment.last_stop;
+      position = src->segment.position;
 
       if (flag_segment) {
         GstMessage *message;
 
         message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
-            format, last_stop);
+            format, position);
         gst_message_set_seqnum (message, src->priv->seqnum);
         gst_element_post_message (GST_ELEMENT_CAST (src), message);
       } else {
         event = gst_event_new_eos ();
         gst_event_set_seqnum (event, src->priv->seqnum);
         gst_pad_push_event (pad, event);
-        src->priv->last_sent_eos = TRUE;
       }
-    } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_UNEXPECTED) {
+    } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_EOS) {
       event = gst_event_new_eos ();
       gst_event_set_seqnum (event, src->priv->seqnum);
       /* for fatal errors we post an error message, post the error
@@ -2624,7 +2668,6 @@ pause:
           (_("Internal data flow error.")),
           ("streaming task paused, reason %s (%d)", reason, ret));
       gst_pad_push_event (pad, event);
-      src->priv->last_sent_eos = TRUE;
     }
     goto done;
   }
@@ -2637,6 +2680,128 @@ null_buffer:
   }
 }
 
+static gboolean
+gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
+    const GstAllocator * allocator, guint prefix, guint alignment)
+{
+  GstBufferPool *oldpool;
+  GstBaseSrcPrivate *priv = basesrc->priv;
+
+  if (pool) {
+    GST_DEBUG_OBJECT (basesrc, "activate pool");
+    if (!gst_buffer_pool_set_active (pool, TRUE))
+      goto activate_failed;
+  }
+
+  GST_OBJECT_LOCK (basesrc);
+  oldpool = priv->pool;
+  priv->pool = pool;
+
+  priv->allocator = allocator;
+
+  priv->prefix = prefix;
+  priv->alignment = alignment;
+  GST_OBJECT_UNLOCK (basesrc);
+
+  if (oldpool) {
+    /* only deactivate if the pool is not the one we're using */
+    if (oldpool != pool) {
+      GST_DEBUG_OBJECT (basesrc, "deactivate old pool");
+      gst_buffer_pool_set_active (oldpool, FALSE);
+    }
+    gst_object_unref (oldpool);
+  }
+  return TRUE;
+
+  /* ERRORS */
+activate_failed:
+  {
+    GST_ERROR_OBJECT (basesrc, "failed to activate bufferpool.");
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_base_src_activate_pool (GstBaseSrc * basesrc, gboolean active)
+{
+  GstBaseSrcPrivate *priv = basesrc->priv;
+  GstBufferPool *pool;
+  gboolean res = TRUE;
+
+  GST_OBJECT_LOCK (basesrc);
+  if ((pool = priv->pool))
+    pool = gst_object_ref (pool);
+  GST_OBJECT_UNLOCK (basesrc);
+
+  if (pool) {
+    res = gst_buffer_pool_set_active (pool, active);
+    gst_object_unref (pool);
+  }
+  return res;
+}
+
+static gboolean
+gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps)
+{
+  GstBaseSrcClass *bclass;
+  gboolean result = TRUE;
+  GstQuery *query;
+  GstBufferPool *pool = NULL;
+  const GstAllocator *allocator = NULL;
+  guint size, min, max, prefix, alignment;
+
+  bclass = GST_BASE_SRC_GET_CLASS (basesrc);
+
+  /* make query and let peer pad answer, we don't really care if it worked or
+   * not, if it failed, the allocation query would contain defaults and the
+   * subclass would then set better values if needed */
+  query = gst_query_new_allocation (caps, TRUE);
+  if (!gst_pad_peer_query (basesrc->srcpad, query)) {
+    /* not a problem, just debug a little */
+    GST_DEBUG_OBJECT (basesrc, "peer ALLOCATION query failed");
+  }
+
+  if (G_LIKELY (bclass->decide_allocation))
+    result = bclass->decide_allocation (basesrc, query);
+
+  GST_DEBUG_OBJECT (basesrc, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
+      query);
+  gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
+      &alignment, &pool);
+
+  if (size == 0) {
+    const gchar *mem = NULL;
+
+    /* no size, we have variable size buffers */
+    if (gst_query_get_n_allocation_memories (query) > 0) {
+      mem = gst_query_parse_nth_allocation_memory (query, 0);
+    }
+    GST_DEBUG_OBJECT (basesrc, "0 size, getting allocator %s",
+        GST_STR_NULL (mem));
+    allocator = gst_allocator_find (mem);
+  } else if (pool == NULL) {
+    /* fixed size, we can use a bufferpool */
+    GstStructure *config;
+
+    /* we did not get a pool, make one ourselves then */
+    pool = gst_buffer_pool_new ();
+    GST_DEBUG_OBJECT (basesrc, "no pool, making new pool");
+
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_set (config, caps, size, min, max, prefix,
+        alignment);
+    gst_buffer_pool_set_config (pool, config);
+  }
+
+  gst_query_unref (query);
+
+  result =
+      gst_base_src_set_allocation (basesrc, pool, allocator, prefix, alignment);
+
+  return result;
+
+}
+
 /* default negotiation code.
  *
  * Take intersection between src and sink pads, take first
@@ -2651,7 +2816,7 @@ gst_base_src_default_negotiate (GstBaseSrc * basesrc)
   gboolean result = FALSE;
 
   /* first see what is possible on our source pad */
-  thiscaps = gst_pad_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
+  thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
   /* nothing or anything is allowed, we're done */
   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
@@ -2661,40 +2826,38 @@ gst_base_src_default_negotiate (GstBaseSrc * basesrc)
     goto no_caps;
 
   /* get the peer caps */
-  peercaps = gst_pad_peer_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
+  peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), thiscaps);
   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
   if (peercaps) {
-    /* get intersection */
-    caps =
-        gst_caps_intersect_full (peercaps, thiscaps, GST_CAPS_INTERSECT_FIRST);
-    GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
-    gst_caps_unref (peercaps);
+    /* The result is already a subset of our caps */
+    caps = peercaps;
+    gst_caps_unref (thiscaps);
   } else {
     /* no peer, work with our own caps then */
-    caps = gst_caps_copy (thiscaps);
+    caps = thiscaps;
   }
-  gst_caps_unref (thiscaps);
-  if (caps) {
-    /* take first (and best, since they are sorted) possibility */
-    gst_caps_truncate (caps);
-
+  if (caps && !gst_caps_is_empty (caps)) {
     /* now fixate */
-    if (!gst_caps_is_empty (caps)) {
-      gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
+    GST_DEBUG_OBJECT (basesrc, "have caps: %" GST_PTR_FORMAT, caps);
+    if (gst_caps_is_any (caps)) {
+      GST_DEBUG_OBJECT (basesrc, "any caps, we stop");
+      /* hmm, still anything, so element can do anything and
+       * nego is not needed */
+      result = TRUE;
+    } else {
+      caps = gst_caps_make_writable (caps);
+      gst_base_src_fixate (basesrc, caps);
       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
-
-      if (gst_caps_is_any (caps)) {
-        /* hmm, still anything, so element can do anything and
-         * nego is not needed */
-        result = TRUE;
-      } else if (gst_caps_is_fixed (caps)) {
+      if (gst_caps_is_fixed (caps)) {
         /* yay, fixed caps, use those then, it's possible that the subclass does
          * not accept this caps after all and we have to fail. */
-        result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
+        result = gst_base_src_set_caps (basesrc, caps);
       }
     }
     gst_caps_unref (caps);
   } else {
+    if (caps)
+      gst_caps_unref (caps);
     GST_DEBUG_OBJECT (basesrc, "no common caps");
   }
   return result;
@@ -2721,13 +2884,27 @@ static gboolean
 gst_base_src_negotiate (GstBaseSrc * basesrc)
 {
   GstBaseSrcClass *bclass;
-  gboolean result = TRUE;
+  gboolean result;
 
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
 
-  if (bclass->negotiate)
+  GST_DEBUG_OBJECT (basesrc, "starting negotiation");
+
+  if (G_LIKELY (bclass->negotiate))
     result = bclass->negotiate (basesrc);
+  else
+    result = TRUE;
+
+  if (G_LIKELY (result)) {
+    GstCaps *caps;
 
+    caps = gst_pad_get_current_caps (basesrc->srcpad);
+
+    result = gst_base_src_prepare_allocation (basesrc, caps);
+
+    if (caps)
+      gst_caps_unref (caps);
+  }
   return result;
 }
 
@@ -2736,23 +2913,22 @@ gst_base_src_start (GstBaseSrc * basesrc)
 {
   GstBaseSrcClass *bclass;
   gboolean result;
-  guint64 size;
-  gboolean seekable;
-  GstFormat format;
-
-  if (GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
-    return TRUE;
 
-  GST_DEBUG_OBJECT (basesrc, "starting source");
+  GST_LIVE_LOCK (basesrc);
+  if (GST_BASE_SRC_IS_STARTING (basesrc))
+    goto was_starting;
+  if (GST_BASE_SRC_IS_STARTED (basesrc))
+    goto was_started;
 
+  basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+  GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTING);
   basesrc->num_buffers_left = basesrc->num_buffers;
-
+  basesrc->running = FALSE;
+  basesrc->priv->segment_pending = FALSE;
   GST_OBJECT_LOCK (basesrc);
   gst_segment_init (&basesrc->segment, basesrc->segment.format);
   GST_OBJECT_UNLOCK (basesrc);
-
-  basesrc->data.ABI.running = FALSE;
-  basesrc->priv->newsegment_pending = FALSE;
+  GST_LIVE_UNLOCK (basesrc);
 
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
   if (bclass->start)
@@ -2763,32 +2939,83 @@ gst_base_src_start (GstBaseSrc * basesrc)
   if (!result)
     goto could_not_start;
 
-  GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
+  if (!gst_base_src_is_async (basesrc))
+    gst_base_src_start_complete (basesrc, GST_FLOW_OK);
+
+  return result;
+
+  /* ERROR */
+was_starting:
+  {
+    GST_DEBUG_OBJECT (basesrc, "was starting");
+    GST_LIVE_UNLOCK (basesrc);
+    return TRUE;
+  }
+was_started:
+  {
+    GST_DEBUG_OBJECT (basesrc, "was started");
+    GST_LIVE_UNLOCK (basesrc);
+    return TRUE;
+  }
+could_not_start:
+  {
+    GST_DEBUG_OBJECT (basesrc, "could not start");
+    /* subclass is supposed to post a message. We don't have to call _stop. */
+    gst_base_src_start_complete (basesrc, GST_FLOW_ERROR);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_base_src_start_complete:
+ * @src: base source instance
+ * @ret: a #GstFlowReturn
+ *
+ * Complete an asynchronous start operation. When the subclass overrides the
+ * start method, it should call gst_base_src_start_complete() when the start
+ * operation completes either from the same thread or from an asynchronous
+ * helper thread.
+ */
+void
+gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
+{
+  gboolean have_size;
+  guint64 size;
+  gboolean seekable;
+  GstFormat format;
+  GstPadMode mode;
+  GstEvent *event;
+  GstBaseSrcClass *bclass;
 
+  bclass = GST_BASE_SRC_GET_CLASS (basesrc);
+
+  if (ret != GST_FLOW_OK)
+    goto error;
+
+  GST_DEBUG_OBJECT (basesrc, "starting source");
   format = basesrc->segment.format;
 
   /* figure out the size */
+  have_size = FALSE;
+  size = -1;
   if (format == GST_FORMAT_BYTES) {
+    bclass = GST_BASE_SRC_GET_CLASS (basesrc);
+
     if (bclass->get_size) {
-      if (!(result = bclass->get_size (basesrc, &size)))
+      if (!(have_size = bclass->get_size (basesrc, &size)))
         size = -1;
-    } else {
-      result = FALSE;
-      size = -1;
     }
     GST_DEBUG_OBJECT (basesrc, "setting size %" G_GUINT64_FORMAT, size);
     /* only update the size when operating in bytes, subclass is supposed
      * to set duration in the start method for other formats */
     GST_OBJECT_LOCK (basesrc);
-    gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES, size);
+    basesrc->segment.duration = size;
     GST_OBJECT_UNLOCK (basesrc);
-  } else {
-    size = -1;
   }
 
   GST_DEBUG_OBJECT (basesrc,
       "format: %s, have size: %d, size: %" G_GUINT64_FORMAT ", duration: %"
-      G_GINT64_FORMAT, gst_format_get_name (format), result, size,
+      G_GINT64_FORMAT, gst_format_get_name (format), have_size, size,
       basesrc->segment.duration);
 
   seekable = gst_base_src_seekable (basesrc);
@@ -2799,46 +3026,107 @@ gst_base_src_start (GstBaseSrc * basesrc)
 
   GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access);
 
-  /* run typefind if we are random_access and the typefinding is enabled. */
-  if (basesrc->random_access && basesrc->data.ABI.typefind && size != -1) {
-    GstCaps *caps;
+  /* stop flushing now but for live sources, still block in the LIVE lock when
+   * we are not yet PLAYING */
+  gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
 
-    if (!(caps = gst_type_find_helper (basesrc->srcpad, size)))
-      goto typefind_failed;
+  GST_OBJECT_LOCK (basesrc->srcpad);
+  mode = GST_PAD_MODE (basesrc->srcpad);
+  GST_OBJECT_UNLOCK (basesrc->srcpad);
 
-    result = gst_pad_set_caps (basesrc->srcpad, caps);
-    gst_caps_unref (caps);
+  if (mode == GST_PAD_MODE_PUSH) {
+    /* do initial seek, which will start the task */
+    GST_OBJECT_LOCK (basesrc);
+    event = basesrc->pending_seek;
+    basesrc->pending_seek = NULL;
+    GST_OBJECT_UNLOCK (basesrc);
+
+    /* no need to unlock anything, the task is certainly
+     * not running here. The perform seek code will start the task when
+     * finished. */
+    if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
+      goto seek_failed;
+
+    if (event)
+      gst_event_unref (event);
   } else {
-    /* use class or default negotiate function */
-    if (!(result = gst_base_src_negotiate (basesrc)))
-      goto could_not_negotiate;
+    /* if not random_access, we cannot operate in pull mode for now */
+    if (G_UNLIKELY (!basesrc->random_access))
+      goto no_get_range;
   }
 
-  return result;
+  gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (basesrc));
 
-  /* ERROR */
-could_not_start:
+  GST_LIVE_LOCK (basesrc);
+  GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTED);
+  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
+  basesrc->priv->start_result = ret;
+  GST_LIVE_SIGNAL (basesrc);
+  GST_LIVE_UNLOCK (basesrc);
+
+  return;
+
+seek_failed:
   {
-    GST_DEBUG_OBJECT (basesrc, "could not start");
-    /* subclass is supposed to post a message. We don't have to call _stop. */
-    return FALSE;
+    GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
+    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
+    if (event)
+      gst_event_unref (event);
+    ret = GST_FLOW_ERROR;
+    goto error;
   }
-could_not_negotiate:
+no_get_range:
   {
-    GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
-    GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
-        ("Could not negotiate format"), ("Check your filtered caps, if any"));
-    /* we must call stop */
-    gst_base_src_stop (basesrc);
-    return FALSE;
+    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
+    GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
+    ret = GST_FLOW_ERROR;
+    goto error;
   }
-typefind_failed:
+error:
   {
-    GST_DEBUG_OBJECT (basesrc, "could not typefind, stopping");
-    GST_ELEMENT_ERROR (basesrc, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
-    /* we must call stop */
-    gst_base_src_stop (basesrc);
-    return FALSE;
+    GST_LIVE_LOCK (basesrc);
+    basesrc->priv->start_result = ret;
+    GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
+    GST_LIVE_SIGNAL (basesrc);
+    GST_LIVE_UNLOCK (basesrc);
+    return;
+  }
+}
+
+/**
+ * gst_base_src_start_complete:
+ * @src: base source instance
+ * @ret: a #GstFlowReturn
+ *
+ * Wait until the start operation completes.
+ *
+ * Returns: a #GstFlowReturn.
+ */
+GstFlowReturn
+gst_base_src_start_wait (GstBaseSrc * basesrc)
+{
+  GstFlowReturn result;
+
+  GST_LIVE_LOCK (basesrc);
+  if (G_UNLIKELY (basesrc->priv->flushing))
+    goto flushing;
+
+  while (GST_BASE_SRC_IS_STARTING (basesrc)) {
+    GST_LIVE_WAIT (basesrc);
+    if (G_UNLIKELY (basesrc->priv->flushing))
+      goto flushing;
+  }
+  result = basesrc->priv->start_result;
+  GST_LIVE_UNLOCK (basesrc);
+
+  return result;
+
+  /* ERRORS */
+flushing:
+  {
+    GST_DEBUG_OBJECT (basesrc, "we are flushing");
+    GST_LIVE_UNLOCK (basesrc);
+    return GST_FLOW_WRONG_STATE;
   }
 }
 
@@ -2848,19 +3136,37 @@ gst_base_src_stop (GstBaseSrc * basesrc)
   GstBaseSrcClass *bclass;
   gboolean result = TRUE;
 
-  if (!GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
-    return TRUE;
-
   GST_DEBUG_OBJECT (basesrc, "stopping source");
 
+  /* flush all */
+  gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
+  /* stop the task */
+  gst_pad_stop_task (basesrc->srcpad);
+
+  GST_LIVE_LOCK (basesrc);
+  if (!GST_BASE_SRC_IS_STARTED (basesrc) && !GST_BASE_SRC_IS_STARTING (basesrc))
+    goto was_stopped;
+
+  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
+  GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
+  basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+  GST_LIVE_SIGNAL (basesrc);
+  GST_LIVE_UNLOCK (basesrc);
+
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
   if (bclass->stop)
     result = bclass->stop (basesrc);
 
-  if (result)
-    GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
+  gst_base_src_set_allocation (basesrc, NULL, NULL, 0, 0);
 
   return result;
+
+was_stopped:
+  {
+    GST_DEBUG_OBJECT (basesrc, "was started");
+    GST_LIVE_UNLOCK (basesrc);
+    return TRUE;
+  }
 }
 
 /* start or stop flushing dataprocessing
@@ -2874,6 +3180,7 @@ gst_base_src_set_flushing (GstBaseSrc * basesrc,
   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
 
   if (flushing && unlock) {
+    gst_base_src_activate_pool (basesrc, 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)*/
@@ -2905,6 +3212,8 @@ gst_base_src_set_flushing (GstBaseSrc * basesrc,
     /* signal the live source that it can start playing */
     basesrc->live_running = live_play;
 
+    gst_base_src_activate_pool (basesrc, TRUE);
+
     /* When unlocking drop all delayed events */
     if (unlock) {
       GST_OBJECT_LOCK (basesrc);
@@ -2967,7 +3276,7 @@ gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play)
     /* have to restart the task in case it stopped because of the unlock when
      * we went to PAUSED. Only do this if we operating in push mode. */
     GST_OBJECT_LOCK (basesrc->srcpad);
-    start = (GST_PAD_ACTIVATE_MODE (basesrc->srcpad) == GST_ACTIVATE_PUSH);
+    start = (GST_PAD_MODE (basesrc->srcpad) == GST_PAD_MODE_PUSH);
     GST_OBJECT_UNLOCK (basesrc->srcpad);
     if (start)
       gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop,
@@ -2981,12 +3290,11 @@ gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play)
 }
 
 static gboolean
-gst_base_src_activate_push (GstPad * pad, gboolean active)
+gst_base_src_activate_push (GstPad * pad, GstObject * parent, gboolean active)
 {
   GstBaseSrc *basesrc;
-  GstEvent *event;
 
-  basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
+  basesrc = GST_BASE_SRC (parent);
 
   /* prepare subclass first */
   if (active) {
@@ -2997,31 +3305,8 @@ gst_base_src_activate_push (GstPad * pad, gboolean active)
 
     if (G_UNLIKELY (!gst_base_src_start (basesrc)))
       goto error_start;
-
-    basesrc->priv->last_sent_eos = FALSE;
-    basesrc->priv->discont = TRUE;
-    gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
-
-    /* do initial seek, which will start the task */
-    GST_OBJECT_LOCK (basesrc);
-    event = basesrc->data.ABI.pending_seek;
-    basesrc->data.ABI.pending_seek = NULL;
-    GST_OBJECT_UNLOCK (basesrc);
-
-    /* no need to unlock anything, the task is certainly
-     * not running here. The perform seek code will start the task when
-     * finished. */
-    if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
-      goto seek_failed;
-
-    if (event)
-      gst_event_unref (event);
   } else {
     GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
-    /* flush all */
-    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
-    /* stop the task */
-    gst_pad_stop_task (pad);
     /* now we can stop the source */
     if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
       goto error_stop;
@@ -3039,19 +3324,6 @@ error_start:
     GST_WARNING_OBJECT (basesrc, "Failed to start in push mode");
     return FALSE;
   }
-seek_failed:
-  {
-    GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
-    /* flush all */
-    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
-    /* stop the task */
-    gst_pad_stop_task (pad);
-    /* Stop the basesrc */
-    gst_base_src_stop (basesrc);
-    if (event)
-      gst_event_unref (event);
-    return FALSE;
-  }
 error_stop:
   {
     GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode");
@@ -3060,33 +3332,19 @@ error_stop:
 }
 
 static gboolean
-gst_base_src_activate_pull (GstPad * pad, gboolean active)
+gst_base_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active)
 {
   GstBaseSrc *basesrc;
 
-  basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
+  basesrc = GST_BASE_SRC (parent);
 
   /* prepare subclass first */
   if (active) {
     GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
     if (G_UNLIKELY (!gst_base_src_start (basesrc)))
       goto error_start;
-
-    /* if not random_access, we cannot operate in pull mode for now */
-    if (G_UNLIKELY (!gst_base_src_check_get_range (basesrc)))
-      goto no_get_range;
-
-    /* stop flushing now but for live sources, still block in the LIVE lock when
-     * we are not yet PLAYING */
-    gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
   } else {
     GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
-    /* flush all, there is no task to stop */
-    gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
-
-    /* don't send EOS when going from PAUSED => READY when in pull mode */
-    basesrc->priv->last_sent_eos = TRUE;
-
     if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
       goto error_stop;
   }
@@ -3098,12 +3356,6 @@ error_start:
     GST_ERROR_OBJECT (basesrc, "Failed to start in pull mode");
     return FALSE;
   }
-no_get_range:
-  {
-    GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
-    gst_base_src_stop (basesrc);
-    return FALSE;
-  }
 error_stop:
   {
     GST_ERROR_OBJECT (basesrc, "Failed to stop in pull mode");
@@ -3111,6 +3363,28 @@ error_stop:
   }
 }
 
+static gboolean
+gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
+{
+  gboolean res;
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_base_src_activate_pull (pad, parent, active);
+      break;
+    case GST_PAD_MODE_PUSH:
+      res = gst_base_src_activate_push (pad, parent, active);
+      break;
+    default:
+      GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
+
 static GstStateChangeReturn
 gst_base_src_change_state (GstElement * element, GstStateChange transition)
 {
@@ -3153,28 +3427,10 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
     {
-      GstEvent **event_p, *event;
-
       /* we don't need to unblock anything here, the pad deactivation code
        * already did this */
-
-      /* FIXME, deprecate this behaviour, it is very dangerous.
-       * the preferred way of sending EOS downstream is by sending
-       * the EOS event to the element */
-      if (!basesrc->priv->last_sent_eos) {
-        GST_DEBUG_OBJECT (basesrc, "Sending EOS event");
-        event = gst_event_new_eos ();
-        gst_event_set_seqnum (event, basesrc->priv->seqnum);
-        gst_pad_push_event (basesrc->srcpad, event);
-        basesrc->priv->last_sent_eos = TRUE;
-      }
       g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
-      event_p = &basesrc->data.ABI.pending_seek;
-      gst_event_replace (event_p, NULL);
-      event_p = &basesrc->priv->close_segment;
-      gst_event_replace (event_p, NULL);
-      event_p = &basesrc->priv->start_segment;
-      gst_event_replace (event_p, NULL);
+      gst_event_replace (&basesrc->pending_seek, NULL);
       break;
     }
     case GST_STATE_CHANGE_READY_TO_NULL:
index 87e1c06..31345bd 100644 (file)
@@ -38,17 +38,22 @@ G_BEGIN_DECLS
 
 /**
  * GstBaseSrcFlags:
- * @GST_BASE_SRC_STARTED: has source been started
+ * @GST_BASE_SRC_FLAG_STARTING: has source is starting
+ * @GST_BASE_SRC_FLAG_STARTED: has source been started
  * @GST_BASE_SRC_FLAG_LAST: offset to define more flags
  *
  * The #GstElement flags that a basesrc element may have.
  */
 typedef enum {
-  GST_BASE_SRC_STARTED           = (GST_ELEMENT_FLAG_LAST << 0),
+  GST_BASE_SRC_FLAG_STARTING     = (GST_ELEMENT_FLAG_LAST << 0),
+  GST_BASE_SRC_FLAG_STARTED      = (GST_ELEMENT_FLAG_LAST << 1),
   /* padding */
-  GST_BASE_SRC_FLAG_LAST         = (GST_ELEMENT_FLAG_LAST << 2)
+  GST_BASE_SRC_FLAG_LAST         = (GST_ELEMENT_FLAG_LAST << 16)
 } GstBaseSrcFlags;
 
+#define GST_BASE_SRC_IS_STARTING(obj) GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTING)
+#define GST_BASE_SRC_IS_STARTED(obj)  GST_OBJECT_FLAG_IS_SET ((obj), GST_BASE_SRC_FLAG_STARTED)
+
 typedef struct _GstBaseSrc GstBaseSrc;
 typedef struct _GstBaseSrcClass GstBaseSrcClass;
 typedef struct _GstBaseSrcPrivate GstBaseSrcPrivate;
@@ -75,61 +80,62 @@ struct _GstBaseSrc {
 
   /* available to subclass implementations */
   /* MT-protected (with LIVE_LOCK) */
-  GMutex        *live_lock;
-  GCond         *live_cond;
+  GMutex         live_lock;
+  GCond          live_cond;
   gboolean       is_live;
   gboolean       live_running;
 
   /* MT-protected (with LOCK) */
-  gint           blocksize;     /* size of buffers when operating push based */
+  guint          blocksize;     /* size of buffers when operating push based */
   gboolean       can_activate_push;     /* some scheduling properties */
-  GstActivateMode pad_mode;
-  gboolean       seekable; /* not used anymore */
   gboolean       random_access;
 
   GstClockID     clock_id;      /* for syncing */
-  GstClockTime   end_time;
 
   /* MT-protected (with STREAM_LOCK *and* OBJECT_LOCK) */
   GstSegment     segment;
   /* MT-protected (with STREAM_LOCK) */
   gboolean       need_newsegment;
 
-  guint64        offset;        /* current offset in the resource, unused */
-  guint64        size;          /* total size of the resource, unused */
-
   gint           num_buffers;
   gint           num_buffers_left;
 
-  /*< private >*/
-  union {
-    struct {
-      /* FIXME: those fields should be moved into the private struct */
-      gboolean  typefind;
-      gboolean  running;
-      GstEvent *pending_seek;
-    } ABI;
-    gpointer       _gst_reserved[GST_PADDING_LARGE-1];
-  } data;
+  gboolean       typefind;
+  gboolean       running;
+  GstEvent      *pending_seek;
 
   GstBaseSrcPrivate *priv;
+
+  /*< private >*/
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 /**
  * GstBaseSrcClass:
  * @parent_class: Element parent class
  * @get_caps: Called to get the caps to report
- * @set_caps: Notify subclass of changed output caps
  * @negotiate: Negotiated the caps with the peer.
- * @newsegment: Generate and send a new_segment event (UNUSED)
+ * @fixate: Called during negotiation if caps need fixating. Implement instead of
+ *   setting a fixate function on the source pad.
+ * @set_caps: Notify subclass of changed output caps
+ * @decide_allocation: configure the allocation query
  * @start: Start processing. Subclasses should open resources and prepare
- *    to produce data.
+ *    to produce data. Implementation should call gst_base_src_start_complete()
+ *    when the operation completes, either from the current thread or any other
+ *    thread that finishes the start operation asynchronously.
  * @stop: Stop processing. Subclasses should use this to close resources.
  * @get_times: Given a buffer, return the start and stop time when it
  *    should be pushed out. The base class will sync on the clock using
  *    these times.
  * @get_size: Return the total size of the resource, in the configured format.
  * @is_seekable: Check if the source can seek
+ * @prepare_seek_segment: Prepare the GstSegment that will be passed to the
+ *   do_seek vmethod for executing a seek request. Sub-classes should override
+ *   this if they support seeking in formats other than the configured native
+ *   format. By default, it tries to convert the seek arguments to the
+ *   configured native format and prepare a segment in that format.
+ *   Since: 0.10.13
+ * @do_seek: Perform seeking on the resource to the indicated segment.
  * @unlock: Unlock any pending access to the resource. Subclasses should
  *    unblock any blocked function ASAP. In particular, any create() function in
  *    progress should be unblocked and should return GST_FLOW_WRONG_STATE. Any
@@ -137,29 +143,19 @@ struct _GstBaseSrc {
  *    until the @unlock_stop<!-- -->() function has been called.
  * @unlock_stop: Clear the previous unlock request. Subclasses should clear
  *    any state they set during unlock(), such as clearing command queues.
+ * @query: Handle a requested query.
  * @event: Override this to implement custom event handling.
  * @create: Ask the subclass to create a buffer with offset and size.
  *   When the subclass returns GST_FLOW_OK, it MUST return a buffer of the
  *   requested size unless fewer bytes are available because an EOS condition
  *   is near. No buffer should be returned when the return value is different
  *   from GST_FLOW_OK. A return value of GST_FLOW_UNEXPECTED signifies that the
- *   end of stream is reached.
- * @do_seek: Perform seeking on the resource to the indicated segment.
- * @prepare_seek_segment: Prepare the GstSegment that will be passed to the
- *   do_seek vmethod for executing a seek request. Sub-classes should override
- *   this if they support seeking in formats other than the configured native
- *   format. By default, it tries to convert the seek arguments to the
- *   configured native format and prepare a segment in that format.
- *   Since: 0.10.13
- * @query: Handle a requested query.
- * @check_get_range: Check whether the source would support pull-based
- *   operation if it were to be opened now. This vfunc is optional, but
- *   should be implemented if possible to avoid unnecessary start/stop
- *   cycles. The default implementation will open and close the resource
- *   to find out whether get_range is supported, and that is usually
- *   undesirable.
- * @fixate: Called during negotiation if caps need fixating. Implement instead of
- *   setting a fixate function on the source pad.
+ *   end of stream is reached. The default implementation will call @alloc and
+ *   then call @fill.
+ * @alloc: Ask the subclass to allocate a buffer with for offset and size. The
+ *   default implementation will create a new buffer from the negotiated allocator.
+ * @fill: Ask the subclass to fill the buffer with data for offset and size. The
+ *   passed buffer is guaranteed to hold the requested amount of bytes.
  *
  * Subclasses can override any of the available virtual methods or not, as
  * needed. At the minimum, the @create method should be overridden to produce
@@ -172,15 +168,16 @@ struct _GstBaseSrcClass {
   /* virtual methods for subclasses */
 
   /* get caps from subclass */
-  GstCaps*      (*get_caps)     (GstBaseSrc *src);
-  /* notify the subclass of new caps */
-  gboolean      (*set_caps)     (GstBaseSrc *src, GstCaps *caps);
-
+  GstCaps*      (*get_caps)     (GstBaseSrc *src, GstCaps *filter);
   /* decide on caps */
   gboolean      (*negotiate)    (GstBaseSrc *src);
+  /* called if, in negotiation, caps need fixating */
+  void          (*fixate)       (GstBaseSrc *src, GstCaps *caps);
+  /* notify the subclass of new caps */
+  gboolean      (*set_caps)     (GstBaseSrc *src, GstCaps *caps);
 
-  /* generate and send a newsegment (UNUSED) */
-  gboolean      (*newsegment)   (GstBaseSrc *src);
+  /* setup allocation query */
+  gboolean      (*decide_allocation)   (GstBaseSrc *src, GstQuery *query);
 
   /* start and stop processing, ideal for opening/closing the resource */
   gboolean      (*start)        (GstBaseSrc *src);
@@ -196,44 +193,40 @@ struct _GstBaseSrcClass {
 
   /* check if the resource is seekable */
   gboolean      (*is_seekable)  (GstBaseSrc *src);
+
+  /* Prepare the segment on which to perform do_seek(), converting to the
+   * current basesrc format. */
+  gboolean      (*prepare_seek_segment) (GstBaseSrc *src, GstEvent *seek,
+                                         GstSegment *segment);
+  /* notify subclasses of a seek */
+  gboolean      (*do_seek)      (GstBaseSrc *src, GstSegment *segment);
+
   /* unlock any pending access to the resource. subclasses should unlock
    * any function ASAP. */
   gboolean      (*unlock)       (GstBaseSrc *src);
+  /* Clear any pending unlock request, as we succeeded in unlocking */
+  gboolean      (*unlock_stop)  (GstBaseSrc *src);
+
+  /* notify subclasses of a query */
+  gboolean      (*query)        (GstBaseSrc *src, GstQuery *query);
 
   /* notify subclasses of an event */
   gboolean      (*event)        (GstBaseSrc *src, GstEvent *event);
 
-  /* ask the subclass to create a buffer with offset and size */
+  /* ask the subclass to create a buffer with offset and size, the default
+   * implementation will call alloc and fill. */
   GstFlowReturn (*create)       (GstBaseSrc *src, guint64 offset, guint size,
                                  GstBuffer **buf);
-
-  /* additions that change padding... */
-  /* notify subclasses of a seek */
-  gboolean      (*do_seek)      (GstBaseSrc *src, GstSegment *segment);
-  /* notify subclasses of a query */
-  gboolean      (*query)        (GstBaseSrc *src, GstQuery *query);
-
-  /* check whether the source would support pull-based operation if
-   * it were to be opened now. This vfunc is optional, but should be
-   * implemented if possible to avoid unnecessary start/stop cycles.
-   * The default implementation will open and close the resource to
-   * find out whether get_range is supported and that is usually
-   * undesirable. */
-  gboolean      (*check_get_range) (GstBaseSrc *src);
-
-  /* called if, in negotiation, caps need fixating */
-  void          (*fixate)       (GstBaseSrc *src, GstCaps *caps);
-
-  /* Clear any pending unlock request, as we succeeded in unlocking */
-  gboolean      (*unlock_stop)  (GstBaseSrc *src);
-
-  /* Prepare the segment on which to perform do_seek(), converting to the
-   * current basesrc format. */
-  gboolean      (*prepare_seek_segment) (GstBaseSrc *src, GstEvent *seek,
-                                         GstSegment *segment);
+  /* ask the subclass to allocate an output buffer. The default implementation
+   * will use the negotiated allocator. */
+  GstFlowReturn (*alloc)        (GstBaseSrc *src, guint64 offset, guint size,
+                                 GstBuffer **buf);
+  /* ask the subclass to fill the buffer with data from offset and size */
+  GstFlowReturn (*fill)         (GstBaseSrc *src, guint64 offset, guint size,
+                                 GstBuffer *buf);
 
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE - 6];
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 GType gst_base_src_get_type (void);
@@ -247,17 +240,26 @@ void            gst_base_src_set_format       (GstBaseSrc *src, GstFormat format
 
 void            gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic);
 
+void            gst_base_src_set_async        (GstBaseSrc *src, gboolean async);
+gboolean        gst_base_src_is_async         (GstBaseSrc *src);
+
+void            gst_base_src_start_complete   (GstBaseSrc * basesrc, GstFlowReturn ret);
+GstFlowReturn   gst_base_src_start_wait       (GstBaseSrc * basesrc);
+
 gboolean        gst_base_src_query_latency    (GstBaseSrc *src, gboolean * live,
                                                GstClockTime * min_latency,
                                                GstClockTime * max_latency);
 
-void            gst_base_src_set_blocksize    (GstBaseSrc *src, gulong blocksize);
-gulong          gst_base_src_get_blocksize    (GstBaseSrc *src);
+void            gst_base_src_set_blocksize    (GstBaseSrc *src, guint blocksize);
+guint           gst_base_src_get_blocksize    (GstBaseSrc *src);
 
 void            gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean timestamp);
 gboolean        gst_base_src_get_do_timestamp (GstBaseSrc *src);
 
 gboolean        gst_base_src_new_seamless_segment (GstBaseSrc *src, gint64 start, gint64 stop, gint64 position);
+
+gboolean        gst_base_src_set_caps         (GstBaseSrc *src, GstCaps *caps);
+
 G_END_DECLS
 
 #endif /* __GST_BASE_SRC_H__ */
index dfaa359..67806fb 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include "../../../gst/gst_private.h"
 #include "../../../gst/gst-i18n-lib.h"
 #include "../../../gst/glib-compat-private.h"
@@ -244,61 +241,33 @@ struct _GstBaseTransformPrivate
   /* previous buffer had a discont */
   gboolean discont;
 
-  GstActivateMode pad_mode;
+  GstPadMode pad_mode;
 
   gboolean gap_aware;
 
-  /* caps used for allocating buffers */
-  gboolean proxy_alloc;
-  GstCaps *sink_alloc;
-  GstCaps *src_alloc;
-
-  /*
-   * This flag controls if basetransform should explicitly
-   * do a pad alloc when it receives a buffer even if it operates on
-   * passthrough, this is needed to check for downstream caps suggestions
-   * and this newly alloc'ed buffer is discarded.
-   *
-   * Without this flag basetransform would try a pad alloc whenever it
-   * gets a new buffer and pipelines like:
-   * "src ! basetrans1 ! basetrans2 ! basetrans3 ! sink"
-   * Would have a 3 pad allocs for each buffer pushed downstream from the src.
-   *
-   * This flag is set to TRUE on start up, on setcaps and when a buffer is
-   * pushed downstream. It is set to FALSE after a pad alloc has been requested
-   * downstream.
-   * The rationale is that when a pad alloc flows through the pipeline, all
-   * basetransform elements on passthrough will avoid pad alloc'ing when they
-   * get the buffer.
-   */
-  gboolean force_alloc;
-
-  /* upstream caps and size suggestions */
-  GstCaps *sink_suggest;
-  guint size_suggest;
-  gboolean suggest_pending;
-
   gboolean reconfigure;
 
   /* QoS stats */
   guint64 processed;
   guint64 dropped;
 
-  GstClockTime last_stop_out;
-  GList *delayed_events;
+  GstClockTime position_out;
 
-  GstCaps *cached_peer_caps[2];
-  GstCaps *cached_transformed_caps[2];
+  GstBufferPool *pool;
+  const GstAllocator *allocator;
+  guint prefix;
+  guint alignment;
 };
 
+
 static GstElementClass *parent_class = NULL;
 
 static void gst_base_transform_class_init (GstBaseTransformClass * klass);
 static void gst_base_transform_init (GstBaseTransform * trans,
     GstBaseTransformClass * klass);
-static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform
-    * trans, GstBuffer * input, GstBuffer ** buf);
 
+/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
+ * method to get to the padtemplates */
 GType
 gst_base_transform_get_type (void)
 {
@@ -330,69 +299,52 @@ static void gst_base_transform_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_base_transform_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
-    gboolean active);
-static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
-    gboolean active);
+static gboolean gst_base_transform_src_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
+static gboolean gst_base_transform_sink_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
 static gboolean gst_base_transform_activate (GstBaseTransform * trans,
     gboolean active);
 static gboolean gst_base_transform_get_unit_size (GstBaseTransform * trans,
-    GstCaps * caps, guint * size);
+    GstCaps * caps, gsize * size);
 
-static gboolean gst_base_transform_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static gboolean gst_base_transform_src_eventfunc (GstBaseTransform * trans,
     GstEvent * event);
-static gboolean gst_base_transform_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static gboolean gst_base_transform_sink_eventfunc (GstBaseTransform * trans,
     GstEvent * event);
-static gboolean gst_base_transform_check_get_range (GstPad * pad);
-static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
-    guint length, GstBuffer ** buffer);
-static GstFlowReturn gst_base_transform_chain (GstPad * pad,
+static GstFlowReturn gst_base_transform_getrange (GstPad * pad,
+    GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
+static GstFlowReturn gst_base_transform_chain (GstPad * pad, GstObject * parent,
     GstBuffer * buffer);
-static GstCaps *gst_base_transform_getcaps (GstPad * pad);
-static gboolean gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_base_transform_default_transform_caps (GstBaseTransform *
+    trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter);
+static void gst_base_transform_default_fixate (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static GstCaps *gst_base_transform_query_caps (GstBaseTransform * trans,
+    GstPad * pad, GstCaps * filter);
 static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps);
-static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
-static gboolean gst_base_transform_query (GstPad * pad, GstQuery * query);
+static gboolean gst_base_transform_setcaps (GstBaseTransform * trans,
+    GstPad * pad, GstCaps * caps);
+static gboolean gst_base_transform_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static gboolean gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query);
-static const GstQueryType *gst_base_transform_query_type (GstPad * pad);
+static gboolean gst_base_transform_default_transform_size (GstBaseTransform *
+    trans, GstPadDirection direction, GstCaps * caps, gsize size,
+    GstCaps * othercaps, gsize * othersize);
+
+static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer ** outbuf);
+static gboolean default_copy_metadata (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf);
 
 /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
 
-static void
-gst_base_transform_drop_delayed_events (GstBaseTransform * trans)
-{
-  GST_OBJECT_LOCK (trans);
-  if (trans->priv->delayed_events) {
-    g_list_foreach (trans->priv->delayed_events, (GFunc) gst_event_unref, NULL);
-    g_list_free (trans->priv->delayed_events);
-    trans->priv->delayed_events = NULL;
-  }
-  GST_OBJECT_UNLOCK (trans);
-}
-
-static void
-gst_base_transform_clear_transformed_caps_cache (GstBaseTransform * trans)
-{
-  struct _GstBaseTransformPrivate *priv = trans->priv;
-  int n;
-
-  for (n = 0; n < 2; ++n) {
-    if (priv->cached_peer_caps[n]) {
-      gst_caps_unref (priv->cached_peer_caps[n]);
-      priv->cached_peer_caps[n] = NULL;
-    }
-    if (priv->cached_transformed_caps[n]) {
-      gst_caps_unref (priv->cached_transformed_caps[n]);
-      priv->cached_transformed_caps[n] = NULL;
-    }
-  }
-}
 
 static void
 gst_base_transform_finalize (GObject * object)
@@ -401,11 +353,7 @@ gst_base_transform_finalize (GObject * object)
 
   trans = GST_BASE_TRANSFORM (object);
 
-  gst_base_transform_drop_delayed_events (trans);
-  gst_caps_replace (&trans->priv->sink_suggest, NULL);
-  g_mutex_free (trans->transform_lock);
-
-  gst_base_transform_clear_transformed_caps_cache (trans);
+  g_mutex_clear (&trans->transform_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -436,11 +384,21 @@ gst_base_transform_class_init (GstBaseTransformClass * klass)
   gobject_class->finalize = gst_base_transform_finalize;
 
   klass->passthrough_on_same_caps = FALSE;
-  klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
-  klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);
+
+  klass->transform_caps =
+      GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_caps);
+  klass->fixate_caps = GST_DEBUG_FUNCPTR (gst_base_transform_default_fixate);
   klass->accept_caps =
       GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default);
   klass->query = GST_DEBUG_FUNCPTR (gst_base_transform_default_query);
+  klass->transform_size =
+      GST_DEBUG_FUNCPTR (gst_base_transform_default_transform_size);
+
+  klass->sink_event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
+  klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);
+  klass->prepare_output_buffer =
+      GST_DEBUG_FUNCPTR (default_prepare_output_buffer);
+  klass->copy_metadata = GST_DEBUG_FUNCPTR (default_copy_metadata);
 }
 
 static void
@@ -457,56 +415,36 @@ gst_base_transform_init (GstBaseTransform * trans,
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
   g_return_if_fail (pad_template != NULL);
   trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
-  gst_pad_set_getcaps_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
-  gst_pad_set_acceptcaps_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
-  gst_pad_set_setcaps_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
   gst_pad_set_event_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
   gst_pad_set_chain_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_chain));
-  gst_pad_set_activatepush_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
-  gst_pad_set_bufferalloc_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_buffer_alloc));
+  gst_pad_set_activatemode_function (trans->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_mode));
   gst_pad_set_query_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_query));
-  gst_pad_set_query_type_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_query_type));
   gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
 
   pad_template =
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
   g_return_if_fail (pad_template != NULL);
   trans->srcpad = gst_pad_new_from_template (pad_template, "src");
-  gst_pad_set_getcaps_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
-  gst_pad_set_acceptcaps_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
   gst_pad_set_event_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
-  gst_pad_set_checkgetrange_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_check_get_range));
   gst_pad_set_getrange_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
-  gst_pad_set_activatepull_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
+  gst_pad_set_activatemode_function (trans->srcpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_mode));
   gst_pad_set_query_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_query));
-  gst_pad_set_query_type_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_query_type));
   gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
 
-  trans->transform_lock = g_mutex_new ();
-  trans->pending_configure = FALSE;
+  g_mutex_init (&trans->transform_lock);
   trans->priv->qos_enabled = DEFAULT_PROP_QOS;
   trans->cache_caps1 = NULL;
   trans->cache_caps2 = NULL;
-  trans->priv->pad_mode = GST_ACTIVATE_NONE;
+  trans->priv->pad_mode = GST_PAD_MODE_NONE;
   trans->priv->gap_aware = FALSE;
-  trans->priv->delayed_events = NULL;
 
   trans->passthrough = FALSE;
   if (bclass->transform == NULL) {
@@ -522,7 +460,22 @@ gst_base_transform_init (GstBaseTransform * trans,
 
   trans->priv->processed = 0;
   trans->priv->dropped = 0;
-  trans->priv->force_alloc = TRUE;
+}
+
+static GstCaps *
+gst_base_transform_default_transform_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+  GstCaps *ret;
+
+  GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps);
+  /* no transform function, use the identity transform */
+  if (filter) {
+    ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+  } else {
+    ret = gst_caps_ref (caps);
+  }
+  return ret;
 }
 
 /* given @caps on the src or sink pad (given by @direction)
@@ -532,9 +485,9 @@ gst_base_transform_init (GstBaseTransform * trans,
  */
 static GstCaps *
 gst_base_transform_transform_caps (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps)
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
-  GstCaps *ret;
+  GstCaps *ret = NULL;
   GstBaseTransformClass *klass;
 
   if (caps == NULL)
@@ -544,94 +497,52 @@ gst_base_transform_transform_caps (GstBaseTransform * trans,
 
   /* if there is a custom transform function, use this */
   if (klass->transform_caps) {
-    GstCaps *temp;
-    gint i;
-
-    /* start with empty caps */
-    ret = gst_caps_new_empty ();
     GST_DEBUG_OBJECT (trans, "transform caps (direction = %d)", direction);
 
-    if (gst_caps_is_any (caps)) {
-      /* for any caps we still have to call the transform function */
-      GST_DEBUG_OBJECT (trans, "from: ANY");
-      temp = klass->transform_caps (trans, direction, caps);
-      GST_DEBUG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, temp);
-
-      temp = gst_caps_make_writable (temp);
-      gst_caps_append (ret, temp);
-    } else {
-      gint n = gst_caps_get_size (caps);
-      /* we send caps with just one structure to the transform
-       * function as this is easier for the element */
-      for (i = 0; i < n; i++) {
-        GstCaps *nth;
-
-        nth = gst_caps_copy_nth (caps, i);
-        GST_LOG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
-        temp = klass->transform_caps (trans, direction, nth);
-        gst_caps_unref (nth);
-        GST_LOG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
-
-        temp = gst_caps_make_writable (temp);
-
-        /* here we need to only append those structures, that are not yet
-         * in there, we use the merge function for this */
-        gst_caps_merge (ret, temp);
-
-        GST_LOG_OBJECT (trans, "  merged[%d]: %" GST_PTR_FORMAT, i, ret);
+    GST_LOG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
+    ret = klass->transform_caps (trans, direction, caps, filter);
+    GST_LOG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, ret);
+
+#ifndef G_DISABLE_ASSERT
+    if (filter) {
+      if (!gst_caps_is_subset (ret, filter)) {
+        GstCaps *intersection;
+
+        GST_ERROR_OBJECT (trans,
+            "transform_caps returned caps %" GST_PTR_FORMAT
+            " which are not a real subset of the filter caps %"
+            GST_PTR_FORMAT, ret, filter);
+        g_warning ("%s: transform_caps returned caps which are not a real "
+            "subset of the filter caps", GST_ELEMENT_NAME (trans));
+
+        intersection =
+            gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
+        gst_caps_unref (ret);
+        ret = intersection;
       }
-      GST_LOG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
-      /* FIXME: we can't do much simplification here because we don't really want to
-       * change the caps order
-       gst_caps_do_simplify (ret);
-       GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));
-       */
     }
-  } else {
-    GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps);
-    /* no transform function, use the identity transform */
-    ret = gst_caps_ref (caps);
+#endif
   }
 
-  GST_DEBUG_OBJECT (trans, "to: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (ret),
-      ret);
+  GST_DEBUG_OBJECT (trans, "to: %" GST_PTR_FORMAT, ret);
 
   return ret;
 }
 
-/* transform a buffer of @size with @caps on the pad with @direction to
- * the size of a buffer with @othercaps and store the result in @othersize
- *
- * We have two ways of doing this:
- *  1) use a custom transform size function, this is for complicated custom
- *     cases with no fixed unit_size.
- *  2) use the unit_size functions where there is a relationship between the
- *     caps and the size of a buffer.
- */
 static gboolean
-gst_base_transform_transform_size (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps,
-    guint size, GstCaps * othercaps, guint * othersize)
+gst_base_transform_default_transform_size (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, gsize size,
+    GstCaps * othercaps, gsize * othersize)
 {
-  guint inunitsize, outunitsize, units;
+  gsize inunitsize, outunitsize, units;
   GstBaseTransformClass *klass;
-  gboolean ret;
 
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  GST_DEBUG_OBJECT (trans, "asked to transform size %d for caps %"
-      GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
-      size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
-
-  if (klass->transform_size) {
-    /* if there is a custom transform function, use this */
-    ret = klass->transform_size (trans, direction, caps, size, othercaps,
-        othersize);
-  } else if (klass->get_unit_size == NULL) {
+  if (klass->get_unit_size == NULL) {
     /* if there is no transform_size and no unit_size, it means the
      * element does not modify the size of a buffer */
     *othersize = size;
-    ret = TRUE;
   } else {
     /* there is no transform_size function, we have to use the unit_size
      * functions. This method assumes there is a fixed unit_size associated with
@@ -639,8 +550,9 @@ gst_base_transform_transform_size (GstBaseTransform * trans,
     if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))
       goto no_in_size;
 
-    GST_DEBUG_OBJECT (trans, "input size %d, input unit size %d", size,
-        inunitsize);
+    GST_DEBUG_OBJECT (trans,
+        "input size %" G_GSIZE_FORMAT ", input unit size %" G_GSIZE_FORMAT,
+        size, inunitsize);
 
     /* input size must be a multiple of the unit_size of the input caps */
     if (inunitsize == 0 || (size % inunitsize != 0))
@@ -656,11 +568,10 @@ gst_base_transform_transform_size (GstBaseTransform * trans,
     /* the output size is the unit_size times the amount of units on the
      * input */
     *othersize = units * outunitsize;
-    GST_DEBUG_OBJECT (trans, "transformed size to %d", *othersize);
-
-    ret = TRUE;
+    GST_DEBUG_OBJECT (trans, "transformed size to %" G_GSIZE_FORMAT,
+        *othersize);
   }
-  return ret;
+  return TRUE;
 
   /* ERRORS */
 no_in_size:
@@ -671,10 +582,10 @@ no_in_size:
   }
 no_multiple:
   {
-    GST_DEBUG_OBJECT (trans, "Size %u is not a multiple of unit size %u", size,
-        inunitsize);
-    g_warning ("%s: size %u is not a multiple of unit size %u",
-        GST_ELEMENT_NAME (trans), size, inunitsize);
+    GST_DEBUG_OBJECT (trans, "Size %" G_GSIZE_FORMAT " is not a multiple of"
+        "unit size %" G_GSIZE_FORMAT, size, inunitsize);
+    g_warning ("%s: size %" G_GSIZE_FORMAT " is not a multiple of unit size %"
+        G_GSIZE_FORMAT, GST_ELEMENT_NAME (trans), size, inunitsize);
     return FALSE;
   }
 no_out_size:
@@ -685,52 +596,91 @@ no_out_size:
   }
 }
 
+/* transform a buffer of @size with @caps on the pad with @direction to
+ * the size of a buffer with @othercaps and store the result in @othersize
+ *
+ * We have two ways of doing this:
+ *  1) use a custom transform size function, this is for complicated custom
+ *     cases with no fixed unit_size.
+ *  2) use the unit_size functions where there is a relationship between the
+ *     caps and the size of a buffer.
+ */
+static gboolean
+gst_base_transform_transform_size (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps,
+    gsize size, GstCaps * othercaps, gsize * othersize)
+{
+  GstBaseTransformClass *klass;
+  gboolean ret = FALSE;
+
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
+
+  GST_DEBUG_OBJECT (trans,
+      "asked to transform size %" G_GSIZE_FORMAT " for caps %"
+      GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
+      size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
+
+  if (klass->transform_size) {
+    /* if there is a custom transform function, use this */
+    ret = klass->transform_size (trans, direction, caps, size, othercaps,
+        othersize);
+  }
+  return ret;
+}
+
 /* get the caps that can be handled by @pad. We perform:
  *
  *  - take the caps of peer of otherpad,
- *  - filter against the padtemplate of otherpad,
+ *  - filter against the padtemplate of otherpad, 
  *  - calculate all transforms of remaining caps
  *  - filter against template of @pad
  *
  * If there is no peer, we simply return the caps of the padtemplate of pad.
  */
 static GstCaps *
-gst_base_transform_getcaps (GstPad * pad)
+gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
+    GstCaps * filter)
 {
-  GstBaseTransform *trans;
   GstPad *otherpad;
-  const GstCaps *templ;
-  GstCaps *peercaps, *caps, *temp;
-  gboolean samecaps;
-  int cache_index;
-
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  GstCaps *peercaps, *caps, *temp, *peerfilter = NULL;
+  GstCaps *templ;
 
   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
-  cache_index = (pad == trans->srcpad) ? 0 : 1;
 
   /* we can do what the peer can */
-  peercaps = gst_pad_peer_get_caps_reffed (otherpad);
-  GST_OBJECT_LOCK (trans);
-  samecaps = (peercaps && trans->priv->cached_peer_caps[cache_index]
-      && gst_caps_is_strictly_equal (peercaps,
-          trans->priv->cached_peer_caps[cache_index]));
-  if (!samecaps) {
-    if (trans->priv->cached_peer_caps[cache_index]) {
-      gst_caps_unref (trans->priv->cached_peer_caps[cache_index]);
-      trans->priv->cached_peer_caps[cache_index] = NULL;
-    }
-    if (trans->priv->cached_transformed_caps[cache_index]) {
-      gst_caps_unref (trans->priv->cached_transformed_caps[cache_index]);
-      trans->priv->cached_transformed_caps[cache_index] = NULL;
-    }
-  } else {
-    GST_DEBUG_OBJECT (trans,
-        "Returning cached transformed caps (index = %d)", cache_index);
-    caps = gst_caps_ref (trans->priv->cached_transformed_caps[cache_index]);
-    goto done;
+  if (filter) {
+
+    GST_DEBUG_OBJECT (pad, "filter caps  %" GST_PTR_FORMAT, filter);
+
+    /* filtered against our padtemplate on the other side */
+    templ = gst_pad_get_pad_template_caps (pad);
+    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
+    temp = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST);
+    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
+    gst_caps_unref (templ);
+
+    /* then see what we can transform this to */
+    peerfilter = gst_base_transform_transform_caps (trans,
+        GST_PAD_DIRECTION (pad), temp, NULL);
+    GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, peerfilter);
+    gst_caps_unref (temp);
+
+    /* and filter against the template of this pad */
+    templ = gst_pad_get_pad_template_caps (otherpad);
+    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
+    /* We keep the caps sorted like the returned caps */
+    temp =
+        gst_caps_intersect_full (peerfilter, templ, GST_CAPS_INTERSECT_FIRST);
+    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
+    gst_caps_unref (peerfilter);
+    gst_caps_unref (templ);
+    peerfilter = temp;
   }
-  GST_OBJECT_UNLOCK (trans);
+
+  peercaps = gst_pad_peer_query_caps (otherpad, peerfilter);
+
+  if (peerfilter)
+    gst_caps_unref (peerfilter);
 
   if (peercaps) {
     GST_DEBUG_OBJECT (pad, "peer caps  %" GST_PTR_FORMAT, peercaps);
@@ -740,30 +690,30 @@ gst_base_transform_getcaps (GstPad * pad)
     GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
     temp = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
+    gst_caps_unref (templ);
   } else {
     temp = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
-    GST_DEBUG_OBJECT (pad, "no peer, using our template caps %" GST_PTR_FORMAT,
-        temp);
   }
 
   /* then see what we can transform this to */
   caps = gst_base_transform_transform_caps (trans,
-      GST_PAD_DIRECTION (otherpad), temp);
+      GST_PAD_DIRECTION (otherpad), temp, filter);
   GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, caps);
   gst_caps_unref (temp);
   if (caps == NULL)
-    goto done_update_cache;
-
-  /* and filter against the template of this pad */
-  templ = gst_pad_get_pad_template_caps (pad);
-  GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
-  /* We keep the caps sorted like the returned caps */
-  temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
-  GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
-  gst_caps_unref (caps);
-  caps = temp;
+    goto done;
 
   if (peercaps) {
+    /* and filter against the template of this pad */
+    templ = gst_pad_get_pad_template_caps (pad);
+    GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
+    /* We keep the caps sorted like the returned caps */
+    temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
+    GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
+    gst_caps_unref (caps);
+    gst_caps_unref (templ);
+    caps = temp;
+
     /* Now try if we can put the untransformed downstream caps first */
     temp = gst_caps_intersect_full (peercaps, caps, GST_CAPS_INTERSECT_FIRST);
     if (!gst_caps_is_empty (temp)) {
@@ -772,28 +722,154 @@ gst_base_transform_getcaps (GstPad * pad)
     } else {
       gst_caps_unref (temp);
     }
+  } else {
+    gst_caps_unref (caps);
+    /* no peer or the peer can do anything, our padtemplate is enough then */
+    caps = gst_pad_get_pad_template_caps (pad);
+
+    if (filter) {
+      GstCaps *temp;
+
+      temp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+      gst_caps_unref (caps);
+      caps = temp;
+    }
   }
 
-done_update_cache:
+done:
   GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);
 
+  if (peercaps)
+    gst_caps_unref (peercaps);
+
+  return caps;
+}
+
+static gboolean
+gst_base_transform_set_allocation (GstBaseTransform * trans,
+    GstBufferPool * pool, const GstAllocator * allocator, guint prefix,
+    guint alignment)
+{
+  GstBufferPool *oldpool;
+  GstBaseTransformPrivate *priv = trans->priv;
+
+  /* activate */
+  if (pool) {
+    GST_DEBUG_OBJECT (trans, "setting pool %p active", pool);
+    if (!gst_buffer_pool_set_active (pool, TRUE))
+      goto activate_failed;
+  }
+
   GST_OBJECT_LOCK (trans);
-  if (peercaps) {
-    trans->priv->cached_peer_caps[cache_index] = gst_caps_ref (peercaps);
+  oldpool = priv->pool;
+  priv->pool = pool;
+  priv->allocator = allocator;
+  priv->prefix = prefix;
+  priv->alignment = alignment;
+  GST_OBJECT_UNLOCK (trans);
+
+  if (oldpool) {
+    GST_DEBUG_OBJECT (trans, "deactivating old pool %p", oldpool);
+    gst_buffer_pool_set_active (oldpool, FALSE);
+    gst_object_unref (oldpool);
   }
-  if (caps) {
-    trans->priv->cached_transformed_caps[cache_index] = gst_caps_ref (caps);
+  return TRUE;
+
+  /* ERRORS */
+activate_failed:
+  {
+    GST_ERROR_OBJECT (trans, "failed to activate bufferpool.");
+    return FALSE;
   }
+}
 
-done:
-  GST_OBJECT_UNLOCK (trans);
+static gboolean
+gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps)
+{
+  GstQuery *query;
+  gboolean result = TRUE;
+  GstBufferPool *pool = NULL, *oldpool;
+  guint size, min, max, prefix, alignment;
+  GstBaseTransformClass *klass;
+  const GstAllocator *allocator = NULL;
 
-  if (peercaps)
-    gst_caps_unref (peercaps);
+  /* there are these possibilities:
+   *
+   * 1) we negotiated passthrough, we can proxy the bufferpool directly and we
+   *    will do that whenever some upstream does an allocation query.
+   * 2) we need to do a transform, we need to get a bufferpool from downstream
+   *    and configure it. When upstream does the ALLOCATION query, the
+   *    propose_allocation vmethod will be called and we will configure the
+   *    upstream allocator with our porposed values then.
+   */
+
+  /* clear old pool */
+  oldpool = trans->priv->pool;
+  if (oldpool) {
+    GST_DEBUG_OBJECT (trans, "unreffing old pool");
+    gst_buffer_pool_set_active (oldpool, FALSE);
+    gst_object_unref (oldpool);
+    trans->priv->pool = oldpool = NULL;
+  }
+
+  if (trans->passthrough || trans->always_in_place) {
+    /* we are in passthrough, the input buffer is never copied and always passed
+     * along. We never allocate an output buffer on the srcpad. What we do is
+     * let the upstream element decide if it wants to use a bufferpool and
+     * then we will proxy the downstream pool */
+    GST_DEBUG_OBJECT (trans, "we're passthough, delay bufferpool");
+    return TRUE;
+  }
+
+  /* not passthrough, we need to allocate */
+  /* find a pool for the negotiated caps now */
+  GST_DEBUG_OBJECT (trans, "doing allocation query");
+  query = gst_query_new_allocation (outcaps, TRUE);
+  if (!gst_pad_peer_query (trans->srcpad, query)) {
+    /* not a problem, just debug a little */
+    GST_DEBUG_OBJECT (trans, "peer ALLOCATION query failed");
+  }
 
-  gst_object_unref (trans);
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  return caps;
+  GST_DEBUG_OBJECT (trans, "calling decide_allocation");
+  if (G_LIKELY (klass->decide_allocation))
+    result = klass->decide_allocation (trans, query);
+
+  /* we got configuration from our peer, parse them */
+  gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
+      &alignment, &pool);
+
+  if (size == 0) {
+    const gchar *mem = NULL;
+
+    /* no size, we have variable size buffers */
+    if (gst_query_get_n_allocation_memories (query) > 0) {
+      mem = gst_query_parse_nth_allocation_memory (query, 0);
+    }
+    allocator = gst_allocator_find (mem);
+    GST_DEBUG_OBJECT (trans, "no size, using allocator %s", GST_STR_NULL (mem));
+  } else if (pool == NULL) {
+    GstStructure *config;
+
+    /* we did not get a pool, make one ourselves then */
+    pool = gst_buffer_pool_new ();
+
+    GST_DEBUG_OBJECT (trans, "no pool, making one");
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_set (config, outcaps, size, min, max, prefix,
+        alignment);
+    gst_buffer_pool_set_config (pool, config);
+  }
+
+  gst_query_unref (query);
+
+  /* and store */
+  result =
+      gst_base_transform_set_allocation (trans, pool, allocator, prefix,
+      alignment);
+
+  return result;
 }
 
 /* function triggered when the in and out caps are negotiated and need
@@ -835,63 +911,17 @@ gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,
     ret = klass->set_caps (trans, in, out);
   }
 
-  GST_OBJECT_LOCK (trans);
-  /* make sure we reevaluate how the buffer_alloc works wrt to proxy allocating
-   * the buffer. FIXME, this triggers some quite heavy codepaths that don't need
-   * to be taken.. */
-  trans->priv->suggest_pending = TRUE;
-  GST_OBJECT_UNLOCK (trans);
   trans->negotiated = ret;
 
   return ret;
 }
 
-/* check if caps @in on @pad can be transformed to @out on the other pad.
- * We don't have a vmethod to test this yet so we have to do a somewhat less
- * efficient check for this.
- */
-static gboolean
-gst_base_transform_can_transform (GstBaseTransform * trans, GstPad * pad,
-    GstCaps * in, GstCaps * out)
+static void
+gst_base_transform_default_fixate (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
 {
-  GstCaps *othercaps;
-
-  /* convert the in caps to all possible out caps */
-  othercaps =
-      gst_base_transform_transform_caps (trans, GST_PAD_DIRECTION (pad), in);
-
-  /* check if transform is empty */
-  if (!othercaps || gst_caps_is_empty (othercaps))
-    goto no_transform;
-
-  /* check if the out caps is a subset of the othercaps */
-  if (!gst_caps_can_intersect (out, othercaps))
-    goto no_subset;
-
-  if (othercaps)
-    gst_caps_unref (othercaps);
-
-  GST_DEBUG_OBJECT (trans, "from %" GST_PTR_FORMAT, in);
-  GST_DEBUG_OBJECT (trans, "to   %" GST_PTR_FORMAT, out);
-
-  return TRUE;
-
-  /* ERRORS */
-no_transform:
-  {
-    GST_DEBUG_OBJECT (trans,
-        "transform returned useless %" GST_PTR_FORMAT, othercaps);
-    if (othercaps)
-      gst_caps_unref (othercaps);
-    return FALSE;
-  }
-no_subset:
-  {
-    GST_DEBUG_OBJECT (trans, "no subset");
-    if (othercaps)
-      gst_caps_unref (othercaps);
-    return FALSE;
-  }
+  GST_DEBUG_OBJECT (trans, "using default caps fixate function");
+  gst_caps_fixate (othercaps);
 }
 
 /* given a fixed @caps on @pad, create the best possible caps for the
@@ -917,7 +947,6 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
   GstBaseTransformClass *klass;
   GstPad *otherpad, *otherpeer;
   GstCaps *othercaps;
-  gboolean peer_checked = FALSE;
   gboolean is_fixed;
 
   /* caps must be fixed here, this is a programming error if it's not */
@@ -932,13 +961,12 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
    * passthrough because it might be possible that this element cannot support
    * passthrough at all. */
   othercaps = gst_base_transform_transform_caps (trans,
-      GST_PAD_DIRECTION (pad), caps);
+      GST_PAD_DIRECTION (pad), caps, NULL);
 
   /* The caps we can actually output is the intersection of the transformed
    * caps with the pad template for the pad */
   if (othercaps) {
-    GstCaps *intersect;
-    const GstCaps *templ_caps;
+    GstCaps *intersect, *templ_caps;
 
     templ_caps = gst_pad_get_pad_template_caps (otherpad);
     GST_DEBUG_OBJECT (trans,
@@ -949,6 +977,7 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
         GST_CAPS_INTERSECT_FIRST);
 
     gst_caps_unref (othercaps);
+    gst_caps_unref (templ_caps);
     othercaps = intersect;
   }
 
@@ -965,117 +994,79 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
     GST_DEBUG_OBJECT (trans,
         "transform returned non fixed  %" GST_PTR_FORMAT, othercaps);
 
-    /* see if the target caps are a superset of the source caps, in this
-     * case we can try to perform passthrough */
-    if (gst_caps_can_intersect (othercaps, caps)) {
-      GST_DEBUG_OBJECT (trans, "try passthrough with %" GST_PTR_FORMAT, caps);
-      if (otherpeer) {
-        /* try passthrough. we know it's fixed, because caps is fixed */
-        if (gst_pad_accept_caps (otherpeer, caps)) {
-          GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);
-          /* peer accepted unmodified caps, we free the original non-fixed
-           * caps and work with the passthrough caps */
-          gst_caps_unref (othercaps);
-          othercaps = gst_caps_ref (caps);
-          is_fixed = TRUE;
-          /* mark that we checked othercaps with the peer, this
-           * makes sure we don't call accept_caps again with these same
-           * caps */
-          peer_checked = TRUE;
-        } else {
-          GST_DEBUG_OBJECT (trans,
-              "peer did not accept %" GST_PTR_FORMAT, caps);
-        }
-      } else {
-        GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
-        gst_caps_unref (othercaps);
-        othercaps = gst_caps_ref (caps);
-        is_fixed = TRUE;
-      }
-    }
-  }
+    /* Now let's see what the peer suggests based on our transformed caps */
+    if (otherpeer) {
+      GstCaps *peercaps, *intersection, *templ_caps;
 
-  /* second attempt at fixation is done by intersecting with
-   * the peer caps */
-  if (!is_fixed && otherpeer) {
-    /* intersect against what the peer can do */
-    GstCaps *peercaps;
-    GstCaps *intersect;
+      GST_DEBUG_OBJECT (trans,
+          "Checking peer caps with filter %" GST_PTR_FORMAT, othercaps);
 
-    GST_DEBUG_OBJECT (trans, "othercaps now %" GST_PTR_FORMAT, othercaps);
+      peercaps = gst_pad_query_caps (otherpeer, othercaps);
+      GST_DEBUG_OBJECT (trans, "Resulted in %" GST_PTR_FORMAT, peercaps);
+      if (!gst_caps_is_empty (peercaps)) {
+        templ_caps = gst_pad_get_pad_template_caps (otherpad);
 
-    peercaps = gst_pad_get_caps_reffed (otherpeer);
-    intersect = gst_caps_intersect (peercaps, othercaps);
-    gst_caps_unref (peercaps);
-    gst_caps_unref (othercaps);
-    othercaps = intersect;
-    peer_checked = FALSE;
+        GST_DEBUG_OBJECT (trans,
+            "Intersecting with template caps %" GST_PTR_FORMAT, templ_caps);
 
-    is_fixed = gst_caps_is_fixed (othercaps);
+        intersection =
+            gst_caps_intersect_full (peercaps, templ_caps,
+            GST_CAPS_INTERSECT_FIRST);
+        GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
+            intersection);
+        gst_caps_unref (peercaps);
+        gst_caps_unref (templ_caps);
+        peercaps = intersection;
 
-    GST_DEBUG_OBJECT (trans,
-        "filtering against peer yields %" GST_PTR_FORMAT, othercaps);
-  }
+        GST_DEBUG_OBJECT (trans,
+            "Intersecting with transformed caps %" GST_PTR_FORMAT, othercaps);
+        intersection =
+            gst_caps_intersect_full (peercaps, othercaps,
+            GST_CAPS_INTERSECT_FIRST);
+        GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
+            intersection);
+        gst_caps_unref (peercaps);
+        gst_caps_unref (othercaps);
+        othercaps = intersection;
+      } else {
+        othercaps = peercaps;
+      }
 
+      is_fixed = gst_caps_is_fixed (othercaps);
+    } else {
+      GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
+      gst_caps_unref (othercaps);
+      othercaps = gst_caps_ref (caps);
+      is_fixed = TRUE;
+    }
+  }
   if (gst_caps_is_empty (othercaps))
     goto no_transform_possible;
 
-  /* third attempt at fixation, call the fixate vmethod and
-   * ultimately call the pad fixate function. */
-  if (!is_fixed) {
-    GST_DEBUG_OBJECT (trans,
-        "trying to fixate %" GST_PTR_FORMAT " on pad %s:%s",
-        othercaps, GST_DEBUG_PAD_NAME (otherpad));
-
-    /* since we have no other way to fixate left, we might as well just take
-     * the first of the caps list and fixate that */
-
-    /* FIXME: when fixating using the vmethod, it might make sense to fixate
-     * each of the caps; but Wim doesn't see a use case for that yet */
-    gst_caps_truncate (othercaps);
-    peer_checked = FALSE;
-
-    if (klass->fixate_caps) {
-      GST_DEBUG_OBJECT (trans, "trying to fixate %" GST_PTR_FORMAT
-          " using caps %" GST_PTR_FORMAT
-          " on pad %s:%s using fixate_caps vmethod", othercaps, caps,
-          GST_DEBUG_PAD_NAME (otherpad));
-      klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
-      is_fixed = gst_caps_is_fixed (othercaps);
-    }
-    /* if still not fixed, no other option but to let the default pad fixate
-     * function do its job */
-    if (!is_fixed) {
-      GST_DEBUG_OBJECT (trans, "trying to fixate %" GST_PTR_FORMAT
-          " on pad %s:%s using gst_pad_fixate_caps", othercaps,
-          GST_DEBUG_PAD_NAME (otherpad));
-      gst_pad_fixate_caps (otherpad, othercaps);
-      is_fixed = gst_caps_is_fixed (othercaps);
-    }
-    GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
-  } else {
-    GST_DEBUG ("caps are fixed");
-    /* else caps are fixed but the subclass may want to add fields */
-    if (klass->fixate_caps) {
-      othercaps = gst_caps_make_writable (othercaps);
+  GST_DEBUG ("have %sfixed caps %" GST_PTR_FORMAT, (is_fixed ? "" : "non-"),
+      othercaps);
 
-      GST_DEBUG_OBJECT (trans, "doing fixate %" GST_PTR_FORMAT
-          " using caps %" GST_PTR_FORMAT
-          " on pad %s:%s using fixate_caps vmethod", othercaps, caps,
-          GST_DEBUG_PAD_NAME (otherpad));
+  /* second attempt at fixation, call the fixate vmethod */
+  /* caps could be fixed but the subclass may want to add fields */
+  if (klass->fixate_caps) {
+    othercaps = gst_caps_make_writable (othercaps);
 
-      klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
-      is_fixed = gst_caps_is_fixed (othercaps);
-    }
+    GST_DEBUG_OBJECT (trans, "calling faxate_caps for %" GST_PTR_FORMAT
+        " using caps %" GST_PTR_FORMAT " on pad %s:%s", othercaps, caps,
+        GST_DEBUG_PAD_NAME (otherpad));
+    /* note that we pass the complete array of structures to the fixate
+     * function, it needs to truncate itself */
+    klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
+    is_fixed = gst_caps_is_fixed (othercaps);
+    GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
   }
 
   /* caps should be fixed now, if not we have to fail. */
   if (!is_fixed)
     goto could_not_fixate;
 
-  /* and peer should accept, don't check again if we already checked the
-   * othercaps against the peer. */
-  if (!peer_checked && otherpeer && !gst_pad_accept_caps (otherpeer, othercaps))
+  /* and peer should accept */
+  if (otherpeer && !gst_pad_query_accept_caps (otherpeer, othercaps))
     goto peer_no_accept;
 
   GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
@@ -1145,19 +1136,19 @@ 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_get_caps_reffed (trans->srcpad);
+      allowed = gst_pad_query_caps (trans->srcpad, NULL);
     else
-      allowed = gst_pad_get_caps_reffed (trans->sinkpad);
+      allowed = gst_pad_query_caps (trans->sinkpad, NULL);
 
     if (!allowed) {
-      GST_DEBUG_OBJECT (trans, "gst_pad_get_caps() failed");
+      GST_DEBUG_OBJECT (trans, "gst_pad_query_caps() failed");
       goto no_transform_possible;
     }
 
     GST_DEBUG_OBJECT (trans, "allowed caps %" GST_PTR_FORMAT, allowed);
 
     /* intersect with the requested format */
-    ret = gst_caps_can_intersect (allowed, caps);
+    ret = gst_caps_is_subset (caps, allowed);
     gst_caps_unref (allowed);
 
     if (!ret)
@@ -1169,7 +1160,7 @@ gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
 
     /* find best possible caps for the other pad as a way to see if we can
      * transform this caps. */
-    othercaps = gst_base_transform_find_transform (trans, pad, caps);
+    othercaps = gst_base_transform_find_transform (trans, pad, caps, FALSE);
     if (!othercaps || gst_caps_is_empty (othercaps))
       goto no_transform_possible;
 
@@ -1197,24 +1188,6 @@ no_transform_possible:
   }
 }
 
-static gboolean
-gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps)
-{
-  gboolean ret = TRUE;
-  GstBaseTransform *trans;
-  GstBaseTransformClass *bclass;
-
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
-  if (bclass->accept_caps)
-    ret = bclass->accept_caps (trans, GST_PAD_DIRECTION (pad), caps);
-
-  gst_object_unref (trans);
-
-  return ret;
-}
-
 /* called when new caps arrive on the sink or source pad,
  * We try to find the best caps for the other side using our _find_transform()
  * function. If there are caps, we configure the transform for this new
@@ -1224,24 +1197,17 @@ gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps)
  * because we never set caps starting from the srcpad.
  */
 static gboolean
-gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
+gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad,
+    GstCaps * caps)
 {
-  GstBaseTransform *trans;
   GstPad *otherpad, *otherpeer;
   GstCaps *othercaps = NULL;
   gboolean ret = TRUE;
   GstCaps *incaps, *outcaps;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
   otherpeer = gst_pad_get_peer (otherpad);
 
-  /* if we get called recursively, we bail out now to avoid an
-   * infinite loop. */
-  if (GST_PAD_IS_IN_SETCAPS (otherpad))
-    goto done;
-
   GST_DEBUG_OBJECT (pad, "have new caps %p %" GST_PTR_FORMAT, caps, caps);
 
   /* find best possible caps for the other pad */
@@ -1270,21 +1236,29 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
   if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
     goto failed_configure;
 
+  GST_OBJECT_LOCK (trans->sinkpad);
+  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_FLAG_NEED_RECONFIGURE);
+  trans->priv->reconfigure = FALSE;
+  GST_OBJECT_UNLOCK (trans->sinkpad);
+
   /* we know this will work, we implement the setcaps */
-  gst_pad_set_caps (otherpad, othercaps);
+  gst_pad_push_event (otherpad, gst_event_new_caps (othercaps));
 
-  if (pad == trans->srcpad && trans->priv->pad_mode == GST_ACTIVATE_PULL) {
+  if (pad == trans->srcpad && trans->priv->pad_mode == GST_PAD_MODE_PULL) {
     /* FIXME hm? */
-    ret &= gst_pad_set_caps (otherpeer, othercaps);
+    ret &= gst_pad_push_event (otherpeer, gst_event_new_caps (othercaps));
     if (!ret) {
       GST_INFO_OBJECT (trans, "otherpeer setcaps(%" GST_PTR_FORMAT ") failed",
           othercaps);
     }
   }
 
+  if (ret) {
+    /* try to get a pool when needed */
+    ret = gst_base_transform_do_bufferpool (trans, othercaps);
+  }
+
 done:
-  /* new caps, force alloc on next buffer on the chain */
-  trans->priv->force_alloc = TRUE;
   if (otherpeer)
     gst_object_unref (otherpeer);
   if (othercaps)
@@ -1292,8 +1266,6 @@ done:
 
   trans->negotiated = ret;
 
-  gst_object_unref (trans);
-
   return ret;
 
   /* ERRORS */
@@ -1319,12 +1291,48 @@ gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query)
 {
   gboolean ret = FALSE;
-  GstPad *otherpad;
+  GstPad *pad, *otherpad;
+  GstBaseTransformClass *klass;
+
+  if (direction == GST_PAD_SRC) {
+    pad = trans->srcpad;
+    otherpad = trans->sinkpad;
+  } else {
+    pad = trans->sinkpad;
+    otherpad = trans->srcpad;
+  }
 
-  otherpad = (direction == GST_PAD_SRC) ? trans->sinkpad : trans->srcpad;
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:{
+    case GST_QUERY_ALLOCATION:
+    {
+      gboolean passthrough;
+
+      /* can only be done on the sinkpad */
+      if (direction != GST_PAD_SINK)
+        goto done;
+
+      GST_BASE_TRANSFORM_LOCK (trans);
+      passthrough = trans->passthrough;
+      GST_BASE_TRANSFORM_UNLOCK (trans);
+
+      GST_DEBUG_OBJECT (trans, "propose allocation values");
+      /* pass the query to the propose_allocation vmethod if any */
+      if (G_LIKELY (klass->propose_allocation)) {
+        ret = klass->propose_allocation (trans, query);
+      } else if (passthrough) {
+        GST_DEBUG_OBJECT (trans, "doing passthrough query");
+        ret = gst_pad_peer_query (otherpad, query);
+      } else {
+        ret = FALSE;
+      }
+      GST_DEBUG_OBJECT (trans, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret,
+          query);
+      break;
+    }
+    case GST_QUERY_POSITION:
+    {
       GstFormat format;
 
       gst_query_parse_position (query, &format, NULL);
@@ -1333,13 +1341,13 @@ gst_base_transform_default_query (GstBaseTransform * trans,
         ret = TRUE;
 
         if ((direction == GST_PAD_SINK)
-            || (trans->priv->last_stop_out == GST_CLOCK_TIME_NONE)) {
+            || (trans->priv->position_out == GST_CLOCK_TIME_NONE)) {
           pos =
               gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
-              trans->segment.last_stop);
+              trans->segment.position);
         } else {
           pos = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
-              trans->priv->last_stop_out);
+              trans->priv->position_out);
         }
         gst_query_set_position (query, format, pos);
       } else {
@@ -1347,413 +1355,161 @@ gst_base_transform_default_query (GstBaseTransform * trans,
       }
       break;
     }
+    case GST_QUERY_ACCEPT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_query_parse_accept_caps (query, &caps);
+      if (klass->accept_caps) {
+        ret = klass->accept_caps (trans, direction, caps);
+        gst_query_set_accept_caps_result (query, ret);
+        /* return TRUE, we answered the query */
+        ret = TRUE;
+      }
+      break;
+    }
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter, *caps;
+
+      gst_query_parse_caps (query, &filter);
+      caps = gst_base_transform_query_caps (trans, pad, filter);
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      ret = TRUE;
+      break;
+    }
     default:
       ret = gst_pad_peer_query (otherpad, query);
       break;
   }
 
+done:
   return ret;
 }
 
 static gboolean
-gst_base_transform_query (GstPad * pad, GstQuery * query)
+gst_base_transform_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
-  gboolean ret;
-
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL))
-    return FALSE;
-
-  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
-  if (bclass->query)
-    ret = bclass->query (trans, GST_PAD_DIRECTION (pad), query);
-  else
-    ret = gst_pad_query_default (pad, query);
-
-  gst_object_unref (trans);
-
-  return ret;
-}
-
-static const GstQueryType *
-gst_base_transform_query_type (GstPad * pad)
-{
-  static const GstQueryType types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_NONE
-  };
-
-  return types;
-}
-
-static void
-compute_upstream_suggestion (GstBaseTransform * trans, guint expsize,
-    GstCaps * caps)
-{
-  GstCaps *othercaps;
-  GstBaseTransformPrivate *priv = trans->priv;
-
-  GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
-
-  /* we cannot convert the current buffer but we might be able to suggest a
-   * new format upstream, try to find what the best format is. */
-  othercaps = gst_base_transform_find_transform (trans, trans->srcpad, caps);
-
-  if (!othercaps) {
-    GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
-    /* we received caps that we cannot transform. Upstream is behaving badly
-     * because it should have checked if we could handle these caps. We can
-     * simply ignore these caps and produce a buffer with our original caps. */
-  } else {
-    guint size_suggest;
-
-    GST_DEBUG_OBJECT (trans, "getting size of suggestion");
-
-    /* not a subset, we have a new upstream suggestion, remember it and
-     * allocate a default buffer. First we try to convert the size */
-    if (gst_base_transform_transform_size (trans,
-            GST_PAD_SRC, caps, expsize, othercaps, &size_suggest)) {
-
-      /* ok, remember the suggestions now */
-      GST_DEBUG_OBJECT (trans,
-          "storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
-          size_suggest, othercaps);
-
-      GST_OBJECT_LOCK (trans->sinkpad);
-      if (priv->sink_suggest)
-        gst_caps_unref (priv->sink_suggest);
-      priv->sink_suggest = gst_caps_ref (othercaps);
-      priv->size_suggest = size_suggest;
-      trans->priv->suggest_pending = TRUE;
-      GST_OBJECT_UNLOCK (trans->sinkpad);
-    }
-    gst_caps_unref (othercaps);
-  }
-}
-
-/* Allocate a buffer using gst_pad_alloc_buffer
- *
- * This function can do renegotiation on the source pad
- *
- * The output buffer is always writable. outbuf can be equal to
- * inbuf, the caller should be prepared for this and perform
- * appropriate refcounting.
- */
-static GstFlowReturn
-gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
-    GstBuffer * in_buf, GstBuffer ** out_buf)
-{
-  GstBaseTransformClass *bclass;
-  GstBaseTransformPrivate *priv;
-  GstFlowReturn ret = GST_FLOW_OK;
-  guint outsize, newsize, expsize;
-  gboolean discard, setcaps, copymeta;
-  GstCaps *incaps, *oldcaps, *newcaps, *outcaps;
-
-  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-
-  priv = trans->priv;
-
-  *out_buf = NULL;
-
-  /* figure out how to allocate a buffer based on the current configuration */
-  if (trans->passthrough) {
-    GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
-    /* passthrough, we don't really need to call pad alloc but we still need to
-     * in order to get upstream negotiation. The output size is the same as the
-     * input size. */
-    outsize = GST_BUFFER_SIZE (in_buf);
-    /* we always alloc and discard here */
-    discard = TRUE;
-  } else {
-    gboolean want_in_place = (bclass->transform_ip != NULL)
-        && trans->always_in_place;
-
-    if (want_in_place) {
-      GST_DEBUG_OBJECT (trans, "doing inplace alloc");
-      /* we alloc a buffer of the same size as the input */
-      outsize = GST_BUFFER_SIZE (in_buf);
-      /* only discard it when the input was not writable, otherwise, we reuse
-       * the input buffer. */
-      discard = gst_buffer_is_writable (in_buf);
-      GST_DEBUG_OBJECT (trans, "discard: %d", discard);
-    } else {
-      GST_DEBUG_OBJECT (trans, "getting output size for copy transform");
-      /* copy transform, figure out the output size */
-      if (!gst_base_transform_transform_size (trans,
-              GST_PAD_SINK, GST_PAD_CAPS (trans->sinkpad),
-              GST_BUFFER_SIZE (in_buf), GST_PAD_CAPS (trans->srcpad),
-              &outsize)) {
-        goto unknown_size;
-      }
-      /* never discard this buffer, we need it for storing the output */
-      discard = FALSE;
-    }
-  }
-
-  oldcaps = GST_PAD_CAPS (trans->srcpad);
-
-  if (bclass->prepare_output_buffer) {
-    GST_DEBUG_OBJECT (trans,
-        "calling prepare buffer with caps %p %" GST_PTR_FORMAT, oldcaps,
-        oldcaps);
-    ret =
-        bclass->prepare_output_buffer (trans, in_buf, outsize, oldcaps,
-        out_buf);
-
-    /* get a new ref to the srcpad caps, the prepare_output_buffer function can
-     * update the pad caps if it wants */
-    oldcaps = GST_PAD_CAPS (trans->srcpad);
-
-    /* FIXME 0.11:
-     * decrease refcount again if vmethod returned refcounted in_buf. This
-     * is because we need to make sure that the buffer is writable for the
-     * in_place transform. The docs of the vmethod say that you should return
-     * a reffed inbuf, which is exactly what we don't want :), oh well.. */
-    if (in_buf == *out_buf)
-      gst_buffer_unref (in_buf);
-
-    /* never discard the buffer from the prepare_buffer method */
-    if (*out_buf != NULL)
-      discard = FALSE;
-  }
-
-  if (ret != GST_FLOW_OK)
-    goto alloc_failed;
-
-  if (*out_buf == NULL) {
-    if (trans->passthrough && !trans->priv->force_alloc) {
-      GST_DEBUG_OBJECT (trans, "Avoiding pad alloc");
-      *out_buf = gst_buffer_ref (in_buf);
-    } else {
-      GST_DEBUG_OBJECT (trans, "doing alloc with caps %" GST_PTR_FORMAT,
-          oldcaps);
-
-      ret = gst_pad_alloc_buffer (trans->srcpad,
-          GST_BUFFER_OFFSET (in_buf), outsize, oldcaps, out_buf);
-      if (ret != GST_FLOW_OK)
-        goto alloc_failed;
-    }
-  }
-
-  /* must always have a buffer by now */
-  if (*out_buf == NULL)
-    goto no_buffer;
+  gboolean ret = FALSE;
 
-  /* check if we got different caps on this new output buffer */
-  newcaps = GST_BUFFER_CAPS (*out_buf);
-  newsize = GST_BUFFER_SIZE (*out_buf);
+  trans = GST_BASE_TRANSFORM (parent);
+  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) {
-    GstCaps *othercaps;
-    gboolean can_convert;
+  if (bclass->query)
+    ret = bclass->query (trans, GST_PAD_DIRECTION (pad), query);
 
-    GST_DEBUG_OBJECT (trans, "received new caps %" GST_PTR_FORMAT, newcaps);
+  return ret;
+}
 
-    incaps = GST_PAD_CAPS (trans->sinkpad);
+/* this function either returns the input buffer without incrementing the
+ * refcount or it allocates a new (writable) buffer */
+static GstFlowReturn
+default_prepare_output_buffer (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer ** outbuf)
+{
+  GstBaseTransformPrivate *priv;
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstBaseTransformClass *bclass;
 
-    /* check if we can convert the current incaps to the new target caps */
-    can_convert =
-        gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
-        newcaps);
+  priv = trans->priv;
+  bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-    if (!can_convert) {
-      GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
+  /* figure out how to allocate an output buffer */
+  if (trans->passthrough) {
+    /* passthrough, we will not modify the incomming buffer so we can just
+     * reuse it */
+    GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer");
+    *outbuf = inbuf;
+  } else {
+    /* we can't reuse the input buffer */
+    if (priv->pool) {
+      GST_DEBUG_OBJECT (trans, "using pool alloc");
+      ret = gst_buffer_pool_acquire_buffer (priv->pool, outbuf, NULL);
+    } else {
+      gsize insize, outsize;
+      gboolean res;
 
-      gst_base_transform_transform_size (trans,
-          GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
+      /* no pool, we need to figure out the size of the output buffer first */
+      insize = gst_buffer_get_size (inbuf);
 
-      compute_upstream_suggestion (trans, expsize, newcaps);
+      if (trans->passthrough) {
+        GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
+        /* passthrough, the output size is the same as the input size. */
+        outsize = insize;
+      } else {
+        gboolean want_in_place = (bclass->transform_ip != NULL)
+            && trans->always_in_place;
 
-      /* we got a suggested caps but we can't transform to it. See if there is
-       * another downstream format that we can transform to */
-      othercaps =
-          gst_base_transform_find_transform (trans, trans->sinkpad, incaps);
+        if (want_in_place) {
+          GST_DEBUG_OBJECT (trans, "doing inplace alloc");
+          /* we alloc a buffer of the same size as the input */
+          outsize = insize;
+        } else {
+          GstCaps *incaps, *outcaps;
 
-      if (othercaps && !gst_caps_is_empty (othercaps)) {
-        GST_DEBUG_OBJECT (trans, "we found target caps %" GST_PTR_FORMAT,
-            othercaps);
-        *out_buf = gst_buffer_make_metadata_writable (*out_buf);
-        gst_buffer_set_caps (*out_buf, othercaps);
-        gst_caps_unref (othercaps);
-        newcaps = GST_BUFFER_CAPS (*out_buf);
-        can_convert = TRUE;
-      } else if (othercaps)
-        gst_caps_unref (othercaps);
-    }
+          /* else use the transform function to get the size */
+          incaps = gst_pad_get_current_caps (trans->sinkpad);
+          outcaps = gst_pad_get_current_caps (trans->srcpad);
 
-    /* it's possible that the buffer we got is of the wrong size, get the
-     * expected size here, we will check the size if we are going to use the
-     * buffer later on. */
-    gst_base_transform_transform_size (trans,
-        GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
-
-    if (can_convert) {
-      GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
-
-      /* subclass might want to add fields to the caps */
-      if (bclass->fixate_caps != NULL) {
-        newcaps = gst_caps_copy (newcaps);
-
-        GST_DEBUG_OBJECT (trans, "doing fixate %" GST_PTR_FORMAT
-            " using caps %" GST_PTR_FORMAT
-            " on pad %s:%s using fixate_caps vmethod", newcaps, incaps,
-            GST_DEBUG_PAD_NAME (trans->srcpad));
-        bclass->fixate_caps (trans, GST_PAD_SINK, incaps, newcaps);
-
-        *out_buf = gst_buffer_make_metadata_writable (*out_buf);
-        gst_buffer_set_caps (*out_buf, newcaps);
-        gst_caps_unref (newcaps);
-        newcaps = GST_BUFFER_CAPS (*out_buf);
-      }
+          GST_DEBUG_OBJECT (trans, "getting output size for alloc");
+          /* copy transform, figure out the output size */
+          res = gst_base_transform_transform_size (trans,
+              GST_PAD_SINK, incaps, insize, outcaps, &outsize);
 
-      /* caps not empty, try to renegotiate to the new format */
-      if (!gst_base_transform_configure_caps (trans, incaps, newcaps)) {
-        /* not sure we need to fail hard here, we can simply continue our
-         * conversion with what we negotiated before */
-        goto failed_configure;
-      }
-      /* new format configure, and use the new output buffer */
-      gst_pad_set_caps (trans->srcpad, newcaps);
-      discard = FALSE;
-      /* clear previous cached sink-pad caps, so buffer_alloc knows that
-       * it needs to revisit the decision about whether to proxy or not: */
-      gst_caps_replace (&priv->sink_alloc, NULL);
-      /* if we got a buffer of the wrong size, discard it now and make sure we
-       * allocate a properly sized buffer later. */
-      if (newsize != expsize) {
-        if (in_buf != *out_buf)
-          gst_buffer_unref (*out_buf);
-        *out_buf = NULL;
-      }
-      outsize = expsize;
-    } else {
-      compute_upstream_suggestion (trans, expsize, newcaps);
+          gst_caps_unref (incaps);
+          gst_caps_unref (outcaps);
 
-      if (in_buf != *out_buf)
-        gst_buffer_unref (*out_buf);
-      *out_buf = NULL;
-    }
-  } else if (outsize != newsize) {
-    GST_WARNING_OBJECT (trans, "Caps did not change but allocated size does "
-        "not match expected size (%d != %d)", newsize, outsize);
-    if (in_buf != *out_buf)
-      gst_buffer_unref (*out_buf);
-    *out_buf = NULL;
-  }
-
-  /* these are the final output caps */
-  outcaps = GST_PAD_CAPS (trans->srcpad);
-
-  copymeta = FALSE;
-  if (*out_buf == NULL) {
-    if (!discard) {
-      GST_DEBUG_OBJECT (trans, "make default output buffer of size %d",
-          outsize);
-      /* no valid buffer yet, make one, metadata is writable */
-      *out_buf = gst_buffer_new_and_alloc (outsize);
-      gst_buffer_copy_metadata (*out_buf, in_buf,
-          GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
-    } else {
-      GST_DEBUG_OBJECT (trans, "reuse input buffer");
-      *out_buf = in_buf;
-    }
-  } else {
-    if (trans->passthrough && in_buf != *out_buf) {
-      /* we are asked to perform a passthrough transform but the input and
-       * output buffers are different. We have to discard the output buffer and
-       * reuse the input buffer. */
-      GST_DEBUG_OBJECT (trans, "passthrough but different buffers");
-      discard = TRUE;
-    }
-    if (discard) {
-      GST_DEBUG_OBJECT (trans, "discard buffer, reuse input buffer");
-      gst_buffer_unref (*out_buf);
-      *out_buf = in_buf;
-    } else {
-      GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", in_buf,
-          *out_buf);
-      /* if we have different buffers, check if the metadata is ok */
-      if (*out_buf != in_buf) {
-        guint mask;
-
-        mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
-            GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
-            GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
-            GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
-        /* see if the flags and timestamps match */
-        copymeta =
-            (GST_MINI_OBJECT_FLAGS (*out_buf) & mask) ==
-            (GST_MINI_OBJECT_FLAGS (in_buf) & mask);
-        copymeta |=
-            GST_BUFFER_TIMESTAMP (*out_buf) != GST_BUFFER_TIMESTAMP (in_buf) ||
-            GST_BUFFER_DURATION (*out_buf) != GST_BUFFER_DURATION (in_buf) ||
-            GST_BUFFER_OFFSET (*out_buf) != GST_BUFFER_OFFSET (in_buf) ||
-            GST_BUFFER_OFFSET_END (*out_buf) != GST_BUFFER_OFFSET_END (in_buf);
+          if (!res)
+            goto unknown_size;
+        }
       }
+      GST_DEBUG_OBJECT (trans, "doing alloc of size %" G_GSIZE_FORMAT, outsize);
+      *outbuf =
+          gst_buffer_new_allocate (priv->allocator, outsize, priv->alignment);
     }
   }
-
-  /* check if we need to make things writable. We need this when we need to
-   * update the caps or the metadata on the output buffer. */
-  newcaps = GST_BUFFER_CAPS (*out_buf);
-  /* we check the pointers as a quick check and then go to the more involved
-   * check. This is needed when we receive different pointers on the sinkpad
-   * that mean the same caps. What we then want to do is prefer those caps over
-   * the ones on the srcpad and set the srcpad caps to the buffer caps */
-  setcaps = !newcaps || ((newcaps != outcaps)
-      && (!gst_caps_is_equal (newcaps, outcaps)));
-  /* we need to modify the metadata when the element is not gap aware,
-   * passthrough is not used and the gap flag is set */
-  copymeta |= !trans->priv->gap_aware && !trans->passthrough
-      && (GST_MINI_OBJECT_FLAGS (*out_buf) & GST_BUFFER_FLAG_GAP);
-
-  if (setcaps || copymeta) {
-    GST_DEBUG_OBJECT (trans, "setcaps %d, copymeta %d", setcaps, copymeta);
-    if (!gst_buffer_is_metadata_writable (*out_buf)) {
-      GST_DEBUG_OBJECT (trans, "buffer metadata %p not writable", *out_buf);
-      if (in_buf == *out_buf)
-        *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf));
-      else
-        *out_buf = gst_buffer_make_metadata_writable (*out_buf);
-    }
-    /* when we get here, the metadata should be writable */
-    if (setcaps)
-      gst_buffer_set_caps (*out_buf, outcaps);
-    if (copymeta)
-      gst_buffer_copy_metadata (*out_buf, in_buf,
-          GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
-    /* clear the GAP flag when the subclass does not understand it */
-    if (!trans->priv->gap_aware)
-      GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
-  }
-
   return ret;
 
   /* ERRORS */
-alloc_failed:
-  {
-    GST_WARNING_OBJECT (trans, "pad-alloc failed: %s", gst_flow_get_name (ret));
-    return ret;
-  }
-no_buffer:
-  {
-    GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
-        ("Sub-class failed to provide an output buffer"), (NULL));
-    return GST_FLOW_ERROR;
-  }
 unknown_size:
   {
     GST_ERROR_OBJECT (trans, "unknown output size");
     return GST_FLOW_ERROR;
   }
-failed_configure:
+}
+
+static gboolean
+default_copy_metadata (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf)
+{
+  GstBaseTransformPrivate *priv = trans->priv;
+
+  /* now copy the metadata */
+  GST_DEBUG_OBJECT (trans, "copying metadata");
+
+  /* this should not happen, buffers allocated from a pool or with
+   * new_allocate should always be writable. */
+  if (!gst_buffer_is_writable (outbuf))
+    goto not_writable;
+
+  /* when we get here, the metadata should be writable */
+  gst_buffer_copy_into (outbuf, inbuf,
+      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
+
+  /* clear the GAP flag when the subclass does not understand it */
+  if (!priv->gap_aware)
+    GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
+
+  return TRUE;
+
+  /* ERRORS */
+not_writable:
   {
-    GST_WARNING_OBJECT (trans, "failed to configure caps");
-    return GST_FLOW_NOT_NEGOTIATED;
+    GST_WARNING_OBJECT (trans, "buffer %p not writable", outbuf);
+    return FALSE;
   }
 }
 
@@ -1772,7 +1528,7 @@ failed_configure:
  */
 static gboolean
 gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
-    guint * size)
+    gsize * size)
 {
   gboolean res = FALSE;
   GstBaseTransformClass *bclass;
@@ -1780,482 +1536,66 @@ gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
   /* see if we have the result cached */
   if (trans->cache_caps1 == caps) {
     *size = trans->cache_caps1_size;
-    GST_DEBUG_OBJECT (trans, "returned %d from first cache", *size);
+    GST_DEBUG_OBJECT (trans,
+        "returned %" G_GSIZE_FORMAT " from first cache", *size);
     return TRUE;
   }
   if (trans->cache_caps2 == caps) {
     *size = trans->cache_caps2_size;
-    GST_DEBUG_OBJECT (trans, "returned %d from second cached", *size);
+    GST_DEBUG_OBJECT (trans,
+        "returned %" G_GSIZE_FORMAT " from second cached", *size);
     return TRUE;
   }
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-  if (bclass->get_unit_size) {
-    res = bclass->get_unit_size (trans, caps, size);
-    GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
-        ") has unit size %d, result %s", caps, *size, res ? "TRUE" : "FALSE");
-
-    if (res) {
-      /* and cache the values */
-      if (trans->cache_caps1 == NULL) {
-        gst_caps_replace (&trans->cache_caps1, caps);
-        trans->cache_caps1_size = *size;
-        GST_DEBUG_OBJECT (trans, "caching %d in first cache", *size);
-      } else if (trans->cache_caps2 == NULL) {
-        gst_caps_replace (&trans->cache_caps2, caps);
-        trans->cache_caps2_size = *size;
-        GST_DEBUG_OBJECT (trans, "caching %d in second cache", *size);
-      } else {
-        GST_DEBUG_OBJECT (trans, "no free spot to cache unit_size");
-      }
-    }
-  } else {
-    GST_DEBUG_OBJECT (trans, "Sub-class does not implement get_unit_size");
-  }
-  return res;
-}
-
-/* your upstream peer wants to send you a buffer
- * that buffer has the given offset, size and caps
- * you're requested to allocate a buffer
- */
-static GstFlowReturn
-gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstBaseTransform *trans;
-  GstBaseTransformPrivate *priv;
-  GstFlowReturn res;
-  gboolean alloced = FALSE;
-  gboolean proxy, suggest, new_caps;
-  GstCaps *sink_suggest = NULL;
-  guint size_suggest;
-
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL))
-    return GST_FLOW_WRONG_STATE;
-  priv = trans->priv;
-
-  GST_DEBUG_OBJECT (pad, "alloc with caps %p %" GST_PTR_FORMAT ", size %u",
-      caps, caps, size);
-
-  /* if the code below does not come up with a better buffer, we will return _OK
-   * and an empty buffer. This will trigger the core to allocate a buffer with
-   * given input size and caps. */
-  *buf = NULL;
-  res = GST_FLOW_OK;
-
-  /* we remember our previous alloc request to quickly see if we can proxy or
-   * not. We skip this check if we have a pending suggestion. */
-  GST_OBJECT_LOCK (pad);
-  suggest = priv->suggest_pending;
-  GST_OBJECT_UNLOCK (pad);
-
-  if (!suggest) {
-    /* we have no suggestion, see below if we need to proxy */
-    gst_caps_replace (&sink_suggest, caps);
-    size_suggest = size;
-    suggest = FALSE;
-    new_caps = sink_suggest
-        && !gst_caps_is_equal (sink_suggest, priv->sink_alloc);
-
-    if (new_caps)
-      GST_DEBUG_OBJECT (trans, "new format %p %" GST_PTR_FORMAT, caps, caps);
-    else
-      GST_DEBUG_OBJECT (trans, "have old caps %p, size %u", caps, size);
-  } else {
-    /* if we have a suggestion, pretend we got these as input */
-    GST_OBJECT_LOCK (pad);
-    if (priv->sink_suggest &&
-        !gst_caps_can_intersect (caps, priv->sink_suggest)) {
-      sink_suggest = gst_caps_ref (priv->sink_suggest);
-      size_suggest = priv->size_suggest;
-      GST_DEBUG_OBJECT (trans, "have suggestion %p %" GST_PTR_FORMAT " size %u",
-          sink_suggest, sink_suggest, priv->size_suggest);
-    } else {
-      GST_DEBUG_OBJECT (trans,
-          "have suggestion equal to upstream caps %p %" GST_PTR_FORMAT, caps,
-          caps);
-      gst_caps_replace (&sink_suggest, caps);
-      size_suggest = size;
-      suggest = FALSE;
-    }
-    priv->suggest_pending = FALSE;
-    GST_OBJECT_UNLOCK (pad);
-
-    /* check if we actually handle this format on the sinkpad */
-    if (suggest) {
-      GstCaps *peercaps;
-
-      /* Always intersect with the peer caps to get correct
-       * and complete caps. The suggested caps could be incomplete,
-       * for example video/x-raw-yuv without any fields at all.
-       */
-      peercaps =
-          gst_pad_peer_get_caps_reffed (GST_BASE_TRANSFORM_SINK_PAD (trans));
-
-      if (peercaps) {
-        GstCaps *intersect;
-
-        intersect =
-            gst_caps_intersect_full (sink_suggest, peercaps,
-            GST_CAPS_INTERSECT_FIRST);
-        gst_caps_unref (peercaps);
-
-        /* If intersected caps is empty then just keep them empty. The
-         * code below will try to come up with possible caps if there
-         * are any */
-        gst_caps_unref (sink_suggest);
-        sink_suggest = intersect;
-      }
-
-      /* If the suggested caps are not empty and not fixed, try to fixate them */
-      if (!gst_caps_is_fixed (sink_suggest)
-          && !gst_caps_is_empty (sink_suggest)) {
-        GST_DEBUG_OBJECT (trans,
-            "Suggested caps is not fixed: %" GST_PTR_FORMAT, sink_suggest);
-
-        /* try the alloc caps if it is still not fixed */
-        if (!gst_caps_is_fixed (sink_suggest)) {
-          GstCaps *intersect;
-
-          GST_DEBUG_OBJECT (trans, "Checking if the input caps is compatible "
-              "with the non-fixed caps suggestion");
-          intersect =
-              gst_caps_intersect_full (sink_suggest, caps,
-              GST_CAPS_INTERSECT_FIRST);
-          if (!gst_caps_is_empty (intersect)) {
-            GST_DEBUG_OBJECT (trans, "It is, using it");
-            gst_caps_replace (&sink_suggest, caps);
-          }
-          gst_caps_unref (intersect);
-        }
-
-        /* be safe and call default fixate */
-        sink_suggest = gst_caps_make_writable (sink_suggest);
-        gst_pad_fixate_caps (GST_BASE_TRANSFORM_SINK_PAD (trans), sink_suggest);
-
-        if (!gst_caps_is_fixed (sink_suggest)) {
-          GST_DEBUG_OBJECT (trans,
-              "Impossible to fixate caps, using upstream caps");
-          gst_caps_replace (&sink_suggest, caps);
-          size_suggest = size;
-          suggest = FALSE;
-        }
-
-        GST_DEBUG_OBJECT (trans, "Caps fixed to: %" GST_PTR_FORMAT,
-            sink_suggest);
-      }
-    }
-
-    new_caps = sink_suggest
-        && !gst_caps_is_equal (sink_suggest, priv->sink_alloc);
-  }
-
-  /* Check if the new caps are compatible with our
-   * sinkpad template caps and if they're not
-   * we try to come up with any supported caps
-   */
-  if (new_caps) {
-    const GstCaps *templ;
-
-    templ = gst_pad_get_pad_template_caps (pad);
-
-    /* Fall back to the upstream caps if the suggested caps
-     * are not actually supported. Shouldn't really happen
-     */
-    if (suggest && !gst_caps_can_intersect (sink_suggest, templ)) {
+  res = bclass->get_unit_size (trans, caps, size);
+  GST_DEBUG_OBJECT (trans,
+      "caps %" GST_PTR_FORMAT ") has unit size %" G_GSIZE_FORMAT ", res %s",
+      caps, *size, res ? "TRUE" : "FALSE");
+
+  if (res) {
+    /* and cache the values */
+    if (trans->cache_caps1 == NULL) {
+      gst_caps_replace (&trans->cache_caps1, caps);
+      trans->cache_caps1_size = *size;
       GST_DEBUG_OBJECT (trans,
-          "Suggested caps not supported by sinkpad, using upstream caps");
-      gst_caps_replace (&sink_suggest, caps);
-      size_suggest = size;
-      suggest = FALSE;
-      new_caps = sink_suggest
-          && !gst_caps_is_equal (sink_suggest, priv->sink_alloc);
-    }
-
-    if (new_caps && (suggest || !gst_caps_can_intersect (sink_suggest, templ))) {
-      GstCaps *allowed, *peercaps;
-
+          "caching %" G_GSIZE_FORMAT " in first cache", *size);
+    } else if (trans->cache_caps2 == NULL) {
+      gst_caps_replace (&trans->cache_caps2, caps);
+      trans->cache_caps2_size = *size;
       GST_DEBUG_OBJECT (trans,
-          "Requested pad alloc caps are not supported: %" GST_PTR_FORMAT,
-          sink_suggest);
-      /* the requested pad alloc caps are not supported, so let's try
-       * picking something allowed between the pads (they are linked,
-       * there must be something) */
-      allowed = gst_pad_get_allowed_caps (pad);
-      if (allowed && !gst_caps_is_empty (allowed)) {
-        GST_DEBUG_OBJECT (trans,
-            "pads could agree on one of the following caps: " "%"
-            GST_PTR_FORMAT, allowed);
-
-        /* Check which caps would be possible with downstream */
-        peercaps =
-            gst_pad_get_allowed_caps (GST_BASE_TRANSFORM_SRC_PAD (trans));
-        if (peercaps) {
-          GstCaps *tmp, *intersect;
-
-          tmp =
-              gst_base_transform_transform_caps (trans, GST_PAD_SRC, peercaps);
-          gst_caps_unref (peercaps);
-          intersect = gst_caps_intersect (allowed, tmp);
-          gst_caps_unref (tmp);
-          gst_caps_unref (allowed);
-
-          if (gst_caps_is_empty (intersect)) {
-            gst_caps_unref (intersect);
-            goto not_supported;
-          }
-
-          allowed = intersect;
-        }
-
-        allowed = gst_caps_make_writable (allowed);
-
-        /* Fixate them to be safe if the subclass didn't do it */
-        gst_caps_truncate (allowed);
-        gst_pad_fixate_caps (pad, allowed);
-
-        if (!gst_caps_is_fixed (allowed)) {
-          GST_ERROR_OBJECT (trans, "Impossible to fixate any caps");
-          gst_caps_unref (allowed);
-          goto not_supported;
-        }
-
-        gst_caps_replace (&sink_suggest, allowed);
-        gst_caps_unref (allowed);
-
-        suggest = TRUE;
-        new_caps = !gst_caps_is_equal (sink_suggest, priv->sink_alloc);
-
-        GST_DEBUG_OBJECT (trans, "Calculated new suggestion caps %"
-            GST_PTR_FORMAT, sink_suggest);
-      } else {
-        if (allowed)
-          gst_caps_unref (allowed);
-        goto not_supported;
-      }
-    }
-  }
-
-  /* find the best format for the other side here we decide if we will proxy
-   * the caps or not. */
-  if (sink_suggest == NULL) {
-    /* always proxy when the caps are NULL. When this is a new format, see if
-     * we can proxy it downstream */
-    GST_DEBUG_OBJECT (trans, "null caps, marking for proxy");
-    priv->proxy_alloc = TRUE;
-  } else if (new_caps) {
-    GstCaps *othercaps;
-
-    /* we have a new format, see what we need to proxy to */
-    othercaps = gst_base_transform_find_transform (trans, pad, sink_suggest);
-    if (!othercaps || gst_caps_is_empty (othercaps)) {
-      /* no transform possible, we certainly can't proxy */
-      GST_DEBUG_OBJECT (trans, "can't find transform, disable proxy");
-      priv->proxy_alloc = FALSE;
-    } else {
-      /* we transformed into something */
-      if (gst_caps_is_equal (sink_suggest, othercaps)) {
-        GST_DEBUG_OBJECT (trans, "best caps same as input, marking for proxy");
-        priv->proxy_alloc = TRUE;
-      } else {
-        GST_DEBUG_OBJECT (trans,
-            "best caps different from input, disable proxy");
-        priv->proxy_alloc = FALSE;
-      }
-    }
-    if (othercaps)
-      gst_caps_unref (othercaps);
-  }
-
-  /* remember the new caps */
-  GST_OBJECT_LOCK (pad);
-  gst_caps_replace (&priv->sink_alloc, sink_suggest);
-  GST_OBJECT_UNLOCK (pad);
-
-  proxy = priv->proxy_alloc;
-  GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d, suggest %d", proxy,
-      suggest);
-
-  /* we only want to proxy if we have no suggestion pending, FIXME */
-  if (proxy && !suggest) {
-    GstCaps *newcaps;
-
-    GST_DEBUG_OBJECT (trans, "proxy buffer-alloc with caps %p %" GST_PTR_FORMAT
-        ", size %u", caps, caps, size);
-
-    /* we always proxy the input caps, never the suggestion. The reason is that
-     * We don't yet handle the caps of renegotiation in here. FIXME */
-    res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
-    if (res != GST_FLOW_OK)
-      goto alloc_failed;
-    alloced = TRUE;
-
-    /* check if the caps changed */
-    newcaps = GST_BUFFER_CAPS (*buf);
-
-    GST_DEBUG_OBJECT (trans, "got caps %" GST_PTR_FORMAT, newcaps);
-
-    if (!gst_caps_is_equal (newcaps, caps)) {
-      GST_DEBUG_OBJECT (trans, "caps are new");
-      /* we have new caps, see if we can proxy downstream */
-      if (gst_pad_peer_accept_caps (pad, newcaps)) {
-        /* peer accepts the caps, return a buffer in this format */
-        GST_DEBUG_OBJECT (trans, "peer accepted new caps");
-        /* remember the format */
-        GST_OBJECT_LOCK (pad);
-        gst_caps_replace (&priv->sink_alloc, newcaps);
-        GST_OBJECT_UNLOCK (pad);
-      } else {
-        GST_DEBUG_OBJECT (trans, "peer did not accept new caps");
-        /* peer does not accept the caps, disable proxy_alloc, free the
-         * buffer we received and create a buffer of the requested format
-         * by the default handler. */
-        GST_DEBUG_OBJECT (trans, "disabling proxy");
-        priv->proxy_alloc = FALSE;
-        gst_buffer_unref (*buf);
-        *buf = NULL;
-      }
+          "caching %" G_GSIZE_FORMAT " in second cache", *size);
     } else {
-      GST_DEBUG_OBJECT (trans, "received required caps from peer");
+      GST_DEBUG_OBJECT (trans, "no free spot to cache unit_size");
     }
-  } else if (suggest) {
-    /* there was a custom suggestion, create a buffer of this format and return
-     * it. Note that this format  */
-    *buf = gst_buffer_new_and_alloc (size_suggest);
-    GST_DEBUG_OBJECT (trans,
-        "doing suggestion of size %u, caps %p %" GST_PTR_FORMAT, size_suggest,
-        sink_suggest, sink_suggest);
-    GST_BUFFER_CAPS (*buf) = sink_suggest;
-    sink_suggest = NULL;
-  } else {
-    /* fallback buffer allocation by gst_pad_alloc_buffer() with the
-     * caps and size provided by the caller */
   }
-
-  if (sink_suggest)
-    gst_caps_unref (sink_suggest);
-
-  if (res == GST_FLOW_OK && alloced) {
-    /* just alloc'ed a buffer, so we only want to do this again if we
-     * received a buffer */
-    GST_DEBUG_OBJECT (trans, "Cleaning force alloc");
-    trans->priv->force_alloc = FALSE;
-  }
-
-  gst_object_unref (trans);
   return res;
-
-  /* ERRORS */
-alloc_failed:
-  {
-    GST_DEBUG_OBJECT (trans, "pad alloc failed: %s", gst_flow_get_name (res));
-    if (sink_suggest)
-      gst_caps_unref (sink_suggest);
-    gst_object_unref (trans);
-    return res;
-  }
-not_supported:
-  {
-    GST_DEBUG_OBJECT (trans, "pad alloc with unsupported caps");
-    if (sink_suggest)
-      gst_caps_unref (sink_suggest);
-    gst_object_unref (trans);
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-}
-
-static void
-gst_base_transform_send_delayed_events (GstBaseTransform * trans)
-{
-  GList *list, *tmp;
-
-  GST_OBJECT_LOCK (trans);
-  list = trans->priv->delayed_events;
-  trans->priv->delayed_events = NULL;
-  GST_OBJECT_UNLOCK (trans);
-  if (!list)
-    return;
-
-  for (tmp = list; tmp; tmp = tmp->next) {
-    GstEvent *ev = tmp->data;
-
-    GST_DEBUG_OBJECT (trans->srcpad, "Sending delayed event %s",
-        GST_EVENT_TYPE_NAME (ev));
-    gst_pad_push_event (trans->srcpad, ev);
-  }
-  g_list_free (list);
 }
 
 static gboolean
-gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
+gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
-  gboolean forward = TRUE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  trans = GST_BASE_TRANSFORM (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  if (bclass->event)
-    forward = bclass->event (trans, event);
-
-  /* FIXME, do this in the default event handler so the subclass can do
-   * something different. */
-  if (forward) {
-    gboolean delay, caps_set = (GST_PAD_CAPS (trans->srcpad) != NULL);
-
-    /* src caps may not yet be set, so we delay any serialized events
-       that we receive before (in particular newsegment events), except
-       EOS and flush stops, since those'll obsolete previous events */
-    if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
-      gst_base_transform_drop_delayed_events (trans);
-      delay = FALSE;
-    } else {
-      delay = GST_EVENT_IS_SERIALIZED (event) && !caps_set
-          && GST_EVENT_TYPE (event) != GST_EVENT_EOS;
-
-      /* do not stall sparse stream update newsegment events */
-      if (delay && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
-        gboolean update;
-
-        gst_event_parse_new_segment_full (event, &update, NULL, NULL, NULL,
-            NULL, NULL, NULL);
-        if (update) {
-          GST_DEBUG_OBJECT (trans, "update segment; triggering delayed events");
-          delay = FALSE;
-          caps_set = TRUE;
-        }
-      }
-    }
-
-    if (delay) {
-      GST_OBJECT_LOCK (trans);
-      trans->priv->delayed_events =
-          g_list_append (trans->priv->delayed_events, event);
-      GST_OBJECT_UNLOCK (trans);
-    } else {
-      if (caps_set && GST_EVENT_IS_SERIALIZED (event))
-        gst_base_transform_send_delayed_events (trans);
-      ret = gst_pad_push_event (trans->srcpad, event);
-    }
-  } else
+  if (bclass->sink_event)
+    ret = bclass->sink_event (trans, event);
+  else
     gst_event_unref (event);
 
-  gst_object_unref (trans);
-
   return ret;
 }
 
 static gboolean
 gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
 {
+  gboolean ret = TRUE, forward = TRUE;
+
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_START:
       break;
@@ -2269,66 +1609,54 @@ gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
       trans->priv->dropped = 0;
       GST_OBJECT_UNLOCK (trans);
       /* we need new segment info after the flush. */
-      trans->have_newsegment = FALSE;
+      trans->have_segment = FALSE;
       gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
-      trans->priv->last_stop_out = GST_CLOCK_TIME_NONE;
+      trans->priv->position_out = GST_CLOCK_TIME_NONE;
       break;
     case GST_EVENT_EOS:
       break;
     case GST_EVENT_TAG:
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_CAPS:
     {
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-      gboolean update;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      trans->have_newsegment = TRUE;
-
-      gst_segment_set_newsegment_full (&trans->segment, update, rate, arate,
-          format, start, stop, time);
-
-      if (format == GST_FORMAT_TIME) {
-        GST_DEBUG_OBJECT (trans, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
-            " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
-            ", accum %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (trans->segment.start),
-            GST_TIME_ARGS (trans->segment.stop),
-            GST_TIME_ARGS (trans->segment.time),
-            GST_TIME_ARGS (trans->segment.accum));
-      } else {
-        GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT
-            " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
-            ", accum %" G_GINT64_FORMAT,
-            trans->segment.start, trans->segment.stop,
-            trans->segment.time, trans->segment.accum);
-      }
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      ret = gst_base_transform_setcaps (trans, trans->sinkpad, caps);
+
+      forward = FALSE;
+      break;
+    }
+    case GST_EVENT_SEGMENT:
+    {
+      gst_event_copy_segment (event, &trans->segment);
+      trans->have_segment = TRUE;
+
+      GST_DEBUG_OBJECT (trans, "received SEGMENT %" GST_SEGMENT_FORMAT,
+          &trans->segment);
       break;
     }
     default:
       break;
   }
 
-  return TRUE;
+  if (ret && forward)
+    ret = gst_pad_push_event (trans->srcpad, event);
+  else
+    gst_event_unref (event);
+
+  return ret;
 }
 
 static gboolean
-gst_base_transform_src_event (GstPad * pad, GstEvent * event)
+gst_base_transform_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
-
+  trans = GST_BASE_TRANSFORM (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->src_event)
@@ -2336,8 +1664,6 @@ gst_base_transform_src_event (GstPad * pad, GstEvent * event)
   else
     gst_event_unref (event);
 
-  gst_object_unref (trans);
-
   return ret;
 }
 
@@ -2359,7 +1685,7 @@ gst_base_transform_src_eventfunc (GstBaseTransform * trans, GstEvent * event)
       GstClockTimeDiff diff;
       GstClockTime timestamp;
 
-      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+      gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
       gst_base_transform_update_qos (trans, proportion, diff, timestamp);
       break;
     }
@@ -2383,36 +1709,49 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
 {
   GstBaseTransformClass *bclass;
   GstFlowReturn ret = GST_FLOW_OK;
-  gboolean want_in_place, reconfigure;
+  gboolean want_in_place;
   GstClockTime running_time;
   GstClockTime timestamp;
-  GstCaps *incaps;
+  gboolean reconfigure;
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  if (G_LIKELY ((incaps = GST_BUFFER_CAPS (inbuf)))) {
-    GST_OBJECT_LOCK (trans);
-    reconfigure = trans->priv->reconfigure;
-    trans->priv->reconfigure = FALSE;
-    GST_OBJECT_UNLOCK (trans);
+  GST_OBJECT_LOCK (trans->sinkpad);
+  reconfigure = GST_PAD_NEEDS_RECONFIGURE (trans->srcpad)
+      || trans->priv->reconfigure;
+  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_FLAG_NEED_RECONFIGURE);
+  trans->priv->reconfigure = FALSE;
+  GST_OBJECT_UNLOCK (trans->sinkpad);
+
+  if (G_UNLIKELY (reconfigure)) {
+    GstCaps *incaps;
+
+    GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
 
-    if (G_UNLIKELY (reconfigure)) {
-      GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
-      /* if we need to reconfigure we pretend a buffer with new caps arrived. This
-       * will reconfigure the transform with the new output format. We can only
-       * do this if the buffer actually has caps. */
-      if (!gst_base_transform_setcaps (trans->sinkpad, incaps))
-        goto not_negotiated;
+    incaps = gst_pad_get_current_caps (trans->sinkpad);
+    if (incaps == NULL)
+      goto no_reconfigure;
+
+    /* if we need to reconfigure we pretend a buffer with new caps arrived. This
+     * will reconfigure the transform with the new output format. We can only
+     * do this if the buffer actually has caps. */
+    if (!gst_base_transform_setcaps (trans, trans->sinkpad, incaps)) {
+      gst_caps_unref (incaps);
+      goto not_negotiated;
     }
+    gst_caps_unref (incaps);
   }
 
+no_reconfigure:
   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
-    GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset %"
-        G_GUINT64_FORMAT, inbuf, GST_BUFFER_SIZE (inbuf),
+    GST_DEBUG_OBJECT (trans,
+        "handling buffer %p of size %" G_GSIZE_FORMAT " and offset %"
+        G_GUINT64_FORMAT, inbuf, gst_buffer_get_size (inbuf),
         GST_BUFFER_OFFSET (inbuf));
   else
-    GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
-        inbuf, GST_BUFFER_SIZE (inbuf));
+    GST_DEBUG_OBJECT (trans,
+        "handling buffer %p of size %" G_GSIZE_FORMAT " and offset NONE", inbuf,
+        gst_buffer_get_size (inbuf));
 
   /* Don't allow buffer handling before negotiation, except in passthrough mode
    * or if the class doesn't implement a set_caps function (in which case it doesn't
@@ -2487,14 +1826,40 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
 no_qos:
 
   /* first try to allocate an output buffer based on the currently negotiated
-   * format. While we call pad-alloc we could renegotiate the srcpad format or
-   * have a new suggestion for upstream buffer-alloc.
-   * In any case, outbuf will contain a buffer suitable for doing the configured
+   * format. outbuf will contain a buffer suitable for doing the configured
    * transform after this function. */
-  ret = gst_base_transform_prepare_output_buffer (trans, inbuf, outbuf);
-  if (G_UNLIKELY (ret != GST_FLOW_OK))
+  if (bclass->prepare_output_buffer == NULL)
+    goto no_prepare;
+
+  GST_DEBUG_OBJECT (trans, "calling prepare buffer");
+  ret = bclass->prepare_output_buffer (trans, inbuf, outbuf);
+
+  if (ret != GST_FLOW_OK || *outbuf == NULL)
     goto no_buffer;
 
+  if (inbuf == *outbuf) {
+    GST_DEBUG_OBJECT (trans, "reusing input buffer");
+  } else if (trans->passthrough) {
+    /* we are asked to perform a passthrough transform but the input and
+     * output buffers are different. We have to discard the output buffer and
+     * reuse the input buffer. This is rather weird, it means that the prepare
+     * output buffer does something wrong. */
+    GST_WARNING_OBJECT (trans, "passthrough but different buffers, check the "
+        "prepare_output_buffer implementation");
+    gst_buffer_unref (*outbuf);
+    *outbuf = inbuf;
+  } else {
+    /* copy the metadata */
+    if (bclass->copy_metadata)
+      if (!bclass->copy_metadata (trans, inbuf, *outbuf)) {
+        /* something failed, post a warning */
+        GST_ELEMENT_WARNING (trans, STREAM, NOT_IMPLEMENTED,
+            ("could not copy metadata"), (NULL));
+      }
+  }
+  GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", inbuf,
+      *outbuf);
+
   /* now perform the needed transform */
   if (trans->passthrough) {
     /* In passthrough mode, give transform_ip a look at the
@@ -2514,16 +1879,20 @@ no_qos:
 
       if (inbuf != *outbuf) {
         guint8 *indata, *outdata;
+        gsize insize, outsize;
 
         /* Different buffer. The data can still be the same when we are dealing
          * with subbuffers of the same buffer. Note that because of the FIXME in
          * prepare_output_buffer() we have decreased the refcounts of inbuf and
          * outbuf to keep them writable */
-        indata = GST_BUFFER_DATA (inbuf);
-        outdata = GST_BUFFER_DATA (*outbuf);
+        indata = gst_buffer_map (inbuf, &insize, NULL, GST_MAP_READ);
+        outdata = gst_buffer_map (*outbuf, &outsize, NULL, GST_MAP_WRITE);
 
         if (indata != outdata)
-          memcpy (outdata, indata, GST_BUFFER_SIZE (inbuf));
+          memcpy (outdata, indata, insize);
+
+        gst_buffer_unmap (inbuf, indata, insize);
+        gst_buffer_unmap (*outbuf, outdata, outsize);
       }
       ret = bclass->transform_ip (trans, *outbuf);
     } else {
@@ -2537,52 +1906,45 @@ no_qos:
   }
 
 skip:
-  /* only unref input buffer if we allocated a new outbuf buffer */
+  /* only unref input buffer if we allocated a new outbuf buffer. If we reused
+   * the input buffer, no refcount is changed to keep the input buffer writable
+   * when needed. */
   if (*outbuf != inbuf)
     gst_buffer_unref (inbuf);
 
-  /* pushed a buffer, we can now try an alloc */
-  GST_DEBUG_OBJECT (trans, "Pushed a buffer, setting force alloc to true");
-  trans->priv->force_alloc = TRUE;
   return ret;
 
   /* ERRORS */
 not_negotiated:
   {
     gst_buffer_unref (inbuf);
+    *outbuf = NULL;
     GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
         ("not negotiated"), ("not negotiated"));
     return GST_FLOW_NOT_NEGOTIATED;
   }
+no_prepare:
+  {
+    gst_buffer_unref (inbuf);
+    GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
+        ("Sub-class has no prepare_output_buffer implementation"), (NULL));
+    return GST_FLOW_NOT_SUPPORTED;
+  }
 no_buffer:
   {
     gst_buffer_unref (inbuf);
+    *outbuf = NULL;
     GST_WARNING_OBJECT (trans, "could not get buffer from pool: %s",
         gst_flow_get_name (ret));
     return ret;
   }
 }
 
-static gboolean
-gst_base_transform_check_get_range (GstPad * pad)
-{
-  GstBaseTransform *trans;
-  gboolean ret;
-
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
-  ret = gst_pad_check_pull_range (trans->sinkpad);
-
-  gst_object_unref (trans);
-
-  return ret;
-}
-
 /* FIXME, getrange is broken, need to pull range from the other
  * end based on the transform_size result.
  */
 static GstFlowReturn
-gst_base_transform_getrange (GstPad * pad, guint64 offset,
+gst_base_transform_getrange (GstPad * pad, GstObject * parent, guint64 offset,
     guint length, GstBuffer ** buffer)
 {
   GstBaseTransform *trans;
@@ -2590,7 +1952,7 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
   GstFlowReturn ret;
   GstBuffer *inbuf;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  trans = GST_BASE_TRANSFORM (parent);
 
   ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
@@ -2605,8 +1967,6 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
   GST_BASE_TRANSFORM_UNLOCK (trans);
 
 done:
-  gst_object_unref (trans);
-
   return ret;
 
   /* ERRORS */
@@ -2619,16 +1979,16 @@ pull_error:
 }
 
 static GstFlowReturn
-gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
+gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *klass;
   GstFlowReturn ret;
-  GstClockTime last_stop = GST_CLOCK_TIME_NONE;
+  GstClockTime position = GST_CLOCK_TIME_NONE;
   GstClockTime timestamp, duration;
   GstBuffer *outbuf = NULL;
 
-  trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
+  trans = GST_BASE_TRANSFORM (parent);
 
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   duration = GST_BUFFER_DURATION (buffer);
@@ -2636,17 +1996,15 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
   /* calculate end position of the incoming buffer */
   if (timestamp != GST_CLOCK_TIME_NONE) {
     if (duration != GST_CLOCK_TIME_NONE)
-      last_stop = timestamp + duration;
+      position = timestamp + duration;
     else
-      last_stop = timestamp;
+      position = timestamp;
   }
 
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   if (klass->before_transform)
     klass->before_transform (trans, buffer);
 
-  gst_base_transform_send_delayed_events (trans);
-
   /* protect transform method and concurrent buffer alloc */
   GST_BASE_TRANSFORM_LOCK (trans);
   ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
@@ -2655,29 +2013,31 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
   /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but
    * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */
   if (outbuf != NULL) {
-    if ((ret == GST_FLOW_OK)) {
-      GstClockTime last_stop_out = GST_CLOCK_TIME_NONE;
+    if (ret == GST_FLOW_OK) {
+      GstClockTime position_out = GST_CLOCK_TIME_NONE;
 
       /* Remember last stop position */
-      if (last_stop != GST_CLOCK_TIME_NONE &&
+      if (position != GST_CLOCK_TIME_NONE &&
           trans->segment.format == GST_FORMAT_TIME)
-        gst_segment_set_last_stop (&trans->segment, GST_FORMAT_TIME, last_stop);
+        trans->segment.position = position;
 
       if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf)) {
-        last_stop_out = GST_BUFFER_TIMESTAMP (outbuf);
+        position_out = GST_BUFFER_TIMESTAMP (outbuf);
         if (GST_BUFFER_DURATION_IS_VALID (outbuf))
-          last_stop_out += GST_BUFFER_DURATION (outbuf);
-      } else if (last_stop != GST_CLOCK_TIME_NONE) {
-        last_stop_out = last_stop;
+          position_out += GST_BUFFER_DURATION (outbuf);
+      } else if (position != GST_CLOCK_TIME_NONE) {
+        position_out = position;
       }
-      if (last_stop_out != GST_CLOCK_TIME_NONE
+      if (position_out != GST_CLOCK_TIME_NONE
           && trans->segment.format == GST_FORMAT_TIME)
-        trans->priv->last_stop_out = last_stop_out;
+        trans->priv->position_out = position_out;
 
       /* apply DISCONT flag if the buffer is not yet marked as such */
       if (trans->priv->discont) {
+        GST_DEBUG_OBJECT (trans, "we have a pending DISCONT");
         if (!GST_BUFFER_IS_DISCONT (outbuf)) {
-          outbuf = gst_buffer_make_metadata_writable (outbuf);
+          GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer");
+          outbuf = gst_buffer_make_writable (outbuf);
           GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
         }
         trans->priv->discont = FALSE;
@@ -2686,12 +2046,14 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
 
       ret = gst_pad_push (trans->srcpad, outbuf);
     } else {
+      GST_DEBUG_OBJECT (trans, "we got return %s", gst_flow_get_name (ret));
       gst_buffer_unref (outbuf);
     }
   }
 
   /* convert internal flow to OK and mark discont for the next buffer. */
   if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) {
+    GST_DEBUG_OBJECT (trans, "dropped a buffer, marking DISCONT");
     trans->priv->discont = TRUE;
     ret = GST_FLOW_OK;
   }
@@ -2744,97 +2106,113 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
 
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
-  GST_OBJECT_LOCK (trans);
-  gst_base_transform_clear_transformed_caps_cache (trans);
-  GST_OBJECT_UNLOCK (trans);
-
   if (active) {
-    if (trans->priv->pad_mode == GST_ACTIVATE_NONE && bclass->start)
+    GstCaps *incaps, *outcaps;
+
+    if (trans->priv->pad_mode == GST_PAD_MODE_NONE && bclass->start)
       result &= bclass->start (trans);
 
-    GST_OBJECT_LOCK (trans);
+    incaps = gst_pad_get_current_caps (trans->sinkpad);
+    outcaps = gst_pad_get_current_caps (trans->srcpad);
 
-    if (GST_PAD_CAPS (trans->sinkpad) && GST_PAD_CAPS (trans->srcpad))
+    GST_OBJECT_LOCK (trans);
+    if (incaps && outcaps)
       trans->have_same_caps =
-          gst_caps_is_equal (GST_PAD_CAPS (trans->sinkpad),
-          GST_PAD_CAPS (trans->srcpad)) || trans->passthrough;
+          gst_caps_is_equal (incaps, outcaps) || trans->passthrough;
     else
       trans->have_same_caps = trans->passthrough;
     GST_DEBUG_OBJECT (trans, "have_same_caps %d", trans->have_same_caps);
     trans->negotiated = FALSE;
-    trans->have_newsegment = FALSE;
+    trans->have_segment = FALSE;
     gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
-    trans->priv->last_stop_out = GST_CLOCK_TIME_NONE;
+    trans->priv->position_out = GST_CLOCK_TIME_NONE;
     trans->priv->proportion = 1.0;
     trans->priv->earliest_time = -1;
     trans->priv->discont = FALSE;
-    gst_caps_replace (&trans->priv->sink_suggest, NULL);
     trans->priv->processed = 0;
     trans->priv->dropped = 0;
-    trans->priv->force_alloc = TRUE;
-
     GST_OBJECT_UNLOCK (trans);
+
+    if (incaps)
+      gst_caps_unref (incaps);
+    if (outcaps)
+      gst_caps_unref (outcaps);
   } else {
     /* We must make sure streaming has finished before resetting things
      * and calling the ::stop vfunc */
     GST_PAD_STREAM_LOCK (trans->sinkpad);
     GST_PAD_STREAM_UNLOCK (trans->sinkpad);
 
-    gst_base_transform_drop_delayed_events (trans);
-
     trans->have_same_caps = FALSE;
-    /* We can only reset the passthrough mode if the instance told us to
+    /* We can only reset the passthrough mode if the instance told us to 
        handle it in configure_caps */
     if (bclass->passthrough_on_same_caps) {
       gst_base_transform_set_passthrough (trans, FALSE);
     }
     gst_caps_replace (&trans->cache_caps1, NULL);
     gst_caps_replace (&trans->cache_caps2, NULL);
-    gst_caps_replace (&trans->priv->sink_alloc, NULL);
-    gst_caps_replace (&trans->priv->sink_suggest, NULL);
 
-    if (trans->priv->pad_mode != GST_ACTIVATE_NONE && bclass->stop)
+    if (trans->priv->pad_mode != GST_PAD_MODE_NONE && bclass->stop)
       result &= bclass->stop (trans);
+
+    gst_base_transform_set_allocation (trans, NULL, NULL, 0, 0);
   }
 
   return result;
 }
 
 static gboolean
-gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
+gst_base_transform_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
-  gboolean result = TRUE;
+  gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  trans = GST_BASE_TRANSFORM (parent);
 
-  result = gst_base_transform_activate (trans, active);
-
-  if (result)
-    trans->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+    {
+      result = gst_base_transform_activate (trans, active);
 
-  gst_object_unref (trans);
+      if (result)
+        trans->priv->pad_mode = active ? GST_PAD_MODE_PUSH : GST_PAD_MODE_NONE;
 
+      break;
+    }
+    default:
+      result = TRUE;
+      break;
+  }
   return result;
 }
 
 static gboolean
-gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
+gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
   gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
-  result = gst_pad_activate_pull (trans->sinkpad, active);
+  trans = GST_BASE_TRANSFORM (parent);
 
-  if (result)
-    result &= gst_base_transform_activate (trans, active);
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+    {
+      result =
+          gst_pad_activate_mode (trans->sinkpad, GST_PAD_MODE_PULL, active);
 
-  if (result)
-    trans->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
+      if (result)
+        result &= gst_base_transform_activate (trans, active);
 
-  gst_object_unref (trans);
+      if (result)
+        trans->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
+      break;
+    }
+    default:
+      result = TRUE;
+      break;
+  }
 
   return result;
 }
@@ -3085,21 +2463,14 @@ gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
  */
 void
 gst_base_transform_suggest (GstBaseTransform * trans, GstCaps * caps,
-    guint size)
+    gsize size)
 {
   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
 
-  GST_OBJECT_LOCK (trans->sinkpad);
-  if (trans->priv->sink_suggest)
-    gst_caps_unref (trans->priv->sink_suggest);
-  if (caps)
-    caps = gst_caps_copy (caps);
-  trans->priv->sink_suggest = caps;
-  trans->priv->size_suggest = size;
-  trans->priv->suggest_pending = TRUE;
-  gst_base_transform_clear_transformed_caps_cache (trans);
-  GST_DEBUG_OBJECT (trans, "new suggest %" GST_PTR_FORMAT, caps);
-  GST_OBJECT_UNLOCK (trans->sinkpad);
+  /* push the renegotiate event */
+  if (!gst_pad_push_event (GST_BASE_TRANSFORM_SINK_PAD (trans),
+          gst_event_new_reconfigure ()))
+    GST_DEBUG_OBJECT (trans, "Renegotiate event wasn't handled");
 }
 
 /**
@@ -3120,7 +2491,5 @@ gst_base_transform_reconfigure (GstBaseTransform * trans)
   GST_OBJECT_LOCK (trans);
   GST_DEBUG_OBJECT (trans, "marking reconfigure");
   trans->priv->reconfigure = TRUE;
-  gst_base_transform_clear_transformed_caps_cache (trans);
-  gst_caps_replace (&trans->priv->sink_alloc, NULL);
   GST_OBJECT_UNLOCK (trans);
 }
index 485e484..d9bc24f 100644 (file)
@@ -85,7 +85,7 @@ G_BEGIN_DECLS
  *
  * Since: 0.10.13
  */
-#define GST_BASE_TRANSFORM_LOCK(obj)   g_mutex_lock (GST_BASE_TRANSFORM_CAST (obj)->transform_lock)
+#define GST_BASE_TRANSFORM_LOCK(obj)   g_mutex_lock (&GST_BASE_TRANSFORM_CAST (obj)->transform_lock)
 
 /**
  * GST_BASE_TRANSFORM_UNLOCK:
@@ -95,7 +95,7 @@ G_BEGIN_DECLS
  *
  * Since: 0.10.13
  */
-#define GST_BASE_TRANSFORM_UNLOCK(obj) g_mutex_unlock (GST_BASE_TRANSFORM_CAST (obj)->transform_lock)
+#define GST_BASE_TRANSFORM_UNLOCK(obj) g_mutex_unlock (&GST_BASE_TRANSFORM_CAST (obj)->transform_lock)
 
 typedef struct _GstBaseTransform GstBaseTransform;
 typedef struct _GstBaseTransformClass GstBaseTransformClass;
@@ -119,36 +119,53 @@ struct _GstBaseTransform {
   gboolean      always_in_place;
 
   GstCaps      *cache_caps1;
-  guint                 cache_caps1_size;
+  gsize                 cache_caps1_size;
   GstCaps      *cache_caps2;
-  guint                 cache_caps2_size;
+  gsize                 cache_caps2_size;
   gboolean      have_same_caps;
 
-  gboolean      delay_configure;
-  gboolean      pending_configure;
   gboolean      negotiated;
 
-  gboolean       have_newsegment;
+  gboolean       have_segment;
 
   /* MT-protected (with STREAM_LOCK) */
   GstSegment     segment;
 
-  GMutex       *transform_lock;
+  GMutex        transform_lock;
 
   /*< private >*/
   GstBaseTransformPrivate *priv;
 
-  gpointer       _gst_reserved[GST_PADDING_LARGE - 1];
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 /**
  * GstBaseTransformClass:
  * @parent_class:   Element parent class
+ * @passthrough_on_same_caps: If set to TRUE, passthrough mode will be
+ *                            automatically enabled if the caps are the same.
  * @transform_caps: Optional.  Given the pad in this direction and the given
  *                  caps, what caps are allowed on the other pad in this
  *                  element ?
  * @fixate_caps:    Optional. Given the pad in this direction and the given
  *                  caps, fixate the caps on the other pad.
+ * @accept_caps:    Optional. Since 0.10.30
+ *                  Subclasses can override this method to check if @caps can be
+ *                  handled by the element. The default implementation might not be
+ *                  the most optimal way to check this in all cases.
+ * @set_caps:       allows the subclass to be notified of the actual caps set.
+ * @query:          Optional Since 0.10.36
+ *                  Handle a requested query. Subclasses that implement this
+ *                  should must chain up to the parent if they didn't handle the
+ *                  query
+ * @propose_allocation: Propose buffer allocation parameters for upstream elements.
+ *                      This function must be implemented if the element reads or
+ *                      writes the buffer content. The default implementation is NULL.
+ * @decide_allocation: Setup the allocation parameters for allocating output
+ *                    buffers. The passed in query contains the result of the
+ *                    downstream allocation query. This function is only called
+ *                    when not operating in passthrough mode. The default
+ *                    implementation is NULL.
  * @transform_size: Optional. Given the size of a buffer in the given direction
  *                  with the given caps, calculate the size in bytes of a buffer
  *                  on the other pad with the given other caps.
@@ -156,44 +173,41 @@ struct _GstBaseTransform {
  *                  the number of units the same.
  * @get_unit_size:  Required if the transform is not in-place.
  *                  get the size in bytes of one unit for the given caps.
- * @set_caps:       allows the subclass to be notified of the actual caps set.
  * @start:          Optional.
  *                  Called when the element starts processing.
  *                  Allows opening external resources.
  * @stop:           Optional.
  *                  Called when the element stops processing.
  *                  Allows closing external resources.
- * @transform:      Required if the element does not operate in-place.
- *                  Transforms one incoming buffer to one outgoing buffer.
- *                  The function is allowed to change size/timestamp/duration
- *                  of the outgoing buffer.
- * @transform_ip:   Required if the element operates in-place.
- *                  Transform the incoming buffer in-place.
- * @event:          Optional.
- *                  Event handler on the sink pad. This function should return
- *                  TRUE if the base class should forward the event.
+ * @sink_event:     Optional.
+ *                  Event handler on the sink pad. The default implementation
+ *                  handles the event and forwards it downstream.
  * @src_event:      Optional.
- *                  Event handler on the source pad.
- * @passthrough_on_same_caps: If set to TRUE, passthrough mode will be
- *                            automatically enabled if the caps are the same.
+ *                  Event handler on the source pad. The default implementation
+ *                  handles the event and forwards it upstream.
  * @prepare_output_buffer: Optional.
  *                         Subclasses can override this to do their own
  *                         allocation of output buffers.  Elements that only do
  *                         analysis can return a subbuffer or even just
- *                         increment the reference to the input buffer (if in
- *                         passthrough mode)
+ *                         return a reference to the input buffer (if in
+ *                         passthrough mode). The default implementation will
+ *                         use the negotiated allocator or bufferpool and
+ *                         transform_size to allocate an output buffer or it
+ *                         will return the input buffer in passthrough mode.
+ * @copy_metadata: Optional.
+ *                 Copy the metadata from the input buffer to the output buffer.
+ *                 The default implementation will copy the flags, timestamps and
+ *                 offsets of the buffer.
  * @before_transform: Optional. Since 0.10.22
  *                    This method is called right before the base class will
  *                    start processing. Dynamic properties or other delayed
  *                    configuration could be performed in this method.
- * @accept_caps: Optional. Since 0.10.30
- *               Subclasses can override this method to check if @caps can be
- *               handled by the element. The default implementation might not be
- *               the most optimal way to check this in all cases.
- * @query: Optional Since 0.10.36
- *                Handle a requested query. Subclasses that implement this
- *                should must chain up to the parent if they didn't handle the
- *                query
+ * @transform:      Required if the element does not operate in-place.
+ *                  Transforms one incoming buffer to one outgoing buffer.
+ *                  The function is allowed to change size/timestamp/duration
+ *                  of the outgoing buffer.
+ * @transform_ip:   Required if the element operates in-place.
+ *                  Transform the incoming buffer in-place.
  *
  * Subclasses can override any of the available virtual methods or not, as
  * needed. At minimum either @transform or @transform_ip need to be overridden.
@@ -204,54 +218,59 @@ struct _GstBaseTransformClass {
   GstElementClass parent_class;
 
   /*< public >*/
-  /* virtual methods for subclasses */
+  gboolean       passthrough_on_same_caps;
 
+  /* virtual methods for subclasses */
   GstCaps*     (*transform_caps) (GstBaseTransform *trans,
                                    GstPadDirection direction,
-                                   GstCaps *caps);
-
+                                   GstCaps *caps, GstCaps *filter);
   void         (*fixate_caps)    (GstBaseTransform *trans,
                                    GstPadDirection direction, GstCaps *caps,
                                    GstCaps *othercaps);
+  gboolean      (*accept_caps)    (GstBaseTransform *trans, GstPadDirection direction,
+                                   GstCaps *caps);
+  gboolean      (*set_caps)       (GstBaseTransform *trans, GstCaps *incaps,
+                                   GstCaps *outcaps);
+  gboolean      (*query)          (GstBaseTransform *trans, GstPadDirection direction,
+                                   GstQuery *query);
+
+  /* propose allocation query parameters for input buffers */
+  gboolean      (*propose_allocation) (GstBaseTransform *trans, GstQuery *query);
+  /* decide allocation query for output buffers */
+  gboolean      (*decide_allocation) (GstBaseTransform *trans, GstQuery *query);
 
+  /* transform size */
   gboolean      (*transform_size) (GstBaseTransform *trans,
                                    GstPadDirection direction,
-                                   GstCaps *caps, guint size,
-                                   GstCaps *othercaps, guint *othersize);
+                                   GstCaps *caps, gsize size,
+                                   GstCaps *othercaps, gsize *othersize);
 
   gboolean      (*get_unit_size)  (GstBaseTransform *trans, GstCaps *caps,
-                                   guint *size);
-
-  gboolean      (*set_caps)     (GstBaseTransform *trans, GstCaps *incaps,
-                                 GstCaps *outcaps);
+                                   gsize *size);
 
+  /* states */
   gboolean      (*start)        (GstBaseTransform *trans);
   gboolean      (*stop)         (GstBaseTransform *trans);
 
-  gboolean      (*event)        (GstBaseTransform *trans, GstEvent *event);
-
-  GstFlowReturn (*transform)    (GstBaseTransform *trans, GstBuffer *inbuf,
-                                 GstBuffer *outbuf);
-  GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
-
-  /* FIXME: When adjusting the padding, move these to nicer places in the class */
-  gboolean       passthrough_on_same_caps;
+  /* sink and src pad event handlers */
+  gboolean      (*sink_event)   (GstBaseTransform *trans, GstEvent *event);
+  gboolean      (*src_event)    (GstBaseTransform *trans, GstEvent *event);
 
   GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
-     GstBuffer *input, gint size, GstCaps *caps, GstBuffer **buf);
+                                          GstBuffer *input, GstBuffer **outbuf);
 
-  /* src event */
-  gboolean      (*src_event)      (GstBaseTransform *trans, GstEvent *event);
+  gboolean      (*copy_metadata)     (GstBaseTransform * trans, GstBuffer *input,
+                                      GstBuffer *outbuf);
 
   void          (*before_transform)  (GstBaseTransform *trans, GstBuffer *buffer);
 
-  gboolean      (*accept_caps)  (GstBaseTransform *trans, GstPadDirection direction,
-                                        GstCaps *caps);
-  gboolean      (*query) (GstBaseTransform * trans, GstPadDirection direction,
-      GstQuery * query);
+  /* transform */
+  GstFlowReturn (*transform)    (GstBaseTransform *trans, GstBuffer *inbuf,
+                                 GstBuffer *outbuf);
+  GstFlowReturn (*transform_ip) (GstBaseTransform *trans, GstBuffer *buf);
 
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE - 4];
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 GType           gst_base_transform_get_type         (void);
@@ -276,7 +295,7 @@ void            gst_base_transform_set_gap_aware    (GstBaseTransform *trans,
                                                      gboolean gap_aware);
 
 void           gst_base_transform_suggest          (GstBaseTransform *trans,
-                                                    GstCaps *caps, guint size);
+                                                    GstCaps *caps, gsize size);
 void           gst_base_transform_reconfigure      (GstBaseTransform *trans);
 G_END_DECLS
 
index ee1a04f..8c4fc6f 100644 (file)
@@ -42,7 +42,7 @@ void gst_bit_reader_skip_unchecked (GstBitReader * reader, guint nbits);
  *
  * Skips until the next byte without checking if there are enough bits
  * available in the bit reader.
- * 
+ *
  * Since: 0.10.31
  */
 void gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader);
@@ -56,7 +56,7 @@ void gst_bit_reader_skip_to_byte_unchecked (GstBitReader * reader);
  * checking if there are enough bits available in the bit reader.
  *
  * Returns: unsigned 8 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, guint nbits);
@@ -70,7 +70,7 @@ guint8 gst_bit_reader_peek_bits_uint8_unchecked (const GstBitReader *reader, gui
  * checking if there are enough bits available in the bit reader
  *
  * Returns: unsigned 8 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbits);
@@ -84,7 +84,7 @@ guint8 gst_bit_reader_get_bits_uint8_unchecked (GstBitReader *reader, guint nbit
  * checking if there are enough bits available in the bit reader.
  *
  * Returns: unsigned 16 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, guint nbits);
@@ -98,7 +98,7 @@ guint16 gst_bit_reader_peek_bits_uint16_unchecked (const GstBitReader *reader, g
  * checking if there are enough bits available in the bit reader
  *
  * Returns: unsigned 16 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nbits);
@@ -112,7 +112,7 @@ guint16 gst_bit_reader_get_bits_uint16_unchecked (GstBitReader *reader, guint nb
  * checking if there are enough bits available in the bit reader.
  *
  * Returns: unsigned 32 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, guint nbits);
@@ -126,7 +126,7 @@ guint32 gst_bit_reader_peek_bits_uint32_unchecked (const GstBitReader *reader, g
  * checking if there are enough bits available in the bit reader
  *
  * Returns: unsigned 32 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nbits);
@@ -140,7 +140,7 @@ guint32 gst_bit_reader_get_bits_uint32_unchecked (GstBitReader *reader, guint nb
  * checking if there are enough bits available in the bit reader.
  *
  * Returns: unsigned 64 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, guint nbits);
@@ -154,7 +154,7 @@ guint64 gst_bit_reader_peek_bits_uint64_unchecked (const GstBitReader *reader, g
  * checking if there are enough bits available in the bit reader
  *
  * Returns: unsigned 64 bit integer with the bits.
- * 
+ *
  * Since: 0.10.31
  */
 guint64 gst_bit_reader_get_bits_uint64_unchecked (GstBitReader *reader, guint nbits);
index 6eccb63..271424a 100644 (file)
@@ -61,33 +61,11 @@ gst_bit_reader_new (const guint8 * data, guint size)
 }
 
 /**
- * gst_bit_reader_new_from_buffer:
- * @buffer: Buffer from which the #GstBitReader should read
- *
- * Create a new #GstBitReader instance, which will read from the
- * #GstBuffer @buffer.
- *
- * Free-function: gst_bit_reader_free
- *
- * Returns: (transfer full): a new #GstBitReader instance
- *
- * Since: 0.10.22
- */
-GstBitReader *
-gst_bit_reader_new_from_buffer (const GstBuffer * buffer)
-{
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
-
-  return gst_bit_reader_new (GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
-}
-
-/**
  * gst_bit_reader_free:
  * @reader: (in) (transfer full): a #GstBitReader instance
  *
  * Frees a #GstBitReader instance, which was previously allocated by
- * gst_bit_reader_new() or gst_bit_reader_new_from_buffer().
+ * gst_bit_reader_new().
  * 
  * Since: 0.10.22
  */
@@ -121,26 +99,6 @@ gst_bit_reader_init (GstBitReader * reader, const guint8 * data, guint size)
 }
 
 /**
- * gst_bit_reader_init_from_buffer:
- * @reader: a #GstBitReader instance
- * @buffer: (transfer none): Buffer from which the #GstBitReader should read
- *
- * Initializes a #GstBitReader instance to read from @buffer. This function
- * can be called on already initialized instances.
- * 
- * Since: 0.10.22
- */
-void
-gst_bit_reader_init_from_buffer (GstBitReader * reader,
-    const GstBuffer * buffer)
-{
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-
-  gst_bit_reader_init (reader, GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
-}
-
-/**
  * gst_bit_reader_set_pos:
  * @reader: a #GstBitReader instance
  * @pos: The new position in bits
index 796dd7e..5233612 100644 (file)
@@ -44,34 +44,35 @@ typedef struct {
 
   guint byte;  /* Byte position */
   guint bit;   /* Bit position in the current byte */
+
+  /* < private > */
+  gpointer _gst_reserved[GST_PADDING];
 } GstBitReader;
 
-GstBitReader * gst_bit_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
-GstBitReader * gst_bit_reader_new_from_buffer (const GstBuffer *buffer) G_GNUC_MALLOC;
-void gst_bit_reader_free (GstBitReader *reader);
+GstBitReader *  gst_bit_reader_new              (const guint8 *data, guint size) G_GNUC_MALLOC;
+void            gst_bit_reader_free             (GstBitReader *reader);
 
-void gst_bit_reader_init (GstBitReader *reader, const guint8 *data, guint size);
-void gst_bit_reader_init_from_buffer (GstBitReader *reader, const GstBuffer *buffer);
+void            gst_bit_reader_init             (GstBitReader *reader, const guint8 *data, guint size);
 
-gboolean gst_bit_reader_set_pos (GstBitReader *reader, guint pos);
+gboolean        gst_bit_reader_set_pos          (GstBitReader *reader, guint pos);
+guint           gst_bit_reader_get_pos          (const GstBitReader *reader);
 
-guint gst_bit_reader_get_pos (const GstBitReader *reader);
-guint gst_bit_reader_get_remaining (const GstBitReader *reader);
+guint           gst_bit_reader_get_remaining    (const GstBitReader *reader);
 
-guint gst_bit_reader_get_size (const GstBitReader *reader);
+guint           gst_bit_reader_get_size         (const GstBitReader *reader);
 
-gboolean gst_bit_reader_skip (GstBitReader *reader, guint nbits);
-gboolean gst_bit_reader_skip_to_byte (GstBitReader *reader);
+gboolean        gst_bit_reader_skip             (GstBitReader *reader, guint nbits);
+gboolean        gst_bit_reader_skip_to_byte     (GstBitReader *reader);
 
-gboolean gst_bit_reader_get_bits_uint8 (GstBitReader *reader, guint8 *val, guint nbits);
-gboolean gst_bit_reader_get_bits_uint16 (GstBitReader *reader, guint16 *val, guint nbits);
-gboolean gst_bit_reader_get_bits_uint32 (GstBitReader *reader, guint32 *val, guint nbits);
-gboolean gst_bit_reader_get_bits_uint64 (GstBitReader *reader, guint64 *val, guint nbits);
+gboolean        gst_bit_reader_get_bits_uint8   (GstBitReader *reader, guint8 *val, guint nbits);
+gboolean        gst_bit_reader_get_bits_uint16  (GstBitReader *reader, guint16 *val, guint nbits);
+gboolean        gst_bit_reader_get_bits_uint32  (GstBitReader *reader, guint32 *val, guint nbits);
+gboolean        gst_bit_reader_get_bits_uint64  (GstBitReader *reader, guint64 *val, guint nbits);
 
-gboolean gst_bit_reader_peek_bits_uint8 (const GstBitReader *reader, guint8 *val, guint nbits);
-gboolean gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
-gboolean gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
-gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
+gboolean        gst_bit_reader_peek_bits_uint8  (const GstBitReader *reader, guint8 *val, guint nbits);
+gboolean        gst_bit_reader_peek_bits_uint16 (const GstBitReader *reader, guint16 *val, guint nbits);
+gboolean        gst_bit_reader_peek_bits_uint32 (const GstBitReader *reader, guint32 *val, guint nbits);
+gboolean        gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *val, guint nbits);
 
 /**
  * GST_BIT_READER_INIT:
@@ -87,19 +88,6 @@ gboolean gst_bit_reader_peek_bits_uint64 (const GstBitReader *reader, guint64 *v
  */
 #define GST_BIT_READER_INIT(data, size) {data, size, 0, 0}
 
-/**
- * GST_BIT_READER_INIT_FROM_BUFFER:
- * @buffer: Buffer from which the #GstBitReader should read
- *
- * A #GstBitReader must be initialized with this macro, before it can be
- * used. This macro can used be to initialize a variable, but it cannot
- * be assigned to a variable. In that case you have to use
- * gst_bit_reader_init().
- *
- * Since: 0.10.22
- */
-#define GST_BIT_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0, 0}
-
 /* Unchecked variants */
 
 static inline void
index 01b8326..e4b6e35 100644 (file)
@@ -80,10 +80,10 @@ void gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes);
  *
  * Since: 0.10.25
  */
-guint8 gst_byte_reader_get_uint8_unchecked (GstByteReader * reader);
-guint8 gst_byte_reader_peek_uint8_unchecked (GstByteReader * reader);
-gint8 gst_byte_reader_get_int8_unchecked (GstByteReader * reader);
-gint8 gst_byte_reader_peek_int8_unchecked (GstByteReader * reader);
+guint8  gst_byte_reader_get_uint8_unchecked     (GstByteReader * reader);
+guint8  gst_byte_reader_peek_uint8_unchecked    (GstByteReader * reader);
+gint8   gst_byte_reader_get_int8_unchecked      (GstByteReader * reader);
+gint8   gst_byte_reader_peek_int8_unchecked     (GstByteReader * reader);
 
 /**
  * gst_byte_reader_get_uint16_le_unchecked:
@@ -181,14 +181,14 @@ gint8 gst_byte_reader_peek_int8_unchecked (GstByteReader * reader);
  *
  * Since: 0.10.25
  */
-guint16 gst_byte_reader_get_uint16_le_unchecked (GstByteReader * reader);
-guint16 gst_byte_reader_get_uint16_be_unchecked (GstByteReader * reader);
+guint16 gst_byte_reader_get_uint16_le_unchecked  (GstByteReader * reader);
+guint16 gst_byte_reader_get_uint16_be_unchecked  (GstByteReader * reader);
 guint16 gst_byte_reader_peek_uint16_le_unchecked (GstByteReader * reader);
 guint16 gst_byte_reader_peek_uint16_be_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_get_int16_le_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_get_int16_be_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_peek_int16_le_unchecked (GstByteReader * reader);
-gint16 gst_byte_reader_peek_int16_be_unchecked (GstByteReader * reader);
+gint16  gst_byte_reader_get_int16_le_unchecked   (GstByteReader * reader);
+gint16  gst_byte_reader_get_int16_be_unchecked   (GstByteReader * reader);
+gint16  gst_byte_reader_peek_int16_le_unchecked  (GstByteReader * reader);
+gint16  gst_byte_reader_peek_int16_be_unchecked  (GstByteReader * reader);
 
 /**
  * gst_byte_reader_get_uint24_le_unchecked:
@@ -286,14 +286,14 @@ gint16 gst_byte_reader_peek_int16_be_unchecked (GstByteReader * reader);
  *
  * Since: 0.10.25
  */
-guint32 gst_byte_reader_get_uint24_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_get_uint24_be_unchecked (GstByteReader * reader);
+guint32 gst_byte_reader_get_uint24_le_unchecked  (GstByteReader * reader);
+guint32 gst_byte_reader_get_uint24_be_unchecked  (GstByteReader * reader);
 guint32 gst_byte_reader_peek_uint24_le_unchecked (GstByteReader * reader);
 guint32 gst_byte_reader_peek_uint24_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int24_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int24_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int24_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int24_be_unchecked (GstByteReader * reader);
+gint32  gst_byte_reader_get_int24_le_unchecked   (GstByteReader * reader);
+gint32  gst_byte_reader_get_int24_be_unchecked   (GstByteReader * reader);
+gint32  gst_byte_reader_peek_int24_le_unchecked  (GstByteReader * reader);
+gint32  gst_byte_reader_peek_int24_be_unchecked  (GstByteReader * reader);
 
 /**
  * gst_byte_reader_get_uint32_le_unchecked:
@@ -391,14 +391,14 @@ gint32 gst_byte_reader_peek_int24_be_unchecked (GstByteReader * reader);
  *
  * Since: 0.10.25
  */
-guint32 gst_byte_reader_get_uint32_le_unchecked (GstByteReader * reader);
-guint32 gst_byte_reader_get_uint32_be_unchecked (GstByteReader * reader);
+guint32 gst_byte_reader_get_uint32_le_unchecked  (GstByteReader * reader);
+guint32 gst_byte_reader_get_uint32_be_unchecked  (GstByteReader * reader);
 guint32 gst_byte_reader_peek_uint32_le_unchecked (GstByteReader * reader);
 guint32 gst_byte_reader_peek_uint32_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int32_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_get_int32_be_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int32_le_unchecked (GstByteReader * reader);
-gint32 gst_byte_reader_peek_int32_be_unchecked (GstByteReader * reader);
+gint32  gst_byte_reader_get_int32_le_unchecked   (GstByteReader * reader);
+gint32  gst_byte_reader_get_int32_be_unchecked   (GstByteReader * reader);
+gint32  gst_byte_reader_peek_int32_le_unchecked  (GstByteReader * reader);
+gint32  gst_byte_reader_peek_int32_be_unchecked  (GstByteReader * reader);
 
 /**
  * gst_byte_reader_get_uint64_le_unchecked:
@@ -496,14 +496,14 @@ gint32 gst_byte_reader_peek_int32_be_unchecked (GstByteReader * reader);
  *
  * Since: 0.10.25
  */
-guint64 gst_byte_reader_get_uint64_le_unchecked (GstByteReader * reader);
-guint64 gst_byte_reader_get_uint64_be_unchecked (GstByteReader * reader);
+guint64 gst_byte_reader_get_uint64_le_unchecked  (GstByteReader * reader);
+guint64 gst_byte_reader_get_uint64_be_unchecked  (GstByteReader * reader);
 guint64 gst_byte_reader_peek_uint64_le_unchecked (GstByteReader * reader);
 guint64 gst_byte_reader_peek_uint64_be_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_get_int64_le_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_get_int64_be_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_peek_int64_le_unchecked (GstByteReader * reader);
-gint64 gst_byte_reader_peek_int64_be_unchecked (GstByteReader * reader);
+gint64  gst_byte_reader_get_int64_le_unchecked   (GstByteReader * reader);
+gint64  gst_byte_reader_get_int64_be_unchecked   (GstByteReader * reader);
+gint64  gst_byte_reader_peek_int64_le_unchecked  (GstByteReader * reader);
+gint64  gst_byte_reader_peek_int64_be_unchecked  (GstByteReader * reader);
 
 /**
  * gst_byte_reader_get_float32_le_unchecked:
@@ -594,10 +594,10 @@ gint64 gst_byte_reader_peek_int64_be_unchecked (GstByteReader * reader);
  * Since: 0.10.25
  */
 
-gfloat  gst_byte_reader_get_float32_le_unchecked (GstByteReader * reader);
-gfloat  gst_byte_reader_get_float32_be_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_get_float64_le_unchecked (GstByteReader * reader);
-gdouble gst_byte_reader_get_float64_be_unchecked (GstByteReader * reader);
+gfloat  gst_byte_reader_get_float32_le_unchecked  (GstByteReader * reader);
+gfloat  gst_byte_reader_get_float32_be_unchecked  (GstByteReader * reader);
+gdouble gst_byte_reader_get_float64_le_unchecked  (GstByteReader * reader);
+gdouble gst_byte_reader_get_float64_be_unchecked  (GstByteReader * reader);
 
 gfloat  gst_byte_reader_peek_float32_le_unchecked (GstByteReader * reader);
 gfloat  gst_byte_reader_peek_float32_be_unchecked (GstByteReader * reader);
index 57567f3..c1875e6 100644 (file)
@@ -67,33 +67,11 @@ gst_byte_reader_new (const guint8 * data, guint size)
 }
 
 /**
- * gst_byte_reader_new_from_buffer:
- * @buffer: (transfer none): Buffer from which the #GstByteReader should read
- *
- * Create a new #GstByteReader instance, which will read from the
- * #GstBuffer @buffer.
- *
- * Free-function: gst_byte_reader_free
- *
- * Returns: (transfer full): a new #GstByteReader instance
- *
- * Since: 0.10.22
- */
-GstByteReader *
-gst_byte_reader_new_from_buffer (const GstBuffer * buffer)
-{
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
-
-  return gst_byte_reader_new (GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
-}
-
-/**
  * gst_byte_reader_free:
  * @reader: (in) (transfer full): a #GstByteReader instance
  *
  * Frees a #GstByteReader instance, which was previously allocated by
- * gst_byte_reader_new() or gst_byte_reader_new_from_buffer().
+ * gst_byte_reader_new().
  * 
  * Since: 0.10.22
  */
@@ -128,26 +106,6 @@ gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
 }
 
 /**
- * gst_byte_reader_init_from_buffer:
- * @reader: a #GstByteReader instance
- * @buffer: (transfer none): Buffer from which the #GstByteReader should read
- *
- * Initializes a #GstByteReader instance to read from @buffer. This function
- * can be called on already initialized instances.
- * 
- * Since: 0.10.22
- */
-void
-gst_byte_reader_init_from_buffer (GstByteReader * reader,
-    const GstBuffer * buffer)
-{
-  g_return_if_fail (GST_IS_BUFFER (buffer));
-
-  gst_byte_reader_init (reader, GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
-}
-
-/**
  * gst_byte_reader_set_pos:
  * @reader: a #GstByteReader instance
  * @pos: The new position in bytes
index 0fcb8a7..2accb10 100644 (file)
@@ -41,89 +41,90 @@ typedef struct {
   guint size;
 
   guint byte;  /* Byte position */
+
+  /* < private > */
+  gpointer _gst_reserved[GST_PADDING];
 } GstByteReader;
 
-GstByteReader * gst_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
-GstByteReader * gst_byte_reader_new_from_buffer (const GstBuffer *buffer) G_GNUC_MALLOC;
-void gst_byte_reader_free (GstByteReader *reader);
-
-void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size);
-void gst_byte_reader_init_from_buffer (GstByteReader *reader, const GstBuffer *buffer);
-
-gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos);
-
-guint gst_byte_reader_get_pos (const GstByteReader *reader);
-guint gst_byte_reader_get_remaining (const GstByteReader *reader);
-
-guint gst_byte_reader_get_size (const GstByteReader *reader);
-
-gboolean gst_byte_reader_skip (GstByteReader *reader, guint nbytes);
-
-gboolean gst_byte_reader_get_uint8 (GstByteReader *reader, guint8 *val);
-gboolean gst_byte_reader_get_int8 (GstByteReader *reader, gint8 *val);
-gboolean gst_byte_reader_get_uint16_le (GstByteReader *reader, guint16 *val);
-gboolean gst_byte_reader_get_int16_le (GstByteReader *reader, gint16 *val);
-gboolean gst_byte_reader_get_uint16_be (GstByteReader *reader, guint16 *val);
-gboolean gst_byte_reader_get_int16_be (GstByteReader *reader, gint16 *val);
-gboolean gst_byte_reader_get_uint24_le (GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_get_int24_le (GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_get_uint24_be (GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_get_int24_be (GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_get_uint32_le (GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_get_int32_le (GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_get_uint32_be (GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_get_int32_be (GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_get_uint64_le (GstByteReader *reader, guint64 *val);
-gboolean gst_byte_reader_get_int64_le (GstByteReader *reader, gint64 *val);
-gboolean gst_byte_reader_get_uint64_be (GstByteReader *reader, guint64 *val);
-gboolean gst_byte_reader_get_int64_be (GstByteReader *reader, gint64 *val);
-
-gboolean gst_byte_reader_peek_uint8 (const GstByteReader *reader, guint8 *val);
-gboolean gst_byte_reader_peek_int8 (const GstByteReader *reader, gint8 *val);
-gboolean gst_byte_reader_peek_uint16_le (const GstByteReader *reader, guint16 *val);
-gboolean gst_byte_reader_peek_int16_le (const GstByteReader *reader, gint16 *val);
-gboolean gst_byte_reader_peek_uint16_be (const GstByteReader *reader, guint16 *val);
-gboolean gst_byte_reader_peek_int16_be (const GstByteReader *reader, gint16 *val);
-gboolean gst_byte_reader_peek_uint24_le (const GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_peek_int24_le (const GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_peek_uint24_be (const GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_peek_int24_be (const GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_peek_uint32_le (const GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_peek_int32_le (const GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_peek_uint32_be (const GstByteReader *reader, guint32 *val);
-gboolean gst_byte_reader_peek_int32_be (const GstByteReader *reader, gint32 *val);
-gboolean gst_byte_reader_peek_uint64_le (const GstByteReader *reader, guint64 *val);
-gboolean gst_byte_reader_peek_int64_le (const GstByteReader *reader, gint64 *val);
-gboolean gst_byte_reader_peek_uint64_be (const GstByteReader *reader, guint64 *val);
-gboolean gst_byte_reader_peek_int64_be (const GstByteReader *reader, gint64 *val);
-
-gboolean gst_byte_reader_get_float32_le (GstByteReader *reader, gfloat *val);
-gboolean gst_byte_reader_get_float32_be (GstByteReader *reader, gfloat *val);
-gboolean gst_byte_reader_get_float64_le (GstByteReader *reader, gdouble *val);
-gboolean gst_byte_reader_get_float64_be (GstByteReader *reader, gdouble *val);
-
-gboolean gst_byte_reader_peek_float32_le (const GstByteReader *reader, gfloat *val);
-gboolean gst_byte_reader_peek_float32_be (const GstByteReader *reader, gfloat *val);
-gboolean gst_byte_reader_peek_float64_le (const GstByteReader *reader, gdouble *val);
-gboolean gst_byte_reader_peek_float64_be (const GstByteReader *reader, gdouble *val);
-
-gboolean gst_byte_reader_dup_data  (GstByteReader * reader, guint size, guint8       ** val);
-gboolean gst_byte_reader_get_data  (GstByteReader * reader, guint size, const guint8 ** val);
-gboolean gst_byte_reader_peek_data (const GstByteReader * reader, guint size, const guint8 ** val);
+GstByteReader * gst_byte_reader_new             (const guint8 *data, guint size) G_GNUC_MALLOC;
+void            gst_byte_reader_free            (GstByteReader *reader);
+
+void            gst_byte_reader_init            (GstByteReader *reader, const guint8 *data, guint size);
+
+gboolean        gst_byte_reader_set_pos         (GstByteReader *reader, guint pos);
+guint           gst_byte_reader_get_pos         (const GstByteReader *reader);
+
+guint           gst_byte_reader_get_remaining   (const GstByteReader *reader);
+
+guint           gst_byte_reader_get_size        (const GstByteReader *reader);
+
+gboolean        gst_byte_reader_skip            (GstByteReader *reader, guint nbytes);
+
+gboolean        gst_byte_reader_get_uint8       (GstByteReader *reader, guint8 *val);
+gboolean        gst_byte_reader_get_int8        (GstByteReader *reader, gint8 *val);
+gboolean        gst_byte_reader_get_uint16_le   (GstByteReader *reader, guint16 *val);
+gboolean        gst_byte_reader_get_int16_le    (GstByteReader *reader, gint16 *val);
+gboolean        gst_byte_reader_get_uint16_be   (GstByteReader *reader, guint16 *val);
+gboolean        gst_byte_reader_get_int16_be    (GstByteReader *reader, gint16 *val);
+gboolean        gst_byte_reader_get_uint24_le   (GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_get_int24_le    (GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_get_uint24_be   (GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_get_int24_be    (GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_get_uint32_le   (GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_get_int32_le    (GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_get_uint32_be   (GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_get_int32_be    (GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_get_uint64_le   (GstByteReader *reader, guint64 *val);
+gboolean        gst_byte_reader_get_int64_le    (GstByteReader *reader, gint64 *val);
+gboolean        gst_byte_reader_get_uint64_be   (GstByteReader *reader, guint64 *val);
+gboolean        gst_byte_reader_get_int64_be    (GstByteReader *reader, gint64 *val);
+
+gboolean        gst_byte_reader_peek_uint8      (const GstByteReader *reader, guint8 *val);
+gboolean        gst_byte_reader_peek_int8       (const GstByteReader *reader, gint8 *val);
+gboolean        gst_byte_reader_peek_uint16_le  (const GstByteReader *reader, guint16 *val);
+gboolean        gst_byte_reader_peek_int16_le   (const GstByteReader *reader, gint16 *val);
+gboolean        gst_byte_reader_peek_uint16_be  (const GstByteReader *reader, guint16 *val);
+gboolean        gst_byte_reader_peek_int16_be   (const GstByteReader *reader, gint16 *val);
+gboolean        gst_byte_reader_peek_uint24_le  (const GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_peek_int24_le   (const GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_peek_uint24_be  (const GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_peek_int24_be   (const GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_peek_uint32_le  (const GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_peek_int32_le   (const GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_peek_uint32_be  (const GstByteReader *reader, guint32 *val);
+gboolean        gst_byte_reader_peek_int32_be   (const GstByteReader *reader, gint32 *val);
+gboolean        gst_byte_reader_peek_uint64_le  (const GstByteReader *reader, guint64 *val);
+gboolean        gst_byte_reader_peek_int64_le   (const GstByteReader *reader, gint64 *val);
+gboolean        gst_byte_reader_peek_uint64_be  (const GstByteReader *reader, guint64 *val);
+gboolean        gst_byte_reader_peek_int64_be   (const GstByteReader *reader, gint64 *val);
+
+gboolean        gst_byte_reader_get_float32_le  (GstByteReader *reader, gfloat *val);
+gboolean        gst_byte_reader_get_float32_be  (GstByteReader *reader, gfloat *val);
+gboolean        gst_byte_reader_get_float64_le  (GstByteReader *reader, gdouble *val);
+gboolean        gst_byte_reader_get_float64_be  (GstByteReader *reader, gdouble *val);
+
+gboolean        gst_byte_reader_peek_float32_le (const GstByteReader *reader, gfloat *val);
+gboolean        gst_byte_reader_peek_float32_be (const GstByteReader *reader, gfloat *val);
+gboolean        gst_byte_reader_peek_float64_le (const GstByteReader *reader, gdouble *val);
+gboolean        gst_byte_reader_peek_float64_be (const GstByteReader *reader, gdouble *val);
+
+gboolean        gst_byte_reader_dup_data        (GstByteReader * reader, guint size, guint8       ** val);
+gboolean        gst_byte_reader_get_data        (GstByteReader * reader, guint size, const guint8 ** val);
+gboolean        gst_byte_reader_peek_data       (const GstByteReader * reader, guint size, const guint8 ** val);
 
 #define gst_byte_reader_dup_string(reader,str) \
     gst_byte_reader_dup_string_utf8(reader,str)
 
-gboolean gst_byte_reader_dup_string_utf8  (GstByteReader * reader, gchar   ** str);
-gboolean gst_byte_reader_dup_string_utf16 (GstByteReader * reader, guint16 ** str);
-gboolean gst_byte_reader_dup_string_utf32 (GstByteReader * reader, guint32 ** str);
+gboolean        gst_byte_reader_dup_string_utf8  (GstByteReader * reader, gchar   ** str);
+gboolean        gst_byte_reader_dup_string_utf16 (GstByteReader * reader, guint16 ** str);
+gboolean        gst_byte_reader_dup_string_utf32 (GstByteReader * reader, guint32 ** str);
 
 #define gst_byte_reader_skip_string(reader) \
     gst_byte_reader_skip_string_utf8(reader)
 
-gboolean gst_byte_reader_skip_string_utf8  (GstByteReader * reader);
-gboolean gst_byte_reader_skip_string_utf16 (GstByteReader * reader);
-gboolean gst_byte_reader_skip_string_utf32 (GstByteReader * reader);
+gboolean        gst_byte_reader_skip_string_utf8  (GstByteReader * reader);
+gboolean        gst_byte_reader_skip_string_utf16 (GstByteReader * reader);
+gboolean        gst_byte_reader_skip_string_utf32 (GstByteReader * reader);
 
 #define gst_byte_reader_get_string(reader,str) \
     gst_byte_reader_get_string_utf8(reader,str)
@@ -131,14 +132,14 @@ gboolean gst_byte_reader_skip_string_utf32 (GstByteReader * reader);
 #define gst_byte_reader_peek_string(reader,str) \
     gst_byte_reader_peek_string_utf8(reader,str)
 
-gboolean gst_byte_reader_get_string_utf8   (GstByteReader * reader, const gchar ** str);
-gboolean gst_byte_reader_peek_string_utf8  (const GstByteReader * reader, const gchar ** str);
+gboolean        gst_byte_reader_get_string_utf8    (GstByteReader * reader, const gchar ** str);
+gboolean        gst_byte_reader_peek_string_utf8   (const GstByteReader * reader, const gchar ** str);
 
-guint    gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader,
-                                             guint32               mask,
-                                             guint32               pattern,
-                                             guint                 offset,
-                                             guint                 size);
+guint           gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader,
+                                                    guint32               mask,
+                                                    guint32               pattern,
+                                                    guint                 offset,
+                                                    guint                 size);
 
 /**
  * GST_BYTE_READER_INIT:
@@ -154,20 +155,6 @@ guint    gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader,
  */
 #define GST_BYTE_READER_INIT(data, size) {data, size, 0}
 
-/**
- * GST_BYTE_READER_INIT_FROM_BUFFER:
- * @buffer: Buffer from which the #GstByteReader should read
- *
- * A #GstByteReader must be initialized with this macro, before it can be
- * used. This macro can used be to initialize a variable, but it cannot
- * be assigned to a variable. In that case you have to use
- * gst_byte_reader_init().
- *
- * Since: 0.10.22
- */
-#define GST_BYTE_READER_INIT_FROM_BUFFER(buffer) {GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), 0}
-
-
 /* unchecked variants */
 static inline void
 gst_byte_reader_skip_unchecked (GstByteReader * reader, guint nbytes)
index 25564f7..e717300 100644 (file)
@@ -116,33 +116,6 @@ gst_byte_writer_new_with_data (guint8 * data, guint size, gboolean initialized)
 }
 
 /**
- * gst_byte_writer_new_with_buffer:
- * @buffer: Buffer used for writing
- * @initialized: If %TRUE the complete data can be read from the beginning
- *
- * Creates a new #GstByteWriter instance with the given
- * buffer. If @initialized is %TRUE it is possible to
- * read the complete buffer from the #GstByteWriter from the beginning.
- *
- * <note>@buffer must be writable</note>
- *
- * Free-function: gst_byte_writer_free
- *
- * Returns: (transfer full): a new #GstByteWriter instance
- *
- * Since: 0.10.26
- */
-GstByteWriter *
-gst_byte_writer_new_with_buffer (GstBuffer * buffer, gboolean initialized)
-{
-  g_return_val_if_fail (GST_IS_BUFFER (buffer)
-      && gst_buffer_is_writable (buffer), NULL);
-
-  return gst_byte_writer_new_with_data (GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer), initialized);
-}
-
-/**
  * gst_byte_writer_init:
  * @writer: #GstByteWriter instance
  *
@@ -214,30 +187,6 @@ gst_byte_writer_init_with_data (GstByteWriter * writer, guint8 * data,
 }
 
 /**
- * gst_byte_writer_init_with_buffer:
- * @writer: #GstByteWriter instance
- * @buffer: (transfer none): Buffer used for writing
- * @initialized: If %TRUE the complete data can be read from the beginning
- *
- * Initializes @writer with the given
- * buffer. If @initialized is %TRUE it is possible to
- * read the complete buffer from the #GstByteWriter from the beginning.
- *
- * <note>@buffer must be writable</note>
- *
- * Since: 0.10.26
- */
-void
-gst_byte_writer_init_with_buffer (GstByteWriter * writer, GstBuffer * buffer,
-    gboolean initialized)
-{
-  g_return_if_fail (GST_IS_BUFFER (buffer) && gst_buffer_is_writable (buffer));
-
-  gst_byte_writer_init_with_data (writer, GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer), initialized);
-}
-
-/**
  * gst_byte_writer_reset:
  * @writer: #GstByteWriter instance
  *
@@ -301,13 +250,19 @@ GstBuffer *
 gst_byte_writer_reset_and_get_buffer (GstByteWriter * writer)
 {
   GstBuffer *buffer;
+  gpointer data;
+  gsize size;
 
   g_return_val_if_fail (writer != NULL, NULL);
 
+  size = writer->parent.size;
+  data = gst_byte_writer_reset_and_get_data (writer);
+
   buffer = gst_buffer_new ();
-  GST_BUFFER_SIZE (buffer) = writer->parent.size;
-  GST_BUFFER_MALLOCDATA (buffer) = gst_byte_writer_reset_and_get_data (writer);
-  GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
+  if (data != NULL) {
+    gst_buffer_take_memory (buffer, -1,
+        gst_memory_new_wrapped (0, data, g_free, size, 0, size));
+  }
 
   return buffer;
 }
@@ -795,3 +750,42 @@ CREATE_WRITE_STRING_FUNC (32, guint32);
  *
  * Since: 0.10.27
  */
+
+/**
+ * gst_byte_writer_put_buffer:
+ * @writer: #GstByteWriter instance
+ * @buffer: (transfer none): source #GstBuffer
+ * @offset: offset to copy from
+ * @size: total size to copy. If -1, all data is copied
+ *
+ * Writes @size bytes of @data to @writer.
+ *
+ * Returns: %TRUE if the data could be written
+ *
+ */
+gboolean
+gst_byte_writer_put_buffer (GstByteWriter * writer, GstBuffer * buffer,
+    gsize offset, gssize size)
+{
+  g_return_val_if_fail (writer != NULL, FALSE);
+  g_return_val_if_fail (size >= -1, FALSE);
+
+  if (size == -1) {
+    size = gst_buffer_get_size (buffer);
+
+    if (offset >= (gsize) size)
+      return TRUE;
+
+    size -= offset;
+  }
+
+  if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
+    return FALSE;
+
+  gst_buffer_extract (buffer, offset,
+      (guint8 *) & writer->parent.data[writer->parent.byte], size);
+  writer->parent.byte += size;
+  writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
+
+  return TRUE;
+}
index 9a765c0..4f5da70 100644 (file)
@@ -46,25 +46,27 @@ typedef struct {
 
   gboolean fixed;
   gboolean owned;
+
+  /* < private > */
+  gpointer _gst_reserved[GST_PADDING];
 } GstByteWriter;
 
-GstByteWriter * gst_byte_writer_new (void) G_GNUC_MALLOC;
-GstByteWriter * gst_byte_writer_new_with_size (guint size, gboolean fixed) G_GNUC_MALLOC;
-GstByteWriter * gst_byte_writer_new_with_data (guint8 *data, guint size, gboolean initialized) G_GNUC_MALLOC;
-GstByteWriter * gst_byte_writer_new_with_buffer (GstBuffer *buffer, gboolean initialized) G_GNUC_MALLOC;
+GstByteWriter * gst_byte_writer_new             (void) G_GNUC_MALLOC;
+GstByteWriter * gst_byte_writer_new_with_size   (guint size, gboolean fixed) G_GNUC_MALLOC;
+GstByteWriter * gst_byte_writer_new_with_data   (guint8 *data, guint size, gboolean initialized) G_GNUC_MALLOC;
 
-void gst_byte_writer_init (GstByteWriter *writer);
-void gst_byte_writer_init_with_size (GstByteWriter *writer, guint size, gboolean fixed);
-void gst_byte_writer_init_with_data (GstByteWriter *writer, guint8 *data, guint size, gboolean initialized);
-void gst_byte_writer_init_with_buffer (GstByteWriter *writer, GstBuffer *buffer, gboolean initialized);
+void            gst_byte_writer_init            (GstByteWriter *writer);
+void            gst_byte_writer_init_with_size  (GstByteWriter *writer, guint size, gboolean fixed);
+void            gst_byte_writer_init_with_data  (GstByteWriter *writer, guint8 *data,
+                                                 guint size, gboolean initialized);
 
-void gst_byte_writer_free (GstByteWriter *writer);
-guint8 * gst_byte_writer_free_and_get_data (GstByteWriter *writer);
-GstBuffer *gst_byte_writer_free_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC;
+void            gst_byte_writer_free                    (GstByteWriter *writer);
+guint8 *        gst_byte_writer_free_and_get_data       (GstByteWriter *writer);
+GstBuffer *     gst_byte_writer_free_and_get_buffer     (GstByteWriter *writer) G_GNUC_MALLOC;
 
-void gst_byte_writer_reset (GstByteWriter *writer);
-guint8 * gst_byte_writer_reset_and_get_data (GstByteWriter *writer);
-GstBuffer *gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer) G_GNUC_MALLOC;
+void            gst_byte_writer_reset                   (GstByteWriter *writer);
+guint8 *        gst_byte_writer_reset_and_get_data      (GstByteWriter *writer);
+GstBuffer *     gst_byte_writer_reset_and_get_buffer    (GstByteWriter *writer) G_GNUC_MALLOC;
 
 /**
  * gst_byte_writer_get_pos:
@@ -95,9 +97,9 @@ GstBuffer *gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer) G_GNUC_M
  * Since: 0.10.26
  */
 #ifdef _FOOL_GTK_DOC_
-G_INLINE_FUNC guint gst_byte_writer_get_pos (const GstByteWriter *writer);
-G_INLINE_FUNC gboolean gst_byte_writer_set_pos (GstByteWriter *writer, guint pos);
-G_INLINE_FUNC guint gst_byte_writer_get_size (const GstByteWriter *writer);
+G_INLINE_FUNC guint     gst_byte_writer_get_pos  (const GstByteWriter *writer);
+G_INLINE_FUNC gboolean  gst_byte_writer_set_pos  (GstByteWriter *writer, guint pos);
+G_INLINE_FUNC guint     gst_byte_writer_get_size (const GstByteWriter *writer);
 #else
 static inline guint
 gst_byte_writer_get_pos (const GstByteWriter *writer)
@@ -118,38 +120,39 @@ gst_byte_writer_get_size (const GstByteWriter *writer)
 }
 #endif
 
-guint gst_byte_writer_get_remaining (const GstByteWriter *writer);
-gboolean gst_byte_writer_ensure_free_space (GstByteWriter *writer, guint size);
-
-gboolean gst_byte_writer_put_uint8 (GstByteWriter *writer, guint8 val);
-gboolean gst_byte_writer_put_int8 (GstByteWriter *writer, gint8 val);
-gboolean gst_byte_writer_put_uint16_be (GstByteWriter *writer, guint16 val);
-gboolean gst_byte_writer_put_uint16_le (GstByteWriter *writer, guint16 val);
-gboolean gst_byte_writer_put_int16_be (GstByteWriter *writer, gint16 val);
-gboolean gst_byte_writer_put_int16_le (GstByteWriter *writer, gint16 val);
-gboolean gst_byte_writer_put_uint24_be (GstByteWriter *writer, guint32 val);
-gboolean gst_byte_writer_put_uint24_le (GstByteWriter *writer, guint32 val);
-gboolean gst_byte_writer_put_int24_be (GstByteWriter *writer, gint32 val);
-gboolean gst_byte_writer_put_int24_le (GstByteWriter *writer, gint32 val);
-gboolean gst_byte_writer_put_uint32_be (GstByteWriter *writer, guint32 val);
-gboolean gst_byte_writer_put_uint32_le (GstByteWriter *writer, guint32 val);
-gboolean gst_byte_writer_put_int32_be (GstByteWriter *writer, gint32 val);
-gboolean gst_byte_writer_put_int32_le (GstByteWriter *writer, gint32 val);
-gboolean gst_byte_writer_put_uint64_be (GstByteWriter *writer, guint64 val);
-gboolean gst_byte_writer_put_uint64_le (GstByteWriter *writer, guint64 val);
-gboolean gst_byte_writer_put_int64_be (GstByteWriter *writer, gint64 val);
-gboolean gst_byte_writer_put_int64_le (GstByteWriter *writer, gint64 val);
-
-gboolean gst_byte_writer_put_float32_be (GstByteWriter *writer, gfloat val);
-gboolean gst_byte_writer_put_float32_le (GstByteWriter *writer, gfloat val);
-gboolean gst_byte_writer_put_float64_be (GstByteWriter *writer, gdouble val);
-gboolean gst_byte_writer_put_float64_le (GstByteWriter *writer, gdouble val);
-
-gboolean gst_byte_writer_put_data (GstByteWriter *writer, const guint8 *data, guint size);
-gboolean gst_byte_writer_fill (GstByteWriter *writer, guint8 value, guint size);
-gboolean gst_byte_writer_put_string_utf8 (GstByteWriter *writer, const gchar *data);
-gboolean gst_byte_writer_put_string_utf16 (GstByteWriter *writer, const guint16 *data);
-gboolean gst_byte_writer_put_string_utf32 (GstByteWriter *writer, const guint32 *data);
+guint           gst_byte_writer_get_remaining     (const GstByteWriter *writer);
+gboolean        gst_byte_writer_ensure_free_space (GstByteWriter *writer, guint size);
+
+gboolean        gst_byte_writer_put_uint8         (GstByteWriter *writer, guint8 val);
+gboolean        gst_byte_writer_put_int8          (GstByteWriter *writer, gint8 val);
+gboolean        gst_byte_writer_put_uint16_be     (GstByteWriter *writer, guint16 val);
+gboolean        gst_byte_writer_put_uint16_le     (GstByteWriter *writer, guint16 val);
+gboolean        gst_byte_writer_put_int16_be      (GstByteWriter *writer, gint16 val);
+gboolean        gst_byte_writer_put_int16_le      (GstByteWriter *writer, gint16 val);
+gboolean        gst_byte_writer_put_uint24_be     (GstByteWriter *writer, guint32 val);
+gboolean        gst_byte_writer_put_uint24_le     (GstByteWriter *writer, guint32 val);
+gboolean        gst_byte_writer_put_int24_be      (GstByteWriter *writer, gint32 val);
+gboolean        gst_byte_writer_put_int24_le      (GstByteWriter *writer, gint32 val);
+gboolean        gst_byte_writer_put_uint32_be     (GstByteWriter *writer, guint32 val);
+gboolean        gst_byte_writer_put_uint32_le     (GstByteWriter *writer, guint32 val);
+gboolean        gst_byte_writer_put_int32_be      (GstByteWriter *writer, gint32 val);
+gboolean        gst_byte_writer_put_int32_le      (GstByteWriter *writer, gint32 val);
+gboolean        gst_byte_writer_put_uint64_be     (GstByteWriter *writer, guint64 val);
+gboolean        gst_byte_writer_put_uint64_le     (GstByteWriter *writer, guint64 val);
+gboolean        gst_byte_writer_put_int64_be      (GstByteWriter *writer, gint64 val);
+gboolean        gst_byte_writer_put_int64_le      (GstByteWriter *writer, gint64 val);
+
+gboolean        gst_byte_writer_put_float32_be    (GstByteWriter *writer, gfloat val);
+gboolean        gst_byte_writer_put_float32_le    (GstByteWriter *writer, gfloat val);
+gboolean        gst_byte_writer_put_float64_be    (GstByteWriter *writer, gdouble val);
+gboolean        gst_byte_writer_put_float64_le    (GstByteWriter *writer, gdouble val);
+
+gboolean        gst_byte_writer_put_data          (GstByteWriter *writer, const guint8 *data, guint size);
+gboolean        gst_byte_writer_fill              (GstByteWriter *writer, guint8 value, guint size);
+gboolean        gst_byte_writer_put_string_utf8   (GstByteWriter *writer, const gchar *data);
+gboolean        gst_byte_writer_put_string_utf16  (GstByteWriter *writer, const guint16 *data);
+gboolean        gst_byte_writer_put_string_utf32  (GstByteWriter *writer, const guint32 *data);
+gboolean        gst_byte_writer_put_buffer        (GstByteWriter *writer, GstBuffer * buffer, gsize offset, gssize size);
 
 /**
  * gst_byte_writer_put_string:
index 7fb0bf4..1ad5015 100644 (file)
@@ -87,24 +87,21 @@ struct _GstCollectPadsPrivate
   gpointer clipfunc_user_data;
 };
 
-GST_BOILERPLATE (GstCollectPads, gst_collect_pads, GstObject, GST_TYPE_OBJECT);
+#define gst_collect_pads_parent_class parent_class
+G_DEFINE_TYPE (GstCollectPads, gst_collect_pads, GST_TYPE_OBJECT);
 
 static void gst_collect_pads_clear (GstCollectPads * pads,
     GstCollectData * data);
-static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_collect_pads_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static gboolean gst_collect_pads_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static void gst_collect_pads_finalize (GObject * object);
 static void ref_data (GstCollectData * data);
 static void unref_data (GstCollectData * data);
 static void gst_collect_pads_check_pads_unlocked (GstCollectPads * pads);
 
 static void
-gst_collect_pads_base_init (gpointer g_class)
-{
-  /* Do nothing here */
-}
-
-static void
 gst_collect_pads_class_init (GstCollectPadsClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
@@ -118,11 +115,11 @@ gst_collect_pads_class_init (GstCollectPadsClass * klass)
 }
 
 static void
-gst_collect_pads_init (GstCollectPads * pads, GstCollectPadsClass * g_class)
+gst_collect_pads_init (GstCollectPads * pads)
 {
-  pads->abidata.ABI.priv = GST_COLLECT_PADS_GET_PRIVATE (pads);
+  pads->priv = GST_COLLECT_PADS_GET_PRIVATE (pads);
 
-  pads->cond = g_cond_new ();
+  g_cond_init (&pads->cond);
   pads->data = NULL;
   pads->cookie = 0;
   pads->numpads = 0;
@@ -131,9 +128,9 @@ gst_collect_pads_init (GstCollectPads * pads, GstCollectPadsClass * g_class)
   pads->started = FALSE;
 
   /* members to manage the pad list */
-  pads->abidata.ABI.pad_lock = g_mutex_new ();
-  pads->abidata.ABI.pad_cookie = 0;
-  pads->abidata.ABI.pad_list = NULL;
+  g_mutex_init (&pads->pad_lock);
+  pads->pad_cookie = 0;
+  pads->pad_list = NULL;
 }
 
 static void
@@ -144,11 +141,11 @@ gst_collect_pads_finalize (GObject * object)
 
   GST_DEBUG ("finalize");
 
-  g_cond_free (pads->cond);
-  g_mutex_free (pads->abidata.ABI.pad_lock);
+  g_cond_clear (&pads->cond);
+  g_mutex_clear (&pads->pad_lock);
 
   /* Remove pads */
-  collected = pads->abidata.ABI.pad_list;
+  collected = pads->pad_list;
   for (; collected; collected = g_slist_next (collected)) {
     GstCollectData *pdata = (GstCollectData *) collected->data;
 
@@ -157,7 +154,7 @@ gst_collect_pads_finalize (GObject * object)
   /* Free pads list */
   g_slist_foreach (pads->data, (GFunc) unref_data, NULL);
   g_slist_free (pads->data);
-  g_slist_free (pads->abidata.ABI.pad_list);
+  g_slist_free (pads->pad_list);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -210,32 +207,23 @@ ref_data (GstCollectData * data)
 {
   g_assert (data != NULL);
 
-  g_atomic_int_inc (&(data->abidata.ABI.refcount));
+  g_atomic_int_inc (&(data->refcount));
 }
 
 static void
 unref_data (GstCollectData * data)
 {
-  GstCollectDataDestroyNotify destroy_notify;
-
   g_assert (data != NULL);
-  g_assert (data->abidata.ABI.refcount > 0);
+  g_assert (data->refcount > 0);
 
-  if (!g_atomic_int_dec_and_test (&(data->abidata.ABI.refcount)))
+  if (!g_atomic_int_dec_and_test (&(data->refcount)))
     return;
 
-  /* FIXME: Ugly hack as we can't add more fields to GstCollectData */
-  destroy_notify = (GstCollectDataDestroyNotify)
-      g_object_get_data (G_OBJECT (data->pad),
-      "gst-collect-data-destroy-notify");
-
-  if (destroy_notify)
-    destroy_notify (data);
-
+  if (data->destroy_notify)
+    data->destroy_notify (data);
   g_object_unref (data->pad);
-  if (data->buffer) {
+  if (data->buffer)
     gst_buffer_unref (data->buffer);
-  }
   g_free (data);
 }
 
@@ -244,41 +232,6 @@ unref_data (GstCollectData * data)
  * @pads: the collectspads to use
  * @pad: (transfer none): the pad to add
  * @size: the size of the returned #GstCollectData structure
- *
- * Add a pad to the collection of collect pads. The pad has to be
- * a sinkpad. The refcount of the pad is incremented. Use
- * gst_collect_pads_remove_pad() to remove the pad from the collection
- * again.
- *
- * This function will override the chain and event functions of the pad
- * along with the element_private data, which is used to store private
- * information for the collectpads.
- *
- * You specify a size for the returned #GstCollectData structure
- * so that you can use it to store additional information.
- *
- * The pad will be automatically activated in push mode when @pads is
- * started.
- *
- * This function calls gst_collect_pads_add_pad_full() passing a value of NULL
- * for destroy_notify.
- *
- * MT safe.
- *
- * Returns: a new #GstCollectData to identify the new pad. Or NULL
- *   if wrong parameters are supplied.
- */
-GstCollectData *
-gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
-{
-  return gst_collect_pads_add_pad_full (pads, pad, size, NULL);
-}
-
-/**
- * gst_collect_pads_add_pad_full:
- * @pads: the collectspads to use
- * @pad: (transfer none): the pad to add
- * @size: the size of the returned #GstCollectData structure
  * @destroy_notify: function to be called before the returned #GstCollectData
  * structure is freed
  *
@@ -300,13 +253,11 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
  *
  * MT safe.
  *
- * Since: 0.10.12
- *
  * Returns: a new #GstCollectData to identify the new pad. Or NULL
  *   if wrong parameters are supplied.
  */
 GstCollectData *
-gst_collect_pads_add_pad_full (GstCollectPads * pads, GstPad * pad, guint size,
+gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size,
     GstCollectDataDestroyNotify destroy_notify)
 {
   GstCollectData *data;
@@ -325,27 +276,23 @@ gst_collect_pads_add_pad_full (GstCollectPads * pads, GstPad * pad, guint size,
   data->buffer = NULL;
   data->pos = 0;
   gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
-  data->abidata.ABI.flushing = FALSE;
-  data->abidata.ABI.new_segment = FALSE;
-  data->abidata.ABI.eos = FALSE;
-  data->abidata.ABI.refcount = 1;
-
-  /* FIXME: Ugly hack as we can't add more fields to GstCollectData */
-  g_object_set_data (G_OBJECT (pad), "gst-collect-data-destroy-notify",
-      (void *) destroy_notify);
+  data->flushing = FALSE;
+  data->new_segment = FALSE;
+  data->eos = FALSE;
+  data->refcount = 1;
+  data->destroy_notify = destroy_notify;
 
   GST_COLLECT_PADS_PAD_LOCK (pads);
   GST_OBJECT_LOCK (pad);
   gst_pad_set_element_private (pad, data);
   GST_OBJECT_UNLOCK (pad);
-  pads->abidata.ABI.pad_list =
-      g_slist_append (pads->abidata.ABI.pad_list, data);
+  pads->pad_list = g_slist_append (pads->pad_list, data);
   gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_chain));
   gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_event));
   /* activate the pad when needed */
   if (pads->started)
     gst_pad_set_active (pad, TRUE);
-  pads->abidata.ABI.pad_cookie++;
+  pads->pad_cookie++;
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
 
   return data;
@@ -379,7 +326,7 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads,
   g_return_if_fail (pads != NULL);
   g_return_if_fail (GST_IS_COLLECT_PADS (pads));
 
-  priv = pads->abidata.ABI.priv;
+  priv = pads->priv;
 
   priv->clipfunc = clipfunc;
   priv->clipfunc_user_data = user_data;
@@ -414,9 +361,7 @@ gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
   GST_DEBUG ("removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
   GST_COLLECT_PADS_PAD_LOCK (pads);
-  list =
-      g_slist_find_custom (pads->abidata.ABI.pad_list, pad,
-      (GCompareFunc) find_pad);
+  list = g_slist_find_custom (pads->pad_list, pad, (GCompareFunc) find_pad);
   if (!list)
     goto unknown_pad;
 
@@ -446,9 +391,8 @@ gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
     }
   }
   /* remove from the pad list */
-  pads->abidata.ABI.pad_list =
-      g_slist_delete_link (pads->abidata.ABI.pad_list, list);
-  pads->abidata.ABI.pad_cookie++;
+  pads->pad_list = g_slist_delete_link (pads->pad_list, list);
+  pads->pad_cookie++;
 
   /* signal waiters because something changed */
   GST_COLLECT_PADS_BROADCAST (pads);
@@ -566,9 +510,9 @@ gst_collect_pads_is_flushing (GstCollectPads * pads)
   for (walk = pads->data; walk; walk = g_slist_next (walk)) {
     GstCollectData *cdata = walk->data;
 
-    GST_DEBUG_OBJECT (cdata->pad, "flushing:%d", cdata->abidata.ABI.flushing);
+    GST_DEBUG_OBJECT (cdata->pad, "flushing:%d", cdata->flushing);
 
-    if (cdata->abidata.ABI.flushing) {
+    if (cdata->flushing) {
       goto done;
     }
   }
@@ -602,7 +546,7 @@ gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads,
         GST_PAD_SET_FLUSHING (cdata->pad);
       else
         GST_PAD_UNSET_FLUSHING (cdata->pad);
-      cdata->abidata.ABI.flushing = flushing;
+      cdata->flushing = flushing;
       gst_collect_pads_clear (pads, cdata);
       GST_OBJECT_UNLOCK (cdata->pad);
     }
@@ -610,7 +554,7 @@ gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads,
   /* Setting the pads to flushing means that we changed the values which
    * are 'protected' by the cookie. We therefore update it to force a
    * recalculation of the current pad status. */
-  pads->abidata.ABI.pad_cookie++;
+  pads->pad_cookie++;
 }
 
 /**
@@ -664,7 +608,7 @@ gst_collect_pads_start (GstCollectPads * pads)
   GST_COLLECT_PADS_PAD_LOCK (pads);
 
   /* loop over the master pad list and reset the segment */
-  collected = pads->abidata.ABI.pad_list;
+  collected = pads->pad_list;
   for (; collected; collected = g_slist_next (collected)) {
     GstCollectData *data;
 
@@ -712,7 +656,7 @@ gst_collect_pads_stop (GstCollectPads * pads)
   pads->queuedpads = 0;
 
   /* loop over the master pad list and flush buffers */
-  collected = pads->abidata.ABI.pad_list;
+  collected = pads->pad_list;
   for (; collected; collected = g_slist_next (collected)) {
     GstCollectData *data;
     GstBuffer **buffer_p;
@@ -723,7 +667,7 @@ gst_collect_pads_stop (GstCollectPads * pads)
       gst_buffer_replace (buffer_p, NULL);
       data->pos = 0;
     }
-    data->abidata.ABI.eos = FALSE;
+    data->eos = FALSE;
   }
 
   GST_COLLECT_PADS_PAD_UNLOCK (pads);
@@ -850,7 +794,7 @@ gst_collect_pads_available (GstCollectPads * pads)
     pdata = (GstCollectData *) collected->data;
 
     /* ignore pad with EOS */
-    if (G_UNLIKELY (pdata->abidata.ABI.eos)) {
+    if (G_UNLIKELY (pdata->eos)) {
       GST_DEBUG ("pad %s:%s is EOS", GST_DEBUG_PAD_NAME (pdata->pad));
       continue;
     }
@@ -862,7 +806,7 @@ gst_collect_pads_available (GstCollectPads * pads)
     }
 
     /* this is the size left of the buffer */
-    size = GST_BUFFER_SIZE (buffer) - pdata->pos;
+    size = gst_buffer_get_size (buffer) - pdata->pos;
     GST_DEBUG ("pad %s:%s has %d bytes left",
         GST_DEBUG_PAD_NAME (pdata->pad), size);
 
@@ -883,48 +827,6 @@ not_filled:
 }
 
 /**
- * gst_collect_pads_read:
- * @pads: the collectspads to query
- * @data: the data to use
- * @bytes: (out) (transfer none) (array length=size): a pointer to a byte array
- * @size: the number of bytes to read
- *
- * Get a pointer in @bytes where @size bytes can be read from the
- * given pad @data.
- *
- * This function should be called with @pads LOCK held, such as
- * in the callback.
- *
- * MT safe.
- *
- * Returns: The number of bytes available for consumption in the
- * memory pointed to by @bytes. This can be less than @size and
- * is 0 if the pad is end-of-stream.
- */
-guint
-gst_collect_pads_read (GstCollectPads * pads, GstCollectData * data,
-    guint8 ** bytes, guint size)
-{
-  guint readsize;
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (pads != NULL, 0);
-  g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0);
-  g_return_val_if_fail (data != NULL, 0);
-  g_return_val_if_fail (bytes != NULL, 0);
-
-  /* no buffer, must be EOS */
-  if ((buffer = data->buffer) == NULL)
-    return 0;
-
-  readsize = MIN (size, GST_BUFFER_SIZE (buffer) - data->pos);
-
-  *bytes = GST_BUFFER_DATA (buffer) + data->pos;
-
-  return readsize;
-}
-
-/**
  * gst_collect_pads_read_buffer:
  * @pads: the collectspads to query
  * @data: the data to use
@@ -959,14 +861,15 @@ gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
   if ((buffer = data->buffer) == NULL)
     return NULL;
 
-  bufsize = GST_BUFFER_SIZE (buffer);
+  bufsize = gst_buffer_get_size (buffer);
 
   readsize = MIN (size, bufsize - data->pos);
 
   if (data->pos == 0 && readsize == bufsize)
     return gst_buffer_ref (buffer);
   else
-    return gst_buffer_create_sub (buffer, data->pos, readsize);
+    return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos,
+        readsize);
 }
 
 /**
@@ -997,7 +900,7 @@ gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data,
   GstBuffer *buffer = gst_collect_pads_read_buffer (pads, data, size);
 
   if (buffer) {
-    gst_collect_pads_flush (pads, data, GST_BUFFER_SIZE (buffer));
+    gst_collect_pads_flush (pads, data, gst_buffer_get_size (buffer));
   }
   return buffer;
 }
@@ -1024,6 +927,7 @@ gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,
 {
   guint flushsize;
   GstBuffer *buffer;
+  gsize bsize;
 
   g_return_val_if_fail (pads != NULL, 0);
   g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0);
@@ -1033,14 +937,16 @@ gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,
   if ((buffer = data->buffer) == NULL)
     return 0;
 
+  bsize = gst_buffer_get_size (buffer);
+
   /* this is what we can flush at max */
-  flushsize = MIN (size, GST_BUFFER_SIZE (buffer) - data->pos);
+  flushsize = MIN (size, bsize - data->pos);
 
   data->pos += size;
 
   GST_LOG_OBJECT (pads, "Flushing %d bytes, requested %u", flushsize, size);
 
-  if (data->pos >= GST_BUFFER_SIZE (buffer))
+  if (data->pos >= bsize)
     /* _clear will also reset data->pos to 0 */
     gst_collect_pads_clear (pads, data);
 
@@ -1060,8 +966,8 @@ static void
 gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
 {
   GST_DEBUG ("stored cookie : %d, used_cookie:%d",
-      pads->abidata.ABI.pad_cookie, pads->cookie);
-  if (G_UNLIKELY (pads->abidata.ABI.pad_cookie != pads->cookie)) {
+      pads->pad_cookie, pads->cookie);
+  if (G_UNLIKELY (pads->pad_cookie != pads->cookie)) {
     GSList *collected;
 
     /* clear list and stats */
@@ -1073,7 +979,7 @@ gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
     pads->eospads = 0;
 
     /* loop over the master pad list */
-    collected = pads->abidata.ABI.pad_list;
+    collected = pads->pad_list;
     for (; collected; collected = g_slist_next (collected)) {
       GstCollectData *data;
 
@@ -1081,10 +987,10 @@ gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
       pads->numpads++;
       data = collected->data;
 
-      if (G_LIKELY (!data->abidata.ABI.flushing)) {
+      if (G_LIKELY (!data->flushing)) {
         if (data->buffer)
           pads->queuedpads++;
-        if (data->abidata.ABI.eos)
+        if (data->eos)
           pads->eospads++;
       }
 
@@ -1093,7 +999,7 @@ gst_collect_pads_check_pads_unlocked (GstCollectPads * pads)
       pads->data = g_slist_prepend (pads->data, data);
     }
     /* and update the cookie */
-    pads->cookie = pads->abidata.ABI.pad_cookie;
+    pads->cookie = pads->pad_cookie;
   }
 }
 
@@ -1159,7 +1065,7 @@ gst_collect_pads_check_collected (GstCollectPads * pads)
 }
 
 static gboolean
-gst_collect_pads_event (GstPad * pad, GstEvent * event)
+gst_collect_pads_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res;
   GstCollectData *data;
@@ -1184,13 +1090,13 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_START:
     {
       /* forward event to unblock check_collected */
-      gst_pad_event_default (pad, event);
+      gst_pad_event_default (pad, parent, event);
 
       /* now unblock the chain function.
        * no cond per pad, so they all unblock,
        * non-flushing block again */
       GST_OBJECT_LOCK (pads);
-      data->abidata.ABI.flushing = TRUE;
+      data->flushing = TRUE;
       gst_collect_pads_clear (pads, data);
       GST_OBJECT_UNLOCK (pads);
 
@@ -1201,16 +1107,16 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
     {
       /* flush the 1 buffer queue */
       GST_OBJECT_LOCK (pads);
-      data->abidata.ABI.flushing = FALSE;
+      data->flushing = FALSE;
       gst_collect_pads_clear (pads, data);
       /* we need new segment info after the flush */
       gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
-      data->abidata.ABI.new_segment = FALSE;
+      data->new_segment = FALSE;
       /* if the pad was EOS, remove the EOS flag and
        * decrement the number of eospads */
-      if (G_UNLIKELY (data->abidata.ABI.eos == TRUE)) {
+      if (G_UNLIKELY (data->eos == TRUE)) {
         pads->eospads--;
-        data->abidata.ABI.eos = FALSE;
+        data->eos = FALSE;
       }
 
       if (!gst_collect_pads_is_flushing (pads)) {
@@ -1228,8 +1134,8 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
       GST_OBJECT_LOCK (pads);
       /* if the pad was not EOS, make it EOS and so we
        * have one more eospad */
-      if (G_LIKELY (data->abidata.ABI.eos == FALSE)) {
-        data->abidata.ABI.eos = TRUE;
+      if (G_LIKELY (data->eos == FALSE)) {
+        data->eos = TRUE;
         pads->eospads++;
       }
       /* check if we need collecting anything, we ignore the
@@ -1242,24 +1148,13 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
       gst_event_unref (event);
       goto done;
     }
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gint64 start, stop, time;
-      gdouble rate, arate;
-      GstFormat format;
-      gboolean update;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      GST_DEBUG_OBJECT (data->pad, "got newsegment, start %" GST_TIME_FORMAT
-          ", stop %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
-          GST_TIME_ARGS (stop));
-
-      gst_segment_set_newsegment_full (&data->segment, update, rate, arate,
-          format, start, stop, time);
+      gst_event_copy_segment (event, &data->segment);
 
-      data->abidata.ABI.new_segment = TRUE;
+      GST_DEBUG_OBJECT (data->pad, "got newsegment %" GST_SEGMENT_FORMAT,
+          &data->segment);
+      data->new_segment = TRUE;
 
       /* we must not forward this event since multiple segments will be
        * accumulated and this is certainly not what we want. */
@@ -1284,7 +1179,7 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
 forward:
   GST_DEBUG_OBJECT (pads, "forward unhandled event: %s",
       GST_EVENT_TYPE_NAME (event));
-  res = gst_pad_event_default (pad, event);
+  res = gst_pad_event_default (pad, parent, event);
 
 done:
   unref_data (data);
@@ -1306,7 +1201,7 @@ pad_removed:
  * collected
  */
 static GstFlowReturn
-gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer)
+gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstCollectData *data;
   GstCollectPads *pads;
@@ -1324,17 +1219,17 @@ gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer)
   GST_OBJECT_UNLOCK (pad);
 
   pads = data->collect;
-  priv = pads->abidata.ABI.priv;
+  priv = pads->priv;
 
   GST_OBJECT_LOCK (pads);
   /* if not started, bail out */
   if (G_UNLIKELY (!pads->started))
     goto not_started;
   /* check if this pad is flushing */
-  if (G_UNLIKELY (data->abidata.ABI.flushing))
+  if (G_UNLIKELY (data->flushing))
     goto flushing;
   /* pad was EOS, we can refuse this data */
-  if (G_UNLIKELY (data->abidata.ABI.eos))
+  if (G_UNLIKELY (data->eos))
     goto unexpected;
 
   /* see if we need to clip */
@@ -1361,7 +1256,7 @@ gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer)
     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (data->buffer);
 
     if (GST_CLOCK_TIME_IS_VALID (timestamp))
-      gst_segment_set_last_stop (&data->segment, GST_FORMAT_TIME, timestamp);
+      data->segment.position = timestamp;
   }
 
   /* While we have data queued on this pad try to collect stuff */
@@ -1403,7 +1298,7 @@ gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer)
     if (G_UNLIKELY (!pads->started))
       goto not_started;
     /* check if this pad is flushing */
-    if (G_UNLIKELY (data->abidata.ABI.flushing))
+    if (G_UNLIKELY (data->flushing))
       goto flushing;
   }
   while (data->buffer != NULL);
@@ -1450,7 +1345,7 @@ unexpected:
     /* we should not post an error for this, just inform upstream that
      * we don't expect anything anymore */
     GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad));
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_EOS;
     goto unlock_done;
   }
 clipped:
index 939c2f6..9dbd8ca 100644 (file)
@@ -52,16 +52,16 @@ typedef void (*GstCollectDataDestroyNotify) (GstCollectData *data);
 
 /**
  * GstCollectPadsClipFunction:
- * @pads: a #GstCollectPads 
- * @data: a #GstCollectData 
- * @buffer: a #GstBuffer 
- * @user_data: user data 
+ * @pads: a #GstCollectPads
+ * @data: a #GstCollectData
+ * @buffer: a #GstBuffer
+ * @user_data: user data
  *
  * A function that will be called when @buffer is received on the pad managed
  * by @data in the collecpad object @pads.
  *
  * The function should use the segment of @data and the negotiated media type on
- * the pad to perform clipping of @buffer. 
+ * the pad to perform clipping of @buffer.
  *
  * This function takes ownership of @buffer.
  *
@@ -92,16 +92,19 @@ struct _GstCollectData
   guint                  pos;
   GstSegment             segment;
 
+  gboolean               flushing;
+  gboolean               new_segment;
+  gboolean               eos;
+  gint                   refcount;
+  GstCollectDataDestroyNotify destroy_notify;
+
   /*< private >*/
   union {
-    struct {
-      gboolean           flushing;
-      gboolean           new_segment;
-      gboolean           eos;
-      gint               refcount;
-    } ABI;
+    /*struct {
+    } ABI;*/
     /* adding + 0 to mark ABI change to be undone later */
-    gpointer _gst_reserved[GST_PADDING + 0];
+    gpointer _gst_reserved[GST_PADDING];
   } abidata;
 };
 
@@ -116,11 +119,11 @@ struct _GstCollectData
  */
 typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data);
 
-#define GST_COLLECT_PADS_GET_PAD_LOCK(pads) (((GstCollectPads *)pads)->abidata.ABI.pad_lock)
+#define GST_COLLECT_PADS_GET_PAD_LOCK(pads) (&((GstCollectPads *)pads)->pad_lock)
 #define GST_COLLECT_PADS_PAD_LOCK(pads)     (g_mutex_lock(GST_COLLECT_PADS_GET_PAD_LOCK (pads)))
 #define GST_COLLECT_PADS_PAD_UNLOCK(pads)   (g_mutex_unlock(GST_COLLECT_PADS_GET_PAD_LOCK (pads)))
 
-#define GST_COLLECT_PADS_GET_COND(pads) (((GstCollectPads *)pads)->cond)
+#define GST_COLLECT_PADS_GET_COND(pads) (&((GstCollectPads *)pads)->cond)
 #define GST_COLLECT_PADS_WAIT(pads)     (g_cond_wait (GST_COLLECT_PADS_GET_COND (pads), GST_OBJECT_GET_LOCK (pads)))
 #define GST_COLLECT_PADS_SIGNAL(pads)   (g_cond_signal (GST_COLLECT_PADS_GET_COND (pads)))
 #define GST_COLLECT_PADS_BROADCAST(pads)(g_cond_broadcast (GST_COLLECT_PADS_GET_COND (pads)))
@@ -143,7 +146,7 @@ struct _GstCollectPads {
   guint32        cookie;                /* @data list cookie */
 
   /* with LOCK */
-  GCond         *cond;                  /* to signal removal of data */
+  GCond          cond;                  /* to signal removal of data */
 
   GstCollectPadsFunction func;          /* function and user_data for callback */
   gpointer       user_data;
@@ -155,17 +158,18 @@ struct _GstCollectPads {
   /* with LOCK and PAD_LOCK*/
   gboolean       started;
 
+  /* with PAD_LOCK */
+  GMutex         pad_lock;              /* used to serialize add/remove */
+  GSList        *pad_list;              /* updated pad list */
+  guint32        pad_cookie;            /* updated cookie */
+  GstCollectPadsPrivate  *priv;
+
   /*< private >*/
   union {
-    struct {
-      /* since 0.10.6 */ /* with PAD_LOCK */
-      GMutex    *pad_lock;              /* used to serialize add/remove */
-      GSList    *pad_list;              /* updated pad list */
-      guint32    pad_cookie;            /* updated cookie */
-      GstCollectPadsPrivate  *priv;
-    } ABI;
+    /*struct {
+    } ABI;*/
     /* adding + 0 to mark ABI change to be undone later */
-    gpointer _gst_reserved[GST_PADDING + 0];
+    gpointer _gst_reserved[GST_PADDING];
   } abidata;
 };
 
@@ -188,8 +192,7 @@ void            gst_collect_pads_set_clip_function (GstCollectPads *pads, GstCol
                                                     gpointer user_data);
 
 /* pad management */
-GstCollectData* gst_collect_pads_add_pad        (GstCollectPads *pads, GstPad *pad, guint size);
-GstCollectData* gst_collect_pads_add_pad_full   (GstCollectPads *pads, GstPad *pad, guint size, GstCollectDataDestroyNotify destroy_notify);
+GstCollectData* gst_collect_pads_add_pad        (GstCollectPads *pads, GstPad *pad, guint size, GstCollectDataDestroyNotify destroy_notify);
 
 
 gboolean        gst_collect_pads_remove_pad     (GstCollectPads *pads, GstPad *pad);
@@ -209,8 +212,6 @@ GstBuffer*      gst_collect_pads_pop            (GstCollectPads *pads, GstCollec
 
 /* get collected bytes */
 guint           gst_collect_pads_available      (GstCollectPads *pads);
-guint           gst_collect_pads_read           (GstCollectPads *pads, GstCollectData *data,
-                                                 guint8 **bytes, guint size);
 GstBuffer *     gst_collect_pads_read_buffer    (GstCollectPads * pads, GstCollectData * data,
                                                  guint size);
 GstBuffer *     gst_collect_pads_take_buffer    (GstCollectPads * pads, GstCollectData * data,
index 3e51a0c..3d14577 100644 (file)
@@ -86,9 +86,6 @@
 #  include "config.h"
 #endif
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <gst/gst_private.h>
 
 #include "gstcollectpads2.h"
@@ -103,8 +100,10 @@ G_DEFINE_TYPE (GstCollectPads2, gst_collect_pads2, GST_TYPE_OBJECT);
 
 static void gst_collect_pads2_clear (GstCollectPads2 * pads,
     GstCollectData2 * data);
-static GstFlowReturn gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_collect_pads2_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_collect_pads2_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static gboolean gst_collect_pads2_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static void gst_collect_pads2_finalize (GObject * object);
 static GstFlowReturn gst_collect_pads2_default_collected (GstCollectPads2 *
     pads, gpointer user_data);
@@ -121,8 +120,8 @@ static void unref_data (GstCollectData2 * data);
  * Alternative implementations are possible, e.g. some low-level re-implementing
  * of the 2 above locks to drop both of them atomically when going into _WAIT.
  */
-#define GST_COLLECT_PADS2_GET_EVT_COND(pads) (((GstCollectPads2 *)pads)->evt_cond)
-#define GST_COLLECT_PADS2_GET_EVT_LOCK(pads) (((GstCollectPads2 *)pads)->evt_lock)
+#define GST_COLLECT_PADS2_GET_EVT_COND(pads) (&((GstCollectPads2 *)pads)->evt_cond)
+#define GST_COLLECT_PADS2_GET_EVT_LOCK(pads) (&((GstCollectPads2 *)pads)->evt_lock)
 #define GST_COLLECT_PADS2_EVT_WAIT(pads, cookie) G_STMT_START {    \
   g_mutex_lock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads));            \
   /* should work unless a lot of event'ing and thread starvation */\
@@ -180,7 +179,7 @@ gst_collect_pads2_init (GstCollectPads2 * pads)
   pads->eospads = 0;
   pads->started = FALSE;
 
-  g_static_rec_mutex_init (&pads->stream_lock);
+  g_rec_mutex_init (&pads->stream_lock);
 
   pads->func = gst_collect_pads2_default_collected;
   pads->user_data = NULL;
@@ -200,8 +199,8 @@ gst_collect_pads2_init (GstCollectPads2 * pads)
   pads->pad_list = NULL;
 
   /* members for event */
-  pads->evt_lock = g_mutex_new ();
-  pads->evt_cond = g_cond_new ();
+  g_mutex_init (&pads->evt_lock);
+  g_cond_init (&pads->evt_cond);
   pads->evt_cookie = 0;
 }
 
@@ -212,10 +211,10 @@ gst_collect_pads2_finalize (GObject * object)
 
   GST_DEBUG_OBJECT (object, "finalize");
 
-  g_static_rec_mutex_free (&pads->stream_lock);
+  g_rec_mutex_clear (&pads->stream_lock);
 
-  g_cond_free (pads->evt_cond);
-  g_mutex_free (pads->evt_lock);
+  g_cond_clear (&pads->evt_cond);
+  g_mutex_clear (&pads->evt_lock);
 
   /* Remove pads and free pads list */
   g_slist_foreach (pads->pad_list, (GFunc) unref_data, NULL);
@@ -435,7 +434,7 @@ gst_collect_pads2_clip_running_time (GstCollectPads2 * pads,
       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));
-      *outbuf = gst_buffer_make_metadata_writable (buf);
+      *outbuf = gst_buffer_make_writable (buf);
       GST_BUFFER_TIMESTAMP (*outbuf) = time;
     }
   }
@@ -1067,7 +1066,7 @@ gst_collect_pads2_available (GstCollectPads2 * pads)
     }
 
     /* this is the size left of the buffer */
-    size = GST_BUFFER_SIZE (buffer) - pdata->pos;
+    size = gst_buffer_get_size (buffer) - pdata->pos;
     GST_DEBUG_OBJECT (pads, "pad %p has %d bytes left", pdata, size);
 
     /* need to return the min of all available data */
@@ -1087,50 +1086,6 @@ not_filled:
 }
 
 /**
- * gst_collect_pads2_read:
- * @pads: the collectspads to query
- * @data: the data to use
- * @bytes: a pointer to a byte array
- * @size: the number of bytes to read
- *
- * Get a pointer in @bytes where @size bytes can be read from the
- * given pad data.
- *
- * This function should be called with @pads STREAM_LOCK held, such as
- * in the callback.
- *
- * Returns: The number of bytes available for consumption in the
- * memory pointed to by @bytes. This can be less than @size and
- * is 0 if the pad is end-of-stream.
- *
- * MT safe.
- *
- * Since: 0.10.36
- */
-guint
-gst_collect_pads2_read (GstCollectPads2 * pads, GstCollectData2 * data,
-    guint8 ** bytes, guint size)
-{
-  guint readsize;
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (pads != NULL, 0);
-  g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), 0);
-  g_return_val_if_fail (data != NULL, 0);
-  g_return_val_if_fail (bytes != NULL, 0);
-
-  /* no buffer, must be EOS */
-  if ((buffer = data->buffer) == NULL)
-    return 0;
-
-  readsize = MIN (size, GST_BUFFER_SIZE (buffer) - data->pos);
-
-  *bytes = GST_BUFFER_DATA (buffer) + data->pos;
-
-  return readsize;
-}
-
-/**
  * gst_collect_pads2_flush:
  * @pads: the collectspads to query
  * @data: the data to use
@@ -1153,6 +1108,7 @@ gst_collect_pads2_flush (GstCollectPads2 * pads, GstCollectData2 * data,
     guint size)
 {
   guint flushsize;
+  gsize bsize;
   GstBuffer *buffer;
 
   g_return_val_if_fail (pads != NULL, 0);
@@ -1163,12 +1119,14 @@ gst_collect_pads2_flush (GstCollectPads2 * pads, GstCollectData2 * data,
   if ((buffer = data->buffer) == NULL)
     return 0;
 
+  bsize = gst_buffer_get_size (buffer);
+
   /* this is what we can flush at max */
-  flushsize = MIN (size, GST_BUFFER_SIZE (buffer) - data->pos);
+  flushsize = MIN (size, bsize - data->pos);
 
   data->pos += size;
 
-  if (data->pos >= GST_BUFFER_SIZE (buffer))
+  if (data->pos >= bsize)
     /* _clear will also reset data->pos to 0 */
     gst_collect_pads2_clear (pads, data);
 
@@ -1209,9 +1167,10 @@ gst_collect_pads2_read_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
   if ((buffer = data->buffer) == NULL)
     return NULL;
 
-  readsize = MIN (size, GST_BUFFER_SIZE (buffer) - data->pos);
+  readsize = MIN (size, gst_buffer_get_size (buffer) - data->pos);
 
-  return gst_buffer_create_sub (buffer, data->pos, readsize);
+  return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos,
+      readsize);
 }
 
 /**
@@ -1241,7 +1200,7 @@ gst_collect_pads2_take_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
   GstBuffer *buffer = gst_collect_pads2_read_buffer (pads, data, size);
 
   if (buffer) {
-    gst_collect_pads2_flush (pads, data, GST_BUFFER_SIZE (buffer));
+    gst_collect_pads2_flush (pads, data, gst_buffer_get_size (buffer));
   }
   return buffer;
 }
@@ -1578,7 +1537,7 @@ gst_collect_pads2_default_collected (GstCollectPads2 * pads, gpointer user_data)
   if (G_UNLIKELY (best == NULL)) {
     ret = func (pads, best, NULL, buffer_user_data);
     if (ret == GST_FLOW_OK)
-      ret = GST_FLOW_UNEXPECTED;
+      ret = GST_FLOW_EOS;
     goto done;
   }
 
@@ -1630,7 +1589,7 @@ gst_collect_pads2_default_compare_func (GstCollectPads2 * pads,
 }
 
 static gboolean
-gst_collect_pads2_event (GstPad * pad, GstEvent * event)
+gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = FALSE, need_unlock = FALSE;
   GstCollectData2 *data;
@@ -1667,7 +1626,7 @@ gst_collect_pads2_event (GstPad * pad, GstEvent * event)
       if (event_func)
         res = event_func (pads, data, event, event_user_data);
       if (!res)
-        res = gst_pad_event_default (pad, event);
+        res = gst_pad_event_default (pad, parent, event);
 
       /* now unblock the chain function.
        * no cond per pad, so they all unblock, 
@@ -1737,26 +1696,18 @@ gst_collect_pads2_event (GstPad * pad, GstEvent * event)
 
       goto forward_or_eat;
     }
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gint64 start, stop, time;
-      gdouble rate, arate;
-      GstFormat format;
-      gboolean update;
+      GstSegment seg;
       gint cmp_res;
 
       GST_COLLECT_PADS2_STREAM_LOCK (pads);
 
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      GST_DEBUG_OBJECT (data->pad, "got newsegment, start %" GST_TIME_FORMAT
-          ", stop %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
-          GST_TIME_ARGS (stop));
+      gst_event_copy_segment (event, &seg);
 
-      gst_segment_set_newsegment_full (&data->segment, update, rate, arate,
-          format, start, stop, time);
+      GST_DEBUG_OBJECT (data->pad, "got segment %" GST_SEGMENT_FORMAT, &seg);
 
+      data->segment = seg;
       GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_NEW_SEGMENT);
 
       /* default muxing functionality */
@@ -1764,7 +1715,7 @@ gst_collect_pads2_event (GstPad * pad, GstEvent * event)
         goto newsegment_done;
 
       /* default collection can not handle other segment formats than time */
-      if (format != GST_FORMAT_TIME) {
+      if (seg.format != GST_FORMAT_TIME) {
         GST_ERROR_OBJECT (pads, "GstCollectPads2 default collecting "
             "can only handle time segments.");
         goto newsegment_done;
@@ -1778,7 +1729,7 @@ gst_collect_pads2_event (GstPad * pad, GstEvent * event)
       }
 
       /* Check if the waiting state of the pad should change. */
-      cmp_res = pads->compare_func (pads, data, start, pads->earliest_data,
+      cmp_res = pads->compare_func (pads, data, seg.start, pads->earliest_data,
           pads->earliest_time, pads->compare_user_data);
 
       if (cmp_res > 0)
@@ -1804,7 +1755,7 @@ forward_or_default:
   if (event_func)
     res = event_func (pads, data, event, event_user_data);
   if (!res)
-    res = gst_pad_event_default (pad, event);
+    res = gst_pad_event_default (pad, parent, event);
   if (need_unlock)
     GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
   goto done;
@@ -1844,7 +1795,7 @@ pad_removed:
  * collected 
  */
 static GstFlowReturn
-gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
+gst_collect_pads2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstCollectData2 *data;
   GstCollectPads2 *pads;
@@ -1875,7 +1826,7 @@ gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
   /* pad was EOS, we can refuse this data */
   if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (data,
               GST_COLLECT_PADS2_STATE_EOS)))
-    goto unexpected;
+    goto eos;
 
   /* see if we need to clip */
   if (pads->clip_func) {
@@ -1886,8 +1837,8 @@ gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
     if (G_UNLIKELY (outbuf == NULL))
       goto clipped;
 
-    if (G_UNLIKELY (ret == GST_FLOW_UNEXPECTED))
-      goto unexpected;
+    if (G_UNLIKELY (ret == GST_FLOW_EOS))
+      goto eos;
     else if (G_UNLIKELY (ret != GST_FLOW_OK))
       goto error;
   }
@@ -1906,7 +1857,7 @@ gst_collect_pads2_chain (GstPad * pad, GstBuffer * buffer)
     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
     if (GST_CLOCK_TIME_IS_VALID (timestamp))
-      gst_segment_set_last_stop (&data->segment, GST_FORMAT_TIME, timestamp);
+      data->segment.position = timestamp;
   }
 
   /* While we have data queued on this pad try to collect stuff */
@@ -1999,12 +1950,12 @@ flushing:
     ret = GST_FLOW_WRONG_STATE;
     goto unlock_done;
   }
-unexpected:
+eos:
   {
     /* we should not post an error for this, just inform upstream that
      * we don't expect anything anymore */
     GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad));
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_EOS;
     goto unlock_done;
   }
 clipped:
index 7890e7a..165203a 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_COLLECT_PADS2                  (gst_collect_pads2_get_type())
-#define GST_COLLECT_PADS2(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECT_PADS2,GstCollectPads2))
-#define GST_COLLECT_PADS2_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECT_PADS2,GstCollectPads2Class))
+#define GST_TYPE_COLLECT_PADS2            (gst_collect_pads2_get_type())
+#define GST_COLLECT_PADS2(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLLECT_PADS2,GstCollectPads2))
+#define GST_COLLECT_PADS2_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COLLECT_PADS2,GstCollectPads2Class))
 #define GST_COLLECT_PADS2_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_COLLECT_PADS2,GstCollectPads2Class))
-#define GST_IS_COLLECT_PADS2(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECT_PADS2))
+#define GST_IS_COLLECT_PADS2(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLLECT_PADS2))
 #define GST_IS_COLLECT_PADS2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLLECT_PADS2))
 
 typedef struct _GstCollectData2 GstCollectData2;
@@ -128,10 +128,10 @@ typedef enum {
 struct _GstCollectData2
 {
   /* with STREAM_LOCK of @collect */
-  GstCollectPads2      *collect;
-  GstPad               *pad;
-  GstBuffer            *buffer;
-  guint                         pos;
+  GstCollectPads2       *collect;
+  GstPad                *pad;
+  GstBuffer             *buffer;
+  guint                  pos;
   GstSegment             segment;
 
   /*< private >*/
@@ -175,7 +175,7 @@ typedef GstFlowReturn (*GstCollectPads2Function) (GstCollectPads2 *pads, gpointe
  * Since: 0.10.36
  */
 typedef GstFlowReturn (*GstCollectPads2BufferFunction) (GstCollectPads2 *pads, GstCollectData2 *data,
-                                                       GstBuffer *buffer, gpointer user_data);
+                                                        GstBuffer *buffer, gpointer user_data);
 
 /**
  * GstCollectPads2CompareFunction:
@@ -195,9 +195,9 @@ typedef GstFlowReturn (*GstCollectPads2BufferFunction) (GstCollectPads2 *pads, G
  * Since: 0.10.36
  */
 typedef gint (*GstCollectPads2CompareFunction) (GstCollectPads2 *pads,
-                                               GstCollectData2 * data1, GstClockTime timestamp1,
-                                               GstCollectData2 * data2, GstClockTime timestamp2,
-                                               gpointer user_data);
+                                                GstCollectData2 * data1, GstClockTime timestamp1,
+                                                GstCollectData2 * data2, GstClockTime timestamp2,
+                                                gpointer user_data);
 
 /**
  * GstCollectPads2EventFunction:
@@ -212,23 +212,23 @@ typedef gint (*GstCollectPads2CompareFunction) (GstCollectPads2 *pads,
  *
  * Since: 0.10.36
  */
-typedef gboolean (*GstCollectPads2EventFunction)       (GstCollectPads2 *pads, GstCollectData2 * pad,
-                                                        GstEvent * event, gpointer user_data);
+typedef gboolean (*GstCollectPads2EventFunction)        (GstCollectPads2 *pads, GstCollectData2 * pad,
+                                                         GstEvent * event, gpointer user_data);
 
 
 /**
  * GstCollectPads2ClipFunction:
- * @pads: a #GstCollectPads2 
+ * @pads: a #GstCollectPads2
  * @data: a #GstCollectData2
- * @inbuffer: the input #GstBuffer 
+ * @inbuffer: the input #GstBuffer
  * @outbuffer: the output #GstBuffer
- * @user_data: user data 
+ * @user_data: user data
  *
  * A function that will be called when @inbuffer is received on the pad managed
  * by @data in the collecpad object @pads.
  *
  * The function should use the segment of @data and the negotiated media type on
- * the pad to perform clipping of @inbuffer. 
+ * the pad to perform clipping of @inbuffer.
  *
  * This function takes ownership of @inbuffer and should output a buffer in
  * @outbuffer or return %NULL in @outbuffer if the buffer should be dropped.
@@ -260,7 +260,7 @@ typedef GstFlowReturn (*GstCollectPads2ClipFunction) (GstCollectPads2 *pads, Gst
  *
  * Since: 0.10.36
  */
-#define GST_COLLECT_PADS2_STREAM_LOCK(pads)     (g_static_rec_mutex_lock(GST_COLLECT_PADS2_GET_STREAM_LOCK (pads)))
+#define GST_COLLECT_PADS2_STREAM_LOCK(pads)     (g_rec_mutex_lock(GST_COLLECT_PADS2_GET_STREAM_LOCK (pads)))
 /**
  * GST_COLLECT_PADS2_STREAM_UNLOCK:
  * @pads: a #GstCollectPads2
@@ -269,7 +269,7 @@ typedef GstFlowReturn (*GstCollectPads2ClipFunction) (GstCollectPads2 *pads, Gst
  *
  * Since: 0.10.36
  */
-#define GST_COLLECT_PADS2_STREAM_UNLOCK(pads)   (g_static_rec_mutex_unlock(GST_COLLECT_PADS2_GET_STREAM_LOCK (pads)))
+#define GST_COLLECT_PADS2_STREAM_UNLOCK(pads)   (g_rec_mutex_unlock(GST_COLLECT_PADS2_GET_STREAM_LOCK (pads)))
 
 /**
  * GstCollectPads2:
@@ -283,28 +283,28 @@ struct _GstCollectPads2 {
   GstObject      object;
 
   /*< public >*/ /* with LOCK and/or STREAM_LOCK */
-  GSList       *data;                  /* list of CollectData items */
+  GSList        *data;                  /* list of CollectData items */
 
   /*< private >*/
-  GStaticRecMutex stream_lock;         /* used to serialize collection among several streams */
+  GRecMutex      stream_lock;          /* used to serialize collection among several streams */
   /* with LOCK and/or STREAM_LOCK*/
-  gboolean      started;
+  gboolean       started;
 
   /* with STREAM_LOCK */
-  guint32       cookie;                /* @data list cookie */
-  guint                 numpads;               /* number of pads in @data */
-  guint                 queuedpads;            /* number of pads with a buffer */
-  guint                 eospads;               /* number of pads that are EOS */
-  GstClockTime   earliest_time;                /* Current earliest time */
-  GstCollectData2 *earliest_data;      /* Pad data for current earliest time */
+  guint32        cookie;                /* @data list cookie */
+  guint          numpads;               /* number of pads in @data */
+  guint          queuedpads;            /* number of pads with a buffer */
+  guint          eospads;               /* number of pads that are EOS */
+  GstClockTime   earliest_time;         /* Current earliest time */
+  GstCollectData2 *earliest_data;       /* Pad data for current earliest time */
 
   /* with LOCK */
   GSList        *pad_list;              /* updated pad list */
-  guint32       pad_cookie;            /* updated cookie */
+  guint32        pad_cookie;            /* updated cookie */
 
-  GstCollectPads2Function func;                /* function and user_data for callback */
-  gpointer      user_data;
-  GstCollectPads2BufferFunction buffer_func;   /* function and user_data for buffer callback */
+  GstCollectPads2Function func;         /* function and user_data for callback */
+  gpointer       user_data;
+  GstCollectPads2BufferFunction buffer_func;    /* function and user_data for buffer callback */
   gpointer       buffer_user_data;
   GstCollectPads2CompareFunction compare_func;
   gpointer       compare_user_data;
@@ -314,12 +314,11 @@ struct _GstCollectPads2 {
   gpointer       clip_user_data;
 
   /* no other lock needed */
-  GMutex        *evt_lock;             /* these make up sort of poor man's event signaling */
-  GCond         *evt_cond;
+  GMutex         evt_lock;              /* these make up sort of poor man's event signaling */
+  GCond          evt_cond;
   guint32        evt_cookie;
 
-  gpointer _gst_reserved[GST_PADDING + 0];
-
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstCollectPads2Class {
@@ -332,53 +331,57 @@ struct _GstCollectPads2Class {
 GType gst_collect_pads2_get_type(void);
 
 /* creating the object */
-GstCollectPads2*       gst_collect_pads2_new           (void);
+GstCollectPads2*        gst_collect_pads2_new           (void);
 
 /* set the callbacks */
-void           gst_collect_pads2_set_function  (GstCollectPads2 *pads, GstCollectPads2Function func,
-                                                gpointer user_data);
-void           gst_collect_pads2_set_buffer_function (GstCollectPads2 *pads,
-                                                GstCollectPads2BufferFunction func, gpointer user_data);
-void            gst_collect_pads2_set_event_function (GstCollectPads2 *pads,
-                                                GstCollectPads2EventFunction func, gpointer user_data);
-void           gst_collect_pads2_set_compare_function (GstCollectPads2 *pads,
-                                                GstCollectPads2CompareFunction func, gpointer user_data);
-void            gst_collect_pads2_set_clip_function (GstCollectPads2 *pads, GstCollectPads2ClipFunction clipfunc,
-                                                 gpointer user_data);
+void            gst_collect_pads2_set_function         (GstCollectPads2 *pads,
+                                                        GstCollectPads2Function func,
+                                                        gpointer user_data);
+void            gst_collect_pads2_set_buffer_function  (GstCollectPads2 *pads,
+                                                        GstCollectPads2BufferFunction func,
+                                                        gpointer user_data);
+void            gst_collect_pads2_set_event_function   (GstCollectPads2 *pads,
+                                                        GstCollectPads2EventFunction func,
+                                                        gpointer user_data);
+void            gst_collect_pads2_set_compare_function (GstCollectPads2 *pads,
+                                                        GstCollectPads2CompareFunction func,
+                                                        gpointer user_data);
+void            gst_collect_pads2_set_clip_function    (GstCollectPads2 *pads,
+                                                        GstCollectPads2ClipFunction clipfunc,
+                                                        gpointer user_data);
 
 /* pad management */
-GstCollectData2* gst_collect_pads2_add_pad     (GstCollectPads2 *pads, GstPad *pad, guint size);
-GstCollectData2* gst_collect_pads2_add_pad_full (GstCollectPads2 *pads, GstPad *pad, guint size,                                                        GstCollectData2DestroyNotify destroy_notify,
-                                                gboolean lock);
-gboolean       gst_collect_pads2_remove_pad    (GstCollectPads2 *pads, GstPad *pad);
-gboolean       gst_collect_pads2_is_active     (GstCollectPads2 *pads, GstPad *pad);
+GstCollectData2* gst_collect_pads2_add_pad      (GstCollectPads2 *pads, GstPad *pad, guint size);
+GstCollectData2* gst_collect_pads2_add_pad_full (GstCollectPads2 *pads, GstPad *pad, guint size,
+                                                 GstCollectData2DestroyNotify destroy_notify,
+                                                 gboolean lock);
+gboolean        gst_collect_pads2_remove_pad    (GstCollectPads2 *pads, GstPad *pad);
+gboolean        gst_collect_pads2_is_active     (GstCollectPads2 *pads, GstPad *pad);
 
 /* start/stop collection */
-GstFlowReturn  gst_collect_pads2_collect       (GstCollectPads2 *pads);
-GstFlowReturn  gst_collect_pads2_collect_range (GstCollectPads2 *pads, guint64 offset, guint length);
+GstFlowReturn   gst_collect_pads2_collect       (GstCollectPads2 *pads);
+GstFlowReturn   gst_collect_pads2_collect_range (GstCollectPads2 *pads, guint64 offset, guint length);
 
-void           gst_collect_pads2_start         (GstCollectPads2 *pads);
-void           gst_collect_pads2_stop          (GstCollectPads2 *pads);
-void           gst_collect_pads2_set_flushing  (GstCollectPads2 *pads, gboolean flushing);
+void            gst_collect_pads2_start         (GstCollectPads2 *pads);
+void            gst_collect_pads2_stop          (GstCollectPads2 *pads);
+void            gst_collect_pads2_set_flushing  (GstCollectPads2 *pads, gboolean flushing);
 
 /* get collected buffers */
-GstBuffer*     gst_collect_pads2_peek          (GstCollectPads2 *pads, GstCollectData2 *data);
-GstBuffer*     gst_collect_pads2_pop           (GstCollectPads2 *pads, GstCollectData2 *data);
+GstBuffer*      gst_collect_pads2_peek          (GstCollectPads2 *pads, GstCollectData2 *data);
+GstBuffer*      gst_collect_pads2_pop           (GstCollectPads2 *pads, GstCollectData2 *data);
 
 /* get collected bytes */
-guint          gst_collect_pads2_available     (GstCollectPads2 *pads);
-guint          gst_collect_pads2_read          (GstCollectPads2 *pads, GstCollectData2 *data,
-                                                guint8 **bytes, guint size);
-guint          gst_collect_pads2_flush         (GstCollectPads2 *pads, GstCollectData2 *data,
-                                                guint size);
-GstBuffer*     gst_collect_pads2_read_buffer   (GstCollectPads2 * pads, GstCollectData2 * data,
-                                                guint size);
-GstBuffer*     gst_collect_pads2_take_buffer   (GstCollectPads2 * pads, GstCollectData2 * data,
-                                                guint size);
+guint           gst_collect_pads2_available     (GstCollectPads2 *pads);
+guint           gst_collect_pads2_flush         (GstCollectPads2 *pads, GstCollectData2 *data,
+                                                 guint size);
+GstBuffer*      gst_collect_pads2_read_buffer   (GstCollectPads2 * pads, GstCollectData2 * data,
+                                                 guint size);
+GstBuffer*      gst_collect_pads2_take_buffer   (GstCollectPads2 * pads, GstCollectData2 * data,
+                                                 guint size);
 
 /* setting and unsetting waiting mode */
-void           gst_collect_pads2_set_waiting   (GstCollectPads2 *pads, GstCollectData2 *data,
-                                                gboolean waiting);
+void            gst_collect_pads2_set_waiting   (GstCollectPads2 *pads, GstCollectData2 *data,
+                                                 gboolean waiting);
 
 /* convenience helper */
 GstFlowReturn  gst_collect_pads2_clip_running_time (GstCollectPads2 * pads,
similarity index 96%
rename from gst/gstindex.c
rename to libs/gst/base/gstindex.c
index d168eee..8d69b06 100644 (file)
  *     sense to ask the app to provide a ptr and fill it.
  */
 
-#include "gst_private.h"
-
-#include "gstinfo.h"
-#include "gstindex.h"
-#include "gstindexfactory.h"
-#include "gstmarshal.h"
-#include "gstregistry.h"
-/* for constructing an entry name */
-#include "gstelement.h"
-#include "gstpad.h"
-#include "gstinfo.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
 
 /* Index signals and args */
 enum
@@ -81,8 +75,10 @@ enum
       /* FILL ME */
 };
 
+#if 0
 GST_DEBUG_CATEGORY_STATIC (index_debug);
 #define GST_CAT_DEFAULT index_debug
+#endif
 
 static void gst_index_finalize (GObject * object);
 
@@ -100,7 +96,6 @@ static gboolean gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
     gchar ** writer_string, gpointer data);
 static void gst_index_add_entry (GstIndex * index, GstIndexEntry * entry);
 
-static GstObject *parent_class = NULL;
 static guint gst_index_signals[LAST_SIGNAL] = { 0 };
 
 typedef struct
@@ -149,21 +144,21 @@ gst_index_entry_get_type (void)
   return index_entry_type;
 }
 
+#if 0
 #define _do_init \
 { \
   GST_DEBUG_CATEGORY_INIT (index_debug, "GST_INDEX", GST_DEBUG_BOLD, \
       "Generic indexing support"); \
 }
+#endif
 
-G_DEFINE_TYPE_WITH_CODE (GstIndex, gst_index, GST_TYPE_OBJECT, _do_init);
+G_DEFINE_TYPE (GstIndex, gst_index, GST_TYPE_OBJECT);
 
 static void
 gst_index_class_init (GstIndexClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
   /**
    * GstIndex::entry-added
    * @gstindex: the object which received the signal.
@@ -240,7 +235,7 @@ gst_index_finalize (GObject * object)
   if (index->resolver_user_data && index->resolver_user_data_destroy)
     index->resolver_user_data_destroy (index->resolver_user_data);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gst_index_parent_class)->finalize (object);
 }
 
 static void
@@ -302,6 +297,8 @@ gst_index_group_free (GstIndexGroup * group)
   g_slice_free (GstIndexGroup, group);
 }
 
+/* do not resurrect this, add a derived dummy index class instead */
+#if 0
 /**
  * gst_index_new:
  *
@@ -341,7 +338,6 @@ gst_index_commit (GstIndex * index, gint id)
     iclass->commit (index, id);
 }
 
-
 /**
  * gst_index_get_group:
  * @index: the index to get the current group from
@@ -410,7 +406,9 @@ gst_index_set_group (GstIndex * index, gint groupnum)
   GST_DEBUG ("couldn't find index group %d", groupnum);
   return FALSE;
 }
+#endif
 
+#if 0
 /**
  * gst_index_set_certainty:
  * @index: the index to set the certainty on
@@ -437,7 +435,9 @@ gst_index_get_certainty (GstIndex * index)
 {
   return index->curgroup->certainty;
 }
+#endif
 
+#if 0
 /**
  * gst_index_set_filter:
  * @index: the index to register the filter on
@@ -522,6 +522,7 @@ gst_index_set_resolver_full (GstIndex * index, GstIndexResolver resolver,
   index->resolver_user_data_destroy = user_data_destroy;
   index->method = GST_INDEX_RESOLVER_CUSTOM;
 }
+#endif
 
 /**
  * gst_index_entry_copy:
@@ -573,6 +574,7 @@ gst_index_entry_free (GstIndexEntry * entry)
   g_slice_free (GstIndexEntry, entry);
 }
 
+#if 0
 /**
  * gst_index_add_format:
  * @index: the index to add the entry to
@@ -611,6 +613,7 @@ gst_index_add_format (GstIndex * index, gint id, GstFormat format)
 
   return entry;
 }
+#endif
 
 /**
  * gst_index_add_id:
@@ -790,8 +793,8 @@ gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
  * Returns: a pointer to the newly added entry in the index.
  */
 GstIndexEntry *
-gst_index_add_associationv (GstIndex * index, gint id, GstAssocFlags flags,
-    gint n, const GstIndexAssociation * list)
+gst_index_add_associationv (GstIndex * index, gint id,
+    GstIndexAssociationFlags flags, gint n, const GstIndexAssociation * list)
 {
   GstIndexEntry *entry;
 
@@ -815,6 +818,7 @@ gst_index_add_associationv (GstIndex * index, gint id, GstAssocFlags flags,
   return entry;
 }
 
+#if 0
 /**
  * gst_index_add_association:
  * @index: the index to add the entry to
@@ -831,8 +835,8 @@ gst_index_add_associationv (GstIndex * index, gint id, GstAssocFlags flags,
  * Returns: a pointer to the newly added entry in the index.
  */
 GstIndexEntry *
-gst_index_add_association (GstIndex * index, gint id, GstAssocFlags flags,
-    GstFormat format, gint64 value, ...)
+gst_index_add_association (GstIndex * index, gint id,
+    GstIndexAssociationFlags flags, GstFormat format, gint64 value, ...)
 {
   va_list args;
   GstIndexEntry *entry;
@@ -902,6 +906,7 @@ gst_index_add_object (GstIndex * index, gint id, gchar * key,
 
   return NULL;
 }
+#endif
 
 static gint
 gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
@@ -929,7 +934,7 @@ gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
  */
 GstIndexEntry *
 gst_index_get_assoc_entry (GstIndex * index, gint id,
-    GstIndexLookupMethod method, GstAssocFlags flags,
+    GstIndexLookupMethod method, GstIndexAssociationFlags flags,
     GstFormat format, gint64 value)
 {
   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
@@ -960,7 +965,7 @@ gst_index_get_assoc_entry (GstIndex * index, gint id,
  */
 GstIndexEntry *
 gst_index_get_assoc_entry_full (GstIndex * index, gint id,
-    GstIndexLookupMethod method, GstAssocFlags flags,
+    GstIndexLookupMethod method, GstIndexAssociationFlags flags,
     GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
 {
   GstIndexClass *iclass;
similarity index 92%
rename from gst/gstindex.h
rename to libs/gst/base/gstindex.h
index e5fc625..7e22efc 100644 (file)
@@ -137,24 +137,24 @@ struct _GstIndexAssociation {
 };
 
 /**
- * GstAssocFlags:
- * @GST_ASSOCIATION_FLAG_NONE: no extra flags
- * @GST_ASSOCIATION_FLAG_KEY_UNIT: the entry marks a key unit, a key unit is one
+ * GstIndexAssociationFlags:
+ * @GST_INDEX_ASSOCIATION_FLAG_NONE: no extra flags
+ * @GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT: the entry marks a key unit, a key unit is one
  *  that marks a place where one can randomly seek to.
- * @GST_ASSOCIATION_FLAG_DELTA_UNIT: the entry marks a delta unit, a delta unit
+ * @GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT: the entry marks a delta unit, a delta unit
  *  is one that marks a place where one can relatively seek to.
- * @GST_ASSOCIATION_FLAG_LAST: extra user defined flags should start here.
+ * @GST_INDEX_ASSOCIATION_FLAG_LAST: extra user defined flags should start here.
  *
  * Flags for an association entry.
  */
 typedef enum {
-  GST_ASSOCIATION_FLAG_NONE       = 0,
-  GST_ASSOCIATION_FLAG_KEY_UNIT   = (1 << 0),
-  GST_ASSOCIATION_FLAG_DELTA_UNIT = (1 << 1),
+  GST_INDEX_ASSOCIATION_FLAG_NONE       = 0,
+  GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT   = (1 << 0),
+  GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT = (1 << 1),
 
   /* new flags should start here */
-  GST_ASSOCIATION_FLAG_LAST     = (1 << 8)
-} GstAssocFlags;
+  GST_INDEX_ASSOCIATION_FLAG_LAST     = (1 << 8)
+} GstIndexAssociationFlags;
 
 /**
  * GST_INDEX_FORMAT_FORMAT:
@@ -205,7 +205,7 @@ struct _GstIndexEntry {
       gint               nassocs;
       GstIndexAssociation
                         *assocs;
-      GstAssocFlags      flags;
+      GstIndexAssociationFlags      flags;
     } assoc;
     struct {
       gchar             *key;
@@ -318,7 +318,7 @@ typedef enum {
 
 /**
  * GstIndex:
- * 
+ *
  * Opaque #GstIndex structure.
  */
 struct _GstIndex {
@@ -332,6 +332,7 @@ struct _GstIndex {
   GstIndexResolverMethod method;
   GstIndexResolver       resolver;
   gpointer               resolver_user_data;
+  GDestroyNotify         resolver_user_data_destroy;
 
   GstIndexFilter         filter;
   gpointer               filter_user_data;
@@ -340,18 +341,15 @@ struct _GstIndex {
   GHashTable            *writers;
   gint                   last_id;
 
-  /* ABI added since 0.10.18 */
-  GDestroyNotify         resolver_user_data_destroy;
-
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstIndexClass {
   GstObjectClass parent_class;
 
   /*< protected >*/
-  gboolean      (*get_writer_id)        (GstIndex *index, gint *writer_id, gchar *writer_string);
+  gboolean      (*get_writer_id)        (GstIndex *index, gint *id, gchar *writer);
 
   void          (*commit)               (GstIndex *index, gint id);
 
@@ -359,7 +357,7 @@ struct _GstIndexClass {
   void          (*add_entry)            (GstIndex *index, GstIndexEntry *entry);
 
   GstIndexEntry* (*get_assoc_entry)     (GstIndex *index, gint id,
-                                         GstIndexLookupMethod method, GstAssocFlags flags,
+                                         GstIndexLookupMethod method, GstIndexAssociationFlags flags,
                                          GstFormat format, gint64 value,
                                          GCompareDataFunc func,
                                          gpointer user_data);
@@ -370,7 +368,10 @@ struct _GstIndexClass {
   gpointer _gst_reserved[GST_PADDING];
 };
 
+static
 GType                   gst_index_get_type              (void);
+
+#if 0
 GstIndex*               gst_index_new                   (void);
 void                    gst_index_commit                (GstIndex *index, gint id);
 
@@ -382,42 +383,61 @@ void                    gst_index_set_certainty         (GstIndex *index,
                                                          GstIndexCertainty certainty);
 GstIndexCertainty       gst_index_get_certainty         (GstIndex *index);
 
+static
 void                    gst_index_set_filter            (GstIndex *index,
                                                          GstIndexFilter filter, gpointer user_data);
+static
 void                    gst_index_set_filter_full       (GstIndex *index,
                                                          GstIndexFilter filter, gpointer user_data,
                                                          GDestroyNotify user_data_destroy);
+
 void                    gst_index_set_resolver          (GstIndex *index,
                                                          GstIndexResolver resolver, gpointer user_data);
 void                    gst_index_set_resolver_full     (GstIndex *index, GstIndexResolver resolver,
                                                          gpointer user_data,
                                                          GDestroyNotify user_data_destroy);
+#endif
 
+static
 gboolean                gst_index_get_writer_id         (GstIndex *index, GstObject *writer, gint *id);
 
+#if 0
 GstIndexEntry*          gst_index_add_format            (GstIndex *index, gint id, GstFormat format);
-GstIndexEntry*          gst_index_add_associationv      (GstIndex * index, gint id, GstAssocFlags flags,
+#endif
+
+static
+GstIndexEntry*          gst_index_add_associationv      (GstIndex * index, gint id, GstIndexAssociationFlags flags,
                                                          gint n, const GstIndexAssociation * list);
-GstIndexEntry*          gst_index_add_association       (GstIndex *index, gint id, GstAssocFlags flags,
-                                                         GstFormat format, gint64 value, ...);
+#if 0
+GstIndexEntry*          gst_index_add_association       (GstIndex *index, gint id, GstIndexAssociationFlags flags,
+                                                         GstFormat format, gint64 value, ...)
 GstIndexEntry*          gst_index_add_object            (GstIndex *index, gint id, gchar *key,
                                                          GType type, gpointer object);
+#endif
+
+static
 GstIndexEntry*          gst_index_add_id                (GstIndex *index, gint id,
                                                          gchar *description);
 
+static
 GstIndexEntry*          gst_index_get_assoc_entry       (GstIndex *index, gint id,
-                                                         GstIndexLookupMethod method, GstAssocFlags flags,
+                                                         GstIndexLookupMethod method, GstIndexAssociationFlags flags,
                                                          GstFormat format, gint64 value);
+static
 GstIndexEntry*          gst_index_get_assoc_entry_full  (GstIndex *index, gint id,
-                                                         GstIndexLookupMethod method, GstAssocFlags flags,
+                                                         GstIndexLookupMethod method, GstIndexAssociationFlags flags,
                                                          GstFormat format, gint64 value,
                                                          GCompareDataFunc func,
                                                          gpointer user_data);
 
 /* working with index entries */
+static
 GType gst_index_entry_get_type (void);
+static
 GstIndexEntry *         gst_index_entry_copy            (GstIndexEntry *entry);
+static
 void                    gst_index_entry_free            (GstIndexEntry *entry);
+static
 gboolean                gst_index_entry_assoc_map       (GstIndexEntry *entry,
                                                          GstFormat format, gint64 *value);
 
similarity index 97%
rename from plugins/indexers/gstmemindex.c
rename to libs/gst/base/gstmemindex.c
index fd276fa..aaeab12 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <gst/gst.h>
 
-#include "gstindexers.h"
-
 #define GST_TYPE_MEM_INDEX              \
   (gst_index_get_type ())
 #define GST_MEM_INDEX(obj)              \
@@ -95,30 +93,16 @@ struct _GstMemIndexClass
   GstIndexClass parent_class;
 };
 
-/* Index signals and args */
-enum
-{
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0,
-  /* FILL ME */
-};
-
 static void gst_mem_index_finalize (GObject * object);
 
 static void gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry);
 static GstIndexEntry *gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
-    GstIndexLookupMethod method, GstAssocFlags flags,
+    GstIndexLookupMethod method, GstIndexAssociationFlags flags,
     GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data);
 
 #define CLASS(mem_index)  GST_MEM_INDEX_CLASS (G_OBJECT_GET_CLASS (mem_index))
 
-/*static guint gst_mem_index_signals[LAST_SIGNAL] = { 0 }; */
-
-GType gst_mem_index_get_type (void);
+static GType gst_mem_index_get_type (void);
 
 G_DEFINE_TYPE (GstMemIndex, gst_mem_index, GST_TYPE_INDEX);
 
@@ -354,7 +338,7 @@ mem_index_search (gconstpointer a, gconstpointer b)
 static GstIndexEntry *
 gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
     GstIndexLookupMethod method,
-    GstAssocFlags flags,
+    GstIndexAssociationFlags flags,
     GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
 {
   GstMemIndex *memindex = GST_MEM_INDEX (index);
@@ -421,6 +405,7 @@ gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
   return entry;
 }
 
+#if 0
 gboolean
 gst_mem_index_plugin_init (GstPlugin * plugin)
 {
@@ -442,3 +427,4 @@ gst_mem_index_plugin_init (GstPlugin * plugin)
 
   return TRUE;
 }
+#endif
index 4201e3a..5eb9dfe 100644 (file)
@@ -36,8 +36,8 @@
  * in a push based mode. If the peer accepts to operate without
  * offsets and within the limits of the allowed block size, this
  * class can operate in getrange based mode automatically. To make
- * this possible, the subclass should override the ::check_get_range
- * method.
+ * this possible, the subclass should implement and override the
+ * SCHEDULING query.
  *
  * The subclass should extend the methods from the baseclass in
  * addition to the ::create method.
 GST_DEBUG_CATEGORY_STATIC (gst_push_src_debug);
 #define GST_CAT_DEFAULT gst_push_src_debug
 
-#define _do_init(type) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_push_src_debug, "pushsrc", 0, \
         "pushsrc element");
 
-GST_BOILERPLATE_FULL (GstPushSrc, gst_push_src, GstBaseSrc, GST_TYPE_BASE_SRC,
-    _do_init);
+#define gst_push_src_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstPushSrc, gst_push_src, GST_TYPE_BASE_SRC, _do_init);
 
-static gboolean gst_push_src_check_get_range (GstBaseSrc * src);
+static gboolean gst_push_src_query (GstBaseSrc * src, GstQuery * query);
 static GstFlowReturn gst_push_src_create (GstBaseSrc * bsrc, guint64 offset,
     guint length, GstBuffer ** ret);
-
-static void
-gst_push_src_base_init (gpointer g_class)
-{
-  /* nop */
-}
+static GstFlowReturn gst_push_src_alloc (GstBaseSrc * bsrc, guint64 offset,
+    guint length, GstBuffer ** ret);
+static GstFlowReturn gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset,
+    guint length, GstBuffer * ret);
 
 static void
 gst_push_src_class_init (GstPushSrcClass * klass)
@@ -85,24 +83,42 @@ gst_push_src_class_init (GstPushSrcClass * klass)
   GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass;
 
   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_push_src_create);
-  gstbasesrc_class->check_get_range =
-      GST_DEBUG_FUNCPTR (gst_push_src_check_get_range);
+  gstbasesrc_class->alloc = GST_DEBUG_FUNCPTR (gst_push_src_alloc);
+  gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_push_src_fill);
+  gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_push_src_query);
 }
 
 static void
-gst_push_src_init (GstPushSrc * pushsrc, GstPushSrcClass * klass)
+gst_push_src_init (GstPushSrc * pushsrc)
 {
   /* nop */
 }
 
 static gboolean
-gst_push_src_check_get_range (GstBaseSrc * src)
+gst_push_src_query (GstBaseSrc * src, GstQuery * query)
 {
-  /* a pushsrc can by default never operate in pull mode override
-   * if you want something different. */
-  return FALSE;
+  gboolean ret;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_SCHEDULING:
+    {
+      /* a pushsrc can by default never operate in pull mode override
+       * if you want something different. */
+      gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1,
+          0);
+      gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
+
+      ret = TRUE;
+      break;
+    }
+    default:
+      ret = GST_BASE_SRC_CLASS (parent_class)->query (src, query);
+      break;
+  }
+  return ret;
 }
 
+
 static GstFlowReturn
 gst_push_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
     GstBuffer ** ret)
@@ -116,7 +132,44 @@ gst_push_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
   if (pclass->create)
     fret = pclass->create (src, ret);
   else
-    fret = GST_FLOW_ERROR;
+    fret =
+        GST_BASE_SRC_CLASS (parent_class)->create (bsrc, offset, length, ret);
+
+  return fret;
+}
+
+static GstFlowReturn
+gst_push_src_alloc (GstBaseSrc * bsrc, guint64 offset, guint length,
+    GstBuffer ** ret)
+{
+  GstFlowReturn fret;
+  GstPushSrc *src;
+  GstPushSrcClass *pclass;
+
+  src = GST_PUSH_SRC (bsrc);
+  pclass = GST_PUSH_SRC_GET_CLASS (src);
+  if (pclass->alloc)
+    fret = pclass->alloc (src, ret);
+  else
+    fret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, ret);
+
+  return fret;
+}
+
+static GstFlowReturn
+gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset, guint length,
+    GstBuffer * ret)
+{
+  GstFlowReturn fret;
+  GstPushSrc *src;
+  GstPushSrcClass *pclass;
+
+  src = GST_PUSH_SRC (bsrc);
+  pclass = GST_PUSH_SRC_GET_CLASS (src);
+  if (pclass->fill)
+    fret = pclass->fill (src, ret);
+  else
+    fret = GST_BASE_SRC_CLASS (parent_class)->fill (bsrc, offset, length, ret);
 
   return fret;
 }
index 49786d5..b936d83 100644 (file)
@@ -54,8 +54,13 @@ struct _GstPushSrc {
 struct _GstPushSrcClass {
   GstBaseSrcClass parent_class;
 
-  /* ask the subclass to create a buffer */
+  /* ask the subclass to create a buffer, the default implementation
+   * uses alloc and fill */
   GstFlowReturn (*create) (GstPushSrc *src, GstBuffer **buf);
+  /* allocate memory for a buffer */
+  GstFlowReturn (*alloc)  (GstPushSrc *src, GstBuffer **buf);
+  /* ask the subclass to fill a buffer */
+  GstFlowReturn (*fill)   (GstPushSrc *src, GstBuffer *buf);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
index d47761f..cbd194f 100644 (file)
@@ -55,6 +55,7 @@ typedef struct
   GstCaps *caps;
   GstTypeFindFactory *factory;  /* for logging */
   GstObject *obj;               /* for logging */
+  GstObject *parent;
 } GstTypeFindHelper;
 
 /*
@@ -70,21 +71,23 @@ typedef struct
  * Returns: address of the data or %NULL if buffer does not cover the
  * requested range.
  */
-static guint8 *
+static const guint8 *
 helper_find_peek (gpointer data, gint64 offset, guint size)
 {
   GstTypeFindHelper *helper;
   GstBuffer *buffer;
   GstFlowReturn ret;
   GSList *insert_pos = NULL;
-  guint buf_size;
+  gsize buf_size;
   guint64 buf_offset;
+#if 0
   GstCaps *caps;
+#endif
 
   helper = (GstTypeFindHelper *) data;
 
   GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT
-      ", %u)", GST_PLUGIN_FEATURE_NAME (helper->factory), offset, size);
+      ", %u)", GST_OBJECT_NAME (helper->factory), offset, size);
 
   if (size == 0)
     return NULL;
@@ -103,14 +106,19 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
     for (walk = helper->buffers; walk; walk = walk->next) {
       GstBuffer *buf = GST_BUFFER_CAST (walk->data);
       guint64 buf_offset = GST_BUFFER_OFFSET (buf);
-      guint buf_size = GST_BUFFER_SIZE (buf);
+      guint buf_size = gst_buffer_get_size (buf);
 
       /* 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 
        * we're after the searched end offset */
       if (buf_offset <= offset) {
         if ((offset + size) < (buf_offset + buf_size)) {
-          return GST_BUFFER_DATA (buf) + (offset - buf_offset);
+          guint8 *data;
+
+          /* FIXME, unmap after usage */
+          data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
+
+          return data + (offset - buf_offset);
         }
       } else if (offset + size >= buf_offset + buf_size) {
         insert_pos = walk;
@@ -126,11 +134,14 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
    * of the file is also not a problem here, we'll just get a truncated buffer
    * in that case (and we'll have to double-check the size we actually get
    * anyway, see below) */
-  ret = helper->func (helper->obj, offset, MAX (size, 4096), &buffer);
+  ret =
+      helper->func (helper->obj, helper->parent, offset, MAX (size, 4096),
+      &buffer);
 
   if (ret != GST_FLOW_OK)
     goto error;
 
+#if 0
   caps = GST_BUFFER_CAPS (buffer);
 
   if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
@@ -143,11 +154,12 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
     gst_buffer_unref (buffer);
     return NULL;
   }
+#endif
 
   /* getrange might silently return shortened buffers at the end of a file,
    * we must, however, always return either the full requested data or NULL */
   buf_offset = GST_BUFFER_OFFSET (buffer);
-  buf_size = GST_BUFFER_SIZE (buffer);
+  buf_size = gst_buffer_get_size (buffer);
 
   if ((buf_offset != -1 && buf_offset != offset) || buf_size < size) {
     GST_DEBUG ("dropping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT
@@ -164,10 +176,12 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
     /* if insert_pos is not set, our offset is bigger than the largest offset
      * we have so far; since we keep the list sorted with highest offsets
      * first, we need to prepend the buffer to the list */
-    helper->last_offset = GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer);
+    helper->last_offset = GST_BUFFER_OFFSET (buffer) + buf_size;
     helper->buffers = g_slist_prepend (helper->buffers, buffer);
   }
-  return GST_BUFFER_DATA (buffer);
+
+  /* FIXME, unmap */
+  return gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
 
 error:
   {
@@ -192,13 +206,12 @@ helper_find_suggest (gpointer data, GstTypeFindProbability probability,
 
   GST_LOG_OBJECT (helper->obj,
       "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
-      GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps);
+      GST_OBJECT_NAME (helper->factory), probability, caps);
 
   if (probability > helper->best_probability) {
     GstCaps *copy = gst_caps_copy (caps);
 
-    gst_caps_replace (&helper->caps, copy);
-    gst_caps_unref (copy);
+    gst_caps_take (&helper->caps, copy);
     helper->best_probability = probability;
   }
 }
@@ -209,15 +222,15 @@ helper_find_get_length (gpointer data)
   GstTypeFindHelper *helper = (GstTypeFindHelper *) data;
 
   GST_LOG_OBJECT (helper->obj, "'%s' called get_length, returning %"
-      G_GUINT64_FORMAT, GST_PLUGIN_FEATURE_NAME (helper->factory),
-      helper->size);
+      G_GUINT64_FORMAT, GST_OBJECT_NAME (helper->factory), helper->size);
 
   return helper->size;
 }
 
 /**
- * gst_type_find_helper_get_range_ext:
+ * gst_type_find_helper_get_range:
  * @obj: A #GstObject that will be passed as first argument to @func
+ * @parent: the parent of @obj or NULL
  * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
  *        be used to access data at random offsets when doing the typefinding
  * @size: The length in bytes
@@ -246,7 +259,7 @@ helper_find_get_length (gpointer data)
  * Since: 0.10.26
  */
 GstCaps *
-gst_type_find_helper_get_range_ext (GstObject * obj,
+gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
     GstTypeFindHelperGetRangeFunction func, guint64 size,
     const gchar * extension, GstTypeFindProbability * prob)
 {
@@ -267,6 +280,7 @@ gst_type_find_helper_get_range_ext (GstObject * obj,
   helper.best_probability = GST_TYPE_FIND_NONE;
   helper.caps = NULL;
   helper.obj = obj;
+  helper.parent = parent;
 
   find.data = &helper;
   find.peek = helper_find_peek;
@@ -303,7 +317,7 @@ gst_type_find_helper_get_range_ext (GstObject * obj,
         continue;
 
       GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
-          GST_PLUGIN_FEATURE_NAME (factory), extension);
+          GST_OBJECT_NAME (factory), extension);
 
       for (i = 0; ext[i]; i++) {
         if (strcmp (ext[i], extension) == 0) {
@@ -347,37 +361,6 @@ gst_type_find_helper_get_range_ext (GstObject * obj,
 }
 
 /**
- * gst_type_find_helper_get_range:
- * @obj: A #GstObject that will be passed as first argument to @func
- * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
- *        be used to access data at random offsets when doing the typefinding
- * @size: The length in bytes
- * @prob: (out) (allow-none): location to store the probability of the found
- *     caps, or #NULL
- *
- * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
- * however, this function will use the specified function @func to obtain the
- * data needed by the typefind functions, rather than operating on a given
- * source pad. This is useful mostly for elements like tag demuxers which
- * strip off data at the beginning and/or end of a file and want to typefind
- * the stripped data stream before adding their own source pad (the specified
- * callback can then call the upstream peer pad with offsets adjusted for the
- * tag size, for example).
- *
- * Free-function: gst_caps_unref
- *
- * Returns: (transfer full): the #GstCaps corresponding to the data stream.
- *     Returns #NULL if no #GstCaps matches the data stream.
- */
-GstCaps *
-gst_type_find_helper_get_range (GstObject * obj,
-    GstTypeFindHelperGetRangeFunction func, guint64 size,
-    GstTypeFindProbability * prob)
-{
-  return gst_type_find_helper_get_range_ext (obj, func, size, NULL, prob);
-}
-
-/**
  * gst_type_find_helper:
  * @src: A source #GstPad
  * @size: The length in bytes
@@ -400,15 +383,16 @@ gst_type_find_helper (GstPad * src, guint64 size)
 
   func = (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (src));
 
-  return gst_type_find_helper_get_range (GST_OBJECT (src), func, size, NULL);
+  return gst_type_find_helper_get_range (GST_OBJECT (src),
+      GST_OBJECT_PARENT (src), func, size, NULL, NULL);
 }
 
 /* ********************** typefinding for buffers ************************* */
 
 typedef struct
 {
-  guint8 *data;                 /* buffer data */
-  guint size;
+  const guint8 *data;           /* buffer data */
+  gsize size;
   GstTypeFindProbability best_probability;
   GstCaps *caps;
   GstTypeFindFactory *factory;  /* for logging */
@@ -426,21 +410,21 @@ typedef struct
  * Returns: address inside the buffer or %NULL if buffer does not cover the
  * requested range.
  */
-static guint8 *
+static const guint8 *
 buf_helper_find_peek (gpointer data, gint64 off, guint size)
 {
   GstTypeFindBufHelper *helper;
 
   helper = (GstTypeFindBufHelper *) data;
   GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
-      GST_PLUGIN_FEATURE_NAME (helper->factory), off, size);
+      GST_OBJECT_NAME (helper->factory), off, size);
 
   if (size == 0)
     return NULL;
 
   if (off < 0) {
     GST_LOG_OBJECT (helper->obj, "'%s' wanted to peek at end; not supported",
-        GST_PLUGIN_FEATURE_NAME (helper->factory));
+        GST_OBJECT_NAME (helper->factory));
     return NULL;
   }
 
@@ -466,7 +450,7 @@ buf_helper_find_suggest (gpointer data, GstTypeFindProbability probability,
 
   GST_LOG_OBJECT (helper->obj,
       "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
-      GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps);
+      GST_OBJECT_NAME (helper->factory), probability, caps);
 
   /* Note: not >= as we call typefinders in order of rank, highest first */
   if (probability > helper->best_probability) {
@@ -479,14 +463,15 @@ buf_helper_find_suggest (gpointer data, GstTypeFindProbability probability,
 }
 
 /**
- * gst_type_find_helper_for_buffer:
+ * gst_type_find_helper_for_data:
  * @obj: object doing the typefinding, or NULL (used for logging)
- * @buf: (in) (transfer none): a #GstBuffer with data to typefind
+ * @data: (in) (transfer none): a pointer with data to typefind
+ * @size: (in) (transfer none): the size of @data
  * @prob: (out) (allow-none): location to store the probability of the found
  *     caps, or #NULL
  *
- * Tries to find what type of data is contained in the given #GstBuffer, the
- * assumption being that the buffer represents the beginning of the stream or
+ * Tries to find what type of data is contained in the given @data, the
+ * assumption being that the data represents the beginning of the stream or
  * file.
  *
  * All available typefinders will be called on the data in order of rank. If
@@ -494,7 +479,7 @@ buf_helper_find_suggest (gpointer data, GstTypeFindProbability probability,
  * typefinding is stopped immediately and the found caps will be returned
  * right away. Otherwise, all available typefind functions will the tried,
  * and the caps with the highest probability will be returned, or #NULL if
- * the content of the buffer could not be identified.
+ * the content of @data could not be identified.
  *
  * Free-function: gst_caps_unref
  *
@@ -503,7 +488,7 @@ buf_helper_find_suggest (gpointer data, GstTypeFindProbability probability,
  *     with gst_caps_unref().
  */
 GstCaps *
-gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
+gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size,
     GstTypeFindProbability * prob)
 {
   GstTypeFindBufHelper helper;
@@ -511,13 +496,10 @@ gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
   GList *l, *type_list;
   GstCaps *result = NULL;
 
-  g_return_val_if_fail (buf != NULL, NULL);
-  g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
-  g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
-      GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);
+  g_return_val_if_fail (data != NULL, NULL);
 
-  helper.data = GST_BUFFER_DATA (buf);
-  helper.size = GST_BUFFER_SIZE (buf);
+  helper.data = data;
+  helper.size = size;
   helper.best_probability = GST_TYPE_FIND_NONE;
   helper.caps = NULL;
   helper.obj = obj;
@@ -553,6 +535,50 @@ gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
 }
 
 /**
+ * gst_type_find_helper_for_buffer:
+ * @obj: object doing the typefinding, or NULL (used for logging)
+ * @buf: (in) (transfer none): a #GstBuffer with data to typefind
+ * @prob: (out) (allow-none): location to store the probability of the found
+ *     caps, or #NULL
+ *
+ * Tries to find what type of data is contained in the given #GstBuffer, the
+ * assumption being that the buffer represents the beginning of the stream or
+ * file.
+ *
+ * All available typefinders will be called on the data in order of rank. If
+ * a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
+ * typefinding is stopped immediately and the found caps will be returned
+ * right away. Otherwise, all available typefind functions will the tried,
+ * and the caps with the highest probability will be returned, or #NULL if
+ * the content of the buffer could not be identified.
+ *
+ * Free-function: gst_caps_unref
+ *
+ * Returns: (transfer full): the #GstCaps corresponding to the data, or #NULL
+ *     if no type could be found. The caller should free the caps returned
+ *     with gst_caps_unref().
+ */
+GstCaps *
+gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
+    GstTypeFindProbability * prob)
+{
+  GstCaps *result;
+  guint8 *data;
+  gsize size;
+
+  g_return_val_if_fail (buf != NULL, NULL);
+  g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
+  g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
+      GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);
+
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  result = gst_type_find_helper_for_data (obj, data, size, prob);
+  gst_buffer_unmap (buf, data, size);
+
+  return result;
+}
+
+/**
  * gst_type_find_helper_for_extension:
  * @obj: (allow-none): object doing the typefinding, or NULL (used for logging)
  * @extension: an extension
index b6ad517..a61c042 100644 (file)
@@ -30,6 +30,10 @@ G_BEGIN_DECLS
 
 GstCaps * gst_type_find_helper (GstPad *src, guint64 size);
 
+GstCaps * gst_type_find_helper_for_data   (GstObject              *obj,
+                                           const guint8           *data,
+                                           gsize                   size,
+                                           GstTypeFindProbability *prob);
 GstCaps * gst_type_find_helper_for_buffer (GstObject              *obj,
                                            GstBuffer              *buf,
                                            GstTypeFindProbability *prob);
@@ -40,6 +44,7 @@ GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
 /**
  * GstTypeFindHelperGetRangeFunction:
  * @obj: a #GstObject that will handle the getrange request
+ * @parent: the parent of @obj or NULL
  * @offset: the offset of the range
  * @length: the length of the range
  * @buffer: a memory location to hold the result buffer
@@ -55,21 +60,18 @@ GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
  * Returns: GST_FLOW_OK for success
  */
 typedef GstFlowReturn (*GstTypeFindHelperGetRangeFunction) (GstObject  *obj,
+                                                            GstObject  *parent,
                                                             guint64     offset,
                                                             guint       length,
                                                             GstBuffer **buffer);
 
-GstCaps * gst_type_find_helper_get_range (GstObject                        * obj,
+GstCaps * gst_type_find_helper_get_range (GstObject                         *obj,
+                                          GstObject                         *parent,
                                           GstTypeFindHelperGetRangeFunction  func,
                                           guint64                            size,
+                                          const gchar                       *extension,
                                           GstTypeFindProbability            *prob);
 
-GstCaps * gst_type_find_helper_get_range_ext (GstObject                        * obj,
-                                              GstTypeFindHelperGetRangeFunction  func,
-                                              guint64                            size,
-                                              const gchar                       *extension,
-                                              GstTypeFindProbability            *prob);
-
 G_END_DECLS
 
 #endif /* __GST_TYPEFINDHELPER_H__ */
index 8dcf66d..16cffad 100644 (file)
@@ -67,6 +67,7 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
        gst_buffer_straw_stop_pipeline \
        gst_check_abi_list \
        gst_check_caps_equal \
+       gst_check_buffer_data \
        gst_check_chain_func \
        gst_check_drop_buffers \
        gst_check_element_push_buffer \
@@ -120,6 +121,8 @@ GstCheck-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_MAJORMI
                $(INTROSPECTION_SCANNER) -v --namespace GstCheck \
                --nsversion=@GST_MAJORMINOR@ \
                --strip-prefix=Gst \
+               --warn-all \
+               -DGST_USE_UNSTABLE_API \
                -I$(top_srcdir) \
                -I$(top_srcdir)/libs \
                -I$(top_builddir) \
@@ -127,12 +130,12 @@ GstCheck-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_MAJORMI
                $(gir_cincludes) \
                --add-include-path=$(top_builddir)/gst \
                --library-path=$(top_builddir)/gst \
-               --library=$(top_builddir)/gst/libgstreamer-0.10.la \
-               --library=libgstcheck-0.10.la \
-               --include=Gst-0.10 \
+               --library=$(top_builddir)/gst/libgstreamer-0.11.la \
+               --library=libgstcheck-0.11.la \
+               --include=Gst-0.11 \
                --libtool="$(top_builddir)/libtool" \
-               --pkg gstreamer-0.10 \
-               --pkg-export gstreamer-check-0.10 \
+               --pkg gstreamer-@GST_MAJORMINOR@ \
+               --pkg-export gstreamer-check-@GST_MAJORMINOR@ \
                --add-init-section="gst_init(NULL,NULL);" \
                --output $@ \
                $(gir_headers) \
index 1089ed9..68405df 100644 (file)
@@ -37,9 +37,11 @@ static gulong id;
 
 /* called for every buffer.  Waits until the global "buf" variable is unset,
  * then sets it to the buffer received, and signals. */
-static gboolean
-buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
+static GstPadProbeReturn
+buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer unused)
 {
+  GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
+
   g_mutex_lock (lock);
 
   while (buf != NULL)
@@ -52,7 +54,7 @@ buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
 
   g_mutex_unlock (lock);
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 /**
@@ -81,7 +83,8 @@ gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad)
 {
   GstStateChangeReturn ret;
 
-  id = gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe), NULL);
+  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
+      buffer_probe, NULL, NULL);
 
   cond = g_cond_new ();
   lock = g_mutex_new ();
@@ -149,7 +152,7 @@ gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad)
   if (buf)
     gst_buffer_unref (buf);
   buf = NULL;
-  gst_pad_remove_buffer_probe (pad, (guint) id);
+  gst_pad_remove_probe (pad, (guint) id);
   id = 0;
   g_cond_signal (cond);
   g_mutex_unlock (lock);
index 9ec4a31..ed49704 100644 (file)
@@ -26,9 +26,9 @@
 
 G_BEGIN_DECLS
 
-void gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad);
-GstBuffer *gst_buffer_straw_get_buffer (GstElement * bin, GstPad * pad);
-void gst_buffer_straw_stop_pipeline (GstElement * bin, GstPad * pad);
+void        gst_buffer_straw_start_pipeline (GstElement * bin, GstPad * pad);
+GstBuffer * gst_buffer_straw_get_buffer     (GstElement * bin, GstPad * pad);
+void        gst_buffer_straw_stop_pipeline  (GstElement * bin, GstPad * pad);
 
 G_END_DECLS
 
index c4370a3..83fdd19 100644 (file)
@@ -98,7 +98,7 @@ print_plugins (void)
 {
   GList *plugins, *l;
 
-  plugins = gst_default_registry_get_plugin_list ();
+  plugins = gst_registry_get_plugin_list (gst_registry_get ());
   plugins = g_list_sort (plugins, (GCompareFunc) sort_plugins);
   for (l = plugins; l != NULL; l = l->next) {
     GstPlugin *plugin = GST_PLUGIN (l->data);
@@ -160,9 +160,9 @@ gst_check_message_error (GstMessage * message, GstMessageType type,
 
 /* helper functions */
 GstFlowReturn
-gst_check_chain_func (GstPad * pad, GstBuffer * buffer)
+gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
-  GST_DEBUG ("chain_func: received buffer %p", buffer);
+  GST_DEBUG_OBJECT (pad, "chain_func: received buffer %p", buffer);
   buffers = g_list_append (buffers, buffer);
 
   g_mutex_lock (check_mutex);
@@ -197,18 +197,10 @@ gst_check_teardown_element (GstElement * element)
   gst_object_unref (element);
 }
 
-/* FIXME: set_caps isn't that useful
- */
 GstPad *
-gst_check_setup_src_pad (GstElement * element,
-    GstStaticPadTemplate * tmpl, GstCaps * caps)
+gst_check_setup_src_pad (GstElement * element, GstStaticPadTemplate * tmpl)
 {
-  GstPad *srcpad;
-
-  srcpad = gst_check_setup_src_pad_by_name (element, tmpl, "sink");
-  if (caps)
-    fail_unless (gst_pad_set_caps (srcpad, caps), "could not set caps on pad");
-  return srcpad;
+  return gst_check_setup_src_pad_by_name (element, tmpl, "sink");
 }
 
 GstPad *
@@ -255,9 +247,6 @@ gst_check_teardown_pad_by_name (GstElement * element, const gchar * name)
       gst_pad_unlink (pad_peer, pad_element);
     else
       gst_pad_unlink (pad_element, pad_peer);
-
-    /* caps could have been set, make sure they get unset */
-    gst_pad_set_caps (pad_peer, NULL);
   }
 
   /* pad refs held by both creator and this function (through _get) */
@@ -279,18 +268,10 @@ gst_check_teardown_src_pad (GstElement * element)
   gst_check_teardown_pad_by_name (element, "sink");
 }
 
-/* FIXME: set_caps isn't that useful; might want to check if fixed,
- * then use set_use_fixed or somesuch */
 GstPad *
-gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl,
-    GstCaps * caps)
+gst_check_setup_sink_pad (GstElement * element, GstStaticPadTemplate * tmpl)
 {
-  GstPad *sinkpad;
-
-  sinkpad = gst_check_setup_sink_pad_by_name (element, tmpl, "src");
-  if (caps)
-    fail_unless (gst_pad_set_caps (sinkpad, caps), "Could not set pad caps");
-  return sinkpad;
+  return gst_check_setup_sink_pad_by_name (element, tmpl, "src");
 }
 
 GstPad *
@@ -366,6 +347,34 @@ gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2)
   g_free (name2);
 }
 
+
+/**
+ * gst_check_buffer_data:
+ * @buffer: buffer to compare
+ * @data: data to compare to
+ * @size: size of data to compare
+ *
+ * Compare the buffer contents with @data and @size.
+ */
+void
+gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size)
+{
+  guint8 *bdata;
+  gsize bsize;
+
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  GST_MEMDUMP ("Converted data", bdata, bsize);
+  GST_MEMDUMP ("Expected data", data, size);
+  if (memcmp (bdata, data, size) != 0) {
+    g_print ("\nConverted data:\n");
+    gst_util_dump_mem (bdata, bsize);
+    g_print ("\nExpected data:\n");
+    gst_util_dump_mem (data, size);
+  }
+  fail_unless (memcmp (bdata, data, size) == 0, "buffer contents not equal");
+  gst_buffer_unmap (buffer, bdata, bsize);
+}
+
 /**
  * gst_check_element_push_buffer_list:
  * @element_name: name of the element that needs to be created
@@ -389,8 +398,10 @@ void
 gst_check_element_push_buffer_list (const gchar * element_name,
     GList * buffer_in, GList * buffer_out, GstFlowReturn last_flow_return)
 {
+#if 0
   GstCaps *sink_caps;
   GstCaps *src_caps = NULL;
+#endif
   GstElement *element;
   GstPad *pad_peer;
   GstPad *sink_pad = NULL;
@@ -407,9 +418,13 @@ gst_check_element_push_buffer_list (const gchar * element_name,
   buffer = GST_BUFFER (buffer_in->data);
 
   fail_unless (GST_IS_BUFFER (buffer), "There should be a buffer in buffer_in");
+#if 0
   src_caps = GST_BUFFER_CAPS (buffer);
+#endif
   src_pad = gst_pad_new (NULL, GST_PAD_SRC);
+#if 0
   gst_pad_set_caps (src_pad, src_caps);
+#endif
   pad_peer = gst_element_get_static_pad (element, "sink");
   fail_if (pad_peer == NULL);
   fail_unless (gst_pad_link (src_pad, pad_peer) == GST_PAD_LINK_OK,
@@ -420,10 +435,13 @@ gst_check_element_push_buffer_list (const gchar * element_name,
   GST_DEBUG ("src pad activated");
   /* don't create the sink_pad if there is no buffer_out list */
   if (buffer_out != NULL) {
+#if 0
     gchar *temp;
+#endif
 
     GST_DEBUG ("buffer out detected, creating the sink pad");
     /* get the sink caps */
+#if 0
     sink_caps = GST_BUFFER_CAPS (GST_BUFFER (buffer_out->data));
     fail_unless (GST_IS_CAPS (sink_caps), "buffer out don't have caps");
     temp = gst_caps_to_string (sink_caps);
@@ -431,10 +449,13 @@ gst_check_element_push_buffer_list (const gchar * element_name,
     GST_DEBUG ("sink caps requested by buffer out: '%s'", temp);
     g_free (temp);
     fail_unless (gst_caps_is_fixed (sink_caps), "we need fixed caps");
+#endif
     /* get the sink pad */
     sink_pad = gst_pad_new (NULL, GST_PAD_SINK);
     fail_unless (GST_IS_PAD (sink_pad));
+#if 0
     gst_pad_set_caps (sink_pad, sink_caps);
+#endif
     /* get the peer pad */
     pad_peer = gst_element_get_static_pad (element, "src");
     fail_unless (gst_pad_link (pad_peer, sink_pad) == GST_PAD_LINK_OK,
@@ -471,22 +492,31 @@ gst_check_element_push_buffer_list (const gchar * element_name,
   while (buffers != NULL) {
     GstBuffer *new = GST_BUFFER (buffers->data);
     GstBuffer *orig = GST_BUFFER (buffer_out->data);
+    gsize newsize, origsize;
+    guint8 *newdata, *origdata;
 
-    GST_LOG ("orig buffer: size %u, caps %" GST_PTR_FORMAT,
-        GST_BUFFER_SIZE (orig), GST_BUFFER_CAPS (orig));
-    GST_LOG ("new  buffer: size %u, caps %" GST_PTR_FORMAT,
-        GST_BUFFER_SIZE (new), GST_BUFFER_CAPS (new));
-    GST_MEMDUMP ("orig buffer", GST_BUFFER_DATA (orig), GST_BUFFER_SIZE (orig));
-    GST_MEMDUMP ("new  buffer", GST_BUFFER_DATA (new), GST_BUFFER_SIZE (new));
+    newdata = gst_buffer_map (new, &newsize, NULL, GST_MAP_READ);
+    origdata = gst_buffer_map (orig, &origsize, NULL, GST_MAP_READ);
+
+    GST_LOG ("orig buffer: size %" G_GSIZE_FORMAT, origsize);
+    GST_LOG ("new  buffer: size %" G_GSIZE_FORMAT, newsize);
+    GST_MEMDUMP ("orig buffer", origdata, origsize);
+    GST_MEMDUMP ("new  buffer", newdata, newsize);
 
     /* remove the buffers */
     buffers = g_list_remove (buffers, new);
     buffer_out = g_list_remove (buffer_out, orig);
-    fail_unless (GST_BUFFER_SIZE (orig) == GST_BUFFER_SIZE (new),
-        "size of the buffers are not the same");
-    fail_unless (memcmp (GST_BUFFER_DATA (orig), GST_BUFFER_DATA (new),
-            GST_BUFFER_SIZE (new)) == 0, "data is not the same");
+
+    fail_unless (origsize == newsize, "size of the buffers are not the same");
+    fail_unless (memcmp (origdata, newdata, newsize) == 0,
+        "data is not the same");
+#if 0
     gst_check_caps_equal (GST_BUFFER_CAPS (orig), GST_BUFFER_CAPS (new));
+#endif
+
+    gst_buffer_unmap (orig, origdata, origsize);
+    gst_buffer_unmap (new, newdata, newsize);
+
     gst_buffer_unref (new);
     gst_buffer_unref (orig);
   }
index 5e3f995..c0d349f 100644 (file)
@@ -64,7 +64,7 @@ GstCheckABIStruct;
 
 void gst_check_init (int *argc, char **argv[]);
 
-GstFlowReturn gst_check_chain_func (GstPad * pad, GstBuffer * buffer);
+GstFlowReturn gst_check_chain_func (GstPad * pad, GstObject * parent, GstBuffer * buffer);
 
 void gst_check_message_error (GstMessage * message, GstMessageType type,
     GQuark domain, gint code);
@@ -72,7 +72,7 @@ void gst_check_message_error (GstMessage * message, GstMessageType type,
 GstElement *gst_check_setup_element (const gchar * factory);
 void gst_check_teardown_element (GstElement * element);
 GstPad *gst_check_setup_src_pad (GstElement * element,
-    GstStaticPadTemplate * tmpl, GstCaps * caps);
+    GstStaticPadTemplate * tmpl);
 GstPad * gst_check_setup_src_pad_by_name (GstElement * element,
           GstStaticPadTemplate * tmpl, const gchar *name);
 GstPad * gst_check_setup_sink_pad_by_name (GstElement * element, 
@@ -81,19 +81,20 @@ void gst_check_teardown_pad_by_name (GstElement * element, const gchar *name);
 void gst_check_teardown_src_pad (GstElement * element);
 void gst_check_drop_buffers (void);
 void gst_check_caps_equal (GstCaps * caps1, GstCaps * caps2);
+void gst_check_buffer_data (GstBuffer * buffer, gconstpointer data, gsize size);
 void gst_check_element_push_buffer_list (const gchar * element_name,
     GList * buffer_in, GList * buffer_out, GstFlowReturn last_flow_return);
 void gst_check_element_push_buffer (const gchar * element_name,
     GstBuffer * buffer_in, GstBuffer * buffer_out);
 GstPad *gst_check_setup_sink_pad (GstElement * element,
-    GstStaticPadTemplate * tmpl, GstCaps * caps);
+    GstStaticPadTemplate * tmpl);
 void gst_check_teardown_sink_pad (GstElement * element);
 void gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes);
 gint gst_check_run_suite (Suite * suite, const gchar * name,
     const gchar * fname);
 
-#define fail_unless_message_error(msg, domain, code)           \
-gst_check_message_error (msg, GST_MESSAGE_ERROR,               \
+#define fail_unless_message_error(msg, domain, code)            \
+gst_check_message_error (msg, GST_MESSAGE_ERROR,                \
   GST_ ## domain ## _ERROR, GST_ ## domain ## _ERROR_ ## code)
 #define assert_message_error(m, d, c) fail_unless_message_error(m, d, c)
 
@@ -128,12 +129,12 @@ static void __testname (int __i__)\
  * case, printing both expressions and the values they evaluated to. This
  * macro is for use in unit tests.
  */
-#define fail_unless_equals_int(a, b)                                   \
-G_STMT_START {                                                         \
-  int first = a;                                                       \
-  int second = b;                                                      \
-  fail_unless(first == second,                                         \
-    "'" #a "' (%d) is not equal to '" #b"' (%d)", first, second);      \
+#define fail_unless_equals_int(a, b)                                    \
+G_STMT_START {                                                          \
+  int first = a;                                                        \
+  int second = b;                                                       \
+  fail_unless(first == second,                                          \
+    "'" #a "' (%d) is not equal to '" #b"' (%d)", first, second);       \
 } G_STMT_END;
 /**
  * assert_equals_int:
@@ -155,13 +156,13 @@ G_STMT_START {                                                            \
  * case, printing both expressions and the values they evaluated to. This
  * macro is for use in unit tests.
  */
-#define fail_unless_equals_int64(a, b)                                 \
-G_STMT_START {                                                         \
-  gint64 first = a;                                                    \
-  gint64 second = b;                                                   \
-  fail_unless(first == second,                                         \
-    "'" #a "' (%" G_GINT64_FORMAT") is not equal to '" #b"' (%"                \
-    G_GINT64_FORMAT")", first, second);                                        \
+#define fail_unless_equals_int64(a, b)                                  \
+G_STMT_START {                                                          \
+  gint64 first = a;                                                     \
+  gint64 second = b;                                                    \
+  fail_unless(first == second,                                          \
+    "'" #a "' (%" G_GINT64_FORMAT") is not equal to '" #b"' (%"         \
+    G_GINT64_FORMAT")", first, second);                                 \
 } G_STMT_END;
 /**
  * assert_equals_int64:
@@ -183,13 +184,13 @@ G_STMT_START {                                                            \
  * case, printing both expressions and the values they evaluated to. This
  * macro is for use in unit tests.
  */
-#define fail_unless_equals_uint64(a, b)                                        \
-G_STMT_START {                                                         \
-  guint64 first = a;                                                   \
-  guint64 second = b;                                                  \
-  fail_unless(first == second,                                         \
-    "'" #a "' (%" G_GUINT64_FORMAT ") is not equal to '" #b"' (%"      \
-    G_GUINT64_FORMAT ")", first, second);                              \
+#define fail_unless_equals_uint64(a, b)                                 \
+G_STMT_START {                                                          \
+  guint64 first = a;                                                    \
+  guint64 second = b;                                                   \
+  fail_unless(first == second,                                          \
+    "'" #a "' (%" G_GUINT64_FORMAT ") is not equal to '" #b"' (%"       \
+    G_GUINT64_FORMAT ")", first, second);                               \
 } G_STMT_END;
 /**
  * assert_equals_uint64:
@@ -269,12 +270,12 @@ G_STMT_START {                                                    \
  */
 extern GList *thread_list;
 extern GMutex *mutex;
-extern GCond *start_cond;      /* used to notify main thread of thread startups */
-extern GCond *sync_cond;       /* used to synchronize all threads and main thread */
+extern GCond *start_cond;       /* used to notify main thread of thread startups */
+extern GCond *sync_cond;        /* used to synchronize all threads and main thread */
 
-#define MAIN_START_THREADS(count, function, data)              \
-MAIN_INIT();                                                   \
-MAIN_START_THREAD_FUNCTIONS(count, function, data);            \
+#define MAIN_START_THREADS(count, function, data)               \
+MAIN_INIT();                                                    \
+MAIN_START_THREAD_FUNCTIONS(count, function, data);             \
 MAIN_SYNCHRONIZE();
 
 #if GLIB_CHECK_VERSION (2, 31, 0)
@@ -352,161 +353,169 @@ gst_g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *abs_time)
 }
 #endif
 
-#define MAIN_INIT()                    \
-G_STMT_START {                         \
-  _gst_check_threads_running = TRUE;   \
-                                       \
-  if (mutex == NULL) {                 \
-    mutex = g_mutex_new ();            \
-    start_cond = g_cond_new ();                \
-    sync_cond = g_cond_new ();         \
-  }                                    \
+#define MAIN_INIT()                     \
+G_STMT_START {                          \
+  _gst_check_threads_running = TRUE;    \
+                                        \
+  if (mutex == NULL) {                  \
+    mutex = g_mutex_new ();             \
+    start_cond = g_cond_new ();         \
+    sync_cond = g_cond_new ();          \
+  }                                     \
 } G_STMT_END;
 
-#define MAIN_START_THREAD_FUNCTIONS(count, function, data)     \
-G_STMT_START {                                                 \
-  int i;                                                       \
-  for (i = 0; i < count; ++i) {                                        \
-    MAIN_START_THREAD_FUNCTION (i, function, data);            \
-  }                                                            \
+#define MAIN_START_THREAD_FUNCTIONS(count, function, data)      \
+G_STMT_START {                                                  \
+  int i;                                                        \
+  for (i = 0; i < count; ++i) {                                 \
+    MAIN_START_THREAD_FUNCTION (i, function, data);             \
+  }                                                             \
 } G_STMT_END;
 
-#define MAIN_START_THREAD_FUNCTION(i, function, data)          \
-G_STMT_START {                                                 \
-    GThread *thread = NULL;                                    \
-    GST_DEBUG ("MAIN: creating thread %d", i);                 \
-    g_mutex_lock (mutex);                                      \
-    thread = g_thread_create ((GThreadFunc) function, data,    \
-       TRUE, NULL);                                            \
-    /* wait for thread to signal us that it's ready */         \
-    GST_DEBUG ("MAIN: waiting for thread %d", i);              \
-    g_cond_wait (start_cond, mutex);                           \
-    g_mutex_unlock (mutex);                                    \
-                                                               \
-    thread_list = g_list_append (thread_list, thread);         \
+#define MAIN_START_THREAD_FUNCTION(i, function, data)           \
+G_STMT_START {                                                  \
+    GThread *thread = NULL;                                     \
+    GST_DEBUG ("MAIN: creating thread %d", i);                  \
+    g_mutex_lock (mutex);                                       \
+    thread = g_thread_create ((GThreadFunc) function, data,     \
+        TRUE, NULL);                                            \
+    /* wait for thread to signal us that it's ready */          \
+    GST_DEBUG ("MAIN: waiting for thread %d", i);               \
+    g_cond_wait (start_cond, mutex);                            \
+    g_mutex_unlock (mutex);                                     \
+                                                                \
+    thread_list = g_list_append (thread_list, thread);          \
 } G_STMT_END;
 
 
-#define MAIN_SYNCHRONIZE()             \
-G_STMT_START {                         \
-  GST_DEBUG ("MAIN: synchronizing");   \
-  g_cond_broadcast (sync_cond);                \
-  GST_DEBUG ("MAIN: synchronized");    \
+#define MAIN_SYNCHRONIZE()              \
+G_STMT_START {                          \
+  GST_DEBUG ("MAIN: synchronizing");    \
+  g_cond_broadcast (sync_cond);         \
+  GST_DEBUG ("MAIN: synchronized");     \
 } G_STMT_END;
 
-#define MAIN_STOP_THREADS()                                    \
-G_STMT_START {                                                 \
-  _gst_check_threads_running = FALSE;                          \
-                                                               \
-  /* join all threads */                                       \
-  GST_DEBUG ("MAIN: joining");                                 \
-  g_list_foreach (thread_list, (GFunc) g_thread_join, NULL);   \
-  g_list_free (thread_list);                                   \
-  thread_list = NULL;                                          \
-  GST_DEBUG ("MAIN: joined");                                  \
+#define MAIN_STOP_THREADS()                                     \
+G_STMT_START {                                                  \
+  _gst_check_threads_running = FALSE;                           \
+                                                                \
+  /* join all threads */                                        \
+  GST_DEBUG ("MAIN: joining");                                  \
+  g_list_foreach (thread_list, (GFunc) g_thread_join, NULL);    \
+  g_list_free (thread_list);                                    \
+  thread_list = NULL;                                           \
+  GST_DEBUG ("MAIN: joined");                                   \
 } G_STMT_END;
 
-#define THREAD_START()                                         \
-THREAD_STARTED();                                              \
+#define THREAD_START()                                          \
+THREAD_STARTED();                                               \
 THREAD_SYNCHRONIZE();
 
-#define THREAD_STARTED()                                       \
-G_STMT_START {                                                 \
-  /* signal main thread that we started */                     \
-  GST_DEBUG ("THREAD %p: started", g_thread_self ());          \
-  g_mutex_lock (mutex);                                                \
-  g_cond_signal (start_cond);                                  \
+#define THREAD_STARTED()                                        \
+G_STMT_START {                                                  \
+  /* signal main thread that we started */                      \
+  GST_DEBUG ("THREAD %p: started", g_thread_self ());           \
+  g_mutex_lock (mutex);                                         \
+  g_cond_signal (start_cond);                                   \
 } G_STMT_END;
 
-#define THREAD_SYNCHRONIZE()                                   \
-G_STMT_START {                                                 \
-  /* synchronize everyone */                                   \
-  GST_DEBUG ("THREAD %p: syncing", g_thread_self ());          \
-  g_cond_wait (sync_cond, mutex);                              \
-  GST_DEBUG ("THREAD %p: synced", g_thread_self ());           \
-  g_mutex_unlock (mutex);                                      \
+#define THREAD_SYNCHRONIZE()                                    \
+G_STMT_START {                                                  \
+  /* synchronize everyone */                                    \
+  GST_DEBUG ("THREAD %p: syncing", g_thread_self ());           \
+  g_cond_wait (sync_cond, mutex);                               \
+  GST_DEBUG ("THREAD %p: synced", g_thread_self ());            \
+  g_mutex_unlock (mutex);                                       \
 } G_STMT_END;
 
-#define THREAD_SWITCH()                                                \
-G_STMT_START {                                                 \
-  /* a minimal sleep is a context switch */                    \
-  g_usleep (1);                                                        \
+#define THREAD_SWITCH()                                         \
+G_STMT_START {                                                  \
+  /* a minimal sleep is a context switch */                     \
+  g_usleep (1);                                                 \
 } G_STMT_END;
 
-#define THREAD_TEST_RUNNING()  (_gst_check_threads_running == TRUE)
+#define THREAD_TEST_RUNNING()   (_gst_check_threads_running == TRUE)
 
 /* additional assertions */
-#define ASSERT_CRITICAL(code)                                  \
-G_STMT_START {                                                 \
-  _gst_check_expecting_log = TRUE;                             \
-  _gst_check_raised_critical = FALSE;                          \
-  code;                                                                \
+#define ASSERT_CRITICAL(code)                                   \
+G_STMT_START {                                                  \
+  _gst_check_expecting_log = TRUE;                              \
+  _gst_check_raised_critical = FALSE;                           \
+  code;                                                         \
   _fail_unless (_gst_check_raised_critical, __FILE__, __LINE__, \
                 "Expected g_critical, got nothing", NULL);      \
-  _gst_check_expecting_log = FALSE;                            \
+  _gst_check_expecting_log = FALSE;                             \
 } G_STMT_END
 
-#define ASSERT_WARNING(code)                                   \
-G_STMT_START {                                                 \
-  _gst_check_expecting_log = TRUE;                             \
-  _gst_check_raised_warning = FALSE;                           \
-  code;                                                                \
+#define ASSERT_WARNING(code)                                    \
+G_STMT_START {                                                  \
+  _gst_check_expecting_log = TRUE;                              \
+  _gst_check_raised_warning = FALSE;                            \
+  code;                                                         \
   _fail_unless (_gst_check_raised_warning, __FILE__, __LINE__,  \
                 "Expected g_warning, got nothing", NULL);       \
-  _gst_check_expecting_log = FALSE;                            \
+  _gst_check_expecting_log = FALSE;                             \
 } G_STMT_END
 
 
-#define ASSERT_OBJECT_REFCOUNT(object, name, value)            \
-G_STMT_START {                                                 \
-  int rc;                                                      \
-  rc = GST_OBJECT_REFCOUNT_VALUE (object);                     \
-  fail_unless (rc == value,                                    \
-      "%s (%p) refcount is %d instead of %d",                  \
-      name, object, rc, value);                                        \
+#define ASSERT_OBJECT_REFCOUNT(object, name, value)             \
+G_STMT_START {                                                  \
+  int rc;                                                       \
+  rc = GST_OBJECT_REFCOUNT_VALUE (object);                      \
+  fail_unless (rc == value,                                     \
+      "%s (%p) refcount is %d instead of %d",                   \
+      name, object, rc, value);                                 \
 } G_STMT_END
 
-#define ASSERT_OBJECT_REFCOUNT_BETWEEN(object, name, lower, upper)     \
-G_STMT_START {                                                         \
-  int rc = GST_OBJECT_REFCOUNT_VALUE (object);                         \
-  int lo = lower;                                                      \
-  int hi = upper;                                                      \
-                                                                       \
-  fail_unless (rc >= lo,                                               \
-      "%s (%p) refcount %d is smaller than %d",                                \
-      name, object, rc, lo);                                           \
-  fail_unless (rc <= hi,                                               \
-      "%s (%p) refcount %d is bigger than %d",                         \
-      name, object, rc, hi);                                           \
+#define ASSERT_OBJECT_REFCOUNT_BETWEEN(object, name, lower, upper)      \
+G_STMT_START {                                                          \
+  int rc = GST_OBJECT_REFCOUNT_VALUE (object);                          \
+  int lo = lower;                                                       \
+  int hi = upper;                                                       \
+                                                                        \
+  fail_unless (rc >= lo,                                                \
+      "%s (%p) refcount %d is smaller than %d",                         \
+      name, object, rc, lo);                                            \
+  fail_unless (rc <= hi,                                                \
+      "%s (%p) refcount %d is bigger than %d",                          \
+      name, object, rc, hi);                                            \
 } G_STMT_END
 
 
-#define ASSERT_CAPS_REFCOUNT(caps, name, value)                        \
-       ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value)
+#define ASSERT_CAPS_REFCOUNT(caps, name, value)                 \
+        ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value)
 
-#define ASSERT_BUFFER_REFCOUNT(buffer, name, value)            \
-       ASSERT_MINI_OBJECT_REFCOUNT(buffer, name, value)
+#define ASSERT_BUFFER_REFCOUNT(buffer, name, value)             \
+        ASSERT_MINI_OBJECT_REFCOUNT(buffer, name, value)
 
-#define ASSERT_MINI_OBJECT_REFCOUNT(caps, name, value)         \
-G_STMT_START {                                                 \
-  int rc;                                                      \
-  rc = GST_MINI_OBJECT_REFCOUNT_VALUE (caps);                  \
-  fail_unless (rc == value,                                    \
-               name " refcount is %d instead of %d", rc, value);\
+#define ASSERT_MEMORY_REFCOUNT(memory, name, value)             \
+G_STMT_START {                                                  \
+  int rc;                                                       \
+  rc = memory->refcount;                                        \
+  fail_unless (rc == value,                                     \
+               name " (%p) refcount is %d instead of %d", memory, rc, value); \
 } G_STMT_END
 
-#define ASSERT_SET_STATE(element, state, ret)                  \
-fail_unless (gst_element_set_state (element,                   \
-  state) == ret,                                               \
+#define ASSERT_MINI_OBJECT_REFCOUNT(miniobj, name, value)       \
+G_STMT_START {                                                  \
+  int rc;                                                       \
+  rc = GST_MINI_OBJECT_REFCOUNT_VALUE (miniobj);                \
+  fail_unless (rc == value,                                     \
+               name " (%p) refcount is %d instead of %d", miniobj, rc, value); \
+} G_STMT_END
+
+#define ASSERT_SET_STATE(element, state, ret)                   \
+fail_unless (gst_element_set_state (element,                    \
+  state) == ret,                                                \
   "could not change state to " #state);
 
-#define GST_CHECK_MAIN(name)                                   \
-int main (int argc, char **argv)                               \
-{                                                              \
+#define GST_CHECK_MAIN(name)                                    \
+int main (int argc, char **argv)                                \
+{                                                               \
   Suite *s;                                                     \
-  gst_check_init (&argc, &argv);                               \
-  s = name ## _suite ();                                       \
-  return gst_check_run_suite (s, # name, __FILE__);            \
+  gst_check_init (&argc, &argv);                                \
+  s = name ## _suite ();                                        \
+  return gst_check_run_suite (s, # name, __FILE__);             \
 }
 
 /* Hack to allow run-time selection of unit tests to run via the
index ded047e..66291f4 100644 (file)
 struct _GstStreamConsistency
 {
   gboolean flushing;
-  gboolean newsegment;
+  gboolean segment;
   gboolean eos;
   gulong probeid;
   GstPad *pad;
 };
 
 static gboolean
-source_pad_data_cb (GstPad * pad, GstMiniObject * data,
+source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info,
     GstStreamConsistency * consist)
 {
+  GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info);
+
   if (GST_IS_BUFFER (data)) {
-    GST_DEBUG_OBJECT (pad, "Buffer %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (GST_BUFFER (data))));
+    GST_DEBUG_OBJECT (pad,
+        "Buffer pts %" GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (GST_BUFFER_PTS (GST_BUFFER_CAST (data))),
+        GST_TIME_ARGS (GST_BUFFER_DTS (GST_BUFFER_CAST (data))));
     /* If an EOS went through, a buffer would be invalid */
     fail_if (consist->eos, "Buffer received after EOS");
-    /* Buffers need to be preceded by a newsegment event */
-    fail_unless (consist->newsegment, "Buffer received without newsegment");
+    /* Buffers need to be preceded by a segment event */
+    fail_unless (consist->segment, "Buffer received without segment");
   } else if (GST_IS_EVENT (data)) {
     GstEvent *event = (GstEvent *) data;
 
@@ -67,23 +71,24 @@ source_pad_data_cb (GstPad * pad, GstMiniObject * data,
         fail_if (consist->eos, "Received a FLUSH_STOP after an EOS");
         consist->flushing = FALSE;
         break;
-      case GST_EVENT_NEWSEGMENT:
-        consist->newsegment = TRUE;
+      case GST_EVENT_SEGMENT:
+        consist->segment = TRUE;
         consist->eos = FALSE;
         break;
       case GST_EVENT_EOS:
         /* FIXME : not 100% sure about whether two eos in a row is valid */
         fail_if (consist->eos, "Received EOS just after another EOS");
         consist->eos = TRUE;
-        consist->newsegment = FALSE;
+        consist->segment = FALSE;
         break;
       case GST_EVENT_TAG:
-        GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT, event->structure);
+        GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT,
+            gst_event_get_structure (event));
         /* fall through */
       default:
         if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_IS_DOWNSTREAM (event)) {
           fail_if (consist->eos, "Event received after EOS");
-          fail_unless (consist->newsegment, "Event received before newsegment");
+          fail_unless (consist->segment, "Event received before segment");
         }
         /* FIXME : Figure out what to do for other events */
         break;
@@ -117,7 +122,8 @@ gst_consistency_checker_new (GstPad * pad)
   consist = g_new0 (GstStreamConsistency, 1);
   consist->pad = g_object_ref (pad);
   consist->probeid =
-      gst_pad_add_data_probe (pad, (GCallback) source_pad_data_cb, consist);
+      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
+      (GstPadProbeCallback) source_pad_data_cb, consist, NULL);
 
   return consist;
 }
@@ -136,7 +142,7 @@ gst_consistency_checker_reset (GstStreamConsistency * consist)
 {
   consist->eos = FALSE;
   consist->flushing = FALSE;
-  consist->newsegment = FALSE;
+  consist->segment = FALSE;
 }
 
 /**
@@ -152,7 +158,7 @@ void
 gst_consistency_checker_free (GstStreamConsistency * consist)
 {
   /* Remove the data probe */
-  gst_pad_remove_data_probe (consist->pad, consist->probeid);
+  gst_pad_remove_probe (consist->pad, consist->probeid);
   g_object_unref (consist->pad);
   g_free (consist);
 }
index bf99b4e..490cb8c 100644 (file)
@@ -2,23 +2,19 @@ lib_LTLIBRARIES = libgstcontroller-@GST_MAJORMINOR@.la
 
 libgstcontroller_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/controller
 libgstcontroller_@GST_MAJORMINOR@_include_HEADERS = \
-       gstcontroller.h \
-       gstcontrolsource.h \
+  gstcontrolbindingargb.h \
+  gstcontrolbindingdirect.h \
+       gsttimedvaluecontrolsource.h \
        gstinterpolationcontrolsource.h \
+       gsttriggercontrolsource.h \
        gstlfocontrolsource.h
 
-noinst_HEADERS = \
-       gstcontrollerprivate.h \
-       gstinterpolationcontrolsourceprivate.h \
-       gstlfocontrolsourceprivate.h
-
 libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
-       lib.c \
-       gstcontroller.c \
-       gstinterpolation.c \
-       gsthelper.c \
-       gstcontrolsource.c \
+  gstcontrolbindingargb.c \
+  gstcontrolbindingdirect.c \
+       gsttimedvaluecontrolsource.c \
        gstinterpolationcontrolsource.c \
+       gsttriggercontrolsource.c \
        gstlfocontrolsource.c
 
 libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
@@ -56,7 +52,9 @@ GstController-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@G
                GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
                $(INTROSPECTION_SCANNER) -v --namespace GstController \
                --nsversion=@GST_MAJORMINOR@ \
+               --warn-all \
                --strip-prefix=Gst \
+               -DGST_USE_UNSTABLE_API \
                -I$(top_srcdir) \
                -I$(top_srcdir)/libs \
                -I$(top_builddir) \
@@ -64,12 +62,12 @@ GstController-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@G
                $(gir_cincludes) \
                --add-include-path=$(top_builddir)/gst \
                --library-path=$(top_builddir)/gst \
-               --library=$(top_builddir)/gst/libgstreamer-0.10.la \
-               --library=libgstcontroller-0.10.la \
-               --include=Gst-0.10 \
+               --library=$(top_builddir)/gst/libgstreamer-0.11.la \
+               --library=libgstcontroller-0.11.la \
+               --include=Gst-0.11 \
                --libtool="$(top_builddir)/libtool" \
-               --pkg gstreamer-0.10 \
-               --pkg-export gstreamer-controller-0.10 \
+               --pkg gstreamer-@GST_MAJORMINOR@ \
+               --pkg-export gstreamer-controller-@GST_MAJORMINOR@ \
                --add-init-section="gst_init(NULL,NULL);" \
                --output $@ \
                $(gir_headers) \
diff --git a/libs/gst/controller/gstcontrolbindingargb.c b/libs/gst/controller/gstcontrolbindingargb.c
new file mode 100644 (file)
index 0000000..d8cae98
--- /dev/null
@@ -0,0 +1,407 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbindingargb.c: Attachment for multiple control sources to gargb
+ *                            properties
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:gstcontrolbindingargb
+ * @short_description: attachment for control source sources to argb properties
+ *
+ * A value mapping object that attaches multiple control sources to a guint
+ * gobject properties representing a color.
+ */
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gstcontrolbindingargb.h"
+
+#include <math.h>
+
+#define GST_CAT_DEFAULT control_binding_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static GObject *gst_control_binding_argb_constructor (GType type,
+    guint n_construct_params, GObjectConstructParam * construct_params);
+static void gst_control_binding_argb_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_control_binding_argb_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_control_binding_argb_dispose (GObject * object);
+static void gst_control_binding_argb_finalize (GObject * object);
+
+static gboolean gst_control_binding_argb_sync_values (GstControlBinding * _self,
+    GstObject * object, GstClockTime timestamp, GstClockTime last_sync);
+static GValue *gst_control_binding_argb_get_value (GstControlBinding * _self,
+    GstClockTime timestamp);
+static gboolean gst_control_binding_argb_get_value_array (GstControlBinding *
+    _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values);
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolbindingargb", 0, \
+      "dynamic parameter control source attachment");
+
+G_DEFINE_TYPE_WITH_CODE (GstControlBindingARGB, gst_control_binding_argb,
+    GST_TYPE_CONTROL_BINDING, _do_init);
+
+enum
+{
+  PROP_0,
+  PROP_CS_A,
+  PROP_CS_R,
+  PROP_CS_G,
+  PROP_CS_B,
+  PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+/* vmethods */
+
+static void
+gst_control_binding_argb_class_init (GstControlBindingARGBClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstControlBindingClass *control_binding_class =
+      GST_CONTROL_BINDING_CLASS (klass);
+
+  gobject_class->constructor = gst_control_binding_argb_constructor;
+  gobject_class->set_property = gst_control_binding_argb_set_property;
+  gobject_class->get_property = gst_control_binding_argb_get_property;
+  gobject_class->dispose = gst_control_binding_argb_dispose;
+  gobject_class->finalize = gst_control_binding_argb_finalize;
+
+  control_binding_class->sync_values = gst_control_binding_argb_sync_values;
+  control_binding_class->get_value = gst_control_binding_argb_get_value;
+  control_binding_class->get_value_array =
+      gst_control_binding_argb_get_value_array;
+
+  properties[PROP_CS_A] =
+      g_param_spec_object ("control-source-a", "ControlSource A",
+      "The control source for the alpha color component",
+      GST_TYPE_CONTROL_SOURCE,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_CS_R] =
+      g_param_spec_object ("control-source-r", "ControlSource R",
+      "The control source for the red color component",
+      GST_TYPE_CONTROL_SOURCE,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_CS_G] =
+      g_param_spec_object ("control-source-g", "ControlSource G",
+      "The control source for the green color component",
+      GST_TYPE_CONTROL_SOURCE,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_CS_B] =
+      g_param_spec_object ("control-source-b", "ControlSource B",
+      "The control source for the blue color component",
+      GST_TYPE_CONTROL_SOURCE,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
+}
+
+static void
+gst_control_binding_argb_init (GstControlBindingARGB * self)
+{
+}
+
+static GObject *
+gst_control_binding_argb_constructor (GType type, guint n_construct_params,
+    GObjectConstructParam * construct_params)
+{
+  GstControlBindingARGB *self;
+
+  self =
+      GST_CONTROL_BINDING_ARGB (G_OBJECT_CLASS
+      (gst_control_binding_argb_parent_class)
+      ->constructor (type, n_construct_params, construct_params));
+
+  if (GST_CONTROL_BINDING_PSPEC (self)) {
+    if (!(G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self)) ==
+            G_TYPE_UINT)) {
+      GST_WARNING ("can't bind to paramspec type '%s'",
+          G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self)));
+      GST_CONTROL_BINDING_PSPEC (self) = NULL;
+    } else {
+      g_value_init (&self->cur_value, G_TYPE_UINT);
+    }
+  }
+  return (GObject *) self;
+}
+
+static void
+gst_control_binding_argb_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (object);
+
+  switch (prop_id) {
+    case PROP_CS_A:
+      self->cs_a = g_value_get_object (value);
+      break;
+    case PROP_CS_R:
+      self->cs_r = g_value_get_object (value);
+      break;
+    case PROP_CS_G:
+      self->cs_r = g_value_get_object (value);
+      break;
+    case PROP_CS_B:
+      self->cs_g = g_value_get_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_control_binding_argb_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (object);
+
+  switch (prop_id) {
+    case PROP_CS_A:
+      g_value_set_object (value, self->cs_a);
+      break;
+    case PROP_CS_R:
+      g_value_set_object (value, self->cs_r);
+      break;
+    case PROP_CS_G:
+      g_value_set_object (value, self->cs_g);
+      break;
+    case PROP_CS_B:
+      g_value_set_object (value, self->cs_b);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_control_binding_argb_dispose (GObject * object)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (object);
+
+  if (self->cs_a)
+    gst_object_replace ((GstObject **) & self->cs_a, NULL);
+  if (self->cs_r)
+    gst_object_replace ((GstObject **) & self->cs_r, NULL);
+  if (self->cs_g)
+    gst_object_replace ((GstObject **) & self->cs_g, NULL);
+  if (self->cs_b)
+    gst_object_replace ((GstObject **) & self->cs_b, NULL);
+}
+
+static void
+gst_control_binding_argb_finalize (GObject * object)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (object);
+
+  g_value_unset (&self->cur_value);
+}
+
+static gboolean
+gst_control_binding_argb_sync_values (GstControlBinding * _self,
+    GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (_self);
+  gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_ARGB (self), FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT,
+      _self->name, GST_TIME_ARGS (timestamp));
+
+  if (self->cs_a)
+    ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a);
+  if (self->cs_r)
+    ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r);
+  if (self->cs_g)
+    ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g);
+  if (self->cs_b)
+    ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b);
+  if (G_LIKELY (ret)) {
+    guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) |
+        (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) |
+        (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) |
+        ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255));
+    GST_LOG_OBJECT (object, "  new value 0x%08x", src_val);
+    /* always set the value for first time, but then only if it changed
+     * this should limit g_object_notify invocations.
+     * FIXME: can we detect negative playback rates?
+     */
+    if ((timestamp < last_sync) || (src_val != self->last_value)) {
+      GValue *dst_val = &self->cur_value;
+
+      g_value_set_uint (dst_val, src_val);
+      /* we can make this faster
+       * http://bugzilla.gnome.org/show_bug.cgi?id=536939
+       */
+      g_object_set_property ((GObject *) object, _self->name, dst_val);
+      self->last_value = src_val;
+    }
+  } else {
+    GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name);
+  }
+  return (ret);
+}
+
+static GValue *
+gst_control_binding_argb_get_value (GstControlBinding * _self,
+    GstClockTime timestamp)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (_self);
+  GValue *dst_val = NULL;
+  gdouble src_val_a = 1.0, src_val_r = 0.0, src_val_g = 0.0, src_val_b = 0.0;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_ARGB (self), NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  /* get current value via control source */
+  if (self->cs_a)
+    ret &= gst_control_source_get_value (self->cs_a, timestamp, &src_val_a);
+  if (self->cs_r)
+    ret &= gst_control_source_get_value (self->cs_r, timestamp, &src_val_r);
+  if (self->cs_g)
+    ret &= gst_control_source_get_value (self->cs_g, timestamp, &src_val_g);
+  if (self->cs_b)
+    ret &= gst_control_source_get_value (self->cs_b, timestamp, &src_val_b);
+  if (G_LIKELY (ret)) {
+    guint src_val = (((guint) (CLAMP (src_val_a, 0.0, 1.0) * 255)) << 24) |
+        (((guint) (CLAMP (src_val_r, 0.0, 1.0) * 255)) << 16) |
+        (((guint) (CLAMP (src_val_g, 0.0, 1.0) * 255)) << 8) |
+        ((guint) (CLAMP (src_val_b, 0.0, 1.0) * 255));
+    dst_val = g_new0 (GValue, 1);
+    g_value_init (dst_val, G_TYPE_UINT);
+    g_value_set_uint (dst_val, src_val);
+  } else {
+    GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT,
+        _self->name, GST_TIME_ARGS (timestamp));
+  }
+
+  return dst_val;
+}
+
+static gboolean
+gst_control_binding_argb_get_value_array (GstControlBinding * _self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  GstControlBindingARGB *self = GST_CONTROL_BINDING_ARGB (_self);
+  gint i;
+  gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b =
+      NULL;
+  guint src_val;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_ARGB (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  if (self->cs_a) {
+    src_val_a = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_a, timestamp,
+        interval, n_values, src_val_a);
+  }
+  if (self->cs_r) {
+    src_val_r = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_r, timestamp,
+        interval, n_values, src_val_r);
+  }
+  if (self->cs_g) {
+    src_val_g = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_g, timestamp,
+        interval, n_values, src_val_g);
+  }
+  if (self->cs_b) {
+    src_val_b = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_b, timestamp,
+        interval, n_values, src_val_b);
+  }
+  if (G_LIKELY (ret)) {
+    for (i = 0; i < n_values; i++) {
+      gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0;
+      if (src_val_a && !isnan (src_val_a[i]))
+        a = src_val_a[i];
+      if (src_val_r && !isnan (src_val_r[i]))
+        r = src_val_r[i];
+      if (src_val_g && !isnan (src_val_g[i]))
+        g = src_val_g[i];
+      if (src_val_b && !isnan (src_val_b[i]))
+        b = src_val_b[i];
+      src_val = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) |
+          (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) |
+          (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) |
+          ((guint) (CLAMP (b, 0.0, 1.0) * 255));
+      g_value_init (&values[i], G_TYPE_UINT);
+      g_value_set_uint (&values[i], src_val);
+    }
+  } else {
+    GST_LOG ("failed to get control value for property %s at ts %"
+        GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
+  }
+  g_free (src_val_a);
+  g_free (src_val_r);
+  g_free (src_val_g);
+  g_free (src_val_b);
+  return ret;
+}
+
+/* functions */
+
+/**
+ * gst_control_binding_argb_new:
+ * @object: the object of the property
+ * @property_name: the property-name to attach the control source
+ * @cs_a: the control source for the alpha channel
+ * @cs_r: the control source for the red channel
+ * @cs_g: the control source for the green channel
+ * @cs_b: the control source for the blue channel
+ *
+ * Create a new control-binding that attaches the given #GstControlSource to the
+ * #GObject property.
+ *
+ * Returns: the new #GstControlBindingARGB
+ */
+GstControlBinding *
+gst_control_binding_argb_new (GstObject * object, const gchar * property_name,
+    GstControlSource * cs_a, GstControlSource * cs_r, GstControlSource * cs_g,
+    GstControlSource * cs_b)
+{
+  return (GstControlBinding *) g_object_new (GST_TYPE_CONTROL_BINDING_ARGB,
+      "object", object, "name", property_name,
+      "control-source-a", cs_a,
+      "control-source-r", cs_r,
+      "control-source-g", cs_g, "control-source-b", cs_b, NULL);
+}
+
+/* functions */
diff --git a/libs/gst/controller/gstcontrolbindingargb.h b/libs/gst/controller/gstcontrolbindingargb.h
new file mode 100644 (file)
index 0000000..8d42ece
--- /dev/null
@@ -0,0 +1,98 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbindingargb.h: Attachment for multiple control sources to gargb
+ *                            properties
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_CONTROL_BINDING_ARGB_H__
+#define __GST_CONTROL_BINDING_ARGB_H__
+
+#include <gst/gstconfig.h>
+
+#include <glib-object.h>
+
+#include <gst/gstcontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CONTROL_BINDING_ARGB \
+  (gst_control_binding_argb_get_type())
+#define GST_CONTROL_BINDING_ARGB(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_BINDING_ARGB,GstControlBindingARGB))
+#define GST_CONTROL_BINDING_ARGB_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_BINDING_ARGB,GstControlBindingARGBClass))
+#define GST_IS_CONTROL_BINDING_ARGB(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_BINDING_ARGB))
+#define GST_IS_CONTROL_BINDING_ARGB_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_BINDING_ARGB))
+#define GST_CONTROL_BINDING_ARGB_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlBindingARGBClass))
+
+typedef struct _GstControlBindingARGB GstControlBindingARGB;
+typedef struct _GstControlBindingARGBClass GstControlBindingARGBClass;
+
+/**
+ * GstControlBindingARGB:
+ * @name: name of the property of this binding
+ *
+ * The instance structure of #GstControlBindingARGB.
+ */
+struct _GstControlBindingARGB {
+  GstControlBinding parent;
+  
+  /*< private >*/
+  GstControlSource *cs_a;       /* GstControlSources for this property */
+  GstControlSource *cs_r;
+  GstControlSource *cs_g;
+  GstControlSource *cs_b;
+
+  GValue cur_value;
+  guint32 last_value;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstControlBindingARGBClass:
+ * @parent_class: Parent class
+ * @convert: Class method to convert control-values
+ *
+ * The class structure of #GstControlBindingARGB.
+ */
+
+struct _GstControlBindingARGBClass
+{
+  GstControlBindingClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_control_binding_argb_get_type (void);
+
+/* Functions */
+
+GstControlBinding * gst_control_binding_argb_new   (GstObject * object, const gchar * property_name,
+                                                            GstControlSource * cs_a, GstControlSource * cs_r,
+                                                            GstControlSource * cs_g, GstControlSource * cs_b);
+
+G_END_DECLS
+
+#endif /* __GST_CONTROL_BINDING_ARGB_H__ */
diff --git a/libs/gst/controller/gstcontrolbindingdirect.c b/libs/gst/controller/gstcontrolbindingdirect.c
new file mode 100644 (file)
index 0000000..90bef49
--- /dev/null
@@ -0,0 +1,387 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbindingdirect.c: Direct attachment for control sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:gstcontrolbindingdirect
+ * @short_description: direct attachment for control source sources
+ *
+ * A value mapping object that attaches control sources to gobject properties.
+ */
+
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gstcontrolbindingdirect.h"
+
+#include <math.h>
+
+#define GST_CAT_DEFAULT control_binding_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static GObject *gst_control_binding_direct_constructor (GType type,
+    guint n_construct_params, GObjectConstructParam * construct_params);
+static void gst_control_binding_direct_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_control_binding_direct_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_control_binding_direct_dispose (GObject * object);
+static void gst_control_binding_direct_finalize (GObject * object);
+
+static gboolean gst_control_binding_direct_sync_values (GstControlBinding *
+    _self, GstObject * object, GstClockTime timestamp, GstClockTime last_sync);
+static GValue *gst_control_binding_direct_get_value (GstControlBinding * _self,
+    GstClockTime timestamp);
+static gboolean gst_control_binding_direct_get_value_array (GstControlBinding *
+    _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values);
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolbindingdirect", 0, \
+      "dynamic parameter control source attachment");
+
+G_DEFINE_TYPE_WITH_CODE (GstControlBindingDirect, gst_control_binding_direct,
+    GST_TYPE_CONTROL_BINDING, _do_init);
+
+enum
+{
+  PROP_0,
+  PROP_CS,
+  PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+/* mapping functions */
+
+#define DEFINE_CONVERT(type,Type,TYPE) \
+static void \
+convert_to_##type (GstControlBindingDirect *self, gdouble s, GValue *d) \
+{ \
+  GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \
+  g##type v; \
+  \
+  s = CLAMP (s, 0.0, 1.0); \
+  v = pspec->minimum + (g##type) ((pspec->maximum - pspec->minimum) * s); \
+  g_value_set_##type (d, v); \
+}
+
+DEFINE_CONVERT (int, Int, INT);
+DEFINE_CONVERT (uint, UInt, UINT);
+DEFINE_CONVERT (long, Long, LONG);
+DEFINE_CONVERT (ulong, ULong, ULONG);
+DEFINE_CONVERT (int64, Int64, INT64);
+DEFINE_CONVERT (uint64, UInt64, UINT64);
+DEFINE_CONVERT (float, Float, FLOAT);
+DEFINE_CONVERT (double, Double, DOUBLE);
+
+static void
+convert_to_boolean (GstControlBindingDirect * self, gdouble s, GValue * d)
+{
+  s = CLAMP (s, 0.0, 1.0);
+  g_value_set_boolean (d, (gboolean) (s + 0.5));
+}
+
+static void
+convert_to_enum (GstControlBindingDirect * self, gdouble s, GValue * d)
+{
+  GParamSpecEnum *pspec =
+      G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec);
+  GEnumClass *e = pspec->enum_class;
+  gint v;
+
+  s = CLAMP (s, 0.0, 1.0);
+  v = s * (e->n_values - 1);
+  g_value_set_enum (d, e->values[v].value);
+}
+
+/* vmethods */
+
+static void
+gst_control_binding_direct_class_init (GstControlBindingDirectClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstControlBindingClass *control_binding_class =
+      GST_CONTROL_BINDING_CLASS (klass);
+
+  gobject_class->constructor = gst_control_binding_direct_constructor;
+  gobject_class->set_property = gst_control_binding_direct_set_property;
+  gobject_class->get_property = gst_control_binding_direct_get_property;
+  gobject_class->dispose = gst_control_binding_direct_dispose;
+  gobject_class->finalize = gst_control_binding_direct_finalize;
+
+  control_binding_class->sync_values = gst_control_binding_direct_sync_values;
+  control_binding_class->get_value = gst_control_binding_direct_get_value;
+  control_binding_class->get_value_array =
+      gst_control_binding_direct_get_value_array;
+
+  properties[PROP_CS] =
+      g_param_spec_object ("control-source", "ControlSource",
+      "The control source",
+      GST_TYPE_CONTROL_SOURCE,
+      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
+}
+
+static void
+gst_control_binding_direct_init (GstControlBindingDirect * self)
+{
+}
+
+static GObject *
+gst_control_binding_direct_constructor (GType type, guint n_construct_params,
+    GObjectConstructParam * construct_params)
+{
+  GstControlBindingDirect *self;
+
+  self =
+      GST_CONTROL_BINDING_DIRECT (G_OBJECT_CLASS
+      (gst_control_binding_direct_parent_class)
+      ->constructor (type, n_construct_params, construct_params));
+
+  if (GST_CONTROL_BINDING_PSPEC (self)) {
+    GType type, base;
+
+    base = type = G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (self));
+    g_value_init (&self->cur_value, type);
+    while ((type = g_type_parent (type)))
+      base = type;
+
+    GST_DEBUG ("  using type %s", g_type_name (base));
+
+    // select mapping function
+    switch (base) {
+      case G_TYPE_INT:
+        self->convert = convert_to_int;
+        break;
+      case G_TYPE_UINT:
+        self->convert = convert_to_uint;
+        break;
+      case G_TYPE_LONG:
+        self->convert = convert_to_long;
+        break;
+      case G_TYPE_ULONG:
+        self->convert = convert_to_ulong;
+        break;
+      case G_TYPE_INT64:
+        self->convert = convert_to_int64;
+        break;
+      case G_TYPE_UINT64:
+        self->convert = convert_to_uint64;
+        break;
+      case G_TYPE_FLOAT:
+        self->convert = convert_to_float;
+        break;
+      case G_TYPE_DOUBLE:
+        self->convert = convert_to_double;
+        break;
+      case G_TYPE_BOOLEAN:
+        self->convert = convert_to_boolean;
+        break;
+      case G_TYPE_ENUM:
+        self->convert = convert_to_enum;
+        break;
+      default:
+        GST_WARNING ("incomplete implementation for paramspec type '%s'",
+            G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (self)));
+        GST_CONTROL_BINDING_PSPEC (self) = NULL;
+        break;
+    }
+  }
+  return (GObject *) self;
+}
+
+static void
+gst_control_binding_direct_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (object);
+
+  switch (prop_id) {
+    case PROP_CS:
+      self->cs = g_value_get_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_control_binding_direct_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (object);
+
+  switch (prop_id) {
+    case PROP_CS:
+      g_value_set_object (value, self->cs);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_control_binding_direct_dispose (GObject * object)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (object);
+
+  if (self->cs)
+    gst_object_replace ((GstObject **) & self->cs, NULL);
+}
+
+static void
+gst_control_binding_direct_finalize (GObject * object)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (object);
+
+  g_value_unset (&self->cur_value);
+}
+
+static gboolean
+gst_control_binding_direct_sync_values (GstControlBinding * _self,
+    GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (_self);
+  gdouble src_val;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_DIRECT (self), FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  GST_LOG_OBJECT (object, "property '%s' at ts=%" GST_TIME_FORMAT,
+      _self->name, GST_TIME_ARGS (timestamp));
+
+  ret = gst_control_source_get_value (self->cs, timestamp, &src_val);
+  if (G_LIKELY (ret)) {
+    GST_LOG_OBJECT (object, "  new value %lf", src_val);
+    /* always set the value for first time, but then only if it changed
+     * this should limit g_object_notify invocations.
+     * FIXME: can we detect negative playback rates?
+     */
+    if ((timestamp < last_sync) || (src_val != self->last_value)) {
+      GValue *dst_val = &self->cur_value;
+
+      GST_LOG_OBJECT (object, "  mapping %s to value of type %s", _self->name,
+          G_VALUE_TYPE_NAME (dst_val));
+      /* run mapping function to convert gdouble to GValue */
+      self->convert (self, src_val, dst_val);
+      /* we can make this faster
+       * http://bugzilla.gnome.org/show_bug.cgi?id=536939
+       */
+      g_object_set_property ((GObject *) object, _self->name, dst_val);
+      self->last_value = src_val;
+    }
+  } else {
+    GST_DEBUG_OBJECT (object, "no control value for param %s", _self->name);
+  }
+  return (ret);
+}
+
+static GValue *
+gst_control_binding_direct_get_value (GstControlBinding * _self,
+    GstClockTime timestamp)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (_self);
+  GValue *dst_val = NULL;
+  gdouble src_val;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_DIRECT (self), NULL);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  /* get current value via control source */
+  if (gst_control_source_get_value (self->cs, timestamp, &src_val)) {
+    dst_val = g_new0 (GValue, 1);
+    g_value_init (dst_val, G_PARAM_SPEC_VALUE_TYPE (_self->pspec));
+    self->convert (self, src_val, dst_val);
+  } else {
+    GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT,
+        _self->name, GST_TIME_ARGS (timestamp));
+  }
+
+  return dst_val;
+}
+
+static gboolean
+gst_control_binding_direct_get_value_array (GstControlBinding * _self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  GstControlBindingDirect *self = GST_CONTROL_BINDING_DIRECT (_self);
+  gint i;
+  gdouble *src_val;
+  gboolean res = FALSE;
+  GType type;
+  GstControlBindingDirectConvert convert;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING_DIRECT (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  convert = self->convert;
+  type = G_PARAM_SPEC_VALUE_TYPE (_self->pspec);
+
+  src_val = g_new0 (gdouble, n_values);
+  if ((res = gst_control_source_get_value_array (self->cs, timestamp,
+              interval, n_values, src_val))) {
+    for (i = 0; i < n_values; i++) {
+      if (!isnan (src_val[i])) {
+        g_value_init (&values[i], type);
+        convert (self, src_val[i], &values[i]);
+      } else {
+        GST_LOG ("no control value for property %s at index %d", _self->name,
+            i);
+      }
+    }
+  } else {
+    GST_LOG ("failed to get control value for property %s at ts %"
+        GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
+  }
+  g_free (src_val);
+  return res;
+}
+
+/* functions */
+
+/**
+ * gst_control_binding_direct_new:
+ * @object: the object of the property
+ * @property_name: the property-name to attach the control source
+ * @csource: the control source
+ *
+ * Create a new control-binding that attaches the #GstControlSource to the
+ * #GObject property.
+ *
+ * Returns: the new #GstControlBindingDirect
+ */
+GstControlBinding *
+gst_control_binding_direct_new (GstObject * object, const gchar * property_name,
+    GstControlSource * cs)
+{
+  return (GstControlBinding *) g_object_new (GST_TYPE_CONTROL_BINDING_DIRECT,
+      "object", object, "name", property_name, "control-source", cs, NULL);
+}
diff --git a/libs/gst/controller/gstcontrolbindingdirect.h b/libs/gst/controller/gstcontrolbindingdirect.h
new file mode 100644 (file)
index 0000000..cad96e1
--- /dev/null
@@ -0,0 +1,103 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gstcontrolbindingdirect.h: Direct attachment for control sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_CONTROL_BINDING_DIRECT_H__
+#define __GST_CONTROL_BINDING_DIRECT_H__
+
+#include <gst/gstconfig.h>
+
+#include <glib-object.h>
+
+#include <gst/gstcontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CONTROL_BINDING_DIRECT \
+  (gst_control_binding_direct_get_type())
+#define GST_CONTROL_BINDING_DIRECT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_BINDING_DIRECT,GstControlBindingDirect))
+#define GST_CONTROL_BINDING_DIRECT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_BINDING_DIRECT,GstControlBindingDirectClass))
+#define GST_IS_CONTROL_BINDING_DIRECT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_BINDING_DIRECT))
+#define GST_IS_CONTROL_BINDING_DIRECT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_BINDING_DIRECT))
+#define GST_CONTROL_BINDING_DIRECT_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlBindingDirectClass))
+
+typedef struct _GstControlBindingDirect GstControlBindingDirect;
+typedef struct _GstControlBindingDirectClass GstControlBindingDirectClass;
+
+/**
+ * GstControlBindingDirectConvert:
+ * @self: the #GstControlBindingDirect instance
+ * @src_value: the value returned by the cotnrol source
+ * @dest_value: the target GValue
+ *
+ * Function to map a control-value to the target GValue.
+ */
+typedef void (* GstControlBindingDirectConvert) (GstControlBindingDirect *self, gdouble src_value, GValue *dest_value);
+
+/**
+ * GstControlBindingDirect:
+ * @name: name of the property of this binding
+ *
+ * The instance structure of #GstControlBindingDirect.
+ */
+struct _GstControlBindingDirect {
+  GstControlBinding parent;
+  
+  /*< private >*/
+  GstControlSource *cs;    /* GstControlSource for this property */
+  GValue cur_value;
+  gdouble last_value;
+
+  GstControlBindingDirectConvert convert;
+
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstControlBindingDirectClass:
+ * @parent_class: Parent class
+ * @convert: Class method to convert control-values
+ *
+ * The class structure of #GstControlBindingDirect.
+ */
+
+struct _GstControlBindingDirectClass
+{
+  GstControlBindingClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_control_binding_direct_get_type (void);
+
+/* Functions */
+
+GstControlBinding * gst_control_binding_direct_new (GstObject * object, const gchar * property_name,
+                                                    GstControlSource * cs);
+G_END_DECLS
+
+#endif /* __GST_CONTROL_BINDING_DIRECT_H__ */
diff --git a/libs/gst/controller/gstcontroller.c b/libs/gst/controller/gstcontroller.c
deleted file mode 100644 (file)
index 4448087..0000000
+++ /dev/null
@@ -1,1293 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * gstcontroller.c: dynamic parameter control subsystem
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstcontroller
- * @short_description: dynamic parameter control subsystem
- *
- * The controller subsystem offers a lightweight way to adjust gobject
- * properties over stream-time. It works by using time-stamped value pairs that
- * are queued for element-properties. At run-time the elements continously pull
- * values changes for the current stream-time.
- *
- * What needs to be changed in a #GstElement?
- * Very little - it is just two steps to make a plugin controllable!
- * <orderedlist>
- *   <listitem><para>
- *     mark gobject-properties paramspecs that make sense to be controlled,
- *     by GST_PARAM_CONTROLLABLE.
- *   </para></listitem>
- *   <listitem><para>
- *     when processing data (get, chain, loop function) at the beginning call
- *     gst_object_sync_values(element,timestamp).
- *     This will made the controller to update all gobject properties that are under
- *     control with the current values based on timestamp.
- *   </para></listitem>
- * </orderedlist>
- *
- * What needs to be done in applications?
- * Again its not a lot to change.
- * <orderedlist>
- *   <listitem><para>
- *     first put some properties under control, by calling
- *     controller = gst_object_control_properties (object, "prop1", "prop2",...);
- *   </para></listitem>
- *   <listitem><para>
- *     create a #GstControlSource.
- *     csource = gst_interpolation_control_source_new ();
- *     gst_interpolation_control_source_set_interpolation_mode(csource, mode);
- *   </para></listitem>
- *   <listitem><para>
- *     Attach the #GstControlSource on the controller to a property.
- *     gst_controller_set_control_source (controller, "prop1", csource);
- *   </para></listitem>
- *   <listitem><para>
- *     Set the control values
- *     gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
- *     gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
- *   </para></listitem>
- *   <listitem><para>
- *     start your pipeline
- *   </para></listitem>
- * </orderedlist>
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gstcontroller.h"
-#include "gstcontrollerprivate.h"
-#include "gstcontrolsource.h"
-#include "gstinterpolationcontrolsource.h"
-#include "gst/glib-compat-private.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
-
-static GObjectClass *parent_class = NULL;
-GQuark priv_gst_controller_key;
-
-/* property ids */
-enum
-{
-  PROP_CONTROL_RATE = 1
-};
-
-struct _GstControllerPrivate
-{
-  GstClockTime control_rate;
-  GstClockTime last_sync;
-};
-
-/* helper */
-#ifndef GST_REMOVE_DEPRECATED
-static void
-gst_controlled_property_add_interpolation_control_source (GstControlledProperty
-    * self)
-{
-  GstControlSource *csource =
-      GST_CONTROL_SOURCE (gst_interpolation_control_source_new ());
-
-  GST_INFO
-      ("Adding a GstInterpolationControlSource because of backward compatibility");
-  g_return_if_fail (!self->csource);
-  gst_control_source_bind (GST_CONTROL_SOURCE (csource), self->pspec);
-  self->csource = csource;
-}
-#endif
-
-/*
- * gst_controlled_property_new:
- * @object: for which object the controlled property should be set up
- * @name: the name of the property to be controlled
- *
- * Private method which initializes the fields of a new controlled property
- * structure.
- *
- * Returns: a freshly allocated structure or %NULL
- */
-static GstControlledProperty *
-gst_controlled_property_new (GObject * object, const gchar * name)
-{
-  GstControlledProperty *prop = NULL;
-  GParamSpec *pspec;
-
-  GST_INFO ("trying to put property '%s' under control", name);
-
-  /* check if the object has a property of that name */
-  if ((pspec =
-          g_object_class_find_property (G_OBJECT_GET_CLASS (object), name))) {
-    GST_DEBUG ("  psec->flags : 0x%08x", pspec->flags);
-
-    /* check if this param is witable && controlable && !construct-only */
-    g_return_val_if_fail ((pspec->flags & (G_PARAM_WRITABLE |
-                GST_PARAM_CONTROLLABLE | G_PARAM_CONSTRUCT_ONLY)) ==
-        (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE), NULL);
-
-    if ((prop = g_slice_new (GstControlledProperty))) {
-      prop->pspec = pspec;
-      prop->name = pspec->name;
-      prop->csource = NULL;
-      prop->disabled = FALSE;
-      memset (&prop->last_value, 0, sizeof (GValue));
-      g_value_init (&prop->last_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
-    }
-  } else {
-    GST_WARNING ("class '%s' has no property '%s'", G_OBJECT_TYPE_NAME (object),
-        name);
-  }
-  return prop;
-}
-
-/*
- * gst_controlled_property_free:
- * @prop: the object to free
- *
- * Private method which frees all data allocated by a #GstControlledProperty
- * instance.
- */
-static void
-gst_controlled_property_free (GstControlledProperty * prop)
-{
-  if (prop->csource)
-    g_object_unref (prop->csource);
-  g_value_unset (&prop->last_value);
-  g_slice_free (GstControlledProperty, prop);
-}
-
-/*
- * gst_controller_find_controlled_property:
- * @self: the controller object to search for a property in
- * @name: the gobject property name to look for
- *
- * Searches the list of properties under control.
- *
- * Returns: a #GstControlledProperty object of %NULL if the property is not
- * being controlled.
- */
-static GstControlledProperty *
-gst_controller_find_controlled_property (GstController * self,
-    const gchar * name)
-{
-  GstControlledProperty *prop;
-  GList *node;
-
-  for (node = self->properties; node; node = g_list_next (node)) {
-    prop = node->data;
-    /* FIXME: eventually use GQuark to speed it up */
-    if (!strcmp (prop->name, name)) {
-      return prop;
-    }
-  }
-  GST_DEBUG ("controller does not (yet) manage property '%s'", name);
-
-  return NULL;
-}
-
-/*
- * gst_controller_add_property:
- * @self: the controller object or %NULL if none yet exists
- * @object: object to bind the property
- * @name: name of projecty in @object
- * @ref_existing: pointer to flag that tracks if we need to ref an existing
- *   controller still
- *
- * Creates a new #GstControlledProperty if there is none for property @name yet.
- * In case this is the first controlled propery, it creates the controller as
- * well.
- *
- * Returns: a newly created controller object or reffed existing one with the
- * given property bound.
- */
-static GstController *
-gst_controller_add_property (GstController * self, GObject * object,
-    const gchar * name, gboolean * ref_existing)
-{
-  /* test if this property isn't yet controlled */
-  if (!self || !gst_controller_find_controlled_property (self, name)) {
-    GstControlledProperty *prop;
-
-    /* create GstControlledProperty and add to self->propeties List */
-    if ((prop = gst_controlled_property_new (object, name))) {
-      /* if we don't have a controller object yet, now is the time to create one */
-      if (!self) {
-        self = g_object_newv (GST_TYPE_CONTROLLER, 0, NULL);
-        self->object = g_object_ref (object);
-        /* store the controller */
-        g_object_set_qdata (object, priv_gst_controller_key, self);
-        *ref_existing = FALSE;
-      } else {
-        /* only want one single _ref(), even for multiple properties */
-        if (*ref_existing) {
-          g_object_ref (self);
-          *ref_existing = FALSE;
-          GST_INFO ("returning existing controller");
-        }
-      }
-      self->properties = g_list_prepend (self->properties, prop);
-    }
-  } else {
-    GST_WARNING ("trying to control property %s again", name);
-    if (*ref_existing) {
-      g_object_ref (self);
-      *ref_existing = FALSE;
-    }
-  }
-  return self;
-}
-
-/* methods */
-
-/**
- * gst_controller_new_valist:
- * @object: the object of which some properties should be controlled
- * @var_args: %NULL terminated list of property names that should be controlled
- *
- * Creates a new GstController for the given object's properties
- *
- * Returns: the new controller.
- */
-GstController *
-gst_controller_new_valist (GObject * object, va_list var_args)
-{
-  GstController *self;
-  gboolean ref_existing = TRUE;
-  gchar *name;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  GST_INFO ("setting up a new controller");
-
-  self = g_object_get_qdata (object, priv_gst_controller_key);
-  /* create GstControlledProperty for each property */
-  while ((name = va_arg (var_args, gchar *))) {
-    self = gst_controller_add_property (self, object, name, &ref_existing);
-  }
-  va_end (var_args);
-
-  if (self)
-    GST_INFO ("controller->ref_count=%d", G_OBJECT (self)->ref_count);
-  return self;
-}
-
-/**
- * gst_controller_new_list:
- * @object: the object of which some properties should be controlled
- * @list: list of property names that should be controlled
- *
- * Creates a new GstController for the given object's properties
- *
- * Returns: the new controller.
- */
-GstController *
-gst_controller_new_list (GObject * object, GList * list)
-{
-  GstController *self;
-  gboolean ref_existing = TRUE;
-  gchar *name;
-  GList *node;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  GST_INFO ("setting up a new controller");
-
-  self = g_object_get_qdata (object, priv_gst_controller_key);
-  /* create GstControlledProperty for each property */
-  for (node = list; node; node = g_list_next (node)) {
-    name = (gchar *) node->data;
-    self = gst_controller_add_property (self, object, name, &ref_existing);
-  }
-
-  if (self)
-    GST_INFO ("controller->ref_count=%d", G_OBJECT (self)->ref_count);
-  return self;
-}
-
-/**
- * gst_controller_new:
- * @object: the object of which some properties should be controlled
- * @...: %NULL terminated list of property names that should be controlled
- *
- * Creates a new GstController for the given object's properties
- *
- * Returns: the new controller.
- */
-GstController *
-gst_controller_new (GObject * object, ...)
-{
-  GstController *self;
-  va_list var_args;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  va_start (var_args, object);
-  self = gst_controller_new_valist (object, var_args);
-  va_end (var_args);
-
-  return self;
-}
-
-/**
- * gst_controller_remove_properties_valist:
- * @self: the controller object from which some properties should be removed
- * @var_args: %NULL terminated list of property names that should be removed
- *
- * Removes the given object properties from the controller
- *
- * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
- */
-gboolean
-gst_controller_remove_properties_valist (GstController * self, va_list var_args)
-{
-  gboolean res = TRUE;
-  GstControlledProperty *prop;
-  gchar *name;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-
-  while ((name = va_arg (var_args, gchar *))) {
-    /* find the property in the properties list of the controller, remove and free it */
-    g_mutex_lock (self->lock);
-    if ((prop = gst_controller_find_controlled_property (self, name))) {
-      self->properties = g_list_remove (self->properties, prop);
-      //g_signal_handler_disconnect (self->object, prop->notify_handler_id);
-      gst_controlled_property_free (prop);
-    } else {
-      res = FALSE;
-    }
-    g_mutex_unlock (self->lock);
-  }
-
-  return res;
-}
-
-/**
- * gst_controller_remove_properties_list:
- * @self: the controller object from which some properties should be removed
- * @list: #GList of property names that should be removed
- *
- * Removes the given object properties from the controller
- *
- * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
- */
-gboolean
-gst_controller_remove_properties_list (GstController * self, GList * list)
-{
-  gboolean res = TRUE;
-  GstControlledProperty *prop;
-  gchar *name;
-  GList *tmp;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-
-  for (tmp = list; tmp; tmp = g_list_next (tmp)) {
-    name = (gchar *) tmp->data;
-
-    /* find the property in the properties list of the controller, remove and free it */
-    g_mutex_lock (self->lock);
-    if ((prop = gst_controller_find_controlled_property (self, name))) {
-      self->properties = g_list_remove (self->properties, prop);
-      //g_signal_handler_disconnect (self->object, prop->notify_handler_id);
-      gst_controlled_property_free (prop);
-    } else {
-      res = FALSE;
-    }
-    g_mutex_unlock (self->lock);
-  }
-
-  return res;
-}
-
-/**
- * gst_controller_remove_properties:
- * @self: the controller object from which some properties should be removed
- * @...: %NULL terminated list of property names that should be removed
- *
- * Removes the given object properties from the controller
- *
- * Returns: %FALSE if one of the given property isn't handled by the controller, %TRUE otherwise
- */
-gboolean
-gst_controller_remove_properties (GstController * self, ...)
-{
-  gboolean res;
-  va_list var_args;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-
-  va_start (var_args, self);
-  res = gst_controller_remove_properties_valist (self, var_args);
-  va_end (var_args);
-
-  return res;
-}
-
-/**
- * gst_controller_set_property_disabled:
- * @self: the #GstController which should be disabled
- * @property_name: property to disable
- * @disabled: boolean that specifies whether to disable the controller
- * or not.
- *
- * This function is used to disable the #GstController on a property for
- * some time, i.e. gst_controller_sync_values() will do nothing for the
- * property.
- *
- * Since: 0.10.14
- */
-
-void
-gst_controller_set_property_disabled (GstController * self,
-    const gchar * property_name, gboolean disabled)
-{
-  GstControlledProperty *prop;
-
-  g_return_if_fail (GST_IS_CONTROLLER (self));
-  g_return_if_fail (property_name);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    prop->disabled = disabled;
-  }
-  g_mutex_unlock (self->lock);
-}
-
-
-/**
- * gst_controller_set_disabled:
- * @self: the #GstController which should be disabled
- * @disabled: boolean that specifies whether to disable the controller
- * or not.
- *
- * This function is used to disable all properties of the #GstController
- * for some time, i.e. gst_controller_sync_values() will do nothing.
- *
- * Since: 0.10.14
- */
-
-void
-gst_controller_set_disabled (GstController * self, gboolean disabled)
-{
-  GList *node;
-  GstControlledProperty *prop;
-
-  g_return_if_fail (GST_IS_CONTROLLER (self));
-
-  g_mutex_lock (self->lock);
-  for (node = self->properties; node; node = node->next) {
-    prop = node->data;
-    prop->disabled = disabled;
-  }
-  g_mutex_unlock (self->lock);
-}
-
-/**
- * gst_controller_set_control_source:
- * @self: the controller object
- * @property_name: name of the property for which the #GstControlSource should be set
- * @csource: the #GstControlSource that should be used for the property
- *
- * Sets the #GstControlSource for @property_name. If there already was a #GstControlSource
- * for this property it will be unreferenced.
- *
- * Returns: %FALSE if the given property isn't handled by the controller or the new #GstControlSource
- * couldn't be bound to the property, %TRUE if everything worked as expected.
- *
- * Since: 0.10.14
- */
-gboolean
-gst_controller_set_control_source (GstController * self,
-    const gchar * property_name, GstControlSource * csource)
-{
-  GstControlledProperty *prop;
-  gboolean ret = FALSE;
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    GstControlSource *old = prop->csource;
-
-    if (csource && (ret = gst_control_source_bind (csource, prop->pspec))) {
-      g_object_ref (csource);
-      prop->csource = csource;
-    } else if (!csource) {
-      ret = TRUE;
-      prop->csource = NULL;
-    }
-
-    if (ret && old)
-      g_object_unref (old);
-  }
-  g_mutex_unlock (self->lock);
-
-  return ret;
-}
-
-/**
- * gst_controller_get_control_source:
- * @self: the controller object
- * @property_name: name of the property for which the #GstControlSource should be get
- *
- * Gets the corresponding #GstControlSource for the property. This should be unreferenced
- * again after use.
- *
- * Returns: the #GstControlSource for @property_name or NULL if the property is not
- * controlled by this controller or no #GstControlSource was assigned yet.
- *
- * Since: 0.10.14
- */
-GstControlSource *
-gst_controller_get_control_source (GstController * self,
-    const gchar * property_name)
-{
-  GstControlledProperty *prop;
-  GstControlSource *ret = NULL;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
-  g_return_val_if_fail (property_name, NULL);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    ret = prop->csource;
-  }
-  g_mutex_unlock (self->lock);
-
-  if (ret)
-    g_object_ref (ret);
-
-  return ret;
-}
-
-/**
- * gst_controller_get:
- * @self: the controller object which handles the properties
- * @property_name: the name of the property to get
- * @timestamp: the time the control-change should be read from
- *
- * Gets the value for the given controller-handled property at the requested
- * time.
- *
- * Returns: the GValue of the property at the given time, or %NULL if the
- * property isn't handled by the controller
- */
-GValue *
-gst_controller_get (GstController * self, const gchar * property_name,
-    GstClockTime timestamp)
-{
-  GstControlledProperty *prop;
-  GValue *val = NULL;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
-  g_return_val_if_fail (property_name, NULL);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    val = g_new0 (GValue, 1);
-    g_value_init (val, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
-    if (prop->csource) {
-      gboolean res;
-
-      /* get current value via control source */
-      res = gst_control_source_get_value (prop->csource, timestamp, val);
-      if (!res) {
-        g_free (val);
-        val = NULL;
-      }
-    } else {
-      g_object_get_property (self->object, prop->name, val);
-    }
-  }
-  g_mutex_unlock (self->lock);
-
-  return val;
-}
-
-/**
- * gst_controller_suggest_next_sync:
- * @self: the controller that handles the values
- *
- * Returns a suggestion for timestamps where buffers should be split
- * to get best controller results.
- *
- * Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE
- * if no control-rate was set.
- *
- * Since: 0.10.13
- */
-GstClockTime
-gst_controller_suggest_next_sync (GstController * self)
-{
-  GstClockTime ret;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), GST_CLOCK_TIME_NONE);
-  g_return_val_if_fail (self->priv->control_rate != GST_CLOCK_TIME_NONE,
-      GST_CLOCK_TIME_NONE);
-
-  g_mutex_lock (self->lock);
-
-  /* TODO: Implement more logic, depending on interpolation mode
-   * and control points
-   * FIXME: we need playback direction
-   */
-  ret = self->priv->last_sync + self->priv->control_rate;
-
-  g_mutex_unlock (self->lock);
-
-  return ret;
-}
-
-/**
- * gst_controller_sync_values:
- * @self: the controller that handles the values
- * @timestamp: the time that should be processed
- *
- * Sets the properties of the element, according to the controller that (maybe)
- * handles them and for the given timestamp.
- *
- * If this function fails, it is most likely the application developers fault.
- * Most probably the control sources are not setup correctly.
- *
- * Returns: %TRUE if the controller values could be applied to the object
- * properties, %FALSE otherwise
- */
-gboolean
-gst_controller_sync_values (GstController * self, GstClockTime timestamp)
-{
-  GstControlledProperty *prop;
-  GList *node;
-  gboolean ret = TRUE, val_ret;
-  GValue value = { 0, };
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
-  GST_LOG ("sync_values");
-
-  g_mutex_lock (self->lock);
-  g_object_freeze_notify (self->object);
-  /* go over the controlled properties of the controller */
-  for (node = self->properties; node; node = g_list_next (node)) {
-    prop = node->data;
-
-    if (!prop->csource || prop->disabled)
-      continue;
-
-    GST_LOG ("property '%s' at ts=%" G_GUINT64_FORMAT, prop->name, timestamp);
-
-    /* we can make this faster
-     * http://bugzilla.gnome.org/show_bug.cgi?id=536939
-     */
-    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
-    val_ret = gst_control_source_get_value (prop->csource, timestamp, &value);
-    if (G_LIKELY (val_ret)) {
-      /* always set the value for first time, but then only if it changed
-       * this should limit g_object_notify invocations.
-       * FIXME: can we detect negative playback rates?
-       */
-      if ((timestamp < self->priv->last_sync) ||
-          gst_value_compare (&value, &prop->last_value) != GST_VALUE_EQUAL) {
-        g_object_set_property (self->object, prop->name, &value);
-        g_value_copy (&value, &prop->last_value);
-      }
-    } else {
-      GST_DEBUG ("no control value for param %s", prop->name);
-    }
-    g_value_unset (&value);
-    ret &= val_ret;
-  }
-  self->priv->last_sync = timestamp;
-  g_object_thaw_notify (self->object);
-
-  g_mutex_unlock (self->lock);
-
-  return ret;
-}
-
-/**
- * gst_controller_get_value_arrays:
- * @self: the controller that handles the values
- * @timestamp: the time that should be processed
- * @value_arrays: list to return the control-values in
- *
- * Function to be able to get an array of values for one or more given element
- * properties.
- *
- * All fields of the %GstValueArray in the list must be filled correctly.
- * Especially the GstValueArray->values arrays must be big enough to keep
- * the requested amount of values.
- *
- * The types of the values in the array are the same as the property's type.
- *
- * <note><para>This doesn't modify the controlled GObject properties!</para></note>
- *
- * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
- */
-gboolean
-gst_controller_get_value_arrays (GstController * self,
-    GstClockTime timestamp, GSList * value_arrays)
-{
-  gboolean res = TRUE;
-  GSList *node;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-  g_return_val_if_fail (value_arrays, FALSE);
-
-  for (node = value_arrays; (res && node); node = g_slist_next (node)) {
-    res = gst_controller_get_value_array (self, timestamp, node->data);
-  }
-
-  return (res);
-}
-
-/**
- * gst_controller_get_value_array:
- * @self: the controller that handles the values
- * @timestamp: the time that should be processed
- * @value_array: array to put control-values in
- *
- * Function to be able to get an array of values for one element property.
- *
- * All fields of @value_array must be filled correctly. Especially the
- * @value_array->values array must be big enough to keep the requested amount
- * of values (as indicated by the nbsamples field).
- *
- * The type of the values in the array is the same as the property's type.
- *
- * <note><para>This doesn't modify the controlled GObject property!</para></note>
- *
- * Returns: %TRUE if the given array could be filled, %FALSE otherwise
- */
-gboolean
-gst_controller_get_value_array (GstController * self, GstClockTime timestamp,
-    GstValueArray * value_array)
-{
-  gboolean res = FALSE;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-  g_return_val_if_fail (value_array, FALSE);
-  g_return_val_if_fail (value_array->property_name, FALSE);
-  g_return_val_if_fail (value_array->values, FALSE);
-
-  g_mutex_lock (self->lock);
-
-  if ((prop =
-          gst_controller_find_controlled_property (self,
-              value_array->property_name))) {
-    /* get current value_array via control source */
-
-    if (!prop->csource)
-      goto out;
-
-    res =
-        gst_control_source_get_value_array (prop->csource, timestamp,
-        value_array);
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-  return res;
-}
-
-/* gobject handling */
-
-static void
-_gst_controller_get_property (GObject * object, guint property_id,
-    GValue * value, GParamSpec * pspec)
-{
-  GstController *self = GST_CONTROLLER (object);
-
-  switch (property_id) {
-    case PROP_CONTROL_RATE:{
-      /* FIXME: don't change if element is playing, controller works for GObject
-         so this wont work
-
-         GstState c_state, p_state;
-         GstStateChangeReturn ret;
-
-         ret = gst_element_get_state (self->object, &c_state, &p_state, 0);
-         if ((ret == GST_STATE_CHANGE_SUCCESS &&
-         (c_state == GST_STATE_NULL || c_state == GST_STATE_READY)) ||
-         (ret == GST_STATE_CHANGE_ASYNC &&
-         (p_state == GST_STATE_NULL || p_state == GST_STATE_READY))) {
-       */
-      g_value_set_uint64 (value, self->priv->control_rate);
-      /*
-         }
-         else {
-         GST_WARNING ("Changing the control rate is only allowed if the elemnt"
-         " is in NULL or READY");
-         }
-       */
-    }
-      break;
-    default:{
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-      break;
-  }
-}
-
-/* sets the given properties for this object */
-static void
-_gst_controller_set_property (GObject * object, guint property_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstController *self = GST_CONTROLLER (object);
-
-  switch (property_id) {
-    case PROP_CONTROL_RATE:{
-      self->priv->control_rate = g_value_get_uint64 (value);
-    }
-      break;
-    default:{
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-      break;
-  }
-}
-
-static void
-_gst_controller_dispose (GObject * object)
-{
-  GstController *self = GST_CONTROLLER (object);
-
-  if (self->object != NULL) {
-    g_mutex_lock (self->lock);
-    /* free list of properties */
-    if (self->properties) {
-      GList *node;
-
-      for (node = self->properties; node; node = g_list_next (node)) {
-        GstControlledProperty *prop = node->data;
-
-        gst_controlled_property_free (prop);
-      }
-      g_list_free (self->properties);
-      self->properties = NULL;
-    }
-
-    /* remove controller from object's qdata list */
-    g_object_set_qdata (self->object, priv_gst_controller_key, NULL);
-    g_object_unref (self->object);
-    self->object = NULL;
-    g_mutex_unlock (self->lock);
-  }
-
-  if (G_OBJECT_CLASS (parent_class)->dispose)
-    (G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
-static void
-_gst_controller_finalize (GObject * object)
-{
-  GstController *self = GST_CONTROLLER (object);
-
-  g_mutex_free (self->lock);
-
-  if (G_OBJECT_CLASS (parent_class)->finalize)
-    (G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
-_gst_controller_init (GTypeInstance * instance, gpointer g_class)
-{
-  GstController *self = GST_CONTROLLER (instance);
-
-  self->lock = g_mutex_new ();
-  self->priv =
-      G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_CONTROLLER,
-      GstControllerPrivate);
-  self->priv->last_sync = GST_CLOCK_TIME_NONE;
-  self->priv->control_rate = 100 * GST_MSECOND;
-}
-
-static void
-_gst_controller_class_init (GstControllerClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-  g_type_class_add_private (klass, sizeof (GstControllerPrivate));
-
-  gobject_class->set_property = _gst_controller_set_property;
-  gobject_class->get_property = _gst_controller_get_property;
-  gobject_class->dispose = _gst_controller_dispose;
-  gobject_class->finalize = _gst_controller_finalize;
-
-  priv_gst_controller_key = g_quark_from_static_string ("gst::controller");
-
-  /* register properties */
-  g_object_class_install_property (gobject_class, PROP_CONTROL_RATE,
-      g_param_spec_uint64 ("control-rate",
-          "control rate",
-          "Controlled properties will be updated at least every control-rate nanoseconds",
-          1, G_MAXUINT, 100 * GST_MSECOND,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  /* register signals */
-  /* set defaults for overridable methods */
-}
-
-GType
-gst_controller_get_type (void)
-{
-  static volatile gsize type = 0;
-
-  if (g_once_init_enter (&type)) {
-    GType _type;
-    static const GTypeInfo info = {
-      sizeof (GstControllerClass),
-      NULL,                     /* base_init */
-      NULL,                     /* base_finalize */
-      (GClassInitFunc) _gst_controller_class_init,      /* class_init */
-      NULL,                     /* class_finalize */
-      NULL,                     /* class_data */
-      sizeof (GstController),
-      0,                        /* n_preallocs */
-      (GInstanceInitFunc) _gst_controller_init, /* instance_init */
-      NULL                      /* value_table */
-    };
-    _type = g_type_register_static (G_TYPE_OBJECT, "GstController", &info, 0);
-    g_once_init_leave (&type, _type);
-  }
-  return type;
-}
-
-/* FIXME: backward compatibility functions */
-
-/*
- * gst_controlled_property_set_interpolation_mode:
- * @self: the controlled property object to change
- * @mode: the new interpolation mode
- *
- * Sets the given Interpolation mode for the controlled property and activates
- * the respective interpolation hooks.
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: %TRUE for success
- */
-#ifndef GST_REMOVE_DEPRECATED
-static gboolean
-gst_controlled_property_set_interpolation_mode (GstControlledProperty * self,
-    GstInterpolateMode mode)
-{
-  GstInterpolationControlSource *icsource;
-
-  /* FIXME: backward compat, add GstInterpolationControlSource */
-  if (!self->csource)
-    gst_controlled_property_add_interpolation_control_source (self);
-
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self->csource),
-      FALSE);
-
-  icsource = GST_INTERPOLATION_CONTROL_SOURCE (self->csource);
-
-  return gst_interpolation_control_source_set_interpolation_mode (icsource,
-      mode);
-}
-#endif
-
-/**
- * gst_controller_set:
- * @self: the controller object which handles the properties
- * @property_name: the name of the property to set
- * @timestamp: the time the control-change is schedules for
- * @value: the control-value
- *
- * Set the value of given controller-handled property at a certain time.
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: FALSE if the values couldn't be set (ex : properties not handled by controller), TRUE otherwise
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_controller_set (GstController * self, const gchar * property_name,
-    GstClockTime timestamp, GValue * value);
-#endif
-gboolean
-gst_controller_set (GstController * self, const gchar * property_name,
-    GstClockTime timestamp, GValue * value)
-{
-  gboolean res = FALSE;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (property_name, FALSE);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    /* FIXME: backward compat, add GstInterpolationControlSource */
-    if (!prop->csource)
-      gst_controlled_property_add_interpolation_control_source (prop);
-
-    if (!GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
-      goto out;
-    res =
-        gst_interpolation_control_source_set (GST_INTERPOLATION_CONTROL_SOURCE
-        (prop->csource), timestamp, value);
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-
-  return res;
-}
-#endif
-
-/**
- * gst_controller_set_from_list:
- * @self: the controller object which handles the properties
- * @property_name: the name of the property to set
- * @timedvalues: a list with #GstTimedValue items
- *
- * Sets multiple timed values at once.
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: %FALSE if the values couldn't be set (ex : properties not handled by controller), %TRUE otherwise
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_controller_set_from_list (GstController * self, const gchar * property_name,
-    GSList * timedvalues);
-#endif
-gboolean
-gst_controller_set_from_list (GstController * self, const gchar * property_name,
-    GSList * timedvalues)
-{
-  gboolean res = FALSE;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (property_name, FALSE);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    /* FIXME: backward compat, add GstInterpolationControlSource */
-    if (!prop->csource)
-      gst_controlled_property_add_interpolation_control_source (prop);
-
-    if (!GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
-      goto out;
-
-    res =
-        gst_interpolation_control_source_set_from_list
-        (GST_INTERPOLATION_CONTROL_SOURCE (prop->csource), timedvalues);
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-
-  return res;
-}
-#endif
-
-/**
- * gst_controller_unset:
- * @self: the controller object which handles the properties
- * @property_name: the name of the property to unset
- * @timestamp: the time the control-change should be removed from
- *
- * Used to remove the value of given controller-handled property at a certain
- * time.
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: %FALSE if the values couldn't be unset (ex : properties not handled by controller), %TRUE otherwise
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_controller_unset (GstController * self, const gchar * property_name,
-    GstClockTime timestamp);
-#endif
-gboolean
-gst_controller_unset (GstController * self, const gchar * property_name,
-    GstClockTime timestamp)
-{
-  gboolean res = FALSE;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (property_name, FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
-      goto out;
-
-    res =
-        gst_interpolation_control_source_unset (GST_INTERPOLATION_CONTROL_SOURCE
-        (prop->csource), timestamp);
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-
-  return res;
-}
-#endif
-
-/**
- * gst_controller_unset_all:
- * @self: the controller object which handles the properties
- * @property_name: the name of the property to unset
- *
- * Used to remove all time-stamped values of given controller-handled property
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: %FALSE if the values couldn't be unset (ex : properties not handled
- * by controller), %TRUE otherwise
- * Since: 0.10.5
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean gst_controller_unset_all (GstController * self,
-    const gchar * property_name);
-#endif
-gboolean
-gst_controller_unset_all (GstController * self, const gchar * property_name)
-{
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (property_name, FALSE);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
-      goto out;
-
-    gst_interpolation_control_source_unset_all (GST_INTERPOLATION_CONTROL_SOURCE
-        (prop->csource));
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-
-  return TRUE;
-}
-#endif
-
-/**
- * gst_controller_get_all:
- * @self: the controller to get the list from
- * @property_name: the name of the property to get the list for
- *
- * Returns a read-only copy of the list of #GstTimedValue for the given property.
- * Free the list after done with it.
- *
- * <note><para>This doesn't modify the controlled GObject property!</para></note>
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: a copy of the list, or %NULL if the property isn't handled by the controller
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-const GList *gst_controller_get_all (GstController * self,
-    const gchar * property_name);
-#endif
-const GList *
-gst_controller_get_all (GstController * self, const gchar * property_name)
-{
-  const GList *res = NULL;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL);
-  g_return_val_if_fail (property_name, NULL);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    if (!prop->csource || !GST_IS_INTERPOLATION_CONTROL_SOURCE (prop->csource))
-      goto out;
-
-    res =
-        gst_interpolation_control_source_get_all
-        (GST_INTERPOLATION_CONTROL_SOURCE (prop->csource));
-  }
-
-out:
-  g_mutex_unlock (self->lock);
-
-  return res;
-}
-#endif
-
-/**
- * gst_controller_set_interpolation_mode:
- * @self: the controller object
- * @property_name: the name of the property for which to change the interpolation
- * @mode: interpolation mode
- *
- * Sets the given interpolation mode on the given property.
- *
- * <note><para>User interpolation is not yet available and quadratic interpolation
- * is deprecated and maps to cubic interpolation.</para></note>
- *
- * Deprecated: Use #GstControlSource, for example #GstInterpolationControlSource
- * directly.
- *
- * Returns: %TRUE if the property is handled by the controller, %FALSE otherwise
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_controller_set_interpolation_mode (GstController * self,
-    const gchar * property_name, GstInterpolateMode mode);
-#endif
-gboolean
-gst_controller_set_interpolation_mode (GstController * self,
-    const gchar * property_name, GstInterpolateMode mode)
-{
-  gboolean res = FALSE;
-  GstControlledProperty *prop;
-
-  g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
-  g_return_val_if_fail (property_name, FALSE);
-
-  g_mutex_lock (self->lock);
-  if ((prop = gst_controller_find_controlled_property (self, property_name))) {
-    res = gst_controlled_property_set_interpolation_mode (prop, mode);
-  }
-  g_mutex_unlock (self->lock);
-
-  return res;
-}
-#endif
diff --git a/libs/gst/controller/gstcontroller.h b/libs/gst/controller/gstcontroller.h
deleted file mode 100644 (file)
index 0b0379f..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- *
- * gst-controller.h: dynamic parameter control subsystem
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_CONTROLLER_H__
-#define __GST_CONTROLLER_H__
-
-#include <string.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <glib/gprintf.h>
-#include <gst/gst.h>
-
-#include <gst/controller/gstcontrolsource.h>
-#include <gst/controller/gstinterpolationcontrolsource.h>
-
-G_BEGIN_DECLS
-
-/* type macros */
-
-#define GST_TYPE_CONTROLLER           (gst_controller_get_type ())
-#define GST_CONTROLLER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CONTROLLER, GstController))
-#define GST_CONTROLLER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CONTROLLER, GstControllerClass))
-#define GST_IS_CONTROLLER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CONTROLLER))
-#define GST_IS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CONTROLLERE))
-#define GST_CONTROLLER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTROLLER, GstControllerClass))
-
-typedef struct _GstController GstController;
-typedef struct _GstControllerClass GstControllerClass;
-typedef struct _GstControllerPrivate GstControllerPrivate;
-
-/**
- * GstController:
- *
- * The instance structure of GstController
- */
-
-struct _GstController
-{
-  GObject parent;
-
-  GList *properties;  /* List of GstControlledProperty */
-  GMutex *lock;       /* Secure property access, elements will access from threads */
-  GObject *object;    /* the object we control */
-
-  /*< private >*/
-  GstControllerPrivate *priv;
-  gpointer       _gst_reserved[GST_PADDING - 1];
-};
-
-struct _GstControllerClass
-{
-  GObjectClass parent_class;
-
-  /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING];
-};
-
-GType gst_controller_get_type (void);
-
-/* GstController functions */
-
-GstController *gst_controller_new_valist (GObject * object, va_list var_args);
-GstController *gst_controller_new_list (GObject * object, GList *list);
-GstController *gst_controller_new (GObject * object, ...) G_GNUC_NULL_TERMINATED;
-
-gboolean gst_controller_remove_properties_valist (GstController * self,
-    va_list var_args);
-gboolean gst_controller_remove_properties_list (GstController * self,
-                                               GList *list);
-gboolean gst_controller_remove_properties (GstController * self, ...) G_GNUC_NULL_TERMINATED;
-
-void gst_controller_set_disabled (GstController *self, gboolean disabled);
-void gst_controller_set_property_disabled (GstController *self, const gchar * property_name, gboolean disabled);
-gboolean gst_controller_set_control_source (GstController *self, const gchar * property_name, GstControlSource *csource);
-GstControlSource * gst_controller_get_control_source (GstController *self, const gchar * property_name);
-
-GstClockTime gst_controller_suggest_next_sync (GstController *self);
-gboolean gst_controller_sync_values (GstController * self,
-    GstClockTime timestamp);
-
-GValue *gst_controller_get (GstController * self, const gchar * property_name,
-    GstClockTime timestamp);
-gboolean gst_controller_get_value_arrays (GstController * self,
-    GstClockTime timestamp, GSList * value_arrays);
-gboolean gst_controller_get_value_array (GstController * self,
-    GstClockTime timestamp, GstValueArray * value_array);
-
-/* GObject convenience functions */
-
-GstController *gst_object_control_properties (GObject * object, ...) G_GNUC_NULL_TERMINATED;
-gboolean gst_object_uncontrol_properties (GObject * object, ...) G_GNUC_NULL_TERMINATED;
-
-GstController *gst_object_get_controller (GObject * object);
-gboolean gst_object_set_controller (GObject * object, GstController * controller);
-
-GstClockTime gst_object_suggest_next_sync (GObject * object);
-gboolean gst_object_sync_values (GObject * object, GstClockTime timestamp);
-
-gboolean gst_object_set_control_source (GObject *object, const gchar * property_name, GstControlSource *csource);
-GstControlSource * gst_object_get_control_source (GObject *object, const gchar * property_name);
-
-gboolean gst_object_get_value_arrays (GObject * object,
-    GstClockTime timestamp, GSList * value_arrays);
-gboolean gst_object_get_value_array (GObject * object,
-    GstClockTime timestamp, GstValueArray * value_array);
-
-GstClockTime gst_object_get_control_rate (GObject * object);
-void gst_object_set_control_rate (GObject * object, GstClockTime control_rate);
-
-/* lib init/done */
-
-gboolean gst_controller_init (int * argc, char ***argv);
-
-
-/* FIXME: deprecated functions */
-#ifndef GST_DISABLE_DEPRECATED
-gboolean gst_controller_set (GstController * self, const gchar * property_name,
-    GstClockTime timestamp, GValue * value);
-gboolean gst_controller_set_from_list (GstController * self,
-    const gchar * property_name, GSList * timedvalues);
-
-gboolean gst_controller_unset (GstController * self, const gchar * property_name,
-    GstClockTime timestamp);
-gboolean gst_controller_unset_all (GstController * self, const gchar * property_name);
-
-const GList *gst_controller_get_all (GstController * self,
-    const gchar * property_name);
-
-gboolean gst_controller_set_interpolation_mode (GstController * self,
-    const gchar * property_name, GstInterpolateMode mode);
-#endif /* GST_DISABLE_DEPRECATED */
-
-G_END_DECLS
-
-#endif /* __GST_CONTROLLER_H__ */
diff --git a/libs/gst/controller/gsthelper.c b/libs/gst/controller/gsthelper.c
deleted file mode 100644 (file)
index 1c1f24a..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- *
- * gsthelper.c: GObject convenience methods for using dynamic properties
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstcontrollergobject
- * @short_description: #GObject convenience methods for using dynamic properties
- * @see_also: #GstController
- *
- * These methods allow to use some #GstController functionality directly from
- * the #GObject class.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <stdarg.h>
-
-#include "gstcontrollerprivate.h"
-#include "gstcontroller.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
-
-/**
- * gst_object_control_properties:
- * @object: the object of which some properties should be controlled
- * @...: %NULL terminated list of property names that should be controlled
- *
- * Convenience function for GObject
- *
- * Creates a GstController that allows you to dynamically control one, or more, GObject properties.
- * If the given GObject already has a GstController, it adds the given properties to the existing
- * controller and returns that controller.
- *
- * Returns: The GstController with which the user can control the given properties dynamically or NULL if
- * one or more of the given properties aren't available, or cannot be controlled, for the given element.
- * Since: 0.9
- */
-GstController *
-gst_object_control_properties (GObject * object, ...)
-{
-  GstController *ctrl;
-  va_list var_args;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  va_start (var_args, object);
-  ctrl = gst_controller_new_valist (object, var_args);
-  va_end (var_args);
-  return (ctrl);
-}
-
-/**
- * gst_object_uncontrol_properties:
- * @object: the object of which some properties should not be controlled anymore
- * @...: %NULL terminated list of property names that should be controlled
- *
- * Convenience function for GObject
- *
- * Removes the given element's properties from it's controller
- *
- * Returns: %FALSE if one of the given property names isn't handled by the
- * controller, %TRUE otherwise
- * Since: 0.9
- */
-gboolean
-gst_object_uncontrol_properties (GObject * object, ...)
-{
-  gboolean res = FALSE;
-  GstController *ctrl;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    va_list var_args;
-
-    va_start (var_args, object);
-    res = gst_controller_remove_properties_valist (ctrl, var_args);
-    va_end (var_args);
-  }
-  return (res);
-}
-
-/**
- * gst_object_get_controller:
- * @object: the object that has controlled properties
- *
- * Gets the controller for the given GObject
- * 
- * Returns: the controller handling some of the given element's properties, %NULL if no controller
- * Since: 0.9
- */
-/* FIXME 0.11: This should return a new reference */
-GstController *
-gst_object_get_controller (GObject * object)
-{
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  return (g_object_get_qdata (object, priv_gst_controller_key));
-}
-
-/**
- * gst_object_set_controller:
- * @object: the object that should get the controller
- * @controller: the controller object to plug in
- *
- * Sets the controller on the given GObject
- *
- * Returns: %FALSE if the GObject already has an controller, %TRUE otherwise
- * Since: 0.9
- */
-/* FIXME 0.11: This should increase the refcount before storing */
-gboolean
-gst_object_set_controller (GObject * object, GstController * controller)
-{
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (controller, FALSE);
-
-  if (!g_object_get_qdata (object, priv_gst_controller_key)) {
-    g_object_set_qdata (object, priv_gst_controller_key, controller);
-    return (TRUE);
-  }
-  return (FALSE);
-}
-
- /**
- * gst_object_suggest_next_sync:
- * @object: the object that has controlled properties
- *
- * Convenience function for GObject
- *
- * Returns: same thing as gst_controller_suggest_next_sync()
- * Since: 0.10.13
- */
-GstClockTime
-gst_object_suggest_next_sync (GObject * object)
-{
-  GstController *ctrl = NULL;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), GST_CLOCK_TIME_NONE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_suggest_next_sync (ctrl);
-  }
-  return (GST_CLOCK_TIME_NONE);
-}
-
-/**
- * gst_object_sync_values:
- * @object: the object that has controlled properties
- * @timestamp: the time that should be processed
- *
- * Convenience function for GObject
- *
- * Returns: same thing as gst_controller_sync_values()
- * Since: 0.9
- */
-gboolean
-gst_object_sync_values (GObject * object, GstClockTime timestamp)
-{
-  GstController *ctrl = NULL;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_sync_values (ctrl, timestamp);
-  }
-  /* this is no failure, its called by elements regardless if there is a
-   * controller assigned or not
-   */
-  return (TRUE);
-}
-
-/**
- * gst_object_set_control_source:
- * @object: the controller object
- * @property_name: name of the property for which the #GstControlSource should be set
- * @csource: the #GstControlSource that should be used for the property
- *
- * Sets the #GstControlSource for @property_name. If there already was a #GstControlSource
- * for this property it will be unreferenced.
- *
- * Returns: %FALSE if the given property isn't handled by the controller or the new #GstControlSource
- * couldn't be bound to the property, %TRUE if everything worked as expected.
- *
- * Since: 0.10.14
- */
-gboolean
-gst_object_set_control_source (GObject * object, const gchar * property_name,
-    GstControlSource * csource)
-{
-  GstController *ctrl = NULL;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (GST_IS_CONTROL_SOURCE (csource), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_set_control_source (ctrl, property_name, csource);
-  }
-  return FALSE;
-}
-
-/**
- * gst_object_get_control_source:
- * @object: the object
- * @property_name: name of the property for which the #GstControlSource should be get
- *
- * Gets the corresponding #GstControlSource for the property. This should be unreferenced
- * again after use.
- *
- * Returns: the #GstControlSource for @property_name or NULL if the property is not
- * controlled by this controller or no #GstControlSource was assigned yet.
- *
- * Since: 0.10.14
- */
-GstControlSource *
-gst_object_get_control_source (GObject * object, const gchar * property_name)
-{
-  GstController *ctrl = NULL;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_get_control_source (ctrl, property_name);
-  }
-  return NULL;
-}
-
-/**
- * gst_object_get_value_arrays:
- * @object: the object that has controlled properties
- * @timestamp: the time that should be processed
- * @value_arrays: list to return the control-values in
- *
- * Function to be able to get an array of values for one or more given element
- * properties.
- *
- * If the GstValueArray->values array in list nodes is NULL, it will be created
- * by the function.
- * The type of the values in the array are the same as the property's type.
- *
- * The g_object_* functions are just convenience functions for GObject
- *
- * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
- * Since: 0.9
- */
-gboolean
-gst_object_get_value_arrays (GObject * object, GstClockTime timestamp,
-    GSList * value_arrays)
-{
-  GstController *ctrl;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_get_value_arrays (ctrl, timestamp, value_arrays);
-  }
-  return (FALSE);
-}
-
-/**
- * gst_object_get_value_array:
- * @object: the object that has controlled properties
- * @timestamp: the time that should be processed
- * @value_array: array to put control-values in
- *
- * Function to be able to get an array of values for one element properties
- *
- * If the GstValueArray->values array is NULL, it will be created by the function.
- * The type of the values in the array are the same as the property's type.
- *
- * The g_object_* functions are just convenience functions for GObject
- *
- * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise
- * Since: 0.9
- */
-gboolean
-gst_object_get_value_array (GObject * object, GstClockTime timestamp,
-    GstValueArray * value_array)
-{
-  GstController *ctrl;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    return gst_controller_get_value_array (ctrl, timestamp, value_array);
-  }
-  return (FALSE);
-}
-
-/**
- * gst_object_get_control_rate:
- * @object: the object that has controlled properties
- *
- * Obtain the control-rate for this @object. Audio processing #GstElement
- * objects will use this rate to sub-divide their processing loop and call
- * gst_object_sync_values() inbetween. The length of the processing segment
- * should be up to @control-rate nanoseconds.
- *
- * If the @object is not under property control, this will return
- * %GST_CLOCK_TIME_NONE. This allows the element to avoid the sub-dividing.
- *
- * The control-rate is not expected to change if the element is in
- * %GST_STATE_PAUSED or %GST_STATE_PLAYING.
- *
- * Returns: the control rate in nanoseconds
- * Since: 0.10.10
- */
-GstClockTime
-gst_object_get_control_rate (GObject * object)
-{
-  GstController *ctrl;
-  GstClockTime control_rate = GST_CLOCK_TIME_NONE;
-
-  g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    g_object_get (ctrl, "control-rate", &control_rate, NULL);
-  }
-  return (control_rate);
-}
-
-/**
- * gst_object_set_control_rate:
- * @object: the object that has controlled properties
- * @control_rate: the new control-rate in nanoseconds.
- *
- * Change the control-rate for this @object. Audio processing #GstElement
- * objects will use this rate to sub-divide their processing loop and call
- * gst_object_sync_values() inbetween. The length of the processing segment
- * should be up to @control-rate nanoseconds.
- *
- * The control-rate should not change if the element is in %GST_STATE_PAUSED or
- * %GST_STATE_PLAYING.
- *
- * Since: 0.10.10
- */
-void
-gst_object_set_control_rate (GObject * object, GstClockTime control_rate)
-{
-  GstController *ctrl;
-
-  g_return_if_fail (G_IS_OBJECT (object));
-
-  if ((ctrl = g_object_get_qdata (object, priv_gst_controller_key))) {
-    g_object_set (ctrl, "control-rate", control_rate, NULL);
-  }
-}
diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c
deleted file mode 100644 (file)
index 54ff60e..0000000
+++ /dev/null
@@ -1,811 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- * Copyright (C) 2007-2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
- *
- * gstinterpolation.c: Interpolation methods for dynamic properties
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include "gstinterpolationcontrolsource.h"
-#include "gstinterpolationcontrolsourceprivate.h"
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
-
-#define EMPTY(x) (x)
-
-/* common helper */
-
-static gint
-gst_control_point_find (gconstpointer p1, gconstpointer p2)
-{
-  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
-  GstClockTime ct2 = *(GstClockTime *) p2;
-
-  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-/*
- * gst_interpolation_control_source_find_control_point_iter:
- * @self: the interpolation control source to search in
- * @timestamp: the search key
- *
- * Find last value before given timestamp in control point list.
- * If all values in the control point list come after the given
- * timestamp or no values exist, %NULL is returned.
- *
- * Returns: the found #GSequenceIter or %NULL
- */
-static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
-    (GstInterpolationControlSource * self, GstClockTime timestamp)
-{
-  GSequenceIter *iter;
-
-  if (!self->priv->values)
-    return NULL;
-
-  iter =
-      g_sequence_search (self->priv->values, &timestamp,
-      (GCompareDataFunc) gst_control_point_find, NULL);
-
-  /* g_sequence_search() returns the iter where timestamp
-   * would be inserted, i.e. the iter > timestamp, so
-   * we need to get the previous one. And of course, if
-   * there is no previous one, we return NULL. */
-  if (g_sequence_iter_is_begin (iter))
-    return NULL;
-
-  return g_sequence_iter_prev (iter);
-}
-
-/*  steps-like (no-)interpolation, default */
-/*  just returns the value for the most recent key-frame */
-static inline const GValue *
-_interpolate_none_get (GstInterpolationControlSource * self,
-    GSequenceIter * iter)
-{
-  const GValue *ret;
-
-  if (iter) {
-    GstControlPoint *cp = g_sequence_get (iter);
-
-    ret = &cp->value;
-  } else {
-    ret = &self->priv->default_value;
-  }
-  return ret;
-}
-
-#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
-static inline const GValue * \
-_interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \
-{ \
-  const GValue *ret; \
-  \
-  if (iter) { \
-    GstControlPoint *cp = g_sequence_get (iter); \
-    g##type ret_val = g_value_get_##type (&cp->value); \
-    \
-    if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
-      ret = &self->priv->minimum_value; \
-    else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
-      ret = &self->priv->maximum_value; \
-    else \
-      ret = &cp->value; \
-  } else { \
-    ret = &self->priv->default_value; \
-  } \
-  return ret; \
-}
-
-#define DEFINE_NONE_GET(type,ctype,get_func) \
-static gboolean \
-interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
-{ \
-  const GValue *ret; \
-  GSequenceIter *iter; \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
-  ret = get_func (self, iter); \
-  g_value_copy (ret, value); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self, \
-    GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  GstClockTime next_ts = 0; \
-  ctype *values = (ctype *) value_array->values; \
-  const GValue *ret_val = NULL; \
-  ctype ret = 0; \
-  GSequenceIter *iter1 = NULL, *iter2 = NULL; \
-  \
-  g_mutex_lock (self->lock); \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    if (!ret_val || ts >= next_ts) { \
-      iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
-      if (!iter1) { \
-        if (G_LIKELY (self->priv->values)) \
-         iter2 = g_sequence_get_begin_iter (self->priv->values); \
-       else \
-         iter2 = NULL; \
-      } else { \
-        iter2 = g_sequence_iter_next (iter1); \
-      } \
-      \
-      if (iter2 && !g_sequence_iter_is_end (iter2)) { \
-        GstControlPoint *cp; \
-        \
-        cp = g_sequence_get (iter2); \
-        next_ts = cp->timestamp; \
-      } else { \
-        next_ts = GST_CLOCK_TIME_NONE; \
-      } \
-      \
-      ret_val = get_func (self, iter1); \
-      ret = g_value_get_##type (ret_val); \
-    } \
-    *values = ret; \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-}
-
-DEFINE_NONE_GET_FUNC_COMPARABLE (int);
-DEFINE_NONE_GET (int, gint, _interpolate_none_get_int);
-DEFINE_NONE_GET_FUNC_COMPARABLE (uint);
-DEFINE_NONE_GET (uint, guint, _interpolate_none_get_uint);
-DEFINE_NONE_GET_FUNC_COMPARABLE (long);
-DEFINE_NONE_GET (long, glong, _interpolate_none_get_long);
-DEFINE_NONE_GET_FUNC_COMPARABLE (ulong);
-DEFINE_NONE_GET (ulong, gulong, _interpolate_none_get_ulong);
-DEFINE_NONE_GET_FUNC_COMPARABLE (int64);
-DEFINE_NONE_GET (int64, gint64, _interpolate_none_get_int64);
-DEFINE_NONE_GET_FUNC_COMPARABLE (uint64);
-DEFINE_NONE_GET (uint64, guint64, _interpolate_none_get_uint64);
-DEFINE_NONE_GET_FUNC_COMPARABLE (float);
-DEFINE_NONE_GET (float, gfloat, _interpolate_none_get_float);
-DEFINE_NONE_GET_FUNC_COMPARABLE (double);
-DEFINE_NONE_GET (double, gdouble, _interpolate_none_get_double);
-
-DEFINE_NONE_GET (boolean, gboolean, _interpolate_none_get);
-DEFINE_NONE_GET (enum, gint, _interpolate_none_get);
-DEFINE_NONE_GET (string, const gchar *, _interpolate_none_get);
-
-static GstInterpolateMethod interpolate_none = {
-  (GstControlSourceGetValue) interpolate_none_get_int,
-  (GstControlSourceGetValueArray) interpolate_none_get_int_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_uint,
-  (GstControlSourceGetValueArray) interpolate_none_get_uint_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_long,
-  (GstControlSourceGetValueArray) interpolate_none_get_long_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_ulong,
-  (GstControlSourceGetValueArray) interpolate_none_get_ulong_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_int64,
-  (GstControlSourceGetValueArray) interpolate_none_get_int64_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_uint64,
-  (GstControlSourceGetValueArray) interpolate_none_get_uint64_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_float,
-  (GstControlSourceGetValueArray) interpolate_none_get_float_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_double,
-  (GstControlSourceGetValueArray) interpolate_none_get_double_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_boolean,
-  (GstControlSourceGetValueArray) interpolate_none_get_boolean_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_enum,
-  (GstControlSourceGetValueArray) interpolate_none_get_enum_value_array,
-  (GstControlSourceGetValue) interpolate_none_get_string,
-  (GstControlSourceGetValueArray) interpolate_none_get_string_value_array
-};
-
-/*  returns the default value of the property, except for times with specific values */
-/*  needed for one-shot events, such as notes and triggers */
-static inline const GValue *
-_interpolate_trigger_get (GstInterpolationControlSource * self,
-    GSequenceIter * iter, GstClockTime timestamp)
-{
-  GstControlPoint *cp;
-
-  /* check if there is a value at the registered timestamp */
-  if (iter) {
-    cp = g_sequence_get (iter);
-    if (timestamp == cp->timestamp) {
-      return &cp->value;
-    }
-  }
-  if (self->priv->nvalues > 0)
-    return &self->priv->default_value;
-  else
-    return NULL;
-}
-
-#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
-static inline const GValue * \
-_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
-{ \
-  GstControlPoint *cp; \
-  \
-  /* check if there is a value at the registered timestamp */ \
-  if (iter) { \
-    cp = g_sequence_get (iter); \
-    if (timestamp == cp->timestamp) { \
-      g##type ret = g_value_get_##type (&cp->value); \
-      if (g_value_get_##type (&self->priv->minimum_value) > ret) \
-        return &self->priv->minimum_value; \
-      else if (g_value_get_##type (&self->priv->maximum_value) < ret) \
-        return &self->priv->maximum_value; \
-      else \
-        return &cp->value; \
-    } \
-  } \
-  \
-  if (self->priv->nvalues > 0) \
-    return &self->priv->default_value; \
-  else \
-    return NULL; \
-}
-
-#define DEFINE_TRIGGER_GET(type, ctype, get_func) \
-static gboolean \
-interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
-{ \
-  const GValue *ret; \
-  GSequenceIter *iter; \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
-  ret = get_func (self, iter, timestamp); \
-  if (!ret) { \
-    g_mutex_unlock (self->lock); \
-    return FALSE; \
-  } \
-  \
-  g_value_copy (ret, value); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-interpolate_trigger_get_##type##_value_array (GstInterpolationControlSource *self, \
-    GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  GstClockTime next_ts = 0; \
-  ctype *values = (ctype *) value_array->values; \
-  const GValue *ret_val = NULL; \
-  ctype ret = 0; \
-  GSequenceIter *iter1 = NULL, *iter2 = NULL; \
-  gboolean triggered = FALSE; \
-  \
-  g_mutex_lock (self->lock); \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    if (!ret_val || ts >= next_ts) { \
-      iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
-      if (!iter1) { \
-        if (G_LIKELY (self->priv->values)) \
-          iter2 = g_sequence_get_begin_iter (self->priv->values); \
-       else \
-         iter2 = NULL; \
-      } else { \
-        iter2 = g_sequence_iter_next (iter1); \
-      } \
-      \
-      if (iter2 && !g_sequence_iter_is_end (iter2)) { \
-        GstControlPoint *cp; \
-        \
-        cp = g_sequence_get (iter2); \
-        next_ts = cp->timestamp; \
-      } else { \
-        next_ts = GST_CLOCK_TIME_NONE; \
-      } \
-      \
-      ret_val = get_func (self, iter1, ts); \
-      if (!ret_val) { \
-        g_mutex_unlock (self->lock); \
-        return FALSE; \
-      } \
-      ret = g_value_get_##type (ret_val); \
-      triggered = TRUE; \
-    } else if (triggered) { \
-      ret_val = get_func (self, iter1, ts); \
-      if (!ret_val) { \
-        g_mutex_unlock (self->lock); \
-        return FALSE; \
-      } \
-      ret = g_value_get_##type (ret_val); \
-      triggered = FALSE; \
-    } \
-    *values = ret; \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-}
-
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
-DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
-DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
-DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
-DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
-DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
-DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
-DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
-DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
-
-DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
-DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
-DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
-
-static GstInterpolateMethod interpolate_trigger = {
-  (GstControlSourceGetValue) interpolate_trigger_get_int,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_uint,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_long,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_ulong,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_int64,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_uint64,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_float,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_double,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_boolean,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_enum,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array,
-  (GstControlSourceGetValue) interpolate_trigger_get_string,
-  (GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array
-};
-
-/*  linear interpolation */
-/*  smoothes inbetween values */
-#define DEFINE_LINEAR_GET(vtype, round, convert) \
-static inline void \
-_interpolate_linear_internal_##vtype (GstClockTime timestamp1, g##vtype value1, GstClockTime timestamp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
-{ \
-  if (GST_CLOCK_TIME_IS_VALID (timestamp2)) { \
-    gdouble slope; \
-    \
-    slope = ((gdouble) convert (value2) - (gdouble) convert (value1)) / gst_guint64_to_gdouble (timestamp2 - timestamp1); \
-    \
-    if (round) \
-      *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope + 0.5); \
-    else \
-      *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope); \
-  } else { \
-    *ret = value1; \
-  } \
-  *ret = CLAMP (*ret, min, max); \
-} \
-\
-static gboolean \
-interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
-{ \
-  g##vtype ret, min, max; \
-  GSequenceIter *iter; \
-  GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  min = g_value_get_##vtype (&self->priv->minimum_value); \
-  max = g_value_get_##vtype (&self->priv->maximum_value); \
-  \
-  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
-  if (iter) { \
-    cp1 = g_sequence_get (iter); \
-    iter = g_sequence_iter_next (iter); \
-  } else { \
-    cp.timestamp = G_GUINT64_CONSTANT(0); \
-    g_value_init (&cp.value, self->priv->type); \
-    g_value_copy (&self->priv->default_value, &cp.value); \
-    cp1 = &cp; \
-    if (G_LIKELY (self->priv->values)) \
-      iter = g_sequence_get_begin_iter (self->priv->values); \
-  } \
-  if (iter && !g_sequence_iter_is_end (iter)) \
-    cp2 = g_sequence_get (iter); \
-  \
-  _interpolate_linear_internal_##vtype (cp1->timestamp, g_value_get_##vtype (&cp1->value), (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), (cp2 ? g_value_get_##vtype (&cp2->value) : 0), timestamp, min, max, &ret); \
-  g_value_set_##vtype (value, ret); \
-  g_mutex_unlock (self->lock); \
-  if (cp1 == &cp) \
-    g_value_unset (&cp.value); \
-  return TRUE; \
-} \
-\
-static gboolean \
-interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \
-    GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  GstClockTime next_ts = 0; \
-  g##vtype *values = (g##vtype *) value_array->values; \
-  GSequenceIter *iter1, *iter2 = NULL; \
-  GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
-  g##vtype val1 = 0, val2 = 0, min, max; \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  cp.timestamp = G_GUINT64_CONSTANT(0); \
-  g_value_init (&cp.value, self->priv->type); \
-  g_value_copy (&self->priv->default_value, &cp.value); \
-  \
-  min = g_value_get_##vtype (&self->priv->minimum_value); \
-  max = g_value_get_##vtype (&self->priv->maximum_value); \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    if (timestamp >= next_ts) { \
-      iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
-      if (!iter1) { \
-        cp1 = &cp; \
-       if (G_LIKELY (self->priv->values)) \
-         iter2 = g_sequence_get_begin_iter (self->priv->values); \
-       else \
-         iter2 = NULL; \
-      } else { \
-        cp1 = g_sequence_get (iter1); \
-        iter2 = g_sequence_iter_next (iter1); \
-      } \
-      \
-      if (iter2 && !g_sequence_iter_is_end (iter2)) { \
-        cp2 = g_sequence_get (iter2); \
-        next_ts = cp2->timestamp; \
-      } else { \
-        next_ts = GST_CLOCK_TIME_NONE; \
-      } \
-      val1 = g_value_get_##vtype (&cp1->value); \
-      if (cp2) \
-        val2 = g_value_get_##vtype (&cp2->value); \
-    } \
-    _interpolate_linear_internal_##vtype (cp1->timestamp, val1, (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), (cp2 ? val2 : 0), ts, min, max, values); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  g_value_unset (&cp.value); \
-  return TRUE; \
-}
-
-DEFINE_LINEAR_GET (int, TRUE, EMPTY);
-DEFINE_LINEAR_GET (uint, TRUE, EMPTY);
-DEFINE_LINEAR_GET (long, TRUE, EMPTY);
-DEFINE_LINEAR_GET (ulong, TRUE, EMPTY);
-DEFINE_LINEAR_GET (int64, TRUE, EMPTY);
-DEFINE_LINEAR_GET (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_LINEAR_GET (float, FALSE, EMPTY);
-DEFINE_LINEAR_GET (double, FALSE, EMPTY);
-
-static GstInterpolateMethod interpolate_linear = {
-  (GstControlSourceGetValue) interpolate_linear_get_int,
-  (GstControlSourceGetValueArray) interpolate_linear_get_int_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_uint,
-  (GstControlSourceGetValueArray) interpolate_linear_get_uint_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_long,
-  (GstControlSourceGetValueArray) interpolate_linear_get_long_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_ulong,
-  (GstControlSourceGetValueArray) interpolate_linear_get_ulong_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_int64,
-  (GstControlSourceGetValueArray) interpolate_linear_get_int64_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_uint64,
-  (GstControlSourceGetValueArray) interpolate_linear_get_uint64_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_float,
-  (GstControlSourceGetValueArray) interpolate_linear_get_float_value_array,
-  (GstControlSourceGetValue) interpolate_linear_get_double,
-  (GstControlSourceGetValueArray) interpolate_linear_get_double_value_array,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL
-};
-
-/*  square interpolation */
-
-/*  cubic interpolation */
-
-/* The following functions implement a natural cubic spline interpolator.
- * For details look at http://en.wikipedia.org/wiki/Spline_interpolation
- *
- * Instead of using a real matrix with n^2 elements for the linear system
- * of equations we use three arrays o, p, q to hold the tridiagonal matrix
- * as following to save memory:
- *
- * p[0] q[0]    0    0    0
- * o[1] p[1] q[1]    0    0
- *    0 o[2] p[2] q[2]    .
- *    .    .    .    .    .
- */
-
-#define DEFINE_CUBIC_GET(vtype,round, convert) \
-static void \
-_interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
-{ \
-  gint i, n = self->priv->nvalues; \
-  gdouble *o = g_new0 (gdouble, n); \
-  gdouble *p = g_new0 (gdouble, n); \
-  gdouble *q = g_new0 (gdouble, n); \
-  \
-  gdouble *h = g_new0 (gdouble, n); \
-  gdouble *b = g_new0 (gdouble, n); \
-  gdouble *z = g_new0 (gdouble, n); \
-  \
-  GSequenceIter *iter; \
-  GstControlPoint *cp; \
-  GstClockTime x, x_next; \
-  g##vtype y_prev, y, y_next; \
-  \
-  /* Fill linear system of equations */ \
-  iter = g_sequence_get_begin_iter (self->priv->values); \
-  cp = g_sequence_get (iter); \
-  x = cp->timestamp; \
-  y = g_value_get_##vtype (&cp->value); \
-  \
-  p[0] = 1.0; \
-  \
-  iter = g_sequence_iter_next (iter); \
-  cp = g_sequence_get (iter); \
-  x_next = cp->timestamp; \
-  y_next = g_value_get_##vtype (&cp->value); \
-  h[0] = gst_guint64_to_gdouble (x_next - x); \
-  \
-  for (i = 1; i < n-1; i++) { \
-    /* Shuffle x and y values */ \
-    y_prev = y; \
-    x = x_next; \
-    y = y_next; \
-    iter = g_sequence_iter_next (iter); \
-    cp = g_sequence_get (iter); \
-    x_next = cp->timestamp; \
-    y_next = g_value_get_##vtype (&cp->value); \
-    \
-    h[i] = gst_guint64_to_gdouble (x_next - x); \
-    o[i] = h[i-1]; \
-    p[i] = 2.0 * (h[i-1] + h[i]); \
-    q[i] = h[i]; \
-    b[i] = convert (y_next - y) / h[i] - convert (y - y_prev) / h[i-1]; \
-  } \
-  p[n-1] = 1.0; \
-  \
-  /* Use Gauss elimination to set everything below the \
-   * diagonal to zero */ \
-  for (i = 1; i < n-1; i++) { \
-    gdouble a = o[i] / p[i-1]; \
-    p[i] -= a * q[i-1]; \
-    b[i] -= a * b[i-1]; \
-  } \
-  \
-  /* Solve everything else from bottom to top */ \
-  for (i = n-2; i > 0; i--) \
-    z[i] = (b[i] - q[i] * z[i+1]) / p[i]; \
-  \
-  /* Save cache next in the GstControlPoint */ \
-  \
-  iter = g_sequence_get_begin_iter (self->priv->values); \
-  for (i = 0; i < n; i++) { \
-    cp = g_sequence_get (iter); \
-    cp->cache.cubic.h = h[i]; \
-    cp->cache.cubic.z = z[i]; \
-    iter = g_sequence_iter_next (iter); \
-  } \
-  \
-  /* Free our temporary arrays */ \
-  g_free (o); \
-  g_free (p); \
-  g_free (q); \
-  g_free (h); \
-  g_free (b); \
-  g_free (z); \
-} \
-\
-static inline void \
-_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
-{ \
-  if (!self->priv->valid_cache) { \
-    _interpolate_cubic_update_cache_##vtype (self); \
-    self->priv->valid_cache = TRUE; \
-  } \
-  \
-  if (cp2) { \
-    gdouble diff1, diff2; \
-    gdouble out; \
-    \
-    diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \
-    diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \
-    \
-    out = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \
-    out += (convert (value2) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \
-    out += (convert (value1) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \
-    \
-    if (round) \
-      *ret = (g##vtype) (out + 0.5); \
-    else \
-      *ret = (g##vtype) out; \
-  } \
-  else { \
-    *ret = value1; \
-  } \
-  *ret = CLAMP (*ret, min, max); \
-} \
-\
-static gboolean \
-interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
-{ \
-  g##vtype ret, min, max; \
-  GSequenceIter *iter; \
-  GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
-  \
-  if (self->priv->nvalues <= 2) \
-    return interpolate_linear_get_##vtype (self, timestamp, value); \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  min = g_value_get_##vtype (&self->priv->minimum_value); \
-  max = g_value_get_##vtype (&self->priv->maximum_value); \
-  \
-  iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
-  if (iter) { \
-    cp1 = g_sequence_get (iter); \
-    iter = g_sequence_iter_next (iter); \
-  } else { \
-    cp.timestamp = G_GUINT64_CONSTANT(0); \
-    g_value_init (&cp.value, self->priv->type); \
-    g_value_copy (&self->priv->default_value, &cp.value); \
-    cp1 = &cp; \
-    if (G_LIKELY (self->priv->values)) \
-      iter = g_sequence_get_begin_iter (self->priv->values); \
-  } \
-  if (iter && !g_sequence_iter_is_end (iter)) \
-    cp2 = g_sequence_get (iter); \
-  \
-  _interpolate_cubic_get_##vtype (self, cp1, g_value_get_##vtype (&cp1->value), cp2, (cp2 ? g_value_get_##vtype (&cp2->value) : 0), timestamp, min, max, &ret); \
-  g_value_set_##vtype (value, ret); \
-  g_mutex_unlock (self->lock); \
-  if (cp1 == &cp) \
-    g_value_unset (&cp.value); \
-  return TRUE; \
-} \
-\
-static gboolean \
-interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \
-    GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  GstClockTime next_ts = 0; \
-  g##vtype *values = (g##vtype *) value_array->values; \
-  GSequenceIter *iter1, *iter2 = NULL; \
-  GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
-  g##vtype val1 = 0, val2 = 0, min, max; \
-  \
-  if (self->priv->nvalues <= 2) \
-    return interpolate_linear_get_##vtype##_value_array (self, timestamp, value_array); \
-  \
-  g_mutex_lock (self->lock); \
-  \
-  cp.timestamp = G_GUINT64_CONSTANT(0); \
-  g_value_init (&cp.value, self->priv->type); \
-  g_value_copy (&self->priv->default_value, &cp.value); \
-  \
-  min = g_value_get_##vtype (&self->priv->minimum_value); \
-  max = g_value_get_##vtype (&self->priv->maximum_value); \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    if (timestamp >= next_ts) { \
-      iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
-      if (!iter1) { \
-        cp1 = &cp; \
-       if (G_LIKELY (self->priv->values)) \
-         iter2 = g_sequence_get_begin_iter (self->priv->values); \
-       else \
-         iter2 = NULL; \
-      } else { \
-        cp1 = g_sequence_get (iter1); \
-        iter2 = g_sequence_iter_next (iter1); \
-      } \
-      \
-      if (iter2 && !g_sequence_iter_is_end (iter2)) { \
-        cp2 = g_sequence_get (iter2); \
-        next_ts = cp2->timestamp; \
-      } else { \
-        next_ts = GST_CLOCK_TIME_NONE; \
-      } \
-      val1 = g_value_get_##vtype (&cp1->value); \
-      if (cp2) \
-        val2 = g_value_get_##vtype (&cp2->value); \
-    } \
-    _interpolate_cubic_get_##vtype (self, cp1, val1, cp2, val2, timestamp, min, max, values); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  g_value_unset (&cp.value); \
-  return TRUE; \
-}
-
-DEFINE_CUBIC_GET (int, TRUE, EMPTY);
-DEFINE_CUBIC_GET (uint, TRUE, EMPTY);
-DEFINE_CUBIC_GET (long, TRUE, EMPTY);
-DEFINE_CUBIC_GET (ulong, TRUE, EMPTY);
-DEFINE_CUBIC_GET (int64, TRUE, EMPTY);
-DEFINE_CUBIC_GET (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_CUBIC_GET (float, FALSE, EMPTY);
-DEFINE_CUBIC_GET (double, FALSE, EMPTY);
-
-static GstInterpolateMethod interpolate_cubic = {
-  (GstControlSourceGetValue) interpolate_cubic_get_int,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_int_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_uint,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_uint_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_long,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_long_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_ulong,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_ulong_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_int64,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_int64_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_uint64,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_uint64_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_float,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_float_value_array,
-  (GstControlSourceGetValue) interpolate_cubic_get_double,
-  (GstControlSourceGetValueArray) interpolate_cubic_get_double_value_array,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL,
-  (GstControlSourceGetValue) NULL,
-  (GstControlSourceGetValueArray) NULL
-};
-
-/*  register all interpolation methods */
-GstInterpolateMethod *priv_gst_interpolation_methods[] = {
-  &interpolate_none,
-  &interpolate_trigger,
-  &interpolate_linear,
-  &interpolate_cubic,
-  &interpolate_cubic
-};
-
-guint priv_gst_num_interpolation_methods =
-G_N_ELEMENTS (priv_gst_interpolation_methods);
index 1dd0a89..07eb4d2 100644 (file)
@@ -29,9 +29,8 @@
  * control points. It supports several interpolation modes and property types.
  *
  * To use #GstInterpolationControlSource get a new instance by calling
- * gst_interpolation_control_source_new(), bind it to a #GParamSpec, select a interpolation mode with
- * gst_interpolation_control_source_set_interpolation_mode() and set some control points by calling
- * gst_interpolation_control_source_set().
+ * gst_interpolation_control_source_new(), bind it to a #GParamSpec and set some
+ * control points by calling gst_timed_value_control_source_set().
  *
  * All functions are MT-safe.
  *
 #include <glib-object.h>
 #include <gst/gst.h>
 
-#include "gstcontrolsource.h"
 #include "gstinterpolationcontrolsource.h"
-#include "gstinterpolationcontrolsourceprivate.h"
 #include "gst/glib-compat-private.h"
+#include "gst/math-compat.h"
 
 #define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
-G_DEFINE_TYPE (GstInterpolationControlSource, gst_interpolation_control_source,
-    GST_TYPE_CONTROL_SOURCE);
-
-/*
- * gst_control_point_free:
- * @prop: the object to free
- *
- * Private method which frees all data allocated by a #GstControlPoint
- * instance.
- */
-static void
-gst_control_point_free (GstControlPoint * cp)
+/*  steps-like (no-)interpolation, default */
+/*  just returns the value for the most recent key-frame */
+static inline gdouble
+_interpolate_none (GstTimedValueControlSource * self, GSequenceIter * iter)
 {
-  g_return_if_fail (cp);
+  GstControlPoint *cp = g_sequence_get (iter);
 
-  g_value_unset (&cp->value);
-  g_slice_free (GstControlPoint, cp);
+  return cp->value;
 }
 
-static void
-gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
+static gboolean
+interpolate_none_get (GstTimedValueControlSource * self, GstClockTime timestamp,
+    gdouble * value)
 {
-  GstControlSource *csource = (GstControlSource *) self;
-
-  csource->get_value = NULL;
-  csource->get_value_array = NULL;
-
-  self->priv->type = self->priv->base = G_TYPE_INVALID;
+  gboolean ret = FALSE;
+  GSequenceIter *iter;
 
-  if (G_IS_VALUE (&self->priv->default_value))
-    g_value_unset (&self->priv->default_value);
-  if (G_IS_VALUE (&self->priv->minimum_value))
-    g_value_unset (&self->priv->minimum_value);
-  if (G_IS_VALUE (&self->priv->maximum_value))
-    g_value_unset (&self->priv->maximum_value);
+  g_mutex_lock (&self->lock);
 
-  if (self->priv->values) {
-    g_sequence_free (self->priv->values);
-    self->priv->values = NULL;
+  iter =
+      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
+  if (iter) {
+    *value = _interpolate_none (self, iter);
+    ret = TRUE;
   }
-
-  self->priv->nvalues = 0;
-  self->priv->valid_cache = FALSE;
-}
-
-/**
- * gst_interpolation_control_source_new:
- *
- * This returns a new, unbound #GstInterpolationControlSource.
- *
- * Returns: a new, unbound #GstInterpolationControlSource.
- */
-GstInterpolationControlSource *
-gst_interpolation_control_source_new (void)
-{
-  return g_object_newv (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, 0, NULL);
+  g_mutex_unlock (&self->lock);
+  return ret;
 }
 
-/**
- * gst_interpolation_control_source_set_interpolation_mode:
- * @self: the #GstInterpolationControlSource object
- * @mode: interpolation mode
- *
- * Sets the given interpolation mode.
- *
- * <note><para>User interpolation is not yet available and quadratic interpolation
- * is deprecated and maps to cubic interpolation.</para></note>
- *
- * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
- */
-/* *INDENT-OFF* */
-gboolean
-gst_interpolation_control_source_set_interpolation_mode (
-    GstInterpolationControlSource * self, GstInterpolateMode mode)
-/* *INDENT-ON* */
+static gboolean
+interpolate_none_get_value_array (GstTimedValueControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
 {
-  gboolean ret = TRUE;
-  GstControlSource *csource = GST_CONTROL_SOURCE (self);
-
-  if (mode >= priv_gst_num_interpolation_methods
-      || priv_gst_interpolation_methods[mode] == NULL) {
-    GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
-    return FALSE;
-  }
+  gboolean ret = FALSE;
+  guint i;
+  GstClockTime ts = timestamp;
+  GstClockTime next_ts = 0;
+  gdouble val;
+  GSequenceIter *iter1 = NULL, *iter2 = NULL;
+
+  g_mutex_lock (&self->lock);
+
+  for (i = 0; i < n_values; i++) {
+    GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
+        i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
+    val = NAN;
+    if (ts >= next_ts) {
+      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
+      if (!iter1) {
+        if (G_LIKELY (self->values))
+          iter2 = g_sequence_get_begin_iter (self->values);
+        else
+          iter2 = NULL;
+      } else {
+        iter2 = g_sequence_iter_next (iter1);
+      }
 
-  if (mode == GST_INTERPOLATE_QUADRATIC) {
-    GST_WARNING ("Quadratic interpolation mode is deprecated, using cubic"
-        "interpolation mode");
-  }
+      if (iter2 && !g_sequence_iter_is_end (iter2)) {
+        GstControlPoint *cp;
 
-  if (mode == GST_INTERPOLATE_USER) {
-    GST_WARNING ("User interpolation mode is not implemented yet");
-    return FALSE;
-  }
-
-  g_mutex_lock (self->lock);
-  switch (self->priv->base) {
-    case G_TYPE_INT:
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_int_value_array;
-      break;
-    case G_TYPE_UINT:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_uint_value_array;
-      break;
-    }
-    case G_TYPE_LONG:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_long_value_array;
-      break;
-    }
-    case G_TYPE_ULONG:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_ulong_value_array;
-      break;
-    }
-    case G_TYPE_INT64:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_int64_value_array;
-      break;
-    }
-    case G_TYPE_UINT64:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_uint64_value_array;
-      break;
-    }
-    case G_TYPE_FLOAT:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_float_value_array;
-      break;
-    }
-    case G_TYPE_DOUBLE:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_double_value_array;
-      break;
-    }
-    case G_TYPE_BOOLEAN:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_boolean_value_array;
-      break;
-    }
-    case G_TYPE_ENUM:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_enum_value_array;
-      break;
+        cp = g_sequence_get (iter2);
+        next_ts = cp->timestamp;
+      } else {
+        next_ts = GST_CLOCK_TIME_NONE;
+      }
     }
-    case G_TYPE_STRING:{
-      csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
-      csource->get_value_array =
-          priv_gst_interpolation_methods[mode]->get_string_value_array;
-      break;
+    if (iter1) {
+      val = _interpolate_none (self, iter1);
+      ret = TRUE;
+      GST_LOG ("values[%3d]=%lf", i, val);
+    } else {
+      GST_LOG ("values[%3d]=-", i);
     }
-    default:
-      ret = FALSE;
-      break;
+    *values = val;
+    ts += interval;
+    values++;
   }
+  g_mutex_unlock (&self->lock);
+  return ret;
+}
 
-  /* Incomplete implementation */
-  if (!ret || !csource->get_value || !csource->get_value_array) {
-    gst_interpolation_control_source_reset (self);
-    ret = FALSE;
-  }
 
-  self->priv->valid_cache = FALSE;
-  self->priv->interpolation_mode = mode;
 
-  g_mutex_unlock (self->lock);
+/*  linear interpolation */
+/*  smoothes inbetween values */
+static inline gdouble
+_interpolate_linear (GstClockTime timestamp1, gdouble value1,
+    GstClockTime timestamp2, gdouble value2, GstClockTime timestamp)
+{
+  if (GST_CLOCK_TIME_IS_VALID (timestamp2)) {
+    gdouble slope;
 
-  return ret;
+    slope =
+        (value2 - value1) / gst_guint64_to_gdouble (timestamp2 - timestamp1);
+    return value1 + (gst_guint64_to_gdouble (timestamp - timestamp1) * slope);
+  } else {
+    return value1;
+  }
 }
 
 static gboolean
-gst_interpolation_control_source_bind (GstControlSource * source,
-    GParamSpec * pspec)
+interpolate_linear_get (GstTimedValueControlSource * self,
+    GstClockTime timestamp, gdouble * value)
 {
-  GType type, base;
-  GstInterpolationControlSource *self =
-      (GstInterpolationControlSource *) source;
-  gboolean ret = TRUE;
-
-  /* get the fundamental base type */
-  self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-  while ((type = g_type_parent (type)))
-    base = type;
-
-  self->priv->base = base;
-  /* restore type */
-  type = self->priv->type;
-
-  if (!gst_interpolation_control_source_set_interpolation_mode (self,
-          self->priv->interpolation_mode))
-    return FALSE;
+  gboolean ret = FALSE;
+  GSequenceIter *iter;
+  GstControlPoint *cp1, *cp2;
 
-  switch (base) {
-    case G_TYPE_INT:{
-      GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
+  g_mutex_lock (&self->lock);
 
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_int (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_UINT:{
-      GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_uint (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_LONG:{
-      GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_long (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_ULONG:{
-      GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_ulong (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_INT64:{
-      GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_int64 (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_UINT64:{
-      GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_uint64 (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_FLOAT:{
-      GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_float (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
-      break;
-    }
-    case G_TYPE_DOUBLE:{
-      GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
-
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_double (&self->priv->default_value, tpspec->default_value);
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
-      break;
+  iter =
+      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
+  if (iter) {
+    cp1 = g_sequence_get (iter);
+    iter = g_sequence_iter_next (iter);
+    if (iter && !g_sequence_iter_is_end (iter)) {
+      cp2 = g_sequence_get (iter);
+    } else {
+      cp2 = NULL;
     }
-    case G_TYPE_BOOLEAN:{
-      GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
 
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_boolean (&self->priv->default_value, tpspec->default_value);
-      break;
-    }
-    case G_TYPE_ENUM:{
-      GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
+    *value = _interpolate_linear (cp1->timestamp, cp1->value,
+        (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE),
+        (cp2 ? cp2->value : 0.0), timestamp);
+    ret = TRUE;
+  }
+  g_mutex_unlock (&self->lock);
+  return ret;
+}
 
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_enum (&self->priv->default_value, tpspec->default_value);
-      break;
-    }
-    case G_TYPE_STRING:{
-      GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
+static gboolean
+interpolate_linear_get_value_array (GstTimedValueControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  gboolean ret = FALSE;
+  guint i;
+  GstClockTime ts = timestamp;
+  GstClockTime next_ts = 0;
+  gdouble val;
+  GSequenceIter *iter1, *iter2 = NULL;
+  GstControlPoint *cp1 = NULL, *cp2 = NULL;
+
+  g_mutex_lock (&self->lock);
+
+  for (i = 0; i < n_values; i++) {
+    GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
+        i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
+    val = NAN;
+    if (ts >= next_ts) {
+      cp1 = cp2 = NULL;
+      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
+      if (!iter1) {
+        if (G_LIKELY (self->values))
+          iter2 = g_sequence_get_begin_iter (self->values);
+        else
+          iter2 = NULL;
+      } else {
+        cp1 = g_sequence_get (iter1);
+        iter2 = g_sequence_iter_next (iter1);
+      }
 
-      g_value_init (&self->priv->default_value, type);
-      g_value_set_string (&self->priv->default_value, tpspec->default_value);
-      break;
+      if (iter2 && !g_sequence_iter_is_end (iter2)) {
+        cp2 = g_sequence_get (iter2);
+        next_ts = cp2->timestamp;
+      } else {
+        next_ts = GST_CLOCK_TIME_NONE;
+      }
     }
-    default:
-      GST_WARNING ("incomplete implementation for paramspec type '%s'",
-          G_PARAM_SPEC_TYPE_NAME (pspec));
-      ret = FALSE;
-      break;
-  }
-
-  if (ret) {
-    self->priv->valid_cache = FALSE;
-    self->priv->nvalues = 0;
-  } else {
-    gst_interpolation_control_source_reset (self);
+    if (cp1) {
+      val = _interpolate_linear (cp1->timestamp, cp1->value,
+          (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE),
+          (cp2 ? cp2->value : 0.0), ts);
+      ret = TRUE;
+      GST_LOG ("values[%3d]=%lf", i, val);
+    } else {
+      GST_LOG ("values[%3d]=-", i);
+    }
+    *values = val;
+    ts += interval;
+    values++;
   }
-
+  g_mutex_unlock (&self->lock);
   return ret;
 }
 
-/*
- * gst_control_point_compare:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstControlPoint
- *
- * Compare function for g_list operations that operates on two #GstControlPoint
- * parameters.
- */
-static gint
-gst_control_point_compare (gconstpointer p1, gconstpointer p2)
-{
-  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
-  GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
 
-  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
 
-/*
- * gst_control_point_find:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstClockTime
+/*  cubic interpolation */
+
+/* The following functions implement a natural cubic spline interpolator.
+ * For details look at http://en.wikipedia.org/wiki/Spline_interpolation
+ *
+ * Instead of using a real matrix with n^2 elements for the linear system
+ * of equations we use three arrays o, p, q to hold the tridiagonal matrix
+ * as following to save memory:
  *
- * Compare function for g_list operations that operates on a #GstControlPoint and
- * a #GstClockTime.
+ * p[0] q[0]    0    0    0
+ * o[1] p[1] q[1]    0    0
+ *    0 o[2] p[2] q[2]    .
+ *    .    .    .    .    .
  */
-static gint
-gst_control_point_find (gconstpointer p1, gconstpointer p2)
+
+static void
+_interpolate_cubic_update_cache (GstTimedValueControlSource * self)
 {
-  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
-  GstClockTime ct2 = *(GstClockTime *) p2;
+  gint i, n = self->nvalues;
+  gdouble *o = g_new0 (gdouble, n);
+  gdouble *p = g_new0 (gdouble, n);
+  gdouble *q = g_new0 (gdouble, n);
 
-  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
+  gdouble *h = g_new0 (gdouble, n);
+  gdouble *b = g_new0 (gdouble, n);
+  gdouble *z = g_new0 (gdouble, n);
 
-static GstControlPoint *
-_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
-    const GValue * value)
-{
+  GSequenceIter *iter;
   GstControlPoint *cp;
+  GstClockTime x, x_next;
+  gdouble y_prev, y, y_next;
+
+  /* Fill linear system of equations */
+  iter = g_sequence_get_begin_iter (self->values);
+  cp = g_sequence_get (iter);
+  x = cp->timestamp;
+  y = cp->value;
+
+  p[0] = 1.0;
+
+  iter = g_sequence_iter_next (iter);
+  cp = g_sequence_get (iter);
+  x_next = cp->timestamp;
+  y_next = cp->value;
+  h[0] = gst_guint64_to_gdouble (x_next - x);
+
+  for (i = 1; i < n - 1; i++) {
+    /* Shuffle x and y values */
+    y_prev = y;
+    x = x_next;
+    y = y_next;
+    iter = g_sequence_iter_next (iter);
+    cp = g_sequence_get (iter);
+    x_next = cp->timestamp;
+    y_next = cp->value;
+
+    h[i] = gst_guint64_to_gdouble (x_next - x);
+    o[i] = h[i - 1];
+    p[i] = 2.0 * (h[i - 1] + h[i]);
+    q[i] = h[i];
+    b[i] = (y_next - y) / h[i] - (y - y_prev) / h[i - 1];
+  }
+  p[n - 1] = 1.0;
+
+  /* Use Gauss elimination to set everything below the diagonal to zero */
+  for (i = 1; i < n - 1; i++) {
+    gdouble a = o[i] / p[i - 1];
+    p[i] -= a * q[i - 1];
+    b[i] -= a * b[i - 1];
+  }
 
-  /* create a new GstControlPoint */
-  cp = g_slice_new0 (GstControlPoint);
-  cp->timestamp = timestamp;
-  g_value_init (&cp->value, self->priv->type);
-  g_value_copy (value, &cp->value);
+  /* Solve everything else from bottom to top */
+  for (i = n - 2; i > 0; i--)
+    z[i] = (b[i] - q[i] * z[i + 1]) / p[i];
+
+  /* Save cache next in the GstControlPoint */
+
+  iter = g_sequence_get_begin_iter (self->values);
+  for (i = 0; i < n; i++) {
+    cp = g_sequence_get (iter);
+    cp->cache.cubic.h = h[i];
+    cp->cache.cubic.z = z[i];
+    iter = g_sequence_iter_next (iter);
+  }
 
-  return cp;
+  /* Free our temporary arrays */
+  g_free (o);
+  g_free (p);
+  g_free (q);
+  g_free (h);
+  g_free (b);
+  g_free (z);
 }
 
-static void
-gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
-    self, GstClockTime timestamp, const GValue * value)
+static inline gdouble
+_interpolate_cubic (GstTimedValueControlSource * self, GstControlPoint * cp1,
+    gdouble value1, GstControlPoint * cp2, gdouble value2,
+    GstClockTime timestamp)
 {
-  GSequenceIter *iter;
+  if (!self->valid_cache) {
+    _interpolate_cubic_update_cache (self);
+    self->valid_cache = TRUE;
+  }
 
-  /* check if a control point for the timestamp already exists */
-
-  /* iter contains the iter right *after* timestamp */
-  if (G_LIKELY (self->priv->values)) {
-    iter =
-        g_sequence_search (self->priv->values, &timestamp,
-        (GCompareDataFunc) gst_control_point_find, NULL);
-    if (iter) {
-      GSequenceIter *prev = g_sequence_iter_prev (iter);
-      GstControlPoint *cp = g_sequence_get (prev);
-
-      /* If the timestamp is the same just update the control point value */
-      if (cp->timestamp == timestamp) {
-        /* update control point */
-        g_value_reset (&cp->value);
-        g_value_copy (value, &cp->value);
-        goto done;
-      }
-    }
+  if (cp2) {
+    gdouble diff1, diff2;
+    gdouble out;
+
+    diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp);
+    diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp);
+
+    out =
+        (cp2->cache.cubic.z * diff1 * diff1 * diff1 +
+        cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h;
+    out +=
+        (value2 / cp1->cache.cubic.h -
+        cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1;
+    out +=
+        (value1 / cp1->cache.cubic.h -
+        cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2;
+    return out;
   } else {
-    self->priv->values =
-        g_sequence_new ((GDestroyNotify) gst_control_point_free);
+    return value1;
   }
-
-  /* sort new cp into the prop->values list */
-  g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
-          value), (GCompareDataFunc) gst_control_point_compare, NULL);
-  self->priv->nvalues++;
-
-done:
-  self->priv->valid_cache = FALSE;
 }
 
-
-/**
- * gst_interpolation_control_source_set:
- * @self: the #GstInterpolationControlSource object
- * @timestamp: the time the control-change is scheduled for
- * @value: the control-value
- *
- * Set the value of given controller-handled property at a certain time.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_set (GstInterpolationControlSource * self,
-    GstClockTime timestamp, const GValue * value)
+static gboolean
+interpolate_cubic_get (GstTimedValueControlSource * self,
+    GstClockTime timestamp, gdouble * value)
 {
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-  g_return_val_if_fail (G_IS_VALUE (value), FALSE);
-  g_return_val_if_fail (G_VALUE_TYPE (value) == self->priv->type, FALSE);
+  gboolean ret = FALSE;
+  GSequenceIter *iter;
+  GstControlPoint *cp1, *cp2 = NULL;
 
-  g_mutex_lock (self->lock);
-  gst_interpolation_control_source_set_internal (self, timestamp, value);
-  g_mutex_unlock (self->lock);
+  if (self->nvalues <= 2)
+    return interpolate_linear_get (self, timestamp, value);
 
-  return TRUE;
-}
+  g_mutex_lock (&self->lock);
 
-/**
- * gst_interpolation_control_source_set_from_list:
- * @self: the #GstInterpolationControlSource object
- * @timedvalues: a list with #GstTimedValue items
- *
- * Sets multiple timed values at once.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_set_from_list (GstInterpolationControlSource *
-    self, const GSList * timedvalues)
-{
-  const GSList *node;
-  GstTimedValue *tv;
-  gboolean res = FALSE;
-
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
-
-  for (node = timedvalues; node; node = g_slist_next (node)) {
-    tv = node->data;
-    if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
-      GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
-          GST_FUNCTION);
-    } else if (!G_IS_VALUE (&tv->value)) {
-      GST_WARNING ("GstTimedValued with invalid value passed to %s",
-          GST_FUNCTION);
-    } else if (G_VALUE_TYPE (&tv->value) != self->priv->type) {
-      GST_WARNING ("incompatible value type for property");
+  iter =
+      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
+  if (iter) {
+    cp1 = g_sequence_get (iter);
+    iter = g_sequence_iter_next (iter);
+    if (iter && !g_sequence_iter_is_end (iter)) {
+      cp2 = g_sequence_get (iter);
     } else {
-      g_mutex_lock (self->lock);
-      gst_interpolation_control_source_set_internal (self, tv->timestamp,
-          &tv->value);
-      g_mutex_unlock (self->lock);
-      res = TRUE;
+      cp2 = NULL;
     }
+    *value = _interpolate_cubic (self, cp1, cp1->value, cp2,
+        (cp2 ? cp2->value : 0.0), timestamp);
+    ret = TRUE;
   }
-  return res;
+  g_mutex_unlock (&self->lock);
+  return ret;
 }
 
-/**
- * gst_interpolation_control_source_unset:
- * @self: the #GstInterpolationControlSource object
- * @timestamp: the time the control-change should be removed from
- *
- * Used to remove the value of given controller-handled property at a certain
- * time.
- *
- * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
-    GstClockTime timestamp)
+static gboolean
+interpolate_cubic_get_value_array (GstTimedValueControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
 {
-  GSequenceIter *iter;
-  gboolean res = FALSE;
-
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
-  g_mutex_lock (self->lock);
-  /* check if a control point for the timestamp exists */
-  if (G_LIKELY (self->priv->values) && (iter =
-          g_sequence_search (self->priv->values, &timestamp,
-              (GCompareDataFunc) gst_control_point_find, NULL))) {
-    GstControlPoint *cp;
-
-    /* Iter contains the iter right after timestamp, i.e.
-     * we need to get the previous one and check the timestamp
-     */
-    iter = g_sequence_iter_prev (iter);
-    cp = g_sequence_get (iter);
-    if (cp->timestamp == timestamp) {
-      g_sequence_remove (iter);
-      self->priv->nvalues--;
-      self->priv->valid_cache = FALSE;
-      res = TRUE;
+  gboolean ret = FALSE;
+  guint i;
+  GstClockTime ts = timestamp;
+  GstClockTime next_ts = 0;
+  gdouble val;
+  GSequenceIter *iter1, *iter2 = NULL;
+  GstControlPoint *cp1 = NULL, *cp2 = NULL;
+
+  if (self->nvalues <= 2)
+    return interpolate_linear_get_value_array (self, timestamp, interval,
+        n_values, values);
+
+  g_mutex_lock (&self->lock);
+
+  for (i = 0; i < n_values; i++) {
+    GST_LOG ("values[%3d] : ts=%" GST_TIME_FORMAT ", next_ts=%" GST_TIME_FORMAT,
+        i, GST_TIME_ARGS (ts), GST_TIME_ARGS (next_ts));
+    val = NAN;
+    if (ts >= next_ts) {
+      cp1 = cp2 = NULL;
+      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
+      if (!iter1) {
+        if (G_LIKELY (self->values))
+          iter2 = g_sequence_get_begin_iter (self->values);
+        else
+          iter2 = NULL;
+      } else {
+        cp1 = g_sequence_get (iter1);
+        iter2 = g_sequence_iter_next (iter1);
+      }
+
+      if (iter2 && !g_sequence_iter_is_end (iter2)) {
+        cp2 = g_sequence_get (iter2);
+        next_ts = cp2->timestamp;
+      } else {
+        next_ts = GST_CLOCK_TIME_NONE;
+      }
+    }
+    if (cp1) {
+      val = _interpolate_cubic (self, cp1, cp1->value, cp2,
+          (cp2 ? cp2->value : 0.0), ts);
+      ret = TRUE;
+      GST_LOG ("values[%3d]=%lf", i, val);
+    } else {
+      GST_LOG ("values[%3d]=-", i);
     }
+    *values = val;
+    ts += interval;
+    values++;
   }
-  g_mutex_unlock (self->lock);
-
-  return res;
+  g_mutex_unlock (&self->lock);
+  return ret;
 }
 
-/**
- * gst_interpolation_control_source_unset_all:
- * @self: the #GstInterpolationControlSource object
- *
- * Used to remove all time-stamped values of given controller-handled property
- *
- */
-void
-gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
-    self)
+static struct
 {
-  g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
+  GstControlSourceGetValue get;
+  GstControlSourceGetValueArray get_value_array;
+} interpolation_modes[] = {
+  {
+  (GstControlSourceGetValue) interpolate_none_get,
+        (GstControlSourceGetValueArray) interpolate_none_get_value_array}, {
+  (GstControlSourceGetValue) interpolate_linear_get,
+        (GstControlSourceGetValueArray) interpolate_linear_get_value_array}, {
+  (GstControlSourceGetValue) interpolate_cubic_get,
+        (GstControlSourceGetValueArray) interpolate_cubic_get_value_array}
+};
+
+static const guint num_interpolation_modes = G_N_ELEMENTS (interpolation_modes);
+
+enum
+{
+  PROP_MODE = 1
+};
 
-  g_mutex_lock (self->lock);
-  /* free GstControlPoint structures */
-  if (self->priv->values) {
-    g_sequence_free (self->priv->values);
-    self->priv->values = NULL;
+GType
+gst_interpolation_mode_get_type (void)
+{
+  static gsize gtype = 0;
+  static const GEnumValue values[] = {
+    {GST_INTERPOLATION_MODE_NONE, "GST_INTERPOLATION_MODE_NONE", "none"},
+    {GST_INTERPOLATION_MODE_LINEAR, "GST_INTERPOLATION_MODE_LINEAR", "linear"},
+    {GST_INTERPOLATION_MODE_CUBIC, "GST_INTERPOLATION_MODE_CUBIC", "cubic"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&gtype)) {
+    GType tmp = g_enum_register_static ("GstInterpolationMode", values);
+    g_once_init_leave (&gtype, tmp);
   }
-  self->priv->nvalues = 0;
-  self->priv->valid_cache = FALSE;
 
-  g_mutex_unlock (self->lock);
+  return (GType) gtype;
 }
 
-static void
-_append_control_point (GstControlPoint * cp, GQueue * res)
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, \
+    "timeline value interpolating control source")
+
+G_DEFINE_TYPE_WITH_CODE (GstInterpolationControlSource,
+    gst_interpolation_control_source, GST_TYPE_TIMED_VALUE_CONTROL_SOURCE,
+    _do_init);
+
+struct _GstInterpolationControlSourcePrivate
 {
-  g_queue_push_tail (res, cp);
-}
+  GstInterpolationMode interpolation_mode;
+};
 
 /**
- * gst_interpolation_control_source_get_all:
- * @self: the #GstInterpolationControlSource to get the list from
+ * gst_interpolation_control_source_new:
  *
- * Returns a read-only copy of the list of #GstTimedValue for the given property.
- * Free the list after done with it.
+ * This returns a new, unbound #GstInterpolationControlSource.
  *
- * Returns: a copy of the list, or %NULL if the property isn't handled by the controller
+ * Returns: a new, unbound #GstInterpolationControlSource.
  */
-GList *
-gst_interpolation_control_source_get_all (GstInterpolationControlSource * self)
+GstInterpolationControlSource *
+gst_interpolation_control_source_new (void)
 {
-  GQueue res = G_QUEUE_INIT;
+  return g_object_newv (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, 0, NULL);
+}
+
+static gboolean
+    gst_interpolation_control_source_set_interpolation_mode
+    (GstInterpolationControlSource * self, GstInterpolationMode mode)
+{
+  GstControlSource *csource = GST_CONTROL_SOURCE (self);
 
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
+  if (mode >= num_interpolation_modes && (int) mode < 0) {
+    GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
+    return FALSE;
+  }
 
-  g_mutex_lock (self->lock);
-  if (G_LIKELY (self->priv->values))
-    g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
-        &res);
-  g_mutex_unlock (self->lock);
+  GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
+  csource->get_value = interpolation_modes[mode].get;
+  csource->get_value_array = interpolation_modes[mode].get_value_array;
 
-  return res.head;
-}
+  gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
+      csource);
+  self->priv->interpolation_mode = mode;
 
-/**
- * gst_interpolation_control_source_get_count:
- * @self: the #GstInterpolationControlSource to get the number of values from
- *
- * Returns the number of control points that are set.
- *
- * Returns: the number of control points that are set.
- *
- */
-gint
-gst_interpolation_control_source_get_count (GstInterpolationControlSource *
-    self)
-{
-  g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 0);
-  return self->priv->nvalues;
-}
+  GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
 
+  return TRUE;
+}
 
 static void
 gst_interpolation_control_source_init (GstInterpolationControlSource * self)
 {
-  self->lock = g_mutex_new ();
   self->priv =
       G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
       GstInterpolationControlSourcePrivate);
-  self->priv->interpolation_mode = GST_INTERPOLATE_NONE;
+  gst_interpolation_control_source_set_interpolation_mode (self,
+      GST_INTERPOLATION_MODE_NONE);
 }
 
 static void
-gst_interpolation_control_source_finalize (GObject * obj)
+gst_interpolation_control_source_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
 {
-  GstInterpolationControlSource *self = GST_INTERPOLATION_CONTROL_SOURCE (obj);
-
-  g_mutex_lock (self->lock);
-  gst_interpolation_control_source_reset (self);
-  g_mutex_unlock (self->lock);
-  g_mutex_free (self->lock);
-  G_OBJECT_CLASS (gst_interpolation_control_source_parent_class)->finalize
-      (obj);
+  GstInterpolationControlSource *self =
+      GST_INTERPOLATION_CONTROL_SOURCE (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      gst_interpolation_control_source_set_interpolation_mode (self,
+          (GstInterpolationMode) g_value_get_enum (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
-gst_interpolation_control_source_dispose (GObject * obj)
+gst_interpolation_control_source_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
 {
-  G_OBJECT_CLASS (gst_interpolation_control_source_parent_class)->dispose (obj);
+  GstInterpolationControlSource *self =
+      GST_INTERPOLATION_CONTROL_SOURCE (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_value_set_enum (value, self->priv->interpolation_mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
@@ -685,12 +592,16 @@ gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
     * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
+  //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass,
       sizeof (GstInterpolationControlSourcePrivate));
 
-  gobject_class->finalize = gst_interpolation_control_source_finalize;
-  gobject_class->dispose = gst_interpolation_control_source_dispose;
-  csource_class->bind = gst_interpolation_control_source_bind;
+  gobject_class->set_property = gst_interpolation_control_source_set_property;
+  gobject_class->get_property = gst_interpolation_control_source_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode", "Mode", "Interpolation mode",
+          GST_TYPE_INTERPOLATION_MODE, GST_INTERPOLATION_MODE_NONE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
index 1f14755..c4b602b 100644 (file)
@@ -27,7 +27,7 @@
 #include <glib-object.h>
 #include <gst/gst.h>
 
-#include <gst/controller/gstcontrolsource.h>
+#include <gst/controller/gsttimedvaluecontrolsource.h>
 
 G_BEGIN_DECLS
 
@@ -44,31 +44,26 @@ G_BEGIN_DECLS
 #define GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS(inst) \
   (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass))
 
+#define GST_TYPE_INTERPOLATION_MODE (gst_interpolation_mode_get_type ())
+
 typedef struct _GstInterpolationControlSource GstInterpolationControlSource;
 typedef struct _GstInterpolationControlSourceClass GstInterpolationControlSourceClass;
 typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSourcePrivate;
 
 /**
- * GstInterpolateMode:
- * @GST_INTERPOLATE_NONE: steps-like interpolation, default
- * @GST_INTERPOLATE_TRIGGER: returns the default value of the property,
- * except for times with specific values
- * @GST_INTERPOLATE_LINEAR: linear interpolation
- * @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
- * @GST_INTERPOLATE_CUBIC: cubic interpolation
- * @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
+ * GstInterpolationMode:
+ * @GST_INTERPOLATION_MODE_NONE: steps-like interpolation, default
+ * @GST_INTERPOLATION_MODE_LINEAR: linear interpolation
+ * @GST_INTERPOLATION_MODE_CUBIC: cubic interpolation
  *
  * The various interpolation modes available.
  */
 typedef enum
 {
-  GST_INTERPOLATE_NONE,
-  GST_INTERPOLATE_TRIGGER,
-  GST_INTERPOLATE_LINEAR,
-  GST_INTERPOLATE_QUADRATIC,
-  GST_INTERPOLATE_CUBIC,
-  GST_INTERPOLATE_USER
-} GstInterpolateMode;
+  GST_INTERPOLATION_MODE_NONE,
+  GST_INTERPOLATION_MODE_LINEAR,
+  GST_INTERPOLATION_MODE_CUBIC
+} GstInterpolationMode;
 
 /**
  * GstInterpolationControlSource:
@@ -76,33 +71,27 @@ typedef enum
  * The instance structure of #GstControlSource.
  */
 struct _GstInterpolationControlSource {
-  GstControlSource parent;
+  GstTimedValueControlSource parent;
 
-  /* <private> */
-  GMutex *lock;
+  /*< private >*/
   GstInterpolationControlSourcePrivate *priv;
   gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstInterpolationControlSourceClass {
-  GstControlSourceClass parent_class;
-  
+  GstTimedValueControlSourceClass parent_class;
+
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
 
 GType gst_interpolation_control_source_get_type (void);
+GType gst_interpolation_mode_get_type (void);
 
 /* Functions */
 
-GstInterpolationControlSource *gst_interpolation_control_source_new (void);
-gboolean gst_interpolation_control_source_set_interpolation_mode (GstInterpolationControlSource *self, GstInterpolateMode mode);
-gboolean gst_interpolation_control_source_set (GstInterpolationControlSource * self, GstClockTime timestamp, const GValue * value);
-gboolean gst_interpolation_control_source_set_from_list (GstInterpolationControlSource * self, const GSList * timedvalues);
-gboolean gst_interpolation_control_source_unset (GstInterpolationControlSource * self, GstClockTime timestamp);
-void gst_interpolation_control_source_unset_all (GstInterpolationControlSource *self);
-GList *gst_interpolation_control_source_get_all (GstInterpolationControlSource * self);
-gint gst_interpolation_control_source_get_count (GstInterpolationControlSource * self);
+GstInterpolationControlSource *
+                gst_interpolation_control_source_new            (void);
 
 G_END_DECLS
 
diff --git a/libs/gst/controller/gstinterpolationcontrolsourceprivate.h b/libs/gst/controller/gstinterpolationcontrolsourceprivate.h
deleted file mode 100644 (file)
index 1058d1b..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * gstinterpolationcontrolsourceprivate.h: Private declarations for the
- *                                         GstInterpolationControlSource
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__
-#define __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__
-
-/**
- * GstInterpolateMethod:
- *
- * Function pointer structure to do user-defined interpolation methods
- */
-typedef struct _GstInterpolateMethod
-{
-  GstControlSourceGetValue get_int;
-  GstControlSourceGetValueArray get_int_value_array;
-  GstControlSourceGetValue get_uint;
-  GstControlSourceGetValueArray get_uint_value_array;
-  GstControlSourceGetValue get_long;
-  GstControlSourceGetValueArray get_long_value_array;
-  GstControlSourceGetValue get_ulong;
-  GstControlSourceGetValueArray get_ulong_value_array;
-  GstControlSourceGetValue get_int64;
-  GstControlSourceGetValueArray get_int64_value_array;
-  GstControlSourceGetValue get_uint64;
-  GstControlSourceGetValueArray get_uint64_value_array;
-  GstControlSourceGetValue get_float;
-  GstControlSourceGetValueArray get_float_value_array;
-  GstControlSourceGetValue get_double;
-  GstControlSourceGetValueArray get_double_value_array;
-  GstControlSourceGetValue get_boolean;
-  GstControlSourceGetValueArray get_boolean_value_array;
-  GstControlSourceGetValue get_enum;
-  GstControlSourceGetValueArray get_enum_value_array;
-  GstControlSourceGetValue get_string;
-  GstControlSourceGetValueArray get_string_value_array;
-} GstInterpolateMethod;
-
-/**
- * GstControlPoint:
- *
- * a internal structure for value+time and various temporary
- * values used for interpolation. This "inherits" from
- * GstTimedValue.
- */
-typedef struct _GstControlPoint
-{
-  /* fields from GstTimedValue. DO NOT CHANGE! */
-  GstClockTime timestamp;       /* timestamp of the value change */
-  GValue value;                 /* the new value */
-
-  /* internal fields */
-
-  /* Caches for the interpolators */
-  union {
-    struct {
-      gdouble h;
-      gdouble z;
-    } cubic;
-  } cache;
-
-} GstControlPoint;
-
-struct _GstInterpolationControlSourcePrivate
-{
-  GType type;                   /* type of the handled property */
-  GType base;                   /* base-type of the handled property */
-
-  GValue default_value;         /* default value for the handled property */
-  GValue minimum_value;         /* min value for the handled property */
-  GValue maximum_value;         /* max value for the handled property */
-  GstInterpolateMode interpolation_mode;
-  
-  GSequence *values;            /* List of GstControlPoint */
-  gint nvalues;                 /* Number of control points */
-  gboolean valid_cache;
-};
-
-extern GstInterpolateMethod *priv_gst_interpolation_methods[];
-extern guint priv_gst_num_interpolation_methods;
-
-#endif /* __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__ */
-
index f462fdd..24f5307 100644 (file)
 
 #include <glib-object.h>
 #include <gst/gst.h>
+#include <gst/gstcontrolsource.h>
 
-#include "gstcontrolsource.h"
 #include "gstlfocontrolsource.h"
-#include "gstlfocontrolsourceprivate.h"
 
 #include "gst/glib-compat-private.h"
 
 #include <gst/math-compat.h>
 
-#define EMPTY(x) (x)
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+struct _GstLFOControlSourcePrivate
+{
+  GstLFOWaveform waveform;
+  gdouble frequency;
+  GstClockTime period;
+  GstClockTime timeshift;
+  gdouble amplitude;
+  gdouble offset;
+};
 
 /* FIXME: as % in C is not the modulo operator we need here for
  * negative numbers implement our own. Are there better ways? */
@@ -63,509 +73,290 @@ _calculate_pos (GstClockTime timestamp, GstClockTime timeshift,
   return timestamp % period;
 }
 
-#define DEFINE_SINE(type,round,convert) \
-static inline g##type \
-_sine_get_##type (GstLFOControlSource *self, g##type max, g##type min, gdouble amp, gdouble off, GstClockTime timeshift, GstClockTime period, gdouble frequency, GstClockTime timestamp) \
-{ \
-  gdouble ret; \
-  GstClockTime pos = _calculate_pos (timestamp, timeshift, period); \
-  \
-  ret = sin (2.0 * M_PI * (frequency / GST_SECOND) * gst_guint64_to_gdouble (pos)); \
-  ret *= amp; \
-  ret += off; \
-  \
-  if (round) \
-    ret += 0.5; \
-  \
-  return (g##type) CLAMP (ret, convert (min), convert (max)); \
-} \
-\
-static gboolean \
-waveform_sine_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
-    GValue *value) \
-{ \
-  g##type ret, max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  ret = _sine_get_##type (self, max, min, amp, off, timeshift, period, frequency, timestamp); \
-  g_value_set_##type (value, ret); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-waveform_sine_get_##type##_value_array (GstLFOControlSource *self, \
-   GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
-  g##type max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    *values = _sine_get_##type (self, max, min, amp, off, timeshift, period, frequency, ts); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
+static inline gdouble
+_sine_get (GstLFOControlSource * self, gdouble amp, gdouble off,
+    GstClockTime timeshift, GstClockTime period, gdouble frequency,
+    GstClockTime timestamp)
+{
+  gdouble pos =
+      gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
+  gdouble ret;
+
+  ret = sin (2.0 * M_PI * (frequency / GST_SECOND) * pos);
+  ret *= amp;
+  ret += off;
+
+  return ret;
 }
 
-DEFINE_SINE (int, TRUE, EMPTY);
-DEFINE_SINE (uint, TRUE, EMPTY);
-DEFINE_SINE (long, TRUE, EMPTY);
-DEFINE_SINE (ulong, TRUE, EMPTY);
-DEFINE_SINE (int64, TRUE, EMPTY);
-DEFINE_SINE (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_SINE (float, FALSE, EMPTY);
-DEFINE_SINE (double, FALSE, EMPTY);
-
-static GstWaveformImplementation waveform_sine = {
-  (GstControlSourceGetValue) waveform_sine_get_int,
-  (GstControlSourceGetValueArray) waveform_sine_get_int_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_uint,
-  (GstControlSourceGetValueArray) waveform_sine_get_uint_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_long,
-  (GstControlSourceGetValueArray) waveform_sine_get_long_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_ulong,
-  (GstControlSourceGetValueArray) waveform_sine_get_ulong_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_int64,
-  (GstControlSourceGetValueArray) waveform_sine_get_int64_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_uint64,
-  (GstControlSourceGetValueArray) waveform_sine_get_uint64_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_float,
-  (GstControlSourceGetValueArray) waveform_sine_get_float_value_array,
-  (GstControlSourceGetValue) waveform_sine_get_double,
-  (GstControlSourceGetValueArray) waveform_sine_get_double_value_array
-};
+static gboolean
+waveform_sine_get (GstLFOControlSource * self, GstClockTime timestamp,
+    gdouble * value)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+
+  gst_object_sync_values (GST_OBJECT (self), timestamp);
+  g_mutex_lock (&self->lock);
+  *value = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift,
+      priv->period, priv->frequency, timestamp);
+  g_mutex_unlock (&self->lock);
+  return TRUE;
+}
 
-#define DEFINE_SQUARE(type,round, convert) \
-\
-static inline g##type \
-_square_get_##type (GstLFOControlSource *self, g##type max, g##type min, gdouble amp, gdouble off, GstClockTime timeshift, GstClockTime period, gdouble frequency, GstClockTime timestamp) \
-{ \
-  GstClockTime pos = _calculate_pos (timestamp, timeshift, period); \
-  gdouble ret; \
-  \
-  if (pos >= period / 2) \
-    ret = amp; \
-  else \
-    ret = - amp; \
-  \
-  ret += off; \
-  \
-  if (round) \
-    ret += 0.5; \
-  \
-  return (g##type) CLAMP (ret, convert (min), convert (max)); \
-} \
-\
-static gboolean \
-waveform_square_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
-    GValue *value) \
-{ \
-  g##type ret, max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  ret = _square_get_##type (self, max, min, amp, off, timeshift, period, frequency, timestamp); \
-  g_value_set_##type (value, ret); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-waveform_square_get_##type##_value_array (GstLFOControlSource *self, \
-   GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
-  g##type max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    *values = _square_get_##type (self, max, min, amp, off, timeshift, period, frequency, ts); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
+static gboolean
+waveform_sine_get_value_array (GstLFOControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+  guint i;
+  GstClockTime ts = timestamp;
+
+  for (i = 0; i < n_values; i++) {
+    gst_object_sync_values (GST_OBJECT (self), ts);
+    g_mutex_lock (&self->lock);
+    *values = _sine_get (self, priv->amplitude, priv->offset, priv->timeshift,
+        priv->period, priv->frequency, ts);
+    g_mutex_unlock (&self->lock);
+    ts += interval;
+    values++;
+  }
+  return TRUE;
 }
 
-DEFINE_SQUARE (int, TRUE, EMPTY);
-DEFINE_SQUARE (uint, TRUE, EMPTY);
-DEFINE_SQUARE (long, TRUE, EMPTY);
-DEFINE_SQUARE (ulong, TRUE, EMPTY);
-DEFINE_SQUARE (int64, TRUE, EMPTY);
-DEFINE_SQUARE (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_SQUARE (float, FALSE, EMPTY);
-DEFINE_SQUARE (double, FALSE, EMPTY);
-
-static GstWaveformImplementation waveform_square = {
-  (GstControlSourceGetValue) waveform_square_get_int,
-  (GstControlSourceGetValueArray) waveform_square_get_int_value_array,
-  (GstControlSourceGetValue) waveform_square_get_uint,
-  (GstControlSourceGetValueArray) waveform_square_get_uint_value_array,
-  (GstControlSourceGetValue) waveform_square_get_long,
-  (GstControlSourceGetValueArray) waveform_square_get_long_value_array,
-  (GstControlSourceGetValue) waveform_square_get_ulong,
-  (GstControlSourceGetValueArray) waveform_square_get_ulong_value_array,
-  (GstControlSourceGetValue) waveform_square_get_int64,
-  (GstControlSourceGetValueArray) waveform_square_get_int64_value_array,
-  (GstControlSourceGetValue) waveform_square_get_uint64,
-  (GstControlSourceGetValueArray) waveform_square_get_uint64_value_array,
-  (GstControlSourceGetValue) waveform_square_get_float,
-  (GstControlSourceGetValueArray) waveform_square_get_float_value_array,
-  (GstControlSourceGetValue) waveform_square_get_double,
-  (GstControlSourceGetValueArray) waveform_square_get_double_value_array
-};
 
-#define DEFINE_SAW(type,round,convert) \
-\
-static inline g##type \
-_saw_get_##type (GstLFOControlSource *self, g##type max, g##type min, gdouble amp, gdouble off, GstClockTime timeshift, GstClockTime period, gdouble frequency, GstClockTime timestamp) \
-{ \
-  GstClockTime pos = _calculate_pos (timestamp, timeshift, period); \
-  gdouble ret; \
-  \
-  ret = - ((gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_guint64_to_gdouble (period)));\
-  \
-  ret += off; \
-  \
-  if (round) \
-    ret += 0.5; \
-  \
-  return (g##type) CLAMP (ret, convert (min), convert (max)); \
-} \
-\
-static gboolean \
-waveform_saw_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
-    GValue *value) \
-{ \
-  g##type ret, max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  ret = _saw_get_##type (self, max, min, amp, off, timeshift, period, frequency, timestamp); \
-  g_value_set_##type (value, ret); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-waveform_saw_get_##type##_value_array (GstLFOControlSource *self, \
-   GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
-  g##type max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    *values = _saw_get_##type (self, max, min, amp, off, timeshift, period, frequency, ts); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
+static inline gdouble
+_square_get (GstLFOControlSource * self, gdouble amp, gdouble off,
+    GstClockTime timeshift, GstClockTime period, gdouble frequency,
+    GstClockTime timestamp)
+{
+  GstClockTime pos = _calculate_pos (timestamp, timeshift, period);
+  gdouble ret;
+
+  if (pos >= period / 2)
+    ret = amp;
+  else
+    ret = -amp;
+  ret += off;
+
+  return ret;
 }
 
-DEFINE_SAW (int, TRUE, EMPTY);
-DEFINE_SAW (uint, TRUE, EMPTY);
-DEFINE_SAW (long, TRUE, EMPTY);
-DEFINE_SAW (ulong, TRUE, EMPTY);
-DEFINE_SAW (int64, TRUE, EMPTY);
-DEFINE_SAW (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_SAW (float, FALSE, EMPTY);
-DEFINE_SAW (double, FALSE, EMPTY);
-
-static GstWaveformImplementation waveform_saw = {
-  (GstControlSourceGetValue) waveform_saw_get_int,
-  (GstControlSourceGetValueArray) waveform_saw_get_int_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_uint,
-  (GstControlSourceGetValueArray) waveform_saw_get_uint_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_long,
-  (GstControlSourceGetValueArray) waveform_saw_get_long_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_ulong,
-  (GstControlSourceGetValueArray) waveform_saw_get_ulong_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_int64,
-  (GstControlSourceGetValueArray) waveform_saw_get_int64_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_uint64,
-  (GstControlSourceGetValueArray) waveform_saw_get_uint64_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_float,
-  (GstControlSourceGetValueArray) waveform_saw_get_float_value_array,
-  (GstControlSourceGetValue) waveform_saw_get_double,
-  (GstControlSourceGetValueArray) waveform_saw_get_double_value_array
-};
+static gboolean
+waveform_square_get (GstLFOControlSource * self, GstClockTime timestamp,
+    gdouble * value)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+
+  gst_object_sync_values (GST_OBJECT (self), timestamp);
+  g_mutex_lock (&self->lock);
+  *value = _square_get (self, priv->amplitude, priv->offset, priv->timeshift,
+      priv->period, priv->frequency, timestamp);
+  g_mutex_unlock (&self->lock);
+  return TRUE;
+}
 
-#define DEFINE_RSAW(type,round,convert) \
-\
-static inline g##type \
-_rsaw_get_##type (GstLFOControlSource *self, g##type max, g##type min, gdouble amp, gdouble off, GstClockTime timeshift, GstClockTime period, gdouble frequency, GstClockTime timestamp) \
-{ \
-  GstClockTime pos = _calculate_pos (timestamp, timeshift, period); \
-  gdouble ret; \
-  \
-  ret = ((gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((2.0 * amp) / gst_guint64_to_gdouble (period)));\
-  \
-  ret += off; \
-  \
-  if (round) \
-    ret += 0.5; \
-  \
-  return (g##type) CLAMP (ret, convert (min), convert (max)); \
-} \
-\
-static gboolean \
-waveform_rsaw_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
-    GValue *value) \
-{ \
-  g##type ret, max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  ret = _rsaw_get_##type (self, max, min, amp, off, timeshift, period, frequency, timestamp); \
-  g_value_set_##type (value, ret); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-waveform_rsaw_get_##type##_value_array (GstLFOControlSource *self, \
-   GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
-  g##type max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    *values = _rsaw_get_##type (self, max, min, amp, off, timeshift, period, frequency, ts); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
+static gboolean
+waveform_square_get_value_array (GstLFOControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+  guint i;
+  GstClockTime ts = timestamp;
+
+  for (i = 0; i < n_values; i++) {
+    gst_object_sync_values (GST_OBJECT (self), ts);
+    g_mutex_lock (&self->lock);
+    *values = _square_get (self, priv->amplitude, priv->offset, priv->timeshift,
+        priv->period, priv->frequency, ts);
+    g_mutex_unlock (&self->lock);
+    ts += interval;
+    values++;
+  }
+  return TRUE;
 }
 
-DEFINE_RSAW (int, TRUE, EMPTY);
-DEFINE_RSAW (uint, TRUE, EMPTY);
-DEFINE_RSAW (long, TRUE, EMPTY);
-DEFINE_RSAW (ulong, TRUE, EMPTY);
-DEFINE_RSAW (int64, TRUE, EMPTY);
-DEFINE_RSAW (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_RSAW (float, FALSE, EMPTY);
-DEFINE_RSAW (double, FALSE, EMPTY);
-
-static GstWaveformImplementation waveform_rsaw = {
-  (GstControlSourceGetValue) waveform_rsaw_get_int,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_int_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_uint,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_uint_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_long,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_long_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_ulong,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_ulong_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_int64,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_int64_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_uint64,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_uint64_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_float,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_float_value_array,
-  (GstControlSourceGetValue) waveform_rsaw_get_double,
-  (GstControlSourceGetValueArray) waveform_rsaw_get_double_value_array
-};
+static inline gdouble
+_saw_get (GstLFOControlSource * self, gdouble amp, gdouble off,
+    GstClockTime timeshift, GstClockTime period, gdouble frequency,
+    GstClockTime timestamp)
+{
+  gdouble pos =
+      gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
+  gdouble per = gst_guint64_to_gdouble (period);
+  gdouble ret;
 
-#define DEFINE_TRIANGLE(type,round,convert) \
-\
-static inline g##type \
-_triangle_get_##type (GstLFOControlSource *self, g##type max, g##type min, gdouble amp, gdouble off, GstClockTime timeshift, GstClockTime period, gdouble frequency, GstClockTime timestamp) \
-{ \
-  GstClockTime pos = _calculate_pos (timestamp, timeshift, period); \
-  gdouble ret; \
-  \
-  if (gst_guint64_to_gdouble (pos) <= gst_guint64_to_gdouble (period) / 4.0) \
-    ret = gst_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
-  else if (gst_guint64_to_gdouble (pos) <= (3.0 * gst_guint64_to_gdouble (period)) / 4.0) \
-    ret = -(gst_guint64_to_gdouble (pos) - gst_guint64_to_gdouble (period) / 2.0) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
-  else \
-    ret = gst_guint64_to_gdouble (period) - gst_guint64_to_gdouble (pos) * ((4.0 * amp) / gst_guint64_to_gdouble (period)); \
-  \
-  ret += off; \
-  \
-  if (round) \
-    ret += 0.5; \
-  \
-  return (g##type) CLAMP (ret, convert (min), convert (max)); \
-} \
-\
-static gboolean \
-waveform_triangle_get_##type (GstLFOControlSource *self, GstClockTime timestamp, \
-    GValue *value) \
-{ \
-  g##type ret, max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  ret = _triangle_get_##type (self, max, min, amp, off, timeshift, period, frequency, timestamp); \
-  g_value_set_##type (value, ret); \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
-} \
-\
-static gboolean \
-waveform_triangle_get_##type##_value_array (GstLFOControlSource *self, \
-   GstClockTime timestamp, GstValueArray * value_array) \
-{ \
-  gint i; \
-  GstClockTime ts = timestamp; \
-  g##type *values = (g##type *) value_array->values; \
-  g##type max, min; \
-  gdouble amp, off, frequency; \
-  GstClockTime timeshift, period; \
-  \
-  g_mutex_lock (self->lock); \
-  max = g_value_get_##type (&self->priv->maximum_value); \
-  min = g_value_get_##type (&self->priv->minimum_value); \
-  amp = convert (g_value_get_##type (&self->priv->amplitude)); \
-  off = convert (g_value_get_##type (&self->priv->offset)); \
-  timeshift = self->priv->timeshift; \
-  period = self->priv->period; \
-  frequency = self->priv->frequency; \
-  \
-  for(i = 0; i < value_array->nbsamples; i++) { \
-    *values = _triangle_get_##type (self, max, min, amp, off, timeshift, period, frequency, ts); \
-    ts += value_array->sample_interval; \
-    values++; \
-  } \
-  g_mutex_unlock (self->lock); \
-  return TRUE; \
+  ret = -((pos - per / 2.0) * ((2.0 * amp) / per));
+  ret += off;
+
+  return ret;
 }
 
-DEFINE_TRIANGLE (int, TRUE, EMPTY);
-DEFINE_TRIANGLE (uint, TRUE, EMPTY);
-DEFINE_TRIANGLE (long, TRUE, EMPTY);
-DEFINE_TRIANGLE (ulong, TRUE, EMPTY);
-DEFINE_TRIANGLE (int64, TRUE, EMPTY);
-DEFINE_TRIANGLE (uint64, TRUE, gst_guint64_to_gdouble);
-DEFINE_TRIANGLE (float, FALSE, EMPTY);
-DEFINE_TRIANGLE (double, FALSE, EMPTY);
-
-static GstWaveformImplementation waveform_triangle = {
-  (GstControlSourceGetValue) waveform_triangle_get_int,
-  (GstControlSourceGetValueArray) waveform_triangle_get_int_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_uint,
-  (GstControlSourceGetValueArray) waveform_triangle_get_uint_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_long,
-  (GstControlSourceGetValueArray) waveform_triangle_get_long_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_ulong,
-  (GstControlSourceGetValueArray) waveform_triangle_get_ulong_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_int64,
-  (GstControlSourceGetValueArray) waveform_triangle_get_int64_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_uint64,
-  (GstControlSourceGetValueArray) waveform_triangle_get_uint64_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_float,
-  (GstControlSourceGetValueArray) waveform_triangle_get_float_value_array,
-  (GstControlSourceGetValue) waveform_triangle_get_double,
-  (GstControlSourceGetValueArray) waveform_triangle_get_double_value_array
-};
+static gboolean
+waveform_saw_get (GstLFOControlSource * self, GstClockTime timestamp,
+    gdouble * value)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+
+  gst_object_sync_values (GST_OBJECT (self), timestamp);
+  g_mutex_lock (&self->lock);
+  *value = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift,
+      priv->period, priv->frequency, timestamp);
+  g_mutex_unlock (&self->lock);
+  return TRUE;
+}
+
+static gboolean
+waveform_saw_get_value_array (GstLFOControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+  guint i;
+  GstClockTime ts = timestamp;
+
+  for (i = 0; i < n_values; i++) {
+    gst_object_sync_values (GST_OBJECT (self), ts);
+    g_mutex_lock (&self->lock);
+    *values = _saw_get (self, priv->amplitude, priv->offset, priv->timeshift,
+        priv->period, priv->frequency, ts);
+    g_mutex_unlock (&self->lock);
+    ts += interval;
+    values++;
+  }
+  return TRUE;
+}
+
+static inline gdouble
+_rsaw_get (GstLFOControlSource * self, gdouble amp, gdouble off,
+    GstClockTime timeshift, GstClockTime period, gdouble frequency,
+    GstClockTime timestamp)
+{
+  gdouble pos =
+      gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
+  gdouble per = gst_guint64_to_gdouble (period);
+  gdouble ret;
+
+  ret = (pos - per / 2.0) * ((2.0 * amp) / per);
+  ret += off;
+
+  return ret;
+}
+
+static gboolean
+waveform_rsaw_get (GstLFOControlSource * self, GstClockTime timestamp,
+    gdouble * value)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+
+  gst_object_sync_values (GST_OBJECT (self), timestamp);
+  g_mutex_lock (&self->lock);
+  *value = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift,
+      priv->period, priv->frequency, timestamp);
+  g_mutex_unlock (&self->lock);
+  return TRUE;
+}
+
+static gboolean
+waveform_rsaw_get_value_array (GstLFOControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+  guint i;
+  GstClockTime ts = timestamp;
+
+  for (i = 0; i < n_values; i++) {
+    gst_object_sync_values (GST_OBJECT (self), ts);
+    g_mutex_lock (&self->lock);
+    *values = _rsaw_get (self, priv->amplitude, priv->offset, priv->timeshift,
+        priv->period, priv->frequency, ts);
+    g_mutex_unlock (&self->lock);
+    ts += interval;
+    values++;
+  }
+  return TRUE;
+}
+
+
+static inline gdouble
+_triangle_get (GstLFOControlSource * self, gdouble amp, gdouble off,
+    GstClockTime timeshift, GstClockTime period, gdouble frequency,
+    GstClockTime timestamp)
+{
+  gdouble pos =
+      gst_guint64_to_gdouble (_calculate_pos (timestamp, timeshift, period));
+  gdouble per = gst_guint64_to_gdouble (period);
+  gdouble ret;
+
+  if (pos <= 0.25 * per)
+    /* 1st quarter */
+    ret = pos * ((4.0 * amp) / per);
+  else if (pos <= 0.75 * per)
+    /* 2nd & 3rd quarter */
+    ret = -(pos - per / 2.0) * ((4.0 * amp) / per);
+  else
+    /* 4th quarter */
+    ret = -(per - pos) * ((4.0 * amp) / per);
+
+  ret += off;
+
+  return ret;
+}
+
+static gboolean
+waveform_triangle_get (GstLFOControlSource * self, GstClockTime timestamp,
+    gdouble * value)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+
+  gst_object_sync_values (GST_OBJECT (self), timestamp);
+  g_mutex_lock (&self->lock);
+  *value = _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift,
+      priv->period, priv->frequency, timestamp);
+  g_mutex_unlock (&self->lock);
+  return TRUE;
+}
 
-static GstWaveformImplementation *waveforms[] = {
-  &waveform_sine,
-  &waveform_square,
-  &waveform_saw,
-  &waveform_rsaw,
-  &waveform_triangle
+static gboolean
+waveform_triangle_get_value_array (GstLFOControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  GstLFOControlSourcePrivate *priv = self->priv;
+  guint i;
+  GstClockTime ts = timestamp;
+
+  for (i = 0; i < n_values; i++) {
+    gst_object_sync_values (GST_OBJECT (self), ts);
+    g_mutex_lock (&self->lock);
+    *values =
+        _triangle_get (self, priv->amplitude, priv->offset, priv->timeshift,
+        priv->period, priv->frequency, ts);
+    g_mutex_unlock (&self->lock);
+    ts += interval;
+    values++;
+  }
+  return TRUE;
+}
+
+static struct
+{
+  GstControlSourceGetValue get;
+  GstControlSourceGetValueArray get_value_array;
+} waveforms[] = {
+  {
+  (GstControlSourceGetValue) waveform_sine_get,
+        (GstControlSourceGetValueArray) waveform_sine_get_value_array}, {
+  (GstControlSourceGetValue) waveform_square_get,
+        (GstControlSourceGetValueArray) waveform_square_get_value_array}, {
+  (GstControlSourceGetValue) waveform_saw_get,
+        (GstControlSourceGetValueArray) waveform_saw_get_value_array}, {
+  (GstControlSourceGetValue) waveform_rsaw_get,
+        (GstControlSourceGetValueArray) waveform_rsaw_get_value_array}, {
+  (GstControlSourceGetValue) waveform_triangle_get,
+        (GstControlSourceGetValueArray) waveform_triangle_get_value_array}
 };
 
 static const guint num_waveforms = G_N_ELEMENTS (waveforms);
@@ -605,8 +396,11 @@ gst_lfo_waveform_get_type (void)
   return (GType) gtype;
 }
 
-G_DEFINE_TYPE (GstLFOControlSource, gst_lfo_control_source,
-    GST_TYPE_CONTROL_SOURCE);
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "lfo control source", 0, "low frequency oscillator control source")
+
+G_DEFINE_TYPE_WITH_CODE (GstLFOControlSource, gst_lfo_control_source,
+    GST_TYPE_CONTROL_SOURCE, _do_init);
 
 static void
 gst_lfo_control_source_reset (GstLFOControlSource * self)
@@ -615,18 +409,6 @@ gst_lfo_control_source_reset (GstLFOControlSource * self)
 
   csource->get_value = NULL;
   csource->get_value_array = NULL;
-
-  self->priv->type = self->priv->base = G_TYPE_INVALID;
-
-  if (G_IS_VALUE (&self->priv->minimum_value))
-    g_value_unset (&self->priv->minimum_value);
-  if (G_IS_VALUE (&self->priv->maximum_value))
-    g_value_unset (&self->priv->maximum_value);
-
-  if (G_IS_VALUE (&self->priv->amplitude))
-    g_value_unset (&self->priv->amplitude);
-  if (G_IS_VALUE (&self->priv->offset))
-    g_value_unset (&self->priv->offset);
 }
 
 /**
@@ -647,282 +429,18 @@ gst_lfo_control_source_set_waveform (GstLFOControlSource * self,
     GstLFOWaveform waveform)
 {
   GstControlSource *csource = GST_CONTROL_SOURCE (self);
-  gboolean ret = TRUE;
 
   if (waveform >= num_waveforms || (int) waveform < 0) {
     GST_WARNING ("waveform %d invalid or not implemented yet", waveform);
     return FALSE;
   }
 
-  if (self->priv->base == G_TYPE_INVALID) {
-    GST_WARNING ("not bound to a property yet");
-    return FALSE;
-  }
-
-  switch (self->priv->base) {
-    case G_TYPE_INT:
-      csource->get_value = waveforms[waveform]->get_int;
-      csource->get_value_array = waveforms[waveform]->get_int_value_array;
-      break;
-    case G_TYPE_UINT:{
-      csource->get_value = waveforms[waveform]->get_uint;
-      csource->get_value_array = waveforms[waveform]->get_uint_value_array;
-      break;
-    }
-    case G_TYPE_LONG:{
-      csource->get_value = waveforms[waveform]->get_long;
-      csource->get_value_array = waveforms[waveform]->get_long_value_array;
-      break;
-    }
-    case G_TYPE_ULONG:{
-      csource->get_value = waveforms[waveform]->get_ulong;
-      csource->get_value_array = waveforms[waveform]->get_ulong_value_array;
-      break;
-    }
-    case G_TYPE_INT64:{
-      csource->get_value = waveforms[waveform]->get_int64;
-      csource->get_value_array = waveforms[waveform]->get_int64_value_array;
-      break;
-    }
-    case G_TYPE_UINT64:{
-      csource->get_value = waveforms[waveform]->get_uint64;
-      csource->get_value_array = waveforms[waveform]->get_uint64_value_array;
-      break;
-    }
-    case G_TYPE_FLOAT:{
-      csource->get_value = waveforms[waveform]->get_float;
-      csource->get_value_array = waveforms[waveform]->get_float_value_array;
-      break;
-    }
-    case G_TYPE_DOUBLE:{
-      csource->get_value = waveforms[waveform]->get_double;
-      csource->get_value_array = waveforms[waveform]->get_double_value_array;
-      break;
-    }
-    default:
-      ret = FALSE;
-      break;
-  }
+  csource->get_value = waveforms[waveform].get;
+  csource->get_value_array = waveforms[waveform].get_value_array;
 
-  if (ret)
-    self->priv->waveform = waveform;
-  else
-    GST_WARNING ("incomplete implementation for type '%s'",
-        GST_STR_NULL (g_type_name (self->priv->type)));
+  self->priv->waveform = waveform;
 
-  return ret;
-}
-
-static gboolean
-gst_lfo_control_source_bind (GstControlSource * source, GParamSpec * pspec)
-{
-  GType type, base;
-  GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (source);
-  gboolean ret = TRUE;
-
-  /* get the fundamental base type */
-  self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-  while ((type = g_type_parent (type)))
-    base = type;
-
-  self->priv->base = base;
-  /* restore type */
-  type = self->priv->type;
-
-  switch (base) {
-    case G_TYPE_INT:{
-      GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
-
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_int (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_int (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_UINT:{
-      GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
-
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_uint (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_uint (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_LONG:{
-      GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_long (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_long (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_ULONG:{
-      GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_ulong (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_ulong (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_INT64:{
-      GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_int64 (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_int64 (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_UINT64:{
-      GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_uint64 (&self->priv->amplitude, 0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_uint64 (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_FLOAT:{
-      GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_float (&self->priv->amplitude, 0.0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_float (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    case G_TYPE_DOUBLE:{
-      GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
-
-      g_value_init (&self->priv->minimum_value, type);
-      g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
-      g_value_init (&self->priv->maximum_value, type);
-      g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
-      if (!G_IS_VALUE (&self->priv->amplitude)) {
-        g_value_init (&self->priv->amplitude, type);
-        g_value_set_double (&self->priv->amplitude, 0.0);
-      }
-
-      if (!G_IS_VALUE (&self->priv->offset)) {
-        g_value_init (&self->priv->offset, type);
-        g_value_set_double (&self->priv->offset, tpspec->default_value);
-      }
-      break;
-    }
-    default:
-      GST_WARNING ("incomplete implementation for paramspec type '%s'",
-          G_PARAM_SPEC_TYPE_NAME (pspec));
-      ret = FALSE;
-      break;
-  }
-
-  if (ret) {
-    GValue amp = { 0, }
-    , off = {
-    0,};
-
-    /* This should never fail unless the user already set amplitude or offset
-     * with an incompatible type before _bind () */
-    if (!g_value_type_transformable (G_VALUE_TYPE (&self->priv->amplitude),
-            base)
-        || !g_value_type_transformable (G_VALUE_TYPE (&self->priv->offset),
-            base)) {
-      GST_WARNING ("incompatible types for amplitude or offset");
-      gst_lfo_control_source_reset (self);
-      return FALSE;
-    }
-
-    /* Generate copies and transform to the correct type */
-    g_value_init (&amp, base);
-    g_value_transform (&self->priv->amplitude, &amp);
-    g_value_init (&off, base);
-    g_value_transform (&self->priv->offset, &off);
-
-    ret = gst_lfo_control_source_set_waveform (self, self->priv->waveform);
-
-    g_value_unset (&self->priv->amplitude);
-    g_value_init (&self->priv->amplitude, self->priv->base);
-    g_value_transform (&amp, &self->priv->amplitude);
-
-    g_value_unset (&self->priv->offset);
-    g_value_init (&self->priv->offset, self->priv->base);
-    g_value_transform (&off, &self->priv->offset);
-
-    g_value_unset (&amp);
-    g_value_unset (&off);
-  }
-
-  if (!ret)
-    gst_lfo_control_source_reset (self);
-
-  return ret;
+  return TRUE;
 }
 
 static void
@@ -931,12 +449,13 @@ gst_lfo_control_source_init (GstLFOControlSource * self)
   self->priv =
       G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_LFO_CONTROL_SOURCE,
       GstLFOControlSourcePrivate);
-  self->priv->waveform = GST_LFO_WAVEFORM_SINE;
+  self->priv->waveform = gst_lfo_control_source_set_waveform (self,
+      GST_LFO_WAVEFORM_SINE);
   self->priv->frequency = 1.0;
   self->priv->period = GST_SECOND / self->priv->frequency;
   self->priv->timeshift = 0;
 
-  self->lock = g_mutex_new ();
+  g_mutex_init (&self->lock);
 }
 
 static void
@@ -945,22 +464,12 @@ gst_lfo_control_source_finalize (GObject * obj)
   GstLFOControlSource *self = GST_LFO_CONTROL_SOURCE (obj);
 
   gst_lfo_control_source_reset (self);
-
-  if (self->lock) {
-    g_mutex_free (self->lock);
-    self->lock = NULL;
-  }
+  g_mutex_clear (&self->lock);
 
   G_OBJECT_CLASS (gst_lfo_control_source_parent_class)->finalize (obj);
 }
 
 static void
-gst_lfo_control_source_dispose (GObject * obj)
-{
-  G_OBJECT_CLASS (gst_lfo_control_source_parent_class)->dispose (obj);
-}
-
-static void
 gst_lfo_control_source_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -968,10 +477,10 @@ gst_lfo_control_source_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_WAVEFORM:
-      g_mutex_lock (self->lock);
+      g_mutex_lock (&self->lock);
       gst_lfo_control_source_set_waveform (self,
           (GstLFOWaveform) g_value_get_enum (value));
-      g_mutex_unlock (self->lock);
+      g_mutex_unlock (&self->lock);
       break;
     case PROP_FREQUENCY:{
       gdouble frequency = g_value_get_double (value);
@@ -979,69 +488,27 @@ gst_lfo_control_source_set_property (GObject * object, guint prop_id,
       g_return_if_fail (frequency > 0
           || ((GstClockTime) (GST_SECOND / frequency)) != 0);
 
-      g_mutex_lock (self->lock);
+      g_mutex_lock (&self->lock);
       self->priv->frequency = frequency;
       self->priv->period = GST_SECOND / frequency;
-      g_mutex_unlock (self->lock);
+      g_mutex_unlock (&self->lock);
       break;
     }
     case PROP_TIMESHIFT:
-      g_mutex_lock (self->lock);
+      g_mutex_lock (&self->lock);
       self->priv->timeshift = g_value_get_uint64 (value);
-      g_mutex_unlock (self->lock);
+      g_mutex_unlock (&self->lock);
       break;
-    case PROP_AMPLITUDE:{
-      GValue *val = g_value_get_boxed (value);
-
-      if (self->priv->type != G_TYPE_INVALID) {
-        g_return_if_fail (g_value_type_transformable (self->priv->type,
-                G_VALUE_TYPE (val)));
-
-        g_mutex_lock (self->lock);
-        if (G_IS_VALUE (&self->priv->amplitude))
-          g_value_unset (&self->priv->amplitude);
-
-        g_value_init (&self->priv->amplitude, self->priv->type);
-        g_value_transform (val, &self->priv->amplitude);
-        g_mutex_unlock (self->lock);
-      } else {
-        g_mutex_lock (self->lock);
-        if (G_IS_VALUE (&self->priv->amplitude))
-          g_value_unset (&self->priv->amplitude);
-
-        g_value_init (&self->priv->amplitude, G_VALUE_TYPE (val));
-        g_value_copy (val, &self->priv->amplitude);
-        g_mutex_unlock (self->lock);
-      }
-
+    case PROP_AMPLITUDE:
+      g_mutex_lock (&self->lock);
+      self->priv->amplitude = g_value_get_double (value);
+      g_mutex_unlock (&self->lock);
       break;
-    }
-    case PROP_OFFSET:{
-      GValue *val = g_value_get_boxed (value);
-
-      if (self->priv->type != G_TYPE_INVALID) {
-        g_return_if_fail (g_value_type_transformable (self->priv->type,
-                G_VALUE_TYPE (val)));
-
-        g_mutex_lock (self->lock);
-        if (G_IS_VALUE (&self->priv->offset))
-          g_value_unset (&self->priv->offset);
-
-        g_value_init (&self->priv->offset, self->priv->type);
-        g_value_transform (val, &self->priv->offset);
-        g_mutex_unlock (self->lock);
-      } else {
-        g_mutex_lock (self->lock);
-        if (G_IS_VALUE (&self->priv->offset))
-          g_value_unset (&self->priv->offset);
-
-        g_value_init (&self->priv->offset, G_VALUE_TYPE (val));
-        g_value_copy (val, &self->priv->offset);
-        g_mutex_unlock (self->lock);
-      }
-
+    case PROP_OFFSET:
+      g_mutex_lock (&self->lock);
+      self->priv->offset = g_value_get_double (value);
+      g_mutex_unlock (&self->lock);
       break;
-    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1065,10 +532,10 @@ gst_lfo_control_source_get_property (GObject * object, guint prop_id,
       g_value_set_uint64 (value, self->priv->timeshift);
       break;
     case PROP_AMPLITUDE:
-      g_value_set_boxed (value, &self->priv->amplitude);
+      g_value_set_double (value, self->priv->amplitude);
       break;
     case PROP_OFFSET:
-      g_value_set_boxed (value, &self->priv->offset);
+      g_value_set_double (value, self->priv->offset);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1080,23 +547,18 @@ static void
 gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GstLFOControlSourcePrivate));
 
   gobject_class->finalize = gst_lfo_control_source_finalize;
-  gobject_class->dispose = gst_lfo_control_source_dispose;
   gobject_class->set_property = gst_lfo_control_source_set_property;
   gobject_class->get_property = gst_lfo_control_source_get_property;
 
-  csource_class->bind = gst_lfo_control_source_bind;
-
   /**
    * GstLFOControlSource:waveform
    *
    * Specifies the waveform that should be used for this #GstLFOControlSource.
-   * 
-   **/
+   */
   g_object_class_install_property (gobject_class, PROP_WAVEFORM,
       g_param_spec_enum ("waveform", "Waveform", "Waveform",
           GST_TYPE_LFO_WAVEFORM, GST_LFO_WAVEFORM_SINE,
@@ -1108,12 +570,11 @@ gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass)
    * Specifies the frequency that should be used for the waveform
    * of this #GstLFOControlSource. It should be large enough
    * so that the period is longer than one nanosecond.
-   * 
-   **/
+   */
   g_object_class_install_property (gobject_class, PROP_FREQUENCY,
       g_param_spec_double ("frequency", "Frequency",
           "Frequency of the waveform", 0.0, G_MAXDOUBLE, 1.0,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:timeshift
@@ -1124,33 +585,29 @@ gst_lfo_control_source_class_init (GstLFOControlSourceClass * klass)
    * To get a n nanosecond shift to the left use
    * "(GST_SECOND / frequency) - n".
    *
-   **/
+   */
   g_object_class_install_property (gobject_class, PROP_TIMESHIFT,
       g_param_spec_uint64 ("timeshift", "Timeshift",
           "Timeshift of the waveform to the right", 0, G_MAXUINT64, 0,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:amplitude
    *
    * Specifies the amplitude for the waveform of this #GstLFOControlSource.
-   *
-   * It should be given as a #GValue with a type that can be transformed
-   * to the type of the bound property.
-   **/
+   */
   g_object_class_install_property (gobject_class, PROP_AMPLITUDE,
-      g_param_spec_boxed ("amplitude", "Amplitude", "Amplitude of the waveform",
-          G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+      g_param_spec_double ("amplitude", "Amplitude",
+          "Amplitude of the waveform", 0.0, 1.0, 1.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
   /**
    * GstLFOControlSource:offset
    *
-   * Specifies the offset for the waveform of this #GstLFOControlSource.
-   *
-   * It should be given as a #GValue with a type that can be transformed
-   * to the type of the bound property.
-   **/
+   * Specifies the value offset for the waveform of this #GstLFOControlSource.
+   */
   g_object_class_install_property (gobject_class, PROP_OFFSET,
-      g_param_spec_boxed ("offset", "Offset", "Offset of the waveform",
-          G_TYPE_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+      g_param_spec_double ("offset", "Offset", "Offset of the waveform",
+          0.0, 1.0, 1.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 }
index d61ad06..581e9d3 100644 (file)
@@ -27,8 +27,6 @@
 #include <glib-object.h>
 #include <gst/gst.h>
 
-#include <gst/controller/gstcontrolsource.h>
-
 G_BEGIN_DECLS
 
 #define GST_TYPE_LFO_CONTROL_SOURCE \
@@ -79,13 +77,13 @@ struct _GstLFOControlSource {
 
   /* <private> */
   GstLFOControlSourcePrivate *priv;
-  GMutex *lock;
+  GMutex lock;
   gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstLFOControlSourceClass {
   GstControlSourceClass parent_class;
-  
+
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
diff --git a/libs/gst/controller/gstlfocontrolsourceprivate.h b/libs/gst/controller/gstlfocontrolsourceprivate.h
deleted file mode 100644 (file)
index fddf357..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * gstlfocontrolsourceprivate.h: Private declarations for the
- *                                         GstLFOControlSource
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_LFO_CONTROL_SOURCE_PRIVATE_H__
-#define __GST_LFO_CONTROL_SOURCE_PRIVATE_H__
-
-typedef struct _GstWaveformImplementation
-{
-  GstControlSourceGetValue get_int;
-  GstControlSourceGetValueArray get_int_value_array;
-  GstControlSourceGetValue get_uint;
-  GstControlSourceGetValueArray get_uint_value_array;
-  GstControlSourceGetValue get_long;
-  GstControlSourceGetValueArray get_long_value_array;
-  GstControlSourceGetValue get_ulong;
-  GstControlSourceGetValueArray get_ulong_value_array;
-  GstControlSourceGetValue get_int64;
-  GstControlSourceGetValueArray get_int64_value_array;
-  GstControlSourceGetValue get_uint64;
-  GstControlSourceGetValueArray get_uint64_value_array;
-  GstControlSourceGetValue get_float;
-  GstControlSourceGetValueArray get_float_value_array;
-  GstControlSourceGetValue get_double;
-  GstControlSourceGetValueArray get_double_value_array;
-} GstWaveformImplementation;
-
-struct _GstLFOControlSourcePrivate
-{
-  GType type;                   /* type of the handled property */
-  GType base;                   /* base-type of the handled property */
-
-  GValue minimum_value;         /* min value for the handled property */
-  GValue maximum_value;         /* max value for the handled property */
-
-  GstLFOWaveform waveform;
-  gdouble frequency;
-  GstClockTime period;
-  GstClockTime timeshift;
-  GValue amplitude;
-  GValue offset; 
-};
-
-#endif /* __GST_LFO_CONTROL_SOURCE_PRIVATE_H__ */
-
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c
new file mode 100644 (file)
index 0000000..38723eb
--- /dev/null
@@ -0,0 +1,422 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *               2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttimedvaluecontrolsource.c: Base class for timeed value based control
+ *                               sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gsttimedvaluecontrolsource
+ * @short_description: timed value control source base class
+ *
+ * Base class for #GstContrlSources that use time-stamped values.
+ *
+ * When overriding bind, chain up first to give this bind implementation a
+ * chance to setup things.
+ *
+ * All functions are MT-safe.
+ *
+ */
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gstinterpolationcontrolsource.h"
+#include "gst/glib-compat-private.h"
+
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "timed value control source", 0, \
+    "timed value control source base class")
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource,
+    gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
+
+/*
+ * gst_control_point_free:
+ * @prop: the object to free
+ *
+ * Private method which frees all data allocated by a #GstControlPoint
+ * instance.
+ */
+static void
+gst_control_point_free (GstControlPoint * cp)
+{
+  g_return_if_fail (cp);
+
+  g_slice_free (GstControlPoint, cp);
+}
+
+static void
+gst_timed_value_control_source_reset (GstTimedValueControlSource * self)
+{
+  GstControlSource *csource = (GstControlSource *) self;
+
+  csource->get_value = NULL;
+  csource->get_value_array = NULL;
+
+  if (self->values) {
+    g_sequence_free (self->values);
+    self->values = NULL;
+  }
+
+  self->nvalues = 0;
+  self->valid_cache = FALSE;
+}
+
+/*
+ * gst_control_point_compare:
+ * @p1: a pointer to a #GstControlPoint
+ * @p2: a pointer to a #GstControlPoint
+ *
+ * Compare function for g_list operations that operates on two #GstControlPoint
+ * parameters.
+ */
+static gint
+gst_control_point_compare (gconstpointer p1, gconstpointer p2)
+{
+  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
+  GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
+
+  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
+}
+
+/*
+ * gst_control_point_find:
+ * @p1: a pointer to a #GstControlPoint
+ * @p2: a pointer to a #GstClockTime
+ *
+ * Compare function for g_list operations that operates on a #GstControlPoint and
+ * a #GstClockTime.
+ */
+static gint
+gst_control_point_find (gconstpointer p1, gconstpointer p2)
+{
+  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
+  GstClockTime ct2 = *(GstClockTime *) p2;
+
+  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
+}
+
+static GstControlPoint *
+_make_new_cp (GstTimedValueControlSource * self, GstClockTime timestamp,
+    const gdouble value)
+{
+  GstControlPoint *cp;
+
+  /* create a new GstControlPoint */
+  cp = g_slice_new0 (GstControlPoint);
+  cp->timestamp = timestamp;
+  cp->value = value;
+
+  return cp;
+}
+
+static void
+gst_timed_value_control_source_set_internal (GstTimedValueControlSource *
+    self, GstClockTime timestamp, const gdouble value)
+{
+  GSequenceIter *iter;
+
+  /* check if a control point for the timestamp already exists */
+
+  /* iter contains the iter right *after* timestamp */
+  if (G_LIKELY (self->values)) {
+    iter =
+        g_sequence_search (self->values, &timestamp,
+        (GCompareDataFunc) gst_control_point_find, NULL);
+    if (iter) {
+      GSequenceIter *prev = g_sequence_iter_prev (iter);
+      GstControlPoint *cp = g_sequence_get (prev);
+
+      /* If the timestamp is the same just update the control point value */
+      if (cp->timestamp == timestamp) {
+        /* update control point */
+        cp->value = value;
+        goto done;
+      }
+    }
+  } else {
+    self->values = g_sequence_new ((GDestroyNotify) gst_control_point_free);
+    GST_INFO ("create new timed value sequence");
+  }
+
+  /* sort new cp into the prop->values list */
+  g_sequence_insert_sorted (self->values, _make_new_cp (self, timestamp,
+          value), (GCompareDataFunc) gst_control_point_compare, NULL);
+  self->nvalues++;
+
+done:
+  self->valid_cache = FALSE;
+}
+
+/**
+ * gst_timed_value_control_source_find_control_point_iter:
+ * @self: the control source to search in
+ * @timestamp: the search key
+ *
+ * Find last value before given timestamp in control point list.
+ * If all values in the control point list come after the given
+ * timestamp or no values exist, %NULL is returned.
+ *
+ * For use in control source implementations.
+ *
+ * Returns: the found #GSequenceIter or %NULL
+ */
+GSequenceIter *gst_timed_value_control_source_find_control_point_iter
+    (GstTimedValueControlSource * self, GstClockTime timestamp)
+{
+  GSequenceIter *iter;
+
+  if (!self->values)
+    return NULL;
+
+  iter =
+      g_sequence_search (self->values, &timestamp,
+      (GCompareDataFunc) gst_control_point_find, NULL);
+
+  /* g_sequence_search() returns the iter where timestamp
+   * would be inserted, i.e. the iter > timestamp, so
+   * we need to get the previous one. And of course, if
+   * there is no previous one, we return NULL. */
+  if (g_sequence_iter_is_begin (iter))
+    return NULL;
+
+  return g_sequence_iter_prev (iter);
+}
+
+
+/**
+ * gst_timed_value_control_source_set:
+ * @self: the #GstTimedValueControlSource object
+ * @timestamp: the time the control-change is scheduled for
+ * @value: the control-value
+ *
+ * Set the value of given controller-handled property at a certain time.
+ *
+ * Returns: FALSE if the values couldn't be set, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_set (GstTimedValueControlSource * self,
+    GstClockTime timestamp, const gdouble value)
+{
+  g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+
+  g_mutex_lock (&self->lock);
+  gst_timed_value_control_source_set_internal (self, timestamp, value);
+  g_mutex_unlock (&self->lock);
+
+  return TRUE;
+}
+
+/**
+ * gst_timed_value_control_source_set_from_list:
+ * @self: the #GstTimedValueControlSource object
+ * @timedvalues: (transfer none) (element-type GstController.TimedValue): a list
+ * with #GstTimedValue items
+ *
+ * Sets multiple timed values at once.
+ *
+ * Returns: FALSE if the values couldn't be set, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_set_from_list (GstTimedValueControlSource *
+    self, const GSList * timedvalues)
+{
+  const GSList *node;
+  GstTimedValue *tv;
+  gboolean res = FALSE;
+
+  g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+
+  for (node = timedvalues; node; node = g_slist_next (node)) {
+    tv = node->data;
+    if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
+      GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
+          GST_FUNCTION);
+    } else {
+      g_mutex_lock (&self->lock);
+      gst_timed_value_control_source_set_internal (self, tv->timestamp,
+          tv->value);
+      g_mutex_unlock (&self->lock);
+      res = TRUE;
+    }
+  }
+  return res;
+}
+
+/**
+ * gst_timed_value_control_source_unset:
+ * @self: the #GstTimedValueControlSource object
+ * @timestamp: the time the control-change should be removed from
+ *
+ * Used to remove the value of given controller-handled property at a certain
+ * time.
+ *
+ * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
+    GstClockTime timestamp)
+{
+  GSequenceIter *iter;
+  gboolean res = FALSE;
+
+  g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+
+  g_mutex_lock (&self->lock);
+  /* check if a control point for the timestamp exists */
+  if (G_LIKELY (self->values) && (iter =
+          g_sequence_search (self->values, &timestamp,
+              (GCompareDataFunc) gst_control_point_find, NULL))) {
+    GstControlPoint *cp;
+
+    /* Iter contains the iter right after timestamp, i.e.
+     * we need to get the previous one and check the timestamp
+     */
+    iter = g_sequence_iter_prev (iter);
+    cp = g_sequence_get (iter);
+    if (cp->timestamp == timestamp) {
+      g_sequence_remove (iter);
+      self->nvalues--;
+      self->valid_cache = FALSE;
+      res = TRUE;
+    }
+  }
+  g_mutex_unlock (&self->lock);
+
+  return res;
+}
+
+/**
+ * gst_timed_value_control_source_unset_all:
+ * @self: the #GstTimedValueControlSource object
+ *
+ * Used to remove all time-stamped values of given controller-handled property
+ *
+ */
+void
+gst_timed_value_control_source_unset_all (GstTimedValueControlSource * self)
+{
+  g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
+
+  g_mutex_lock (&self->lock);
+  /* free GstControlPoint structures */
+  if (self->values) {
+    g_sequence_free (self->values);
+    self->values = NULL;
+  }
+  self->nvalues = 0;
+  self->valid_cache = FALSE;
+
+  g_mutex_unlock (&self->lock);
+}
+
+static void
+_append_control_point (GstControlPoint * cp, GQueue * res)
+{
+  g_queue_push_tail (res, cp);
+}
+
+/**
+ * gst_timed_value_control_source_get_all:
+ * @self: the #GstTimedValueControlSource to get the list from
+ *
+ * Returns a read-only copy of the list of #GstTimedValue for the given property.
+ * Free the list after done with it.
+ *
+ * Returns: (transfer container) (element-type GstController.TimedValue): a copy
+ * of the list, or %NULL if the property isn't handled by the controller
+ */
+GList *
+gst_timed_value_control_source_get_all (GstTimedValueControlSource * self)
+{
+  GQueue res = G_QUEUE_INIT;
+
+  g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), NULL);
+
+  g_mutex_lock (&self->lock);
+  if (G_LIKELY (self->values))
+    g_sequence_foreach (self->values, (GFunc) _append_control_point, &res);
+  g_mutex_unlock (&self->lock);
+
+  return res.head;
+}
+
+/**
+ * gst_timed_value_control_source_get_count:
+ * @self: the #GstTimedValueControlSource to get the number of values from
+ *
+ * Get the number of control points that are set.
+ *
+ * Returns: the number of control points that are set.
+ */
+gint
+gst_timed_value_control_source_get_count (GstTimedValueControlSource * self)
+{
+  g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), 0);
+  return self->nvalues;
+}
+
+/**
+ * gst_timed_value_control_invalidate_cache:
+ * @self: the #GstTimedValueControlSource
+ *
+ * Reset the controlled value cache.
+ */
+void
+gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self)
+{
+  g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
+  self->valid_cache = FALSE;
+}
+
+static void
+gst_timed_value_control_source_init (GstTimedValueControlSource * self)
+{
+  g_mutex_init (&self->lock);
+}
+
+static void
+gst_timed_value_control_source_finalize (GObject * obj)
+{
+  GstTimedValueControlSource *self = GST_TIMED_VALUE_CONTROL_SOURCE (obj);
+
+  g_mutex_lock (&self->lock);
+  gst_timed_value_control_source_reset (self);
+  g_mutex_unlock (&self->lock);
+  g_mutex_clear (&self->lock);
+
+  G_OBJECT_CLASS (gst_timed_value_control_source_parent_class)->finalize (obj);
+}
+
+static void
+gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
+    * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
+
+  gobject_class->finalize = gst_timed_value_control_source_finalize;
+}
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.h b/libs/gst/controller/gsttimedvaluecontrolsource.h
new file mode 100644 (file)
index 0000000..e1dde55
--- /dev/null
@@ -0,0 +1,131 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *               2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttimedvaluecontrolsource.h: Base class for timeed value based control
+ *                               sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_TIMED_VALUE_CONTROL_SOURCE_H__
+#define __GST_TIMED_VALUE_CONTROL_SOURCE_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include <gst/gstcontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_TIMED_VALUE_CONTROL_SOURCE \
+  (gst_timed_value_control_source_get_type ())
+#define GST_TIMED_VALUE_CONTROL_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSource))
+#define GST_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
+  (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
+#define GST_IS_TIMED_VALUE_CONTROL_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
+#define GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
+  (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
+#define GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS(inst) \
+  (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
+
+typedef struct _GstTimedValueControlSource GstTimedValueControlSource;
+typedef struct _GstTimedValueControlSourceClass GstTimedValueControlSourceClass;
+typedef struct _GstTimedValueControlSourcePrivate GstTimedValueControlSourcePrivate;
+
+/**
+ * GstControlPoint:
+ *
+ * a internal structure for value+time and various temporary
+ * values used for interpolation. This "inherits" from
+ * GstTimedValue.
+ */
+typedef struct _GstControlPoint
+{
+  /* fields from GstTimedValue. DO NOT CHANGE! */
+  GstClockTime timestamp;       /* timestamp of the value change */
+  gdouble value;                /* the new value */
+
+  /* internal fields */
+
+  /* Caches for the interpolators */
+  // FIXME: we should not have this here already ...
+  union {
+    struct {
+      gdouble h;
+      gdouble z;
+    } cubic;
+  } cache;
+
+} GstControlPoint;
+
+/**
+ * GstTimedValueControlSource:
+ *
+ * The instance structure of #GstControlSource.
+ */
+struct _GstTimedValueControlSource {
+  GstControlSource parent;
+
+  /*< protected >*/
+  GMutex lock;
+
+  GSequence *values;            /* List of GstControlPoint */
+  gint nvalues;                 /* Number of control points */
+  gboolean valid_cache;
+
+  GstTimedValueControlSourcePrivate *priv;
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstTimedValueControlSourceClass {
+  GstControlSourceClass parent_class;
+
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+#define GST_TIMED_VALUE_CONTROL_SOURCE_LOCK(o) \
+  g_mutex_lock(&((GstTimedValueControlSource *)o)->lock)
+#define GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK(o) \
+  g_mutex_unlock(&((GstTimedValueControlSource *)o)->lock)
+
+GType gst_timed_value_control_source_get_type (void);
+
+/* Functions */
+
+GSequenceIter * gst_timed_value_control_source_find_control_point_iter (
+                                                               GstTimedValueControlSource * self, 
+                                                               GstClockTime timestamp);
+
+gboolean        gst_timed_value_control_source_set            (GstTimedValueControlSource * self,
+                                                               GstClockTime timestamp,
+                                                               const gdouble value);
+gboolean        gst_timed_value_control_source_set_from_list  (GstTimedValueControlSource * self,
+                                                               const GSList * timedvalues);
+gboolean        gst_timed_value_control_source_unset          (GstTimedValueControlSource * self,
+                                                               GstClockTime timestamp);
+void            gst_timed_value_control_source_unset_all      (GstTimedValueControlSource *self);
+GList *         gst_timed_value_control_source_get_all        (GstTimedValueControlSource * self);
+gint            gst_timed_value_control_source_get_count      (GstTimedValueControlSource * self);
+void            gst_timed_value_control_invalidate_cache      (GstTimedValueControlSource * self);
+
+G_END_DECLS
+
+#endif /* __GST_TIMED_VALUE_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/gsttriggercontrolsource.c b/libs/gst/controller/gsttriggercontrolsource.c
new file mode 100644 (file)
index 0000000..6c8329d
--- /dev/null
@@ -0,0 +1,256 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *               2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttriggercontrolsource.c: Control source that provides some values at time-
+ *                            stamps
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+ /**
+ * SECTION:gsttriggercontrolsource
+ * @short_description: interpolation control source
+ *
+ * #GstTriggerControlSource is a #GstControlSource, that returns values from user-given
+ * control points. It allows for a tolerance on the time-stamps.
+ *
+ * To use #GstTriggerControlSource get a new instance by calling
+ * gst_trigger_control_source_new(), bind it to a #GParamSpec and set some
+ * control points by calling gst_timed_value_control_source_set().
+ *
+ * All functions are MT-safe.
+ */
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gsttriggercontrolsource.h"
+#include "gst/glib-compat-private.h"
+#include "gst/math-compat.h"
+
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+struct _GstTriggerControlSourcePrivate
+{
+  gint64 tolerance;
+};
+
+/* control point accessors */
+
+/*  returns the default value of the property, except for times with specific values */
+/*  needed for one-shot events, such as notes and triggers */
+
+static inline gdouble
+_interpolate_trigger (GstTimedValueControlSource * self, GSequenceIter * iter,
+    GstClockTime timestamp)
+{
+  GstControlPoint *cp;
+  gint64 tolerance = ((GstTriggerControlSource *) self)->priv->tolerance;
+  gboolean found = FALSE;
+
+  cp = g_sequence_get (iter);
+  if (GST_CLOCK_DIFF (cp->timestamp, timestamp) <= tolerance) {
+    found = TRUE;
+  } else {
+    if ((iter = g_sequence_iter_next (iter))) {
+      cp = g_sequence_get (iter);
+      if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) {
+        found = TRUE;
+      }
+    }
+  }
+  if (found) {
+    return cp->value;
+  }
+  return NAN;
+}
+
+static gboolean
+interpolate_trigger_get (GstTimedValueControlSource * self,
+    GstClockTime timestamp, gdouble * value)
+{
+  gboolean ret = FALSE;
+  GSequenceIter *iter;
+
+  g_mutex_lock (&self->lock);
+
+  iter =
+      gst_timed_value_control_source_find_control_point_iter (self, timestamp);
+  if (iter) {
+    *value = _interpolate_trigger (self, iter, timestamp);
+    if (!isnan (*value))
+      ret = TRUE;
+  }
+  g_mutex_unlock (&self->lock);
+  return ret;
+}
+
+static gboolean
+interpolate_trigger_get_value_array (GstTimedValueControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  gboolean ret = FALSE;
+  guint i;
+  GstClockTime ts = timestamp;
+  GstClockTime next_ts = 0;
+  gdouble val;
+  GSequenceIter *iter1 = NULL, *iter2 = NULL;
+  gboolean triggered = FALSE;
+
+  g_mutex_lock (&self->lock);
+  for (i = 0; i < n_values; i++) {
+    val = NAN;
+    if (ts >= next_ts) {
+      iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts);
+      if (!iter1) {
+        if (G_LIKELY (self->values))
+          iter2 = g_sequence_get_begin_iter (self->values);
+        else
+          iter2 = NULL;
+      } else {
+        iter2 = g_sequence_iter_next (iter1);
+      }
+
+      if (iter2 && !g_sequence_iter_is_end (iter2)) {
+        GstControlPoint *cp;
+
+        cp = g_sequence_get (iter2);
+        next_ts = cp->timestamp;
+      } else {
+        next_ts = GST_CLOCK_TIME_NONE;
+      }
+
+      if (iter1) {
+        val = _interpolate_trigger (self, iter1, ts);
+        if (!isnan (val))
+          ret = TRUE;
+      } else {
+        g_mutex_unlock (&self->lock);
+        return FALSE;
+      }
+      triggered = TRUE;
+    } else if (triggered) {
+      if (iter1) {
+        val = _interpolate_trigger (self, iter1, ts);
+        if (!isnan (val))
+          ret = TRUE;
+      } else {
+        g_mutex_unlock (&self->lock);
+        return FALSE;
+      }
+      triggered = FALSE;
+    }
+    *values = val;
+    ts += interval;
+    values++;
+  }
+  g_mutex_unlock (&self->lock);
+  return ret;
+}
+
+enum
+{
+  PROP_TOLERANCE = 1,
+};
+
+#define _do_init \
+  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "trigger control source", 0, \
+    "timeline value trigger control source")
+
+G_DEFINE_TYPE_WITH_CODE (GstTriggerControlSource, gst_trigger_control_source,
+    GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, _do_init);
+
+/**
+ * gst_trigger_control_source_new:
+ *
+ * This returns a new, unbound #GstTriggerControlSource.
+ *
+ * Returns: a new, unbound #GstTriggerControlSource.
+ */
+GstTriggerControlSource *
+gst_trigger_control_source_new (void)
+{
+  return g_object_newv (GST_TYPE_TRIGGER_CONTROL_SOURCE, 0, NULL);
+}
+
+static void
+gst_trigger_control_source_init (GstTriggerControlSource * self)
+{
+  GstControlSource *csource = (GstControlSource *) self;
+
+  self->priv =
+      G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_TRIGGER_CONTROL_SOURCE,
+      GstTriggerControlSourcePrivate);
+
+  csource->get_value = (GstControlSourceGetValue) interpolate_trigger_get;
+  csource->get_value_array = (GstControlSourceGetValueArray)
+      interpolate_trigger_get_value_array;
+}
+
+static void
+gst_trigger_control_source_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
+
+  switch (prop_id) {
+    case PROP_TOLERANCE:
+      GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
+      self->priv->tolerance = g_value_get_int64 (value);
+      GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_trigger_control_source_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
+
+  switch (prop_id) {
+    case PROP_TOLERANCE:
+      g_value_set_int64 (value, self->priv->tolerance);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_trigger_control_source_class_init (GstTriggerControlSourceClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GstTriggerControlSourcePrivate));
+
+  gobject_class->set_property = gst_trigger_control_source_set_property;
+  gobject_class->get_property = gst_trigger_control_source_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_TOLERANCE,
+      g_param_spec_int64 ("tolerance", "Tolerance",
+          "Amount of ns a control time can be off to still trigger",
+          0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+}
diff --git a/libs/gst/controller/gsttriggercontrolsource.h b/libs/gst/controller/gsttriggercontrolsource.h
new file mode 100644 (file)
index 0000000..f3d9939
--- /dev/null
@@ -0,0 +1,83 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *               2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttriggercontrolsource.h: Control source that provides some values at time-
+ *                            stamps
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_TRIGGER_CONTROL_SOURCE_H__
+#define __GST_TRIGGER_CONTROL_SOURCE_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include <gst/controller/gsttimedvaluecontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_TRIGGER_CONTROL_SOURCE \
+  (gst_trigger_control_source_get_type ())
+#define GST_TRIGGER_CONTROL_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSource))
+#define GST_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
+  (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
+#define GST_IS_TRIGGER_CONTROL_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE))
+#define GST_IS_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
+  (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE))
+#define GST_TRIGGER_CONTROL_SOURCE_GET_CLASS(inst) \
+  (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
+
+#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ())
+
+typedef struct _GstTriggerControlSource GstTriggerControlSource;
+typedef struct _GstTriggerControlSourceClass GstTriggerControlSourceClass;
+typedef struct _GstTriggerControlSourcePrivate GstTriggerControlSourcePrivate;
+
+/**
+ * GstTriggerControlSource:
+ *
+ * The instance structure of #GstControlSource.
+ */
+struct _GstTriggerControlSource {
+  GstTimedValueControlSource parent;
+
+  /*< private >*/
+  GstTriggerControlSourcePrivate *priv;
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstTriggerControlSourceClass {
+  GstTimedValueControlSourceClass parent_class;
+  
+  /*< private >*/
+  gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_trigger_control_source_get_type (void);
+
+/* Functions */
+
+GstTriggerControlSource *gst_trigger_control_source_new (void);
+
+G_END_DECLS
+
+#endif /* __GST_TRIGGER_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/lib.c b/libs/gst/controller/lib.c
deleted file mode 100644 (file)
index d81185f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- *
- * lib.c: controller subsystem init
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-#include <gst/gst.h>
-#include <gst/controller/gstcontroller.h>
-
-/* library initialisation */
-
-#define GST_CAT_DEFAULT controller_debug
-GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
-
-/**
- * gst_controller_init:
- * @argc: pointer to the commandline argument count
- * @argv: pointer to the commandline argument values
- *
- * Initializes the use of the controller library. Suggested to be called right
- * after gst_init().
- *
- * Returns: the %TRUE for success.
- */
-gboolean
-gst_controller_init (int *argc, char ***argv)
-{
-  static gboolean _gst_controller_initialized = FALSE;
-
-  if (_gst_controller_initialized)
-    return TRUE;
-
-  _gst_controller_initialized = TRUE;
-
-  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontroller", 0,
-      "dynamic parameter control for gstreamer elements");
-
-  return TRUE;
-}
diff --git a/libs/gst/dataprotocol/.gitignore b/libs/gst/dataprotocol/.gitignore
deleted file mode 100644 (file)
index 39b6275..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-libgstdataprotocol.def
-dataprotocol-test
-*.gcno
-*.c.gcov.out
-*.c.gcov.out
-*.o
-*.lo
-*.la
diff --git a/libs/gst/dataprotocol/Makefile.am b/libs/gst/dataprotocol/Makefile.am
deleted file mode 100644 (file)
index cde4a53..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-lib_LTLIBRARIES = libgstdataprotocol-@GST_MAJORMINOR@.la
-
-libgstdataprotocol_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/dataprotocol
-libgstdataprotocol_@GST_MAJORMINOR@_include_HEADERS = \
-    dataprotocol.h
-noinst_HEADERS = dp-private.h
-
-libgstdataprotocol_@GST_MAJORMINOR@_la_SOURCES = \
-    dataprotocol.c
-
-libgstdataprotocol_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
-libgstdataprotocol_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS)
-libgstdataprotocol_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
-
-CLEANFILES = *.gcno *.gcda *.gcov *.gcov.out
-
-%.c.gcov: .libs/libgstdataprotocol_@GST_MAJORMINOR@_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstdataprotocol_@GST_MAJORMINOR@_la_SOURCES:=.gcov)
-
-Android.mk: Makefile.am
-       androgenizer -:PROJECT gstreamer -:SHARED libgstdataprotocol-@GST_MAJORMINOR@ -:TAGS eng debug \
-        -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-        -:SOURCES $(libgstdataprotocol_@GST_MAJORMINOR@_la_SOURCES) \
-        -:CFLAGS $(libgstdataprotocol_@GST_MAJORMINOR@_la_CFLAGS) \
-        -:LDFLAGS $(libgstdataprotocol_@GST_MAJORMINOR@_la_LDFLAGS) \
-                  $(libgstdataprotocol_@GST_MAJORMINOR@_la_LIBADD) \
-        -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/dataprotocol \
-        -:HEADERS $(libgstdataprotocol_@GST_MAJORMINOR@_include_HEADERS) \
-        -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-       > $@
-
-# Disabled until this is fixed:
-# http://bugzilla.gnome.org/show_bug.cgi?id=594202
-if FALSE
-if HAVE_INTROSPECTION
-BUILT_GIRSOURCES = GstDataprotocol-@GST_MAJORMINOR@.gir
-
-gir_headers=$(patsubst %,$(srcdir)/%, $(libgstdataprotocol_@GST_MAJORMINOR@_include_HEADERS))
-gir_sources=$(patsubst %,$(srcdir)/%, $(libgstdataprotocol_@GST_MAJORMINOR@_la_SOURCES))
-gir_cincludes=$(patsubst %,--c-include='gst/dataprotocol/%',$(libgstdataprotocol_@GST_MAJORMINOR@_include_HEADERS))
-
-GstDataprotocol-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstdataprotocol-@GST_MAJORMINOR@.la
-       $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \
-               GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
-               $(INTROSPECTION_SCANNER) -v --namespace GstDataprotocol \
-               --strip-prefix=Gst \
-               --nsversion=@GST_MAJORMINOR@ \
-               -I$(top_srcdir) \
-               -I$(top_builddir) \
-               $(gir_cincludes) \
-               --add-include-path=$(top_builddir)/gst \
-               --library-path=$(top_builddir)/gst \
-               --library=$(top_builddir)/gst/libgstreamer-0.10.la \
-               --library=libgstdataprotocol-0.10.la \
-               --include=Gst-0.10 \
-               --libtool="$(top_builddir)/libtool" \
-               --pkg gstreamer-0.10 \
-               --pkg-export=gstreamer-dataprotocol-0.10 \
-               --add-init-section="gst_init(NULL,NULL);" \
-               --output $@ \
-               $(gir_headers) \
-               $(gir_sources)
-
-# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to
-# install anything - we need to install inside our prefix.
-girdir = $(datadir)/gir-1.0
-gir_DATA = $(BUILT_GIRSOURCES)
-
-typelibsdir = $(libdir)/girepository-1.0/
-
-typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib)
-
-%.typelib: %.gir $(INTROSPECTION_COMPILER)
-       $(AM_V_GEN)$(INTROSPECTION_COMPILER) --includedir=$(srcdir) --includedir=$(builddir) --includedir=$(top_builddir)/gst $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F)
-
-CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA)
-endif
-endif
diff --git a/libs/gst/dataprotocol/dataprotocol.c b/libs/gst/dataprotocol/dataprotocol.c
deleted file mode 100644 (file)
index b57d377..0000000
+++ /dev/null
@@ -1,922 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * dataprotocol.c: Functions implementing the GStreamer Data Protocol
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstdataprotocol
- * @short_description: Serialization of caps, buffers and events.
- * @see_also: #GstCaps, #GstEvent, #GstBuffer
- *
- * This helper library provides serialization of GstBuffer, GstCaps and
- * GstEvent structures.
- *
- * This serialization is useful when GStreamer needs to interface with
- * the outside world to transport data between distinct GStreamer pipelines.
- * The connections with the outside world generally don't have mechanisms
- * to transport properties of these structures.
- *
- * For example, transporting buffers across named pipes or network connections
- * doesn't maintain the buffer size and separation.
- *
- * This data protocol assumes a reliable connection-oriented transport, such as
- * TCP, a pipe, or a file.  The protocol does not serialize the caps for
- * each buffer; instead, it transport the caps only when they change in the
- * stream.  This implies that there will always be a caps packet before any
- * buffer packets.
- *
- * The versioning of the protocol is independent of GStreamer's version.
- * The major number gets incremented, and the minor reset, for incompatible
- * changes.  The minor number gets incremented for compatible changes that
- * allow clients who do not completely understand the newer protocol version
- * to still decode what they do understand.
- *
- * Version 0.2 serializes only a small subset of all events, with a custom
- * payload for each type.  Also, all GDP streams start with the initial caps
- * packet.
- *
- * Version 1.0 serializes all events by taking the string representation of
- * the event as the payload.  In addition, GDP streams can now start with
- * events as well, as required by the new data stream model in GStreamer 0.10.
- *
- * Converting buffers, caps and events to GDP buffers is done using a
- * #GstDPPacketizer object and invoking its packetizer functions.
- * For backwards-compatibility reasons, the old 0.2 methods are still
- * available but deprecated.
- *
- * For reference, this image shows the byte layout of the GDP header:
- *
- * <inlinegraphic format="PNG" fileref="gdp-header.png"></inlinegraphic>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <gst/dataprotocol/dataprotocol.h>
-#include <glib/gprintf.h>       /* g_sprintf */
-#include <string.h>             /* strlen */
-#include "dp-private.h"
-
-/* debug category */
-GST_DEBUG_CATEGORY_STATIC (data_protocol_debug);
-#define GST_CAT_DEFAULT data_protocol_debug
-
-/* helper macros */
-
-/* write first 6 bytes of header */
-#define GST_DP_INIT_HEADER(h, version, flags, type)            \
-G_STMT_START {                                                 \
-  gint maj = 0, min = 0;                                       \
-  switch (version) {                                           \
-    case GST_DP_VERSION_0_2: maj = 0; min = 2; break;          \
-    case GST_DP_VERSION_1_0: maj = 1; min = 0; break;          \
-  }                                                            \
-  h[0] = (guint8) maj;                                         \
-  h[1] = (guint8) min;                                         \
-  h[2] = (guint8) flags;                                       \
-  h[3] = 0; /* padding byte */                                 \
-  GST_WRITE_UINT16_BE (h + 4, type);                           \
-} G_STMT_END
-
-#define GST_DP_SET_CRC(h, flags, payload, length);             \
-G_STMT_START {                                                 \
-  guint16 crc = 0;                                             \
-  if (flags & GST_DP_HEADER_FLAG_CRC_HEADER)                   \
-    /* we don't crc the last four bytes since they are crc's */ \
-    crc = gst_dp_crc (h, 58);                                  \
-  GST_WRITE_UINT16_BE (h + 58, crc);                           \
-                                                               \
-  crc = 0;                                                     \
-  if (length && (flags & GST_DP_HEADER_FLAG_CRC_PAYLOAD))      \
-    crc = gst_dp_crc (payload, length);                                \
-  GST_WRITE_UINT16_BE (h + 60, crc);                           \
-} G_STMT_END
-
-/* calculate a CCITT 16 bit CRC check value for a given byte array */
-/*
- * this code snippet is adapted from a web page I found
- * it is identical except for cleanups, and a final XOR with 0xffff
- * as outlined in the uecp spec
- *
- * XMODEM    x^16 + x^12 + x^5 + 1
- */
-
-#define POLY       0x1021
-#define CRC_INIT   0xFFFF
-
-/*** HELPER FUNCTIONS ***/
-
-static gboolean
-gst_dp_header_from_buffer_any (const GstBuffer * buffer, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, GstDPVersion version)
-{
-  guint8 *h;
-  guint16 flags_mask;
-
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-  g_return_val_if_fail (length, FALSE);
-  g_return_val_if_fail (header, FALSE);
-
-  *length = GST_DP_HEADER_LENGTH;
-  h = g_malloc0 (GST_DP_HEADER_LENGTH);
-
-  /* version, flags, type */
-  GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_BUFFER);
-
-  /* buffer properties */
-  GST_WRITE_UINT32_BE (h + 6, GST_BUFFER_SIZE (buffer));
-  GST_WRITE_UINT64_BE (h + 10, GST_BUFFER_TIMESTAMP (buffer));
-  GST_WRITE_UINT64_BE (h + 18, GST_BUFFER_DURATION (buffer));
-  GST_WRITE_UINT64_BE (h + 26, GST_BUFFER_OFFSET (buffer));
-  GST_WRITE_UINT64_BE (h + 34, GST_BUFFER_OFFSET_END (buffer));
-
-  /* data flags; eats two bytes from the ABI area */
-  /* we copy everything but the read-only flags */
-  flags_mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_DISCONT |
-      GST_BUFFER_FLAG_IN_CAPS | GST_BUFFER_FLAG_GAP |
-      GST_BUFFER_FLAG_DELTA_UNIT;
-
-  GST_WRITE_UINT16_BE (h + 42, GST_BUFFER_FLAGS (buffer) & flags_mask);
-
-  GST_DP_SET_CRC (h, flags, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
-
-  GST_LOG ("created header from buffer:");
-  gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH);
-  *header = h;
-  return TRUE;
-}
-
-static gboolean
-gst_dp_packet_from_caps_any (const GstCaps * caps, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload, GstDPVersion version)
-{
-  guint8 *h;
-  guchar *string;
-  guint payload_length;
-
-  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
-  g_return_val_if_fail (length, FALSE);
-  g_return_val_if_fail (header, FALSE);
-  g_return_val_if_fail (payload, FALSE);
-
-  *length = GST_DP_HEADER_LENGTH;
-  h = g_malloc0 (GST_DP_HEADER_LENGTH);
-
-  string = (guchar *) gst_caps_to_string (caps);
-  payload_length = strlen ((gchar *) string) + 1;       /* include trailing 0 */
-
-  /* version, flags, type */
-  GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_CAPS);
-
-  /* buffer properties */
-  GST_WRITE_UINT32_BE (h + 6, payload_length);
-  GST_WRITE_UINT64_BE (h + 10, (guint64) 0);
-  GST_WRITE_UINT64_BE (h + 18, (guint64) 0);
-  GST_WRITE_UINT64_BE (h + 26, (guint64) 0);
-  GST_WRITE_UINT64_BE (h + 34, (guint64) 0);
-
-  GST_DP_SET_CRC (h, flags, string, payload_length);
-
-  GST_LOG ("created header from caps:");
-  gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH);
-  *header = h;
-  *payload = string;
-  return TRUE;
-}
-
-
-/*** PUBLIC FUNCTIONS ***/
-
-static const guint16 gst_dp_crc_table[256] = {
-  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
-  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
-  0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
-  0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
-  0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
-  0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
-  0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
-  0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
-  0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
-  0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
-  0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
-  0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
-  0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
-  0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
-  0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
-  0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
-  0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
-  0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
-  0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
-  0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
-  0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
-  0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
-  0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
-  0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
-  0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
-  0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
-  0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
-  0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
-  0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
-  0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
-  0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
-  0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
-};
-
-/**
- * gst_dp_crc:
- * @buffer: array of bytes
- * @length: the length of @buffer
- *
- * Calculate a CRC for the given buffer over the given number of bytes.
- * This is only provided for verification purposes; typical GDP users
- * will not need this function.
- *
- * Returns: a two-byte CRC checksum.
- */
-guint16
-gst_dp_crc (const guint8 * buffer, guint length)
-{
-  guint16 crc_register = CRC_INIT;
-
-  g_return_val_if_fail (buffer != NULL || length == 0, 0);
-
-  /* calc CRC */
-  for (; length--;) {
-    crc_register = (guint16) ((crc_register << 8) ^
-        gst_dp_crc_table[((crc_register >> 8) & 0x00ff) ^ *buffer++]);
-  }
-  return (0xffff ^ crc_register);
-}
-
-/* debugging function; dumps byte array values per 8 bytes */
-/* FIXME: would be nice to merge this with gst_util_dump_mem () */
-void
-gst_dp_dump_byte_array (guint8 * array, guint length)
-{
-  int i;
-  int n = 8;                    /* number of bytes per line */
-  gchar *line = g_malloc0 (3 * n + 1);
-
-  GST_LOG ("dumping byte array of length %d", length);
-  for (i = 0; i < length; ++i) {
-    g_sprintf (line + 3 * (i % n), "%02x ", array[i]);
-    if (i % n == (n - 1)) {
-      GST_LOG ("%03d: %s", i - (n - 1), line);
-    }
-  }
-  if (i % n != 0) {
-    GST_LOG ("%03d: %s", (i / n) * n, line);
-  }
-  g_free (line);
-}
-
-GType
-gst_dp_version_get_type (void)
-{
-  static gsize gst_dp_version_type = 0;
-  static const GEnumValue gst_dp_version[] = {
-    {GST_DP_VERSION_0_2, "GST_DP_VERSION_0_2", "0.2"},
-    {GST_DP_VERSION_1_0, "GST_DP_VERSION_1_0", "1.0"},
-    {0, NULL, NULL},
-  };
-
-  if (g_once_init_enter (&gst_dp_version_type)) {
-    GType tmp = g_enum_register_static ("GstDPVersion", gst_dp_version);
-    g_once_init_leave (&gst_dp_version_type, tmp);
-  }
-
-  return (GType) gst_dp_version_type;
-};
-
-/**
- * gst_dp_init:
- *
- * Initialize GStreamer Data Protocol library.
- *
- * Should be called before using these functions from source linking
- * to this source file.
- */
-void
-gst_dp_init (void)
-{
-  static gboolean _gst_dp_initialized = FALSE;
-
-  if (_gst_dp_initialized)
-    return;
-
-  _gst_dp_initialized = TRUE;
-
-  g_type_class_ref (gst_dp_version_get_type ());
-
-  GST_DEBUG_CATEGORY_INIT (data_protocol_debug, "gdp", 0,
-      "GStreamer Data Protocol");
-}
-
-/**
- * gst_dp_header_payload_length:
- * @header: the byte header of the packet array
- *
- * Get the length of the payload described by @header.
- *
- * Returns: the length of the payload this header describes.
- */
-guint32
-gst_dp_header_payload_length (const guint8 * header)
-{
-  g_return_val_if_fail (header != NULL, 0);
-
-  return GST_DP_HEADER_PAYLOAD_LENGTH (header);
-}
-
-/**
- * gst_dp_header_payload_type:
- * @header: the byte header of the packet array
- *
- * Get the type of the payload described by @header.
- *
- * Returns: the #GstDPPayloadType the payload this header describes.
- */
-GstDPPayloadType
-gst_dp_header_payload_type (const guint8 * header)
-{
-  g_return_val_if_fail (header != NULL, GST_DP_PAYLOAD_NONE);
-
-  return GST_DP_HEADER_PAYLOAD_TYPE (header);
-}
-
-/*** PACKETIZER FUNCTIONS ***/
-
-/**
- * gst_dp_header_from_buffer:
- * @buffer: a #GstBuffer to create a header for
- * @flags: the #GstDPHeaderFlag to create the header with
- * @length: a guint pointer to store the header length in
- * @header: a guint8 * pointer to store a newly allocated header byte array in
- *
- * Creates a GDP header from the given buffer.
- *
- * Deprecated: use a #GstDPPacketizer
- *
- * Returns: %TRUE if the header was successfully created.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_dp_header_from_buffer (const GstBuffer * buffer, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header);
-#endif
-gboolean
-gst_dp_header_from_buffer (const GstBuffer * buffer, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header)
-{
-  return gst_dp_header_from_buffer_any (buffer, flags, length, header,
-      GST_DP_VERSION_0_2);
-}
-#endif
-
-static gboolean
-gst_dp_header_from_buffer_1_0 (const GstBuffer * buffer, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header)
-{
-  return gst_dp_header_from_buffer_any (buffer, flags, length, header,
-      GST_DP_VERSION_1_0);
-}
-
-/**
- * gst_dp_packet_from_caps:
- * @caps: a #GstCaps to create a packet for
- * @flags: the #GstDPHeaderFlag to create the header with
- * @length: a guint pointer to store the header length in
- * @header: a guint8 pointer to store a newly allocated header byte array in
- * @payload: a guint8 pointer to store a newly allocated payload byte array in
- *
- * Creates a GDP packet from the given caps.
- *
- * Deprecated: use a #GstDPPacketizer
- *
- * Returns: %TRUE if the packet was successfully created.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_dp_packet_from_caps (const GstCaps * caps, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload);
-#endif
-gboolean
-gst_dp_packet_from_caps (const GstCaps * caps, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload)
-{
-  return gst_dp_packet_from_caps_any (caps, flags, length, header, payload,
-      GST_DP_VERSION_0_2);
-}
-#endif
-
-static gboolean
-gst_dp_packet_from_caps_1_0 (const GstCaps * caps, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload)
-{
-  return gst_dp_packet_from_caps_any (caps, flags, length, header, payload,
-      GST_DP_VERSION_1_0);
-}
-
-/**
- * gst_dp_packet_from_event:
- * @event: a #GstEvent to create a packet for
- * @flags: the #GstDPHeaderFlag to create the header with
- * @length: a guint pointer to store the header length in
- * @header: a guint8 pointer to store a newly allocated header byte array in
- * @payload: a guint8 pointer to store a newly allocated payload byte array in
- *
- * Creates a GDP packet from the given event.
- *
- * Deprecated: use a #GstDPPacketizer
- *
- * Returns: %TRUE if the packet was successfully created.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-gboolean
-gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload);
-#endif
-gboolean
-gst_dp_packet_from_event (const GstEvent * event, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload)
-{
-  guint8 *h;
-  guint pl_length;              /* length of payload */
-
-  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
-  g_return_val_if_fail (length, FALSE);
-  g_return_val_if_fail (header, FALSE);
-  g_return_val_if_fail (payload, FALSE);
-
-  /* first construct payload, since we need the length */
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_UNKNOWN:
-      GST_WARNING ("Unknown event, ignoring");
-      return FALSE;
-    case GST_EVENT_EOS:
-    case GST_EVENT_FLUSH_START:
-    case GST_EVENT_FLUSH_STOP:
-    case GST_EVENT_NEWSEGMENT:
-      pl_length = 0;
-      *payload = NULL;
-      break;
-    case GST_EVENT_SEEK:
-    {
-      gdouble rate;
-      GstFormat format;
-      GstSeekFlags flags;
-      GstSeekType cur_type, stop_type;
-      gint64 cur, stop;
-
-      gst_event_parse_seek ((GstEvent *) event, &rate, &format, &flags,
-          &cur_type, &cur, &stop_type, &stop);
-
-      pl_length = 4 + 4 + 4 + 8 + 4 + 8;
-      *payload = g_malloc0 (pl_length);
-      /* FIXME write rate */
-      GST_WRITE_UINT32_BE (*payload, (guint32) format);
-      GST_WRITE_UINT32_BE (*payload + 4, (guint32) flags);
-      GST_WRITE_UINT32_BE (*payload + 8, (guint32) cur_type);
-      GST_WRITE_UINT64_BE (*payload + 12, (guint64) cur);
-      GST_WRITE_UINT32_BE (*payload + 20, (guint32) stop_type);
-      GST_WRITE_UINT64_BE (*payload + 24, (guint64) stop);
-      break;
-    }
-    case GST_EVENT_QOS:
-    case GST_EVENT_NAVIGATION:
-    case GST_EVENT_TAG:
-      GST_WARNING ("Unhandled event type %d, ignoring", GST_EVENT_TYPE (event));
-      return FALSE;
-    default:
-      GST_WARNING ("Unknown event type %d, ignoring", GST_EVENT_TYPE (event));
-      return FALSE;
-  }
-
-  /* now we can create and fill the header */
-  h = g_malloc0 (GST_DP_HEADER_LENGTH);
-  *length = GST_DP_HEADER_LENGTH;
-
-  /* version, flags, type */
-  GST_DP_INIT_HEADER (h, GST_DP_VERSION_0_2, flags,
-      GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event));
-
-  /* length */
-  GST_WRITE_UINT32_BE (h + 6, (guint32) pl_length);
-  /* timestamp */
-  GST_WRITE_UINT64_BE (h + 10, GST_EVENT_TIMESTAMP (event));
-
-  GST_DP_SET_CRC (h, flags, *payload, pl_length);
-
-  GST_LOG ("created header from event:");
-  gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH);
-
-  *header = h;
-  return TRUE;
-}
-#endif
-
-static gboolean
-gst_dp_packet_from_event_1_0 (const GstEvent * event, GstDPHeaderFlag flags,
-    guint * length, guint8 ** header, guint8 ** payload)
-{
-  guint8 *h;
-  guint32 pl_length;            /* length of payload */
-  guchar *string = NULL;
-
-  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
-  g_return_val_if_fail (length, FALSE);
-  g_return_val_if_fail (header, FALSE);
-  g_return_val_if_fail (payload, FALSE);
-
-  *length = GST_DP_HEADER_LENGTH;
-  h = g_malloc0 (GST_DP_HEADER_LENGTH);
-
-  if (event->structure) {
-    string = (guchar *) gst_structure_to_string (event->structure);
-    GST_LOG ("event %p has structure, string %s", event, string);
-    pl_length = strlen ((gchar *) string) + 1;  /* include trailing 0 */
-  } else {
-    GST_LOG ("event %p has no structure", event);
-    pl_length = 0;
-  }
-
-  /* version, flags, type */
-  GST_DP_INIT_HEADER (h, GST_DP_VERSION_1_0, flags,
-      GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event));
-
-  /* length */
-  GST_WRITE_UINT32_BE (h + 6, pl_length);
-  /* timestamp */
-  GST_WRITE_UINT64_BE (h + 10, GST_EVENT_TIMESTAMP (event));
-
-  GST_DP_SET_CRC (h, flags, string, pl_length);
-
-  GST_LOG ("created header from event:");
-  gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH);
-  *header = h;
-  *payload = string;
-  return TRUE;
-}
-
-/*** DEPACKETIZING FUNCTIONS ***/
-
-/**
- * gst_dp_buffer_from_header:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- *
- * Creates a newly allocated #GstBuffer from the given header.
- * The buffer data needs to be copied into it before validating.
- *
- * Use this function if you want to pre-allocate a buffer based on the
- * packet header to read the packet payload in to.
- *
- * This function does not check the header passed to it, use
- * gst_dp_validate_header() first if the header data is unchecked.
- *
- * Returns: A #GstBuffer if the buffer was successfully created, or NULL.
- */
-GstBuffer *
-gst_dp_buffer_from_header (guint header_length, const guint8 * header)
-{
-  GstBuffer *buffer;
-
-  g_return_val_if_fail (header != NULL, NULL);
-  g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, NULL);
-  g_return_val_if_fail (GST_DP_HEADER_PAYLOAD_TYPE (header) ==
-      GST_DP_PAYLOAD_BUFFER, NULL);
-
-  buffer =
-      gst_buffer_new_and_alloc ((guint) GST_DP_HEADER_PAYLOAD_LENGTH (header));
-
-  GST_BUFFER_TIMESTAMP (buffer) = GST_DP_HEADER_TIMESTAMP (header);
-  GST_BUFFER_DURATION (buffer) = GST_DP_HEADER_DURATION (header);
-  GST_BUFFER_OFFSET (buffer) = GST_DP_HEADER_OFFSET (header);
-  GST_BUFFER_OFFSET_END (buffer) = GST_DP_HEADER_OFFSET_END (header);
-  GST_BUFFER_FLAGS (buffer) = GST_DP_HEADER_BUFFER_FLAGS (header);
-
-  return buffer;
-}
-
-/**
- * gst_dp_caps_from_packet:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- * @payload: the byte array of the packet payload
- *
- * Creates a newly allocated #GstCaps from the given packet.
- *
- * This function does not check the arguments passed to it, use
- * gst_dp_validate_packet() first if the header and payload data are
- * unchecked.
- *
- * Returns: A #GstCaps containing the caps represented in the packet,
- *          or NULL if the packet could not be converted.
- */
-GstCaps *
-gst_dp_caps_from_packet (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  GstCaps *caps;
-  gchar *string;
-
-  g_return_val_if_fail (header, NULL);
-  g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, NULL);
-  g_return_val_if_fail (GST_DP_HEADER_PAYLOAD_TYPE (header) ==
-      GST_DP_PAYLOAD_CAPS, NULL);
-  g_return_val_if_fail (payload, NULL);
-
-  /* 0 sized payload length will work create NULL string */
-  string = g_strndup ((gchar *) payload, GST_DP_HEADER_PAYLOAD_LENGTH (header));
-  caps = gst_caps_from_string (string);
-  g_free (string);
-
-  return caps;
-}
-
-static GstEvent *
-gst_dp_event_from_packet_0_2 (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  GstEvent *event = NULL;
-  GstEventType type;
-
-  type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE;
-  switch (type) {
-    case GST_EVENT_UNKNOWN:
-      GST_WARNING ("Unknown event, ignoring");
-      return NULL;
-    case GST_EVENT_EOS:
-    case GST_EVENT_FLUSH_START:
-    case GST_EVENT_FLUSH_STOP:
-    case GST_EVENT_NEWSEGMENT:
-      event = gst_event_new_custom (type, NULL);
-      GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header);
-      break;
-    case GST_EVENT_SEEK:
-    {
-      gdouble rate;
-      GstFormat format;
-      GstSeekFlags flags;
-      GstSeekType cur_type, stop_type;
-      gint64 cur, stop;
-
-      g_return_val_if_fail (payload != NULL, NULL);
-
-      /* FIXME, read rate */
-      rate = 1.0;
-      format = (GstFormat) GST_READ_UINT32_BE (payload);
-      flags = (GstSeekFlags) GST_READ_UINT32_BE (payload + 4);
-      cur_type = (GstSeekType) GST_READ_UINT32_BE (payload + 8);
-      cur = (gint64) GST_READ_UINT64_BE (payload + 12);
-      stop_type = (GstSeekType) GST_READ_UINT32_BE (payload + 20);
-      stop = (gint64) GST_READ_UINT64_BE (payload + 24);
-
-      event = gst_event_new_seek (rate, format, flags, cur_type, cur,
-          stop_type, stop);
-      GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header);
-      break;
-    }
-    case GST_EVENT_QOS:
-    case GST_EVENT_NAVIGATION:
-    case GST_EVENT_TAG:
-      GST_WARNING ("Unhandled event type %d, ignoring", type);
-      return NULL;
-    default:
-      GST_WARNING ("Unknown event type %d, ignoring", type);
-      return NULL;
-  }
-
-  return event;
-}
-
-static GstEvent *
-gst_dp_event_from_packet_1_0 (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  GstEvent *event = NULL;
-  GstEventType type;
-  gchar *string = NULL;
-  GstStructure *s = NULL;
-
-  type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE;
-  if (payload) {
-    string =
-        g_strndup ((gchar *) payload, GST_DP_HEADER_PAYLOAD_LENGTH (header));
-    s = gst_structure_from_string (string, NULL);
-    g_free (string);
-  }
-  event = gst_event_new_custom (type, s);
-  return event;
-}
-
-
-/**
- * gst_dp_event_from_packet:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- * @payload: the byte array of the packet payload
- *
- * Creates a newly allocated #GstEvent from the given packet.
- *
- * This function does not check the arguments passed to it, use
- * gst_dp_validate_packet() first if the header and payload data are
- * unchecked.
- *
- * Returns: A #GstEvent if the event was successfully created,
- *          or NULL if an event could not be read from the payload.
- */
-GstEvent *
-gst_dp_event_from_packet (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  guint8 major, minor;
-
-  g_return_val_if_fail (header, NULL);
-  g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, NULL);
-
-  major = GST_DP_HEADER_MAJOR_VERSION (header);
-  minor = GST_DP_HEADER_MINOR_VERSION (header);
-
-  if (major == 0 && minor == 2)
-    return gst_dp_event_from_packet_0_2 (header_length, header, payload);
-  else if (major == 1 && minor == 0)
-    return gst_dp_event_from_packet_1_0 (header_length, header, payload);
-  else {
-    GST_ERROR ("Unknown GDP version %d.%d", major, minor);
-    return NULL;
-  }
-}
-
-/**
- * gst_dp_validate_header:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- *
- * Validates the given packet header by checking the CRC checksum.
- *
- * Returns: %TRUE if the CRC matches, or no CRC checksum is present.
- */
-gboolean
-gst_dp_validate_header (guint header_length, const guint8 * header)
-{
-  guint16 crc_read, crc_calculated;
-
-  g_return_val_if_fail (header != NULL, FALSE);
-  g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, FALSE);
-
-  if (!(GST_DP_HEADER_FLAGS (header) & GST_DP_HEADER_FLAG_CRC_HEADER))
-    return TRUE;
-
-  crc_read = GST_DP_HEADER_CRC_HEADER (header);
-
-  /* don't include the last two crc fields for the crc check */
-  crc_calculated = gst_dp_crc (header, header_length - 4);
-  if (crc_read != crc_calculated)
-    goto crc_error;
-
-  GST_LOG ("header crc validation: %02x", crc_read);
-  return TRUE;
-
-  /* ERRORS */
-crc_error:
-  {
-    GST_WARNING ("header crc mismatch: read %02x, calculated %02x", crc_read,
-        crc_calculated);
-    return FALSE;
-  }
-}
-
-/**
- * gst_dp_validate_payload:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- * @payload: the byte array of the packet payload
- *
- * Validates the given packet payload using the given packet header
- * by checking the CRC checksum.
- *
- * Returns: %TRUE if the CRC matches, or no CRC checksum is present.
- */
-gboolean
-gst_dp_validate_payload (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  guint16 crc_read, crc_calculated;
-
-  g_return_val_if_fail (header != NULL, FALSE);
-  g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, FALSE);
-
-  if (!(GST_DP_HEADER_FLAGS (header) & GST_DP_HEADER_FLAG_CRC_PAYLOAD))
-    return TRUE;
-
-  crc_read = GST_DP_HEADER_CRC_PAYLOAD (header);
-  crc_calculated = gst_dp_crc (payload, GST_DP_HEADER_PAYLOAD_LENGTH (header));
-  if (crc_read != crc_calculated)
-    goto crc_error;
-
-  GST_LOG ("payload crc validation: %02x", crc_read);
-  return TRUE;
-
-  /* ERRORS */
-crc_error:
-  {
-    GST_WARNING ("payload crc mismatch: read %02x, calculated %02x", crc_read,
-        crc_calculated);
-    return FALSE;
-  }
-}
-
-/**
- * gst_dp_validate_packet:
- * @header_length: the length of the packet header
- * @header: the byte array of the packet header
- * @payload: the byte array of the packet payload
- *
- * Validates the given packet by checking version information and checksums.
- *
- * Returns: %TRUE if the packet validates.
- */
-gboolean
-gst_dp_validate_packet (guint header_length, const guint8 * header,
-    const guint8 * payload)
-{
-  if (!gst_dp_validate_header (header_length, header))
-    return FALSE;
-  if (!gst_dp_validate_payload (header_length, header, payload))
-    return FALSE;
-
-  return TRUE;
-}
-
-/**
- * gst_dp_packetizer_new:
- * @version: the #GstDPVersion of the protocol to packetize for.
- *
- * Creates a new packetizer.
- *
- * Returns: a newly allocated #GstDPPacketizer
- */
-GstDPPacketizer *
-gst_dp_packetizer_new (GstDPVersion version)
-{
-  GstDPPacketizer *ret;
-
-  ret = g_malloc0 (sizeof (GstDPPacketizer));
-  ret->version = version;
-
-  switch (version) {
-#ifndef GST_REMOVE_DEPRECATED
-    case GST_DP_VERSION_0_2:
-      ret->header_from_buffer = gst_dp_header_from_buffer;
-      ret->packet_from_caps = gst_dp_packet_from_caps;
-      ret->packet_from_event = gst_dp_packet_from_event;
-      break;
-#endif
-    case GST_DP_VERSION_1_0:
-      ret->header_from_buffer = gst_dp_header_from_buffer_1_0;
-      ret->packet_from_caps = gst_dp_packet_from_caps_1_0;
-      ret->packet_from_event = gst_dp_packet_from_event_1_0;
-      break;
-    default:
-      g_free (ret);
-      ret = NULL;
-      break;
-  }
-
-  return ret;
-}
-
-/**
- * gst_dp_packetizer_free:
- * @packetizer: the #GstDPPacketizer to free.
- *
- * Free the given packetizer.
- */
-void
-gst_dp_packetizer_free (GstDPPacketizer * packetizer)
-{
-  g_free (packetizer);
-}
diff --git a/libs/gst/dataprotocol/dataprotocol.h b/libs/gst/dataprotocol/dataprotocol.h
deleted file mode 100644 (file)
index 150b5cc..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * dataprotocol.h: Functions implementing the GStreamer Data Protocol
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_DATA_PROTOCOL_H__
-#define __GST_DATA_PROTOCOL_H__
-
-#include <gst/gstbuffer.h>
-#include <gst/gstevent.h>
-#include <gst/gstcaps.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstDPVersion:
- * @GST_DP_VERSION_0_2: protocol version 0.2
- * @GST_DP_VERSION_1_0: protocol version 1.0
- *
- * The version of the GDP protocol being used.
- */
-typedef enum {
-  GST_DP_VERSION_0_2 = 1,
-  GST_DP_VERSION_1_0,
-} GstDPVersion;
-
-GType gst_dp_version_get_type (void);
-#define GST_TYPE_DP_VERSION (gst_dp_version_get_type ())
-
-/**
- * GST_DP_VERSION_MAJOR:
- *
- * The major version number of the GStreamer Data Protocol.
- */
-#define GST_DP_VERSION_MAJOR 0
-/**
- * GST_DP_VERSION_MINOR:
- *
- * The minor version number of the GStreamer Data Protocol.
- */
-#define GST_DP_VERSION_MINOR 2
-
-/**
- * GST_DP_HEADER_LENGTH:
- *
- * The header size in bytes.
- */
-#define GST_DP_HEADER_LENGTH 62
-
-/**
- * GstDPHeaderFlag:
- * @GST_DP_HEADER_FLAG_NONE: No flag present.
- * @GST_DP_HEADER_FLAG_CRC_HEADER: a header CRC field is present.
- * @GST_DP_HEADER_FLAG_CRC_PAYLOAD: a payload CRC field is present.
- * @GST_DP_HEADER_FLAG_CRC: a CRC for header and payload is present.
- *
- * header flags for the dataprotocol.
- */
-typedef enum {
-  GST_DP_HEADER_FLAG_NONE        = 0,
-  GST_DP_HEADER_FLAG_CRC_HEADER  = (1 << 0),
-  GST_DP_HEADER_FLAG_CRC_PAYLOAD = (1 << 1),
-  GST_DP_HEADER_FLAG_CRC         = (1 << 1) | (1 << 0),
-} GstDPHeaderFlag;
-
-/**
- * GstDPPayloadType:
- * @GST_DP_PAYLOAD_NONE: Invalid payload type.
- * @GST_DP_PAYLOAD_BUFFER: #GstBuffer payload packet.
- * @GST_DP_PAYLOAD_CAPS: #GstCaps payload packet.
- * @GST_DP_PAYLOAD_EVENT_NONE: First value of #GstEvent payload packets.
- *
- * The GDP payload types. a #GstEvent payload type is encoded with the
- * event type number starting from @GST_DP_PAYLOAD_EVENT_NONE.
- */
-typedef enum {
-  GST_DP_PAYLOAD_NONE            = 0,
-  GST_DP_PAYLOAD_BUFFER,
-  GST_DP_PAYLOAD_CAPS,
-  GST_DP_PAYLOAD_EVENT_NONE      = 64,
-} GstDPPayloadType;
-
-typedef gboolean (*GstDPHeaderFromBufferFunction) (const GstBuffer * buffer,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header);
-typedef gboolean (*GstDPPacketFromCapsFunction) (const GstCaps * caps,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header,
-                                               guint8 ** payload);
-typedef gboolean (*GstDPPacketFromEventFunction) (const GstEvent * event,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header,
-                                               guint8 ** payload);
-
-/**
- * GstDPPacketizer:
- * @version: the #GstDPVersion of the protocol to be used
- * @header_from_buffer: buffer serializer function
- * @packet_from_caps: caps serializer function
- * @packet_from_event: event serializer function
- *
- * Data protocol packetizer handle.
- */
-typedef struct {
-  GstDPVersion version;
-
-  GstDPHeaderFromBufferFunction header_from_buffer;
-  GstDPPacketFromCapsFunction packet_from_caps;
-  GstDPPacketFromEventFunction packet_from_event;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
-} GstDPPacketizer;
-
-
-void           gst_dp_init                     (void);
-
-/* packetizer */
-GstDPPacketizer *
-                gst_dp_packetizer_new           (GstDPVersion version);
-void            gst_dp_packetizer_free          (GstDPPacketizer *packetizer);
-
-/* crc checksum */
-guint16         gst_dp_crc                      (const guint8 * buffer,
-                                                 guint length);
-
-/* payload information from header */
-guint32                gst_dp_header_payload_length    (const guint8 * header);
-GstDPPayloadType
-               gst_dp_header_payload_type      (const guint8 * header);
-
-/* converting from GstBuffer/GstEvent/GstCaps */
-#ifndef GST_DISABLE_DEPRECATED
-gboolean       gst_dp_header_from_buffer       (const GstBuffer * buffer,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header);
-#endif
-#ifndef GST_DISABLE_DEPRECATED
-gboolean       gst_dp_packet_from_caps         (const GstCaps * caps,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header,
-                                               guint8 ** payload);
-#endif
-#ifndef GST_DISABLE_DEPRECATED
-gboolean       gst_dp_packet_from_event        (const GstEvent * event,
-                                               GstDPHeaderFlag flags,
-                                               guint * length,
-                                               guint8 ** header,
-                                               guint8 ** payload);
-#endif
-/* converting to GstBuffer/GstEvent/GstCaps */
-GstBuffer *    gst_dp_buffer_from_header       (guint header_length,
-                                               const guint8 * header);
-GstCaps *      gst_dp_caps_from_packet         (guint header_length,
-                                               const guint8 * header,
-                                               const guint8 * payload);
-GstEvent *     gst_dp_event_from_packet        (guint header_length,
-                                               const guint8 * header,
-                                               const guint8 * payload);
-
-/* validation */
-gboolean       gst_dp_validate_header          (guint header_length,
-                                               const guint8 * header);
-gboolean       gst_dp_validate_payload         (guint header_length,
-                                               const guint8 * header,
-                                               const guint8 * payload);
-gboolean       gst_dp_validate_packet          (guint header_length,
-                                               const guint8 * header,
-                                               const guint8 * payload);
-
-G_END_DECLS
-
-#endif /* __GST_DATA_PROTOCOL_H__ */
-
diff --git a/libs/gst/dataprotocol/dp-private.h b/libs/gst/dataprotocol/dp-private.h
deleted file mode 100644 (file)
index 5e54045..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * dp-private.h: private defines/macros for dataprotocol implementation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_DP_PRIVATE_H__
-#define __GST_DP_PRIVATE_H__
-
-#include <gst/gstbuffer.h>
-#include <gst/gstevent.h>
-#include <gst/gstcaps.h>
-
-G_BEGIN_DECLS
-
-/* accessor defines */
-#define GST_DP_HEADER_MAJOR_VERSION(x) ((x)[0])
-#define GST_DP_HEADER_MINOR_VERSION(x)  ((x)[1])
-#define GST_DP_HEADER_FLAGS(x)          ((x)[2])
-/* free byte here to align */
-#define GST_DP_HEADER_PAYLOAD_TYPE(x)   GST_READ_UINT16_BE (x + 4)
-#define GST_DP_HEADER_PAYLOAD_LENGTH(x) GST_READ_UINT32_BE (x + 6)
-#define GST_DP_HEADER_TIMESTAMP(x)      GST_READ_UINT64_BE (x + 10)
-#define GST_DP_HEADER_DURATION(x)       GST_READ_UINT64_BE (x + 18)
-#define GST_DP_HEADER_OFFSET(x)         GST_READ_UINT64_BE (x + 26)
-#define GST_DP_HEADER_OFFSET_END(x)     GST_READ_UINT64_BE (x + 34)
-#define GST_DP_HEADER_BUFFER_FLAGS(x)   GST_READ_UINT16_BE (x + 42)
-#define GST_DP_HEADER_CRC_HEADER(x)     GST_READ_UINT16_BE (x + 58)
-#define GST_DP_HEADER_CRC_PAYLOAD(x)    GST_READ_UINT16_BE (x + 60)
-
-void gst_dp_dump_byte_array (guint8 *array, guint length);
-
-G_END_DECLS
-
-#endif /* __GST_DP_PRIVATE_H__ */
-
index d54c656..09cb852 100644 (file)
@@ -41,11 +41,6 @@ main (int argc, char *argv[])
   if (argc != 2 || strcmp (argv[1], "-l"))
     return 1;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  if (!g_thread_supported ())
-    g_thread_init (NULL);
-#endif
-
   my_argc = 2;
   my_argv = g_malloc (my_argc * sizeof (char *));
   my_argv[0] = argv[0];
index 93b522e..1436f1d 100644 (file)
@@ -3,17 +3,19 @@ lib_LTLIBRARIES = libgstnet-@GST_MAJORMINOR@.la
 libgstnet_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/net
 libgstnet_@GST_MAJORMINOR@_include_HEADERS = \
     gstnet.h \
+    gstnetaddressmeta.h \
     gstnetclientclock.h \
     gstnettimepacket.h \
     gstnettimeprovider.h
 
 libgstnet_@GST_MAJORMINOR@_la_SOURCES = \
+    gstnetaddressmeta.c \
     gstnetclientclock.c \
     gstnettimepacket.c \
     gstnettimeprovider.c
 
-libgstnet_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
-libgstnet_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) $(INET_ATON_LIBS) $(WIN32_LIBS)
+libgstnet_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) $(GIO_CFLAGS)
+libgstnet_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) $(GIO_LIBS)
 libgstnet_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
 
 CLEANFILES = *.gcno *.gcda *.gcov
@@ -48,7 +50,9 @@ GstNet-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_MAJORMINOR@
                GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
                $(INTROSPECTION_SCANNER) -v --namespace GstNet \
                --strip-prefix=Gst \
+               --warn-all \
                --nsversion=@GST_MAJORMINOR@ \
+               -DGST_USE_UNSTABLE_API \
                -I$(top_srcdir) \
                -I$(top_srcdir)/libs \
                -I$(top_builddir) \
@@ -56,12 +60,14 @@ GstNet-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_MAJORMINOR@
                $(gir_cincludes) \
                --add-include-path=$(top_builddir)/gst \
                --library-path=$(top_builddir)/gst \
-               --library=$(top_builddir)/gst/libgstreamer-0.10.la \
-               --library=libgstnet-0.10.la \
-               --include=Gst-0.10 \
+               --library=$(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la \
+               --library=libgstnet-@GST_MAJORMINOR@.la \
+               --include=Gst-@GST_MAJORMINOR@ \
+               --include=Gio-2.0 \
                --libtool="$(top_builddir)/libtool" \
-               --pkg gstreamer-0.10 \
-               --pkg-export="gstreamer-net-0.10" \
+               --pkg gstreamer-@GST_MAJORMINOR@ \
+               --pkg gio-2.0 \
+               --pkg-export="gstreamer-net-@GST_MAJORMINOR@" \
                --add-init-section="gst_init(NULL,NULL);" \
                --output $@ \
                $(gir_headers) \
diff --git a/libs/gst/net/gstnetaddressmeta.c b/libs/gst/net/gstnetaddressmeta.c
new file mode 100644 (file)
index 0000000..5e687d4
--- /dev/null
@@ -0,0 +1,90 @@
+/* GStreamer
+ * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstnetaddressmeta
+ * @short_description: Network address metadata
+ *
+ * #GstNetAddress can be used to store a network address. #GstNetAddressMeta can
+ * be used to store a network address in a #GstBuffer so that it network
+ * elements can track the to and from address of the buffer.
+ *
+ * Last reviewed on 2011-11-03 (0.11.2)
+ */
+
+#include <string.h>
+
+#include "gstnetaddressmeta.h"
+
+static gboolean
+net_address_meta_init (GstNetAddressMeta * meta, gpointer params,
+    GstBuffer * buffer)
+{
+  meta->addr = NULL;
+
+  return TRUE;
+}
+
+static void
+net_address_meta_copy (GstBuffer * copybuf, GstNetAddressMeta * meta,
+    GstBuffer * buffer, gsize offset, gsize size)
+{
+  gst_buffer_add_net_address_meta (copybuf, meta->addr);
+}
+
+static void
+net_address_meta_free (GstNetAddressMeta * meta, GstBuffer * buffer)
+{
+  if (meta->addr)
+    g_object_unref (meta->addr);
+  meta->addr = NULL;
+}
+
+const GstMetaInfo *
+gst_net_address_meta_get_info (void)
+{
+  static const GstMetaInfo *meta_info = NULL;
+
+  if (meta_info == NULL) {
+    meta_info = gst_meta_register ("GstNetAddressMeta", "GstNetAddressMeta",
+        sizeof (GstNetAddressMeta),
+        (GstMetaInitFunction) net_address_meta_init,
+        (GstMetaFreeFunction) net_address_meta_free,
+        (GstMetaCopyFunction) net_address_meta_copy,
+        (GstMetaTransformFunction) NULL);
+  }
+  return meta_info;
+}
+
+GstNetAddressMeta *
+gst_buffer_add_net_address_meta (GstBuffer * buffer, GSocketAddress * addr)
+{
+  GstNetAddressMeta *meta;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (addr), NULL);
+
+  meta =
+      (GstNetAddressMeta *) gst_buffer_add_meta (buffer,
+      GST_NET_ADDRESS_META_INFO, NULL);
+
+  meta->addr = g_object_ref (addr);
+
+  return meta;
+}
similarity index 50%
rename from libs/gst/controller/gstcontrollerprivate.h
rename to libs/gst/net/gstnetaddressmeta.h
index 2dc57a5..c40cf48 100644 (file)
@@ -1,8 +1,5 @@
 /* GStreamer
- *
- * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
- *
- * gstcontrollerprivate.h: dynamic parameter control subsystem
+ * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef __GST_CONTROLLER_PRIVATE_H__
-#define __GST_CONTROLLER_PRIVATE_H__
+#ifndef __GST_NET_ADDRESS_META_H__
+#define __GST_NET_ADDRESS_META_H__
 
-#include <glib.h>
-#include <glib-object.h>
 #include <gst/gst.h>
-
-#include <gst/controller/gstcontroller.h>
-#include <gst/controller/gstcontrolsource.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
+typedef struct _GstNetAddressMeta GstNetAddressMeta;
+
 /**
- * GstControlledProperty:
+ * GstNetAddressMeta:
+ *
+ * Buffer metadata for network addresses.
  */
-typedef struct _GstControlledProperty
-{
-  GParamSpec *pspec;            /* GParamSpec for this property */
-  const gchar *name;            /* name of the property */
-  GstControlSource *csource;    /* GstControlSource for this property */
-  gboolean disabled;
-  GValue last_value;
-} GstControlledProperty;
+struct _GstNetAddressMeta {
+  GstMeta       meta;
+
+  GSocketAddress *addr;
+};
 
-#define GST_CONTROLLED_PROPERTY(obj)    ((GstControlledProperty *)(obj))
+const GstMetaInfo *gst_net_address_meta_get_info (void);
+#define GST_NET_ADDRESS_META_INFO (gst_net_address_meta_get_info())
 
-extern GQuark priv_gst_controller_key;
+#define gst_buffer_get_net_address_meta(b) \
+  ((GstNetAddressMeta*)gst_buffer_get_meta((b),GST_NET_ADDRESS_META_INFO))
+GstNetAddressMeta * gst_buffer_add_net_address_meta (GstBuffer      *buffer,
+                                                     GSocketAddress *addr);
 
 G_END_DECLS
 
-#endif /* __GST_CONTROLLER_PRIVATE_H__ */
+#endif /* __GST_NET_ADDRESS_META_H__ */
+
index 9a0e397..59b24a9 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2005 Wim Taymans <wim@fluendo.com>
  *                    2005 Andy Wingo <wingo@pobox.com>
+ * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
  *
  * gstnetclientclock.h: clock that synchronizes itself to a time provider over
  * the network
 #include "gstnettimepacket.h"
 #include "gstnetclientclock.h"
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if defined (_MSC_VER) && _MSC_VER >= 1400
-#include <io.h>
-#endif
+#include <gio/gio.h>
 
 GST_DEBUG_CATEGORY_STATIC (ncc_debug);
 #define GST_CAT_DEFAULT (ncc_debug)
@@ -68,15 +63,11 @@ GST_DEBUG_CATEGORY_STATIC (ncc_debug);
 #define DEFAULT_PORT            5637
 #define DEFAULT_TIMEOUT         GST_SECOND
 
-#ifdef G_OS_WIN32
-#define getsockname(sock,addr,len) getsockname(sock,addr,(int *)len)
-#endif
-
 enum
 {
   PROP_0,
   PROP_ADDRESS,
-  PROP_PORT,
+  PROP_PORT
 };
 
 #define GST_NET_CLIENT_CLOCK_GET_PRIVATE(obj)  \
@@ -84,15 +75,23 @@ enum
 
 struct _GstNetClientClockPrivate
 {
-  GstPollFD sock;
-  GstPoll *fdset;
+  GThread *thread;
+
+  GSocket *socket;
+  GSocketAddress *servaddr;
+  GCancellable *cancel;
+
+  GstClockTime timeout_expiration;
+
+  gchar *address;
+  gint port;
 };
 
-#define _do_init(type) \
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (ncc_debug, "netclock", 0, "Network client clock");
-
-GST_BOILERPLATE_FULL (GstNetClientClock, gst_net_client_clock,
-    GstSystemClock, GST_TYPE_SYSTEM_CLOCK, _do_init);
+#define gst_net_client_clock_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstNetClientClock, gst_net_client_clock,
+    GST_TYPE_SYSTEM_CLOCK, _do_init);
 
 static void gst_net_client_clock_finalize (GObject * object);
 static void gst_net_client_clock_set_property (GObject * object, guint prop_id,
@@ -102,27 +101,6 @@ static void gst_net_client_clock_get_property (GObject * object, guint prop_id,
 
 static void gst_net_client_clock_stop (GstNetClientClock * self);
 
-#ifdef G_OS_WIN32
-static int
-inet_aton (const char *c, struct in_addr *paddr)
-{
-  /* note that inet_addr is deprecated on unix because
-   * inet_addr returns -1 (INADDR_NONE) for the valid 255.255.255.255
-   * address. */
-  paddr->s_addr = inet_addr (c);
-  if (paddr->s_addr == INADDR_NONE)
-    return 0;
-
-  return 1;
-}
-#endif
-
-static void
-gst_net_client_clock_base_init (gpointer g_class)
-{
-  /* nop */
-}
-
 static void
 gst_net_client_clock_class_init (GstNetClientClockClass * klass)
 {
@@ -138,9 +116,8 @@ gst_net_client_clock_class_init (GstNetClientClockClass * klass)
 
   g_object_class_install_property (gobject_class, PROP_ADDRESS,
       g_param_spec_string ("address", "address",
-          "The address of the machine providing a time server, "
-          "as a dotted quad (x.x.x.x)", DEFAULT_ADDRESS,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          "The IP address of the machine providing a time server",
+          DEFAULT_ADDRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PORT,
       g_param_spec_int ("port", "port",
           "The port on which the remote server is listening", 0, G_MAXUINT16,
@@ -148,33 +125,20 @@ gst_net_client_clock_class_init (GstNetClientClockClass * klass)
 }
 
 static void
-gst_net_client_clock_init (GstNetClientClock * self,
-    GstNetClientClockClass * g_class)
+gst_net_client_clock_init (GstNetClientClock * self)
 {
   GstClock *clock = GST_CLOCK_CAST (self);
 
-#ifdef G_OS_WIN32
-  WSADATA w;
-  int error = WSAStartup (0x0202, &w);
-
-  if (error) {
-    GST_DEBUG_OBJECT (self, "Error on WSAStartup");
-  }
-  if (w.wVersion != 0x0202) {
-    WSACleanup ();
-  }
-#endif
   self->priv = GST_NET_CLIENT_CLOCK_GET_PRIVATE (self);
 
-  self->port = DEFAULT_PORT;
-  self->address = g_strdup (DEFAULT_ADDRESS);
+  self->priv->port = DEFAULT_PORT;
+  self->priv->address = g_strdup (DEFAULT_ADDRESS);
 
   clock->timeout = DEFAULT_TIMEOUT;
 
-  self->priv->sock.fd = -1;
-  self->thread = NULL;
+  self->priv->thread = NULL;
 
-  self->servaddr = NULL;
+  self->priv->servaddr = NULL;
 }
 
 static void
@@ -182,25 +146,23 @@ gst_net_client_clock_finalize (GObject * object)
 {
   GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object);
 
-  if (self->thread) {
+  if (self->priv->thread) {
     gst_net_client_clock_stop (self);
-    g_assert (self->thread == NULL);
-  }
-
-  if (self->priv->fdset) {
-    gst_poll_free (self->priv->fdset);
-    self->priv->fdset = NULL;
   }
 
-  g_free (self->address);
-  self->address = NULL;
+  g_free (self->priv->address);
+  self->priv->address = NULL;
 
-  g_free (self->servaddr);
-  self->servaddr = NULL;
+  if (self->priv->servaddr != NULL) {
+    g_object_unref (self->priv->servaddr);
+    self->priv->servaddr = NULL;
+  }
 
-#ifdef G_OS_WIN32
-  WSACleanup ();
-#endif
+  if (self->priv->socket != NULL) {
+    g_socket_close (self->priv->socket, NULL);
+    g_object_unref (self->priv->socket);
+    self->priv->socket = NULL;
+  }
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -213,14 +175,13 @@ gst_net_client_clock_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_ADDRESS:
-      g_free (self->address);
-      if (g_value_get_string (value) == NULL)
-        self->address = g_strdup (DEFAULT_ADDRESS);
-      else
-        self->address = g_strdup (g_value_get_string (value));
+      g_free (self->priv->address);
+      self->priv->address = g_value_dup_string (value);
+      if (self->priv->address == NULL)
+        self->priv->address = g_strdup (DEFAULT_ADDRESS);
       break;
     case PROP_PORT:
-      self->port = g_value_get_int (value);
+      self->priv->port = g_value_get_int (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -236,10 +197,10 @@ gst_net_client_clock_get_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_ADDRESS:
-      g_value_set_string (value, self->address);
+      g_value_set_string (value, self->priv->address);
       break;
     case PROP_PORT:
-      g_value_set_int (value, self->port);
+      g_value_set_int (value, self->priv->port);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -251,6 +212,7 @@ static void
 gst_net_client_clock_observe_times (GstNetClientClock * self,
     GstClockTime local_1, GstClockTime remote, GstClockTime local_2)
 {
+  GstClockTime current_timeout;
   GstClockTime local_avg;
   gdouble r_squared;
   GstClock *clock;
@@ -266,13 +228,14 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
 
   GST_CLOCK_SLAVE_LOCK (self);
   if (clock->filling) {
-    self->current_timeout = 0;
+    current_timeout = 0;
   } else {
     /* geto formula */
-    self->current_timeout =
-        (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
-    self->current_timeout = MIN (self->current_timeout, clock->timeout);
+    current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
+    current_timeout = MIN (current_timeout, clock->timeout);
   }
+  GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout));
+  self->priv->timeout_expiration = gst_util_get_timestamp () + current_timeout;
   GST_CLOCK_SLAVE_UNLOCK (clock);
 
   return;
@@ -286,67 +249,111 @@ bogus_observation:
   }
 }
 
-static gint
-gst_net_client_clock_do_select (GstNetClientClock * self)
+typedef struct
 {
-  while (TRUE) {
-    GstClockTime diff;
-    gint ret;
+  GSource source;
+  GstNetClientClock *clock;
+  gboolean *p_timeout;
+} GstNetClientClockTimeoutSource;
 
-    GST_LOG_OBJECT (self, "doing select");
+static gboolean
+gst_net_client_clock_timeout_source_prepare (GSource * s, gint * p_timeout)
+{
+  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
+  GstClockTime expiration_time = source->clock->priv->timeout_expiration;
+  GstClockTime now = gst_util_get_timestamp ();
 
-    diff = gst_clock_get_internal_time (GST_CLOCK (self));
-    ret = gst_poll_wait (self->priv->fdset, self->current_timeout);
-    diff = gst_clock_get_internal_time (GST_CLOCK (self)) - diff;
+  if (now >= expiration_time || (expiration_time - now) <= GST_MSECOND) {
+    *p_timeout = 0;
+    return TRUE;
+  }
 
-    if (diff > self->current_timeout)
-      self->current_timeout = 0;
-    else
-      self->current_timeout -= diff;
+  *p_timeout = (expiration_time - now) / GST_MSECOND;
+  GST_TRACE_OBJECT (source->clock, "time out in %d ms please", *p_timeout);
+  return FALSE;
+}
 
-    GST_LOG_OBJECT (self, "select returned %d", ret);
+static gboolean
+gst_net_client_clock_timeout_source_check (GSource * s)
+{
+  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
 
-    if (ret < 0 && errno != EBUSY) {
-      if (errno != EAGAIN && errno != EINTR)
-        goto select_error;
-      else
-        continue;
-    } else {
-      return ret;
-    }
+  return (gst_util_get_timestamp () >= source->clock->priv->timeout_expiration);
+}
 
-    g_assert_not_reached ();
+static gboolean
+gst_net_client_clock_timeout_source_dispatch (GSource * s, GSourceFunc cb,
+    gpointer data)
+{
+  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
 
-    /* log errors and keep going */
-  select_error:
-    {
-      GST_WARNING_OBJECT (self, "select error %d: %s (%d)", ret,
-          g_strerror (errno), errno);
-      continue;
-    }
-  }
+  GST_TRACE_OBJECT (source->clock, "timed out");
+  *source->p_timeout = TRUE;
+  return TRUE;
+}
+
+static gboolean
+gst_net_client_clock_socket_cb (GSocket * socket, GIOCondition condition,
+    gpointer user_data)
+{
+  GIOCondition *p_cond = user_data;
 
-  g_assert_not_reached ();
-  return -1;
+  GST_TRACE ("socket %p I/O condition: 0x%02x", socket, condition);
+  *p_cond = condition;
+  return TRUE;
 }
 
 static gpointer
 gst_net_client_clock_thread (gpointer data)
 {
   GstNetClientClock *self = data;
-  struct sockaddr_in tmpaddr;
-  socklen_t len;
   GstNetTimePacket *packet;
-  gint ret;
+  GMainContext *ctx;
+  GSourceFuncs funcs = { NULL, };
+  GSource *source;
+  GIOCondition cond;
+  gboolean timeout;
+  GSocket *socket = self->priv->socket;
+  GError *err = NULL;
   GstClock *clock = data;
 
-  while (TRUE) {
-    ret = gst_net_client_clock_do_select (self);
+  GST_INFO_OBJECT (self, "net client clock thread running, socket=%p", socket);
+
+  g_socket_set_blocking (socket, TRUE);
+  g_socket_set_timeout (socket, 0);
+
+  ctx = g_main_context_new ();
+
+  source = g_socket_create_source (socket, G_IO_IN, self->priv->cancel);
+  g_source_set_name (source, "GStreamer net client clock thread socket");
+  g_source_set_callback (source, (GSourceFunc) gst_net_client_clock_socket_cb,
+      &cond, NULL);
+  g_source_attach (source, ctx);
+  g_source_unref (source);
+
+  /* GSocket only support second granularity for timeouts, so roll our own
+   * timeout source (so we don't have to create a new source whenever the
+   * timeout changes, as we would have to do with the default timeout source) */
+  funcs.prepare = gst_net_client_clock_timeout_source_prepare;
+  funcs.check = gst_net_client_clock_timeout_source_check;
+  funcs.dispatch = gst_net_client_clock_timeout_source_dispatch;
+  funcs.finalize = NULL;
+  source = g_source_new (&funcs, sizeof (GstNetClientClockTimeoutSource));
+  ((GstNetClientClockTimeoutSource *) source)->clock = self;
+  ((GstNetClientClockTimeoutSource *) source)->p_timeout = &timeout;
+  g_source_set_name (source, "GStreamer net client clock timeout");
+  g_source_attach (source, ctx);
+  g_source_unref (source);
+
+  while (!g_cancellable_is_cancelled (self->priv->cancel)) {
+    cond = 0;
+    timeout = FALSE;
+    g_main_context_iteration (ctx, TRUE);
+
+    if (g_cancellable_is_cancelled (self->priv->cancel))
+      break;
 
-    if (ret < 0 && errno == EBUSY) {
-      GST_LOG_OBJECT (self, "stop");
-      goto stopped;
-    } else if (ret == 0) {
+    if (timeout) {
       /* timed out, let's send another packet */
       GST_DEBUG_OBJECT (self, "timed out");
 
@@ -356,24 +363,32 @@ gst_net_client_clock_thread (gpointer data)
 
       GST_DEBUG_OBJECT (self, "sending packet, local time = %" GST_TIME_FORMAT,
           GST_TIME_ARGS (packet->local_time));
-      gst_net_time_packet_send (packet, self->priv->sock.fd,
-          (struct sockaddr *) self->servaddr, sizeof (struct sockaddr_in));
+
+      gst_net_time_packet_send (packet, self->priv->socket,
+          self->priv->servaddr, NULL);
 
       g_free (packet);
 
-      /* reset timeout */
-      self->current_timeout = clock->timeout;
+      /* reset timeout (but are expecting a response sooner anyway) */
+      self->priv->timeout_expiration =
+          gst_util_get_timestamp () + clock->timeout;
       continue;
-    } else if (gst_poll_fd_can_read (self->priv->fdset, &self->priv->sock)) {
-      /* got data in */
-      GstClockTime new_local = gst_clock_get_internal_time (GST_CLOCK (self));
+    }
+
+    /* got data to read? */
+    if ((cond & G_IO_IN)) {
+      GstClockTime new_local;
 
-      len = sizeof (struct sockaddr);
-      packet = gst_net_time_packet_receive (self->priv->sock.fd,
-          (struct sockaddr *) &tmpaddr, &len);
+      new_local = gst_clock_get_internal_time (GST_CLOCK (self));
 
-      if (!packet)
-        goto receive_error;
+      packet = gst_net_time_packet_receive (socket, NULL, &err);
+
+      if (err != NULL) {
+        GST_WARNING_OBJECT (self, "receive error: %s", err->message);
+        g_error_free (err);
+        err = NULL;
+        continue;
+      }
 
       GST_LOG_OBJECT (self, "got packet back");
       GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT,
@@ -389,81 +404,69 @@ gst_net_client_clock_thread (gpointer data)
 
       g_free (packet);
       continue;
-    } else {
-      GST_WARNING_OBJECT (self, "unhandled select return state?");
-      continue;
     }
 
-    g_assert_not_reached ();
-
-  stopped:
-    {
-      GST_DEBUG_OBJECT (self, "shutting down");
-      /* socket gets closed in _stop() */
-      return NULL;
-    }
-  receive_error:
-    {
-      GST_WARNING_OBJECT (self, "receive error");
+    if ((cond & (G_IO_ERR | G_IO_HUP))) {
+      GST_DEBUG_OBJECT (self, "socket error?! %s", g_strerror (errno));
+      g_usleep (G_USEC_PER_SEC / 10);
       continue;
     }
-
-    g_assert_not_reached ();
-
   }
 
-  g_assert_not_reached ();
-
+  GST_INFO_OBJECT (self, "shutting down net client clock thread");
+  g_main_context_unref (ctx);
   return NULL;
 }
 
 static gboolean
 gst_net_client_clock_start (GstNetClientClock * self)
 {
-  struct sockaddr_in servaddr, myaddr;
-  socklen_t len;
-  gint ret;
+  GSocketAddress *servaddr;
+  GSocketAddress *myaddr;
+  GInetAddress *inetaddr;
+  GSocket *socket;
   GError *error = NULL;
 
-  g_return_val_if_fail (self->address != NULL, FALSE);
-  g_return_val_if_fail (self->servaddr == NULL, FALSE);
+  g_return_val_if_fail (self->priv->address != NULL, FALSE);
+  g_return_val_if_fail (self->priv->servaddr == NULL, FALSE);
 
-  if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+  socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
+      G_SOCKET_PROTOCOL_UDP, &error);
+
+  if (socket == NULL)
     goto no_socket;
 
-  self->priv->sock.fd = ret;
+  /* check address we're bound to, mostly for debugging purposes */
+  myaddr = g_socket_get_local_address (socket, &error);
 
-  len = sizeof (myaddr);
-  ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &myaddr, &len);
-  if (ret < 0)
+  if (myaddr == NULL)
     goto getsockname_error;
 
-  memset (&servaddr, 0, sizeof (servaddr));
-  servaddr.sin_family = AF_INET;        /* host byte order */
-  servaddr.sin_port = htons (self->port);       /* short, network byte order */
-
   GST_DEBUG_OBJECT (self, "socket opened on UDP port %hd",
-      ntohs (servaddr.sin_port));
+      g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr)));
 
-  if (!inet_aton (self->address, &servaddr.sin_addr))
+  g_object_unref (myaddr);
+
+  /* create target address */
+  inetaddr = g_inet_address_new_from_string (self->priv->address);
+
+  if (inetaddr == NULL)
     goto bad_address;
 
-  self->servaddr = g_malloc (sizeof (struct sockaddr_in));
-  memcpy (self->servaddr, &servaddr, sizeof (servaddr));
+  servaddr = g_inet_socket_address_new (inetaddr, self->priv->port);
+  g_object_unref (inetaddr);
+
+  g_assert (servaddr != NULL);
 
-  GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address,
-      self->port);
+  GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->priv->address,
+      self->priv->port);
 
-  gst_poll_add_fd (self->priv->fdset, &self->priv->sock);
-  gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE);
+  self->priv->cancel = g_cancellable_new ();
+  self->priv->socket = socket;
+  self->priv->servaddr = G_SOCKET_ADDRESS (servaddr);
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  self->thread = g_thread_create (gst_net_client_clock_thread, self, TRUE,
-      &error);
-#else
-  self->thread = g_thread_try_new ("GstNetClientClock",
+  self->priv->thread = g_thread_try_new ("GstNetClientClock",
       gst_net_client_clock_thread, self, &error);
-#endif
 
   if (error != NULL)
     goto no_thread;
@@ -473,34 +476,31 @@ gst_net_client_clock_start (GstNetClientClock * self)
   /* ERRORS */
 no_socket:
   {
-    GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
+    GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message);
+    g_error_free (error);
     return FALSE;
   }
 getsockname_error:
   {
-    GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
+    GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message);
+    g_error_free (error);
+    g_object_unref (socket);
     return FALSE;
   }
 bad_address:
   {
-    GST_ERROR_OBJECT (self, "inet_aton failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
+    GST_ERROR_OBJECT (self, "inet_address_new_from_string('%s') failed",
+        self->priv->address);
+    g_object_unref (socket);
     return FALSE;
   }
 no_thread:
   {
     GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
-    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    g_free (self->servaddr);
-    self->servaddr = NULL;
+    g_object_unref (self->priv->servaddr);
+    self->priv->servaddr = NULL;
+    g_object_unref (self->priv->socket);
+    self->priv->socket = NULL;
     g_error_free (error);
     return FALSE;
   }
@@ -509,15 +509,25 @@ no_thread:
 static void
 gst_net_client_clock_stop (GstNetClientClock * self)
 {
-  gst_poll_set_flushing (self->priv->fdset, TRUE);
-  g_thread_join (self->thread);
-  self->thread = NULL;
-
-  if (self->priv->sock.fd != -1) {
-    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-  }
+  if (self->priv->thread == NULL)
+    return;
+
+  GST_INFO_OBJECT (self, "stopping...");
+  g_cancellable_cancel (self->priv->cancel);
+
+  g_thread_join (self->priv->thread);
+  self->priv->thread = NULL;
+
+  g_object_unref (self->priv->cancel);
+  self->priv->cancel = NULL;
+
+  g_object_unref (self->priv->servaddr);
+  self->priv->servaddr = NULL;
+
+  g_object_unref (self->priv->socket);
+  self->priv->socket = NULL;
+
+  GST_INFO_OBJECT (self, "stopped");
 }
 
 /**
@@ -538,6 +548,7 @@ GstClock *
 gst_net_client_clock_new (gchar * name, const gchar * remote_address,
     gint remote_port, GstClockTime base_time)
 {
+  /* FIXME: gst_net_client_clock_new() should be a thin wrapper for g_object_new() */
   GstNetClientClock *ret;
   GstClockTime internal;
 
@@ -569,22 +580,12 @@ gst_net_client_clock_new (gchar * name, const gchar * remote_address,
     }
   }
 
-  if ((ret->priv->fdset = gst_poll_new (TRUE)) == NULL)
-    goto no_fdset;
-
   if (!gst_net_client_clock_start (ret))
     goto failed_start;
 
   /* all systems go, cap'n */
   return (GstClock *) ret;
 
-no_fdset:
-  {
-    GST_ERROR_OBJECT (ret, "could not create an fdset: %s (%d)",
-        g_strerror (errno), errno);
-    gst_object_unref (ret);
-    return NULL;
-  }
 failed_start:
   {
     /* already printed a nice error */
index 44b2e2e..a0fcf1f 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2005 Wim Taymans <wim@fluendo.com>
  *                    2005 Andy Wingo <wingo@pobox.com>
+ * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
  *
  * gstnetclientclock.h: clock that synchronizes itself to a time provider over
  * the network
 
 G_BEGIN_DECLS
 
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-
-#ifdef G_OS_WIN32
-# include <winsock2.h>
-#else
-# include <netdb.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-#endif /*G_OS_WIN32 */
-
-#include <fcntl.h>
-
 #define GST_TYPE_NET_CLIENT_CLOCK \
   (gst_net_client_clock_get_type())
 #define GST_NET_CLIENT_CLOCK(obj) \
@@ -69,24 +55,10 @@ typedef struct _GstNetClientClockPrivate GstNetClientClockPrivate;
 struct _GstNetClientClock {
   GstSystemClock clock;
 
-  /*< protected >*/
-  gchar *address;
-  gint port;
-
-  /*< private >*/
-  int sock;
-  int control_sock[2];
-
-  GstClockTime current_timeout;
-
-  struct sockaddr_in *servaddr;
-
-  GThread *thread;
-
   /*< private >*/
   GstNetClientClockPrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstNetClientClockClass {
@@ -97,6 +69,7 @@ struct _GstNetClientClockClass {
 };
 
 GType           gst_net_client_clock_get_type  (void);
+
 GstClock*      gst_net_client_clock_new        (gchar *name, const gchar *remote_address,
                                                  gint remote_port, GstClockTime base_time);
 
index bf8a027..597199e 100644 (file)
@@ -1,5 +1,7 @@
 /* GStreamer
  * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
+ * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -107,112 +109,106 @@ gst_net_time_packet_serialize (const GstNetTimePacket * packet)
 
 /**
  * gst_net_time_packet_receive:
- * @fd: a file descriptor created by socket(2)
- * @addr: a pointer to a sockaddr to hold the address of the sender
- * @len: a pointer to the size of the data pointed to by @addr
+ * @socket: socket to receive the time packet on
+ * @src_addr: (out): address of variable to return sender address
+ * @err: return address for a #GError, or NULL
  *
- * Receives a #GstNetTimePacket over a socket. Handles interrupted system calls,
- * but otherwise returns NULL on error. See recvfrom(2) for more information on
- * how to interpret @sockaddr.
+ * Receives a #GstNetTimePacket over a socket. Handles interrupted system
+ * calls, but otherwise returns NULL on error.
  *
- * MT safe. Caller owns return value (g_free to free).
- *
- * Returns: The new #GstNetTimePacket.
+ * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free
+ *    with g_free() when done.
  */
 GstNetTimePacket *
-gst_net_time_packet_receive (gint fd, struct sockaddr * addr, socklen_t * len)
+gst_net_time_packet_receive (GSocket * socket,
+    GSocketAddress ** src_address, GError ** error)
 {
-  guint8 buffer[GST_NET_TIME_PACKET_SIZE];
-  gint ret;
+  gchar buffer[GST_NET_TIME_PACKET_SIZE];
+  GError *err = NULL;
+  gssize ret;
+
+  g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   while (TRUE) {
-#ifdef G_OS_WIN32
-    ret = recvfrom (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE,
-#else
-    ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
-#endif
-        0, (struct sockaddr *) addr, len);
+    ret = g_socket_receive_from (socket, src_address, buffer,
+        GST_NET_TIME_PACKET_SIZE, NULL, &err);
+
     if (ret < 0) {
-      if (errno != EAGAIN && errno != EINTR)
-        goto receive_error;
-      else
+      if (err->code == G_IO_ERROR_WOULD_BLOCK) {
+        g_error_free (err);
+        err = NULL;
         continue;
+      } else {
+        goto receive_error;
+      }
     } else if (ret < GST_NET_TIME_PACKET_SIZE) {
       goto short_packet;
     } else {
-      return gst_net_time_packet_new (buffer);
+      return gst_net_time_packet_new ((const guint8 *) buffer);
     }
   }
 
 receive_error:
   {
-    GST_DEBUG ("receive error %d: %s (%d)", ret, g_strerror (errno), errno);
+    GST_DEBUG ("receive error: %s", err->message);
+    g_propagate_error (error, err);
     return NULL;
   }
 short_packet:
   {
     GST_DEBUG ("someone sent us a short packet (%d < %d)",
         ret, GST_NET_TIME_PACKET_SIZE);
+    g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+        "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE);
     return NULL;
   }
 }
 
 /**
  * gst_net_time_packet_send:
- * @packet: the #GstNetTimePacket
- * @fd: a file descriptor created by socket(2)
- * @addr: a pointer to a sockaddr to hold the address of the sender
- * @len: the size of the data pointed to by @addr
+ * @packet: the #GstNetTimePacket to send
+ * @socket: socket to send the time packet on
+ * @dest_addr: address to send the time packet to
+ * @err: return address for a #GError, or NULL
  *
- * Sends a #GstNetTimePacket over a socket. Essentially a thin wrapper around
- * sendto(2) and gst_net_time_packet_serialize(). 
+ * Sends a #GstNetTimePacket over a socket.
  *
  * MT safe.
  *
- * Returns: The return value of sendto(2).
+ * Returns: TRUE if successful, FALSE in case an error occured.
  */
-gint
-gst_net_time_packet_send (const GstNetTimePacket * packet, gint fd,
-    struct sockaddr * addr, socklen_t len)
+gboolean
+gst_net_time_packet_send (const GstNetTimePacket * packet,
+    GSocket * socket, GSocketAddress * dest_address, GError ** error)
 {
-#if defined __CYGWIN__
-  gint fdflags;
-#elif defined G_OS_WIN32
-  gulong flags;
-#endif
-
+  gboolean was_blocking;
   guint8 *buffer;
-  gint ret, send_flags;
+  gssize res;
 
-  g_return_val_if_fail (packet != NULL, -EINVAL);
+  g_return_val_if_fail (packet != NULL, FALSE);
+  g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-#ifdef __CYGWIN__
-  send_flags = 0;
-  fdflags = fcntl (fd, F_GETFL);
-  fcntl (fd, F_SETFL, fdflags | O_NONBLOCK);
-#elif defined G_OS_WIN32
-  flags = 1;
-  send_flags = 0;
-#else
-  send_flags = MSG_DONTWAIT;
-#endif
+  was_blocking = g_socket_get_blocking (socket);
 
+  if (was_blocking)
+    g_socket_set_blocking (socket, FALSE);
+
+  /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
   buffer = gst_net_time_packet_serialize (packet);
 
-#ifdef G_OS_WIN32
-  ioctlsocket (fd, FIONBIO, &flags);    /* Set nonblocking mode */
-  ret =
-      sendto (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr,
-      len);
-#else
-  ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
-#endif
+  res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
+      GST_NET_TIME_PACKET_SIZE, NULL, error);
 
-#ifdef __CYGWIN__
-  fcntl (fd, F_SETFL, fdflags);
-#endif
+  /* datagram packets should be sent as a whole or not at all */
+  g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE);
 
   g_free (buffer);
 
-  return ret;
+  if (was_blocking)
+    g_socket_set_blocking (socket, TRUE);
+
+  return (res == GST_NET_TIME_PACKET_SIZE);
 }
index 48eefa7..e37342c 100644 (file)
 #define __GST_NET_TIME_PACKET_H__
 
 #include <gst/gst.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-
-#ifdef G_OS_WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#ifndef socklen_t
-#define socklen_t int
-#endif
-#else
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
 /**
  * GST_NET_TIME_PACKET_SIZE:
  *
@@ -63,14 +47,18 @@ struct _GstNetTimePacket {
   GstClockTime remote_time;
 };
 
-GstNetTimePacket*      gst_net_time_packet_new         (const guint8 *buffer);
-guint8*                        gst_net_time_packet_serialize   (const GstNetTimePacket *packet);
+/* FIXME 0.11: get rid of the packet stuff? add an unref/free function? */
+GstNetTimePacket*       gst_net_time_packet_new         (const guint8 *buffer);
+guint8*                 gst_net_time_packet_serialize   (const GstNetTimePacket *packet);
+
+GstNetTimePacket*      gst_net_time_packet_receive     (GSocket         * socket,
+                                                         GSocketAddress ** src_address,
+                                                         GError         ** error);
 
-GstNetTimePacket*      gst_net_time_packet_receive     (gint fd, struct sockaddr *addr,
-                                                         socklen_t *len);
-gint                   gst_net_time_packet_send        (const GstNetTimePacket *packet,
-                                                         gint fd, struct sockaddr *addr,
-                                                         socklen_t len);
+gboolean                gst_net_time_packet_send        (const GstNetTimePacket * packet,
+                                                         GSocket                * socket,
+                                                         GSocketAddress         * dest_address,
+                                                         GError                ** error);
 
 G_END_DECLS
 
index dacdd87..f008c00 100644 (file)
 #include "gstnettimeprovider.h"
 #include "gstnettimepacket.h"
 
-#include <glib.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if defined (_MSC_VER) && _MSC_VER >= 1400
-#include <io.h>
-#endif
-
-#ifndef G_OS_WIN32
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_FIONREAD_IN_SYS_FILIO
-#include <sys/filio.h>
-#endif
-
 GST_DEBUG_CATEGORY_STATIC (ntp_debug);
 #define GST_CAT_DEFAULT (ntp_debug)
 
-#ifdef G_OS_WIN32
-#define close(sock) closesocket(sock)
-#endif
-
 #define DEFAULT_ADDRESS         "0.0.0.0"
 #define DEFAULT_PORT            5637
 
-#define IS_ACTIVE(self) (g_atomic_int_get (&((self)->active.active)))
+#define IS_ACTIVE(self) (g_atomic_int_get (&((self)->priv->active)))
 
-#ifdef G_OS_WIN32
-#define setsockopt(sock, sol_flags, reuse_flags, ru, sizeofru) setsockopt (sock, sol_flags, reuse_flags, (char *)ru, sizeofru)
-#endif
 enum
 {
   PROP_0,
@@ -82,7 +57,6 @@ enum
   PROP_ADDRESS,
   PROP_CLOCK,
   PROP_ACTIVE
-      /* FILL ME */
 };
 
 #define GST_NET_TIME_PROVIDER_GET_PRIVATE(obj)  \
@@ -90,8 +64,17 @@ enum
 
 struct _GstNetTimeProviderPrivate
 {
-  GstPollFD sock;
-  GstPoll *fdset;
+  gchar *address;
+  int port;
+
+  GThread *thread;
+
+  GstClock *clock;
+
+  gboolean active;              /* ATOMIC */
+
+  GSocket *socket;
+  GCancellable *cancel;
 };
 
 static gboolean gst_net_time_provider_start (GstNetTimeProvider * bself);
@@ -105,30 +88,13 @@ static void gst_net_time_provider_set_property (GObject * object, guint prop_id,
 static void gst_net_time_provider_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-#define _do_init(type) \
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (ntp_debug, "nettime", 0, "Network time provider");
 
-GST_BOILERPLATE_FULL (GstNetTimeProvider, gst_net_time_provider, GstObject,
+#define gst_net_time_provider_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstNetTimeProvider, gst_net_time_provider,
     GST_TYPE_OBJECT, _do_init);
 
-#ifdef G_OS_WIN32
-static int
-inet_aton (const char *c, struct in_addr *paddr)
-{
-  paddr->s_addr = inet_addr (c);
-  if (paddr->s_addr == INADDR_NONE)
-    return 0;
-
-  return 1;
-}
-#endif
-
-static void
-gst_net_time_provider_base_init (gpointer g_class)
-{
-  /* Do nothing here */
-}
-
 static void
 gst_net_time_provider_class_init (GstNetTimeProviderClass * klass)
 {
@@ -163,27 +129,14 @@ gst_net_time_provider_class_init (GstNetTimeProviderClass * klass)
 }
 
 static void
-gst_net_time_provider_init (GstNetTimeProvider * self,
-    GstNetTimeProviderClass * g_class)
+gst_net_time_provider_init (GstNetTimeProvider * self)
 {
-#ifdef G_OS_WIN32
-  WSADATA w;
-  int error = WSAStartup (0x0202, &w);
-
-  if (error) {
-    GST_DEBUG_OBJECT (self, "Error on WSAStartup");
-  }
-  if (w.wVersion != 0x0202) {
-    WSACleanup ();
-  }
-#endif
   self->priv = GST_NET_TIME_PROVIDER_GET_PRIVATE (self);
 
-  self->port = DEFAULT_PORT;
-  self->priv->sock.fd = -1;
-  self->address = g_strdup (DEFAULT_ADDRESS);
-  self->thread = NULL;
-  self->active.active = TRUE;
+  self->priv->port = DEFAULT_PORT;
+  self->priv->address = g_strdup (DEFAULT_ADDRESS);
+  self->priv->thread = NULL;
+  self->priv->active = TRUE;
 }
 
 static void
@@ -191,26 +144,17 @@ gst_net_time_provider_finalize (GObject * object)
 {
   GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
 
-  if (self->thread) {
+  if (self->priv->thread) {
     gst_net_time_provider_stop (self);
-    g_assert (self->thread == NULL);
-  }
-
-  if (self->priv->fdset) {
-    gst_poll_free (self->priv->fdset);
-    self->priv->fdset = NULL;
+    g_assert (self->priv->thread == NULL);
   }
 
-  g_free (self->address);
-  self->address = NULL;
-
-  if (self->clock)
-    gst_object_unref (self->clock);
-  self->clock = NULL;
+  g_free (self->priv->address);
+  self->priv->address = NULL;
 
-#ifdef G_OS_WIN32
-  WSACleanup ();
-#endif
+  if (self->priv->clock)
+    gst_object_unref (self->priv->clock);
+  self->priv->clock = NULL;
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -219,75 +163,56 @@ static gpointer
 gst_net_time_provider_thread (gpointer data)
 {
   GstNetTimeProvider *self = data;
-  struct sockaddr_in tmpaddr;
-  socklen_t len;
+  GCancellable *cancel = self->priv->cancel;
+  GSocket *socket = self->priv->socket;
   GstNetTimePacket *packet;
-  gint ret;
-
-  while (TRUE) {
-    GST_LOG_OBJECT (self, "doing select");
-    ret = gst_poll_wait (self->priv->fdset, GST_CLOCK_TIME_NONE);
-    GST_LOG_OBJECT (self, "select returned %d", ret);
-
-    if (ret <= 0) {
-      if (errno == EBUSY) {
-        GST_LOG_OBJECT (self, "stop");
-        goto stopped;
-      } else if (errno != EAGAIN && errno != EINTR)
-        goto select_error;
-      else
-        continue;
-    } else {
-      /* got data in */
-      len = sizeof (struct sockaddr);
-
-      packet = gst_net_time_packet_receive (self->priv->sock.fd,
-          (struct sockaddr *) &tmpaddr, &len);
+  GError *err = NULL;
 
-      if (!packet)
-        goto receive_error;
+  GST_INFO_OBJECT (self, "time provider thread is running");
 
-      if (IS_ACTIVE (self)) {
-        /* do what we were asked to and send the packet back */
-        packet->remote_time = gst_clock_get_time (self->clock);
+  while (TRUE) {
+    GSocketAddress *sender_addr = NULL;
 
-        /* ignore errors */
-        gst_net_time_packet_send (packet, self->priv->sock.fd,
-            (struct sockaddr *) &tmpaddr, len);
-      }
+    GST_LOG_OBJECT (self, "waiting on socket");
+    if (!g_socket_condition_wait (socket, G_IO_IN, cancel, &err)) {
+      GST_INFO_OBJECT (self, "socket error: %s", err->message);
 
-      g_free (packet);
+      if (err->code == G_IO_ERROR_CANCELLED)
+        break;
 
+      /* try again */
+      g_usleep (G_USEC_PER_SEC / 10);
+      g_error_free (err);
+      err = NULL;
       continue;
     }
 
-    g_assert_not_reached ();
+    /* got data in */
+    packet = gst_net_time_packet_receive (socket, &sender_addr, &err);
 
-    /* log errors and keep going */
-  select_error:
-    {
-      GST_DEBUG_OBJECT (self, "select error %d: %s (%d)", ret,
-          g_strerror (errno), errno);
-      continue;
-    }
-  stopped:
-    {
-      GST_DEBUG_OBJECT (self, "shutting down");
-      /* close socket */
-      return NULL;
-    }
-  receive_error:
-    {
-      GST_DEBUG_OBJECT (self, "receive error");
+    if (err != NULL) {
+      GST_DEBUG_OBJECT (self, "receive error: %s", err->message);
+      g_usleep (G_USEC_PER_SEC / 10);
+      g_error_free (err);
+      err = NULL;
       continue;
     }
 
-    g_assert_not_reached ();
+    if (IS_ACTIVE (self)) {
+      /* do what we were asked to and send the packet back */
+      packet->remote_time = gst_clock_get_time (self->priv->clock);
 
+      /* ignore errors */
+      gst_net_time_packet_send (packet, socket, sender_addr, NULL);
+      g_object_unref (sender_addr);
+      g_free (packet);
+    }
   }
 
-  g_assert_not_reached ();
+  if (err != NULL)
+    g_error_free (err);
 
+  GST_INFO_OBJECT (self, "time provider thread is stopping");
   return NULL;
 }
 
@@ -296,25 +221,25 @@ gst_net_time_provider_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
   GstNetTimeProvider *self = GST_NET_TIME_PROVIDER (object);
-  GstClock **clock_p = &self->clock;
+  GstClock **clock_p = &self->priv->clock;
 
   switch (prop_id) {
     case PROP_PORT:
-      self->port = g_value_get_int (value);
+      self->priv->port = g_value_get_int (value);
       break;
     case PROP_ADDRESS:
-      g_free (self->address);
+      g_free (self->priv->address);
       if (g_value_get_string (value) == NULL)
-        self->address = g_strdup (DEFAULT_ADDRESS);
+        self->priv->address = g_strdup (DEFAULT_ADDRESS);
       else
-        self->address = g_strdup (g_value_get_string (value));
+        self->priv->address = g_strdup (g_value_get_string (value));
       break;
     case PROP_CLOCK:
       gst_object_replace ((GstObject **) clock_p,
           (GstObject *) g_value_get_object (value));
       break;
     case PROP_ACTIVE:
-      g_atomic_int_set (&self->active.active, g_value_get_boolean (value));
+      g_atomic_int_set (&self->priv->active, g_value_get_boolean (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -330,13 +255,13 @@ gst_net_time_provider_get_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_PORT:
-      g_value_set_int (value, self->port);
+      g_value_set_int (value, self->priv->port);
       break;
     case PROP_ADDRESS:
-      g_value_set_string (value, self->address);
+      g_value_set_string (value, self->priv->address);
       break;
     case PROP_CLOCK:
-      g_value_set_object (value, self->clock);
+      g_value_set_object (value, self->priv->clock);
       break;
     case PROP_ACTIVE:
       g_value_set_boolean (value, IS_ACTIVE (self));
@@ -350,118 +275,86 @@ gst_net_time_provider_get_property (GObject * object, guint prop_id,
 static gboolean
 gst_net_time_provider_start (GstNetTimeProvider * self)
 {
-  gint ru;
-  struct sockaddr_in my_addr;
-  socklen_t len;
+  GSocketAddress *socket_addr, *bound_addr;
+  GInetAddress *inet_addr;
+  GSocket *socket;
+  GError *err = NULL;
   int port;
-  gint ret;
-  GError *error = NULL;
 
-  if ((ret = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+  if (self->priv->address) {
+    inet_addr = g_inet_address_new_from_string (self->priv->address);
+    if (inet_addr == NULL)
+      goto invalid_address;
+  } else {
+    inet_addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
+  }
+
+  GST_LOG_OBJECT (self, "creating socket");
+  socket = g_socket_new (g_inet_address_get_family (inet_addr),
+      G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err);
+
+  if (err != NULL)
     goto no_socket;
 
-  self->priv->sock.fd = ret;
-
-  ru = 1;
-  ret =
-      setsockopt (self->priv->sock.fd, SOL_SOCKET, SO_REUSEADDR, &ru,
-      sizeof (ru));
-  if (ret < 0)
-    goto setsockopt_error;
-
-  memset (&my_addr, 0, sizeof (my_addr));
-  my_addr.sin_family = AF_INET; /* host byte order */
-  my_addr.sin_port = htons ((gint16) self->port);       /* short, network byte order */
-  my_addr.sin_addr.s_addr = INADDR_ANY;
-  if (self->address) {
-    ret = inet_aton (self->address, &my_addr.sin_addr);
-    if (ret == 0)
-      goto invalid_address_error;
-  }
+  GST_DEBUG_OBJECT (self, "binding on port %d", self->priv->port);
+  socket_addr = g_inet_socket_address_new (inet_addr, self->priv->port);
+  g_socket_bind (socket, socket_addr, TRUE, &err);
+  g_object_unref (socket_addr);
+  g_object_unref (inet_addr);
 
-  GST_DEBUG_OBJECT (self, "binding on port %d", self->port);
-  ret =
-      bind (self->priv->sock.fd, (struct sockaddr *) &my_addr,
-      sizeof (my_addr));
-  if (ret < 0)
+  if (err != NULL)
     goto bind_error;
 
-  len = sizeof (my_addr);
-  ret = getsockname (self->priv->sock.fd, (struct sockaddr *) &my_addr, &len);
-  if (ret < 0)
-    goto getsockname_error;
+  bound_addr = g_socket_get_local_address (socket, NULL);
+  port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_addr));
+  GST_DEBUG_OBJECT (self, "bound on UDP port %d", port);
+  g_object_unref (bound_addr);
 
-  port = ntohs (my_addr.sin_port);
-  GST_DEBUG_OBJECT (self, "bound, on port %d", port);
-
-  if (port != self->port) {
-    self->port = port;
-    GST_DEBUG_OBJECT (self, "notifying %d", port);
+  if (port != self->priv->port) {
+    self->priv->port = port;
+    GST_DEBUG_OBJECT (self, "notifying port %d", port);
     g_object_notify (G_OBJECT (self), "port");
   }
 
-  gst_poll_add_fd (self->priv->fdset, &self->priv->sock);
-  gst_poll_fd_ctl_read (self->priv->fdset, &self->priv->sock, TRUE);
+  self->priv->socket = socket;
+  self->priv->cancel = g_cancellable_new ();
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  self->thread = g_thread_create (gst_net_time_provider_thread, self, TRUE,
-      &error);
-#else
-  self->thread = g_thread_try_new ("GstNetTimeProvider",
-      gst_net_time_provider_thread, self, &error);
-#endif
+  self->priv->thread = g_thread_try_new ("GstNetTimeProvider",
+      gst_net_time_provider_thread, self, &err);
 
-  if (error != NULL)
+  if (err != NULL)
     goto no_thread;
 
   return TRUE;
 
   /* ERRORS */
-no_socket:
+invalid_address:
   {
-    GST_ERROR_OBJECT (self, "socket failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
+    GST_ERROR_OBJECT (self, "invalid address: %s", self->priv->address);
     return FALSE;
   }
-setsockopt_error:
-  {
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    GST_ERROR_OBJECT (self, "setsockopt failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
-    return FALSE;
-  }
-invalid_address_error:
+no_socket:
   {
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    GST_ERROR_OBJECT (self, "invalid network address %s: %s (%d)",
-        self->address, g_strerror (errno), errno);
+    GST_ERROR_OBJECT (self, "could not create socket: %s", err->message);
+    g_error_free (err);
+    g_object_unref (inet_addr);
     return FALSE;
   }
 bind_error:
   {
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    GST_ERROR_OBJECT (self, "bind failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
-    return FALSE;
-  }
-getsockname_error:
-  {
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    GST_ERROR_OBJECT (self, "getsockname failed %d: %s (%d)", ret,
-        g_strerror (errno), errno);
+    GST_ERROR_OBJECT (self, "bind failed: %s", err->message);
+    g_error_free (err);
+    g_object_unref (socket);
     return FALSE;
   }
 no_thread:
   {
-    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-    GST_ERROR_OBJECT (self, "could not create thread: %s", error->message);
-    g_error_free (error);
+    GST_ERROR_OBJECT (self, "could not create thread: %s", err->message);
+    g_error_free (err);
+    g_object_unref (self->priv->socket);
+    self->priv->socket = NULL;
+    g_object_unref (self->priv->cancel);
+    self->priv->cancel = NULL;
     return FALSE;
   }
 }
@@ -469,15 +362,21 @@ no_thread:
 static void
 gst_net_time_provider_stop (GstNetTimeProvider * self)
 {
-  gst_poll_set_flushing (self->priv->fdset, TRUE);
-  g_thread_join (self->thread);
-  self->thread = NULL;
-
-  if (self->priv->sock.fd != -1) {
-    gst_poll_remove_fd (self->priv->fdset, &self->priv->sock);
-    close (self->priv->sock.fd);
-    self->priv->sock.fd = -1;
-  }
+  g_return_if_fail (self->priv->thread != NULL);
+
+  GST_INFO_OBJECT (self, "stopping..");
+  g_cancellable_cancel (self->priv->cancel);
+
+  g_thread_join (self->priv->thread);
+  self->priv->thread = NULL;
+
+  g_object_unref (self->priv->cancel);
+  self->priv->cancel = NULL;
+
+  g_object_unref (self->priv->socket);
+  self->priv->socket = NULL;
+
+  GST_INFO_OBJECT (self, "stopped");
 }
 
 /**
@@ -502,22 +401,12 @@ gst_net_time_provider_new (GstClock * clock, const gchar * address, gint port)
   ret = g_object_new (GST_TYPE_NET_TIME_PROVIDER, "clock", clock, "address",
       address, "port", port, NULL);
 
-  if ((ret->priv->fdset = gst_poll_new (TRUE)) == NULL)
-    goto no_fdset;
-
   if (!gst_net_time_provider_start (ret))
     goto failed_start;
 
   /* all systems go, cap'n */
   return ret;
 
-no_fdset:
-  {
-    GST_ERROR_OBJECT (ret, "could not create an fdset: %s (%d)",
-        g_strerror (errno), errno);
-    gst_object_unref (ret);
-    return NULL;
-  }
 failed_start:
   {
     /* already printed a nice error */
index c9609e1..81c0fbe 100644 (file)
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
  *               2006 Joni Valtanen <joni.valtanen@movial.fi>
+ * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #ifndef __GST_NET_TIME_PROVIDER_H__
 #define __GST_NET_TIME_PROVIDER_H__
 
-/* to determinate os */
-#include <glib.h>
-
 #include <gst/gst.h>
 
 G_BEGIN_DECLS
 
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-
-#ifdef G_OS_WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#ifndef socklen_t
-#define socklen_t int
-#endif
-#else
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#include <fcntl.h>
-
 #define GST_TYPE_NET_TIME_PROVIDER \
   (gst_net_time_provider_get_type())
 #define GST_NET_TIME_PROVIDER(obj) \
@@ -63,7 +42,6 @@ typedef struct _GstNetTimeProvider GstNetTimeProvider;
 typedef struct _GstNetTimeProviderClass GstNetTimeProviderClass;
 typedef struct _GstNetTimeProviderPrivate GstNetTimeProviderPrivate;
 
-
 /**
  * GstNetTimeProvider:
  *
@@ -73,34 +51,20 @@ struct _GstNetTimeProvider {
   GstObject parent;
 
   /*< private >*/
-  gchar *address;
-  int port;
-
-  int sock;
-  int control_sock[2];
-
-  GThread *thread;
-
-  GstClock *clock;
-
-  union {
-    gpointer _gst_reserved1;
-    /* has to be a gint, we use atomic ops here */
-    gint active;
-  } active;
-
-  /*< private >*/
   GstNetTimeProviderPrivate *priv;
 
-  gpointer _gst_reserved[GST_PADDING - 2];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstNetTimeProviderClass {
   GstObjectClass parent_class;
+
+  gpointer _gst_reserved[GST_PADDING];
 };
 
-GType                  gst_net_time_provider_get_type  (void);
-GstNetTimeProvider*    gst_net_time_provider_new       (GstClock *clock,
+GType                   gst_net_time_provider_get_type  (void);
+
+GstNetTimeProvider*     gst_net_time_provider_new       (GstClock *clock,
                                                          const gchar *address,
                                                          gint port);
 
index c928f25..e4b3831 100644 (file)
@@ -12,7 +12,6 @@ pcfiles =                                                     \
        gstreamer-base-@GST_MAJORMINOR@.pc                      \
        $(CHECK_PC_I)                                           \
        gstreamer-controller-@GST_MAJORMINOR@.pc                \
-       gstreamer-dataprotocol-@GST_MAJORMINOR@.pc              \
        gstreamer-net-@GST_MAJORMINOR@.pc
 
 pcfiles_uninstalled =                                          \
@@ -20,7 +19,6 @@ pcfiles_uninstalled =                                         \
        gstreamer-base-@GST_MAJORMINOR@-uninstalled.pc          \
        $(CHECK_PC_U)                                           \
        gstreamer-controller-@GST_MAJORMINOR@-uninstalled.pc    \
-       gstreamer-dataprotocol-@GST_MAJORMINOR@-uninstalled.pc  \
        gstreamer-net-@GST_MAJORMINOR@-uninstalled.pc
 
 all-local: $(pcfiles) $(pcfiles_uninstalled)
@@ -47,8 +45,6 @@ EXTRA_DIST =                                                  \
        gstreamer-check-uninstalled.pc.in                       \
        gstreamer-controller.pc.in                              \
        gstreamer-controller-uninstalled.pc.in                  \
-       gstreamer-dataprotocol.pc.in                            \
-       gstreamer-dataprotocol-uninstalled.pc.in                \
        gstreamer-net.pc.in                                     \
        gstreamer-net-uninstalled.pc.in
 
diff --git a/pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in b/pkgconfig/gstreamer-dataprotocol-uninstalled.pc.in
deleted file mode 100644 (file)
index fff856a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# the standard variables don't make sense for an uninstalled copy
-prefix=
-exec_prefix=
-libdir=@abs_top_builddir@/libs/gst/dataprotocol
-includedir=
-girdir=@abs_top_builddir@/libs/gst/dataprotocol
-typelibdir=@abs_top_builddir@/libs/gst/dataprotocol
-
-Name: GStreamer data protocol library, uninstalled
-Description: Data protocol for plug-ins, Not Installed
-Requires: gstreamer-@GST_MAJORMINOR@ = @VERSION@
-Version: @VERSION@
-
-Libs: @abs_top_builddir@/libs/gst/dataprotocol/libgstdataprotocol-@GST_MAJORMINOR@.la
-Cflags: -I@abs_top_srcdir@/libs -I@abs_top_builddir@/libs
diff --git a/pkgconfig/gstreamer-dataprotocol.pc.in b/pkgconfig/gstreamer-dataprotocol.pc.in
deleted file mode 100644 (file)
index e06b7e9..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
-datarootdir=${prefix}/share
-datadir=${datarootdir}
-girdir=${datadir}/gir-1.0
-typelibdir=${libdir}/girepository-1.0
-
-Name: GStreamer data protocol library
-Description: Data protocol for plug-ins
-Requires: gstreamer-@GST_MAJORMINOR@
-Version: @VERSION@
-Libs: -L${libdir} -lgstdataprotocol-@GST_MAJORMINOR@
-Cflags: -I${includedir}
index 80a1691..366df18 100644 (file)
@@ -8,7 +8,7 @@ typelibdir=@abs_top_builddir@/libs/gst/net
 
 Name: GStreamer networking library, uninstalled
 Description: Network-enabled GStreamer plug-ins and clocking, uninstalled
-Requires: gstreamer-@GST_MAJORMINOR@ = @VERSION@
+Requires: gstreamer-@GST_MAJORMINOR@ = @VERSION@ gio-2.0
 Version: @VERSION@
 
 Libs: @abs_top_builddir@/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la
index d8b510b..582f00c 100644 (file)
@@ -9,7 +9,7 @@ typelibdir=${libdir}/girepository-1.0
 
 Name: GStreamer networking library
 Description: Network-enabled GStreamer plug-ins and clocking
-Requires: gstreamer-@GST_MAJORMINOR@
+Requires: gstreamer-@GST_MAJORMINOR@ gio-2.0
 Version: @VERSION@
 Libs: -L${libdir} -lgstnet-@GST_MAJORMINOR@
 Cflags: -I${includedir}
index 7ee1407..481f81f 100644 (file)
@@ -12,7 +12,7 @@ typelibdir=@abs_top_builddir@/gst
 Name: GStreamer Uninstalled
 Description: Streaming media framework, Not Installed
 Version: @VERSION@
-Requires: @GST_PKG_DEPS@@LIBXML_PKG@
+Requires: @GST_PKG_DEPS@
 Libs: @abs_top_builddir@/gst/libgstreamer-@GST_MAJORMINOR@.la
 # FIXME: the libs dir doesn't really belong here
 Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/libs -I@abs_top_builddir@ -I@abs_top_builddir@/libs
index ad4554d..36fb2f4 100644 (file)
@@ -11,7 +11,7 @@ typelibdir=${libdir}/girepository-1.0
 
 Name: GStreamer
 Description: Streaming media framework
-Requires: @GST_PKG_DEPS@@LIBXML_PKG@
+Requires: @GST_PKG_DEPS@
 Version: @VERSION@
 Libs: -L${libdir} -lgstreamer-@GST_MAJORMINOR@
 Cflags: -I${includedir}
index 6fc0a1b..17233d2 100644 (file)
@@ -1,6 +1,6 @@
-SUBDIRS = elements indexers
+SUBDIRS = elements
 
-DIST_SUBDIRS = elements indexers
+DIST_SUBDIRS = elements
 
 Android.mk: Makefile.am
        androgenizer -:PROJECT gstreamer \
index f743cf2..a4d4c81 100644 (file)
@@ -15,6 +15,7 @@ libgstcoreelements_la_SOURCES =       \
        gstidentity.c           \
        gstinputselector.c      \
        gstoutputselector.c     \
+       gstdataqueue.c          \
        gstmultiqueue.c         \
        gstqueue.c              \
        gstqueue2.c             \
@@ -41,6 +42,7 @@ noinst_HEADERS =              \
        gstidentity.h           \
        gstinputselector.h      \
        gstoutputselector.h     \
+       gstdataqueue.h          \
        gstmultiqueue.h         \
        gstqueue.h              \
        gstqueue2.h             \
index 61e4ddf..ceed308 100644 (file)
@@ -61,12 +61,12 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug);
 #define GST_CAT_DEFAULT gst_capsfilter_debug
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, \
     "capsfilter element");
-
-GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM, _do_init);
+#define gst_capsfilter_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstCapsFilter, gst_capsfilter, GST_TYPE_BASE_TRANSFORM,
+    _do_init);
 
 
 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
@@ -76,34 +76,19 @@ static void gst_capsfilter_get_property (GObject * object, guint prop_id,
 static void gst_capsfilter_dispose (GObject * object);
 
 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
-    GstPadDirection direction, GstCaps * caps);
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
 static gboolean gst_capsfilter_accept_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps);
 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
     GstBuffer * buf);
 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
-    GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
-
-static void
-gst_capsfilter_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "CapsFilter",
-      "Generic",
-      "Pass data without modification, limiting formats",
-      "David Schleef <ds@schleef.org>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
+    GstBuffer * input, GstBuffer ** buf);
 
 static void
 gst_capsfilter_class_init (GstCapsFilterClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseTransformClass *trans_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
@@ -118,6 +103,17 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass)
               "object."), GST_TYPE_CAPS,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gstelement_class = GST_ELEMENT_CLASS (klass);
+  gst_element_class_set_details_simple (gstelement_class,
+      "CapsFilter",
+      "Generic",
+      "Pass data without modification, limiting formats",
+      "David Schleef <ds@schleef.org>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   trans_class->transform_caps =
       GST_DEBUG_FUNCPTR (gst_capsfilter_transform_caps);
@@ -128,7 +124,7 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass)
 }
 
 static void
-gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
+gst_capsfilter_init (GstCapsFilter * filter)
 {
   GstBaseTransform *trans = GST_BASE_TRANSFORM (filter);
   gst_base_transform_set_gap_aware (trans, TRUE);
@@ -172,8 +168,7 @@ gst_capsfilter_set_property (GObject * object, guint prop_id,
       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
 
       /* filter the currently negotiated format against the new caps */
-      GST_OBJECT_LOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
-      nego = GST_PAD_CAPS (GST_BASE_TRANSFORM_SINK_PAD (object));
+      nego = gst_pad_get_current_caps (GST_BASE_TRANSFORM_SINK_PAD (object));
       if (nego) {
         GST_DEBUG_OBJECT (capsfilter, "we had negotiated caps %" GST_PTR_FORMAT,
             nego);
@@ -202,6 +197,7 @@ gst_capsfilter_set_property (GObject * object, guint prop_id,
             suggest = gst_caps_copy (new_caps);
           }
         }
+        gst_caps_unref (nego);
       } else {
         GST_DEBUG_OBJECT (capsfilter, "no negotiated caps");
         /* Suggest the new caps, we can't just rely on _get_caps as this may
@@ -209,7 +205,6 @@ gst_capsfilter_set_property (GObject * object, guint prop_id,
          * pushed yet */
         suggest = gst_caps_copy (new_caps);
       }
-      GST_OBJECT_UNLOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
 
       GST_DEBUG_OBJECT (capsfilter, "suggesting new caps %" GST_PTR_FORMAT,
           suggest);
@@ -255,18 +250,28 @@ gst_capsfilter_dispose (GObject * object)
 
 static GstCaps *
 gst_capsfilter_transform_caps (GstBaseTransform * base,
-    GstPadDirection direction, GstCaps * caps)
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
-  GstCaps *ret, *filter_caps;
+  GstCaps *ret, *filter_caps, *tmp;
 
   GST_OBJECT_LOCK (capsfilter);
   filter_caps = gst_caps_ref (capsfilter->filter_caps);
   GST_OBJECT_UNLOCK (capsfilter);
 
-  ret = gst_caps_intersect (caps, filter_caps);
+  if (filter) {
+    tmp =
+        gst_caps_intersect_full (filter, filter_caps, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (filter_caps);
+    filter_caps = tmp;
+  }
+
+  ret = gst_caps_intersect_full (filter_caps, caps, GST_CAPS_INTERSECT_FIRST);
+
   GST_DEBUG_OBJECT (capsfilter, "input:     %" GST_PTR_FORMAT, caps);
-  GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter_caps);
+  GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter);
+  GST_DEBUG_OBJECT (capsfilter, "caps filter:    %" GST_PTR_FORMAT,
+      filter_caps);
   GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret);
 
   gst_caps_unref (filter_caps);
@@ -291,9 +296,13 @@ gst_capsfilter_accept_caps (GstBaseTransform * base,
   if (ret) {
     /* if we can intersect, see if the other end also accepts */
     if (direction == GST_PAD_SRC)
-      ret = gst_pad_peer_accept_caps (GST_BASE_TRANSFORM_SINK_PAD (base), caps);
+      ret =
+          gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SINK_PAD (base),
+          caps);
     else
-      ret = gst_pad_peer_accept_caps (GST_BASE_TRANSFORM_SRC_PAD (base), caps);
+      ret =
+          gst_pad_peer_query_accept_caps (GST_BASE_TRANSFORM_SRC_PAD (base),
+          caps);
     GST_DEBUG_OBJECT (capsfilter, "peer accept: %d", ret);
   }
 
@@ -322,43 +331,21 @@ gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
  */
 static GstFlowReturn
 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
-    gint size, GstCaps * caps, GstBuffer ** buf)
+    GstBuffer ** buf)
 {
   GstFlowReturn ret = GST_FLOW_OK;
 
-  if (GST_BUFFER_CAPS (input) != NULL) {
-    /* Output buffer already has caps */
-    GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitly fixed)");
-    /* FIXME : Move this behaviour to basetransform. The given caps are the ones
-     * of the source pad, therefore our outgoing buffers should always have
-     * those caps. */
-    if (GST_BUFFER_CAPS (input) != caps) {
-      /* caps are different, make a metadata writable output buffer to set
-       * caps */
-      if (gst_buffer_is_metadata_writable (input)) {
-        /* input is writable, just set caps and use this as the output */
-        *buf = input;
-        gst_buffer_set_caps (*buf, caps);
-        gst_buffer_ref (input);
-      } else {
-        GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
-        *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
-        gst_buffer_set_caps (*buf, caps);
-      }
-    } else {
-      /* caps are right, just use a ref of the input as the outbuf */
-      *buf = input;
-      gst_buffer_ref (input);
-    }
-  } else {
+  /* always return the input as output buffer */
+  *buf = input;
+
+  if (!gst_pad_has_current_caps (trans->sinkpad)) {
     /* Buffer has no caps. See if the output pad only supports fixed caps */
     GstCaps *out_caps;
 
-    out_caps = GST_PAD_CAPS (trans->srcpad);
+    GST_LOG_OBJECT (trans, "Input pad does not have caps");
 
-    if (out_caps != NULL) {
-      gst_caps_ref (out_caps);
-    } else {
+    out_caps = gst_pad_get_current_caps (trans->srcpad);
+    if (out_caps == NULL) {
       out_caps = gst_pad_get_allowed_caps (trans->srcpad);
       g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
     }
@@ -368,18 +355,11 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
 
     if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
       GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
-          GST_PTR_FORMAT " to apply to buffer with no caps", out_caps);
-      if (gst_buffer_is_metadata_writable (input)) {
-        gst_buffer_ref (input);
-        *buf = input;
-      } else {
-        GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
-        *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
-      }
-      GST_BUFFER_CAPS (*buf) = out_caps;
+          GST_PTR_FORMAT " to apply to srcpad", out_caps);
 
-      if (GST_PAD_CAPS (trans->srcpad) == NULL)
-        gst_pad_set_caps (trans->srcpad, out_caps);
+      if (!gst_pad_has_current_caps (trans->srcpad))
+        gst_pad_push_event (trans->srcpad, gst_event_new_caps (out_caps));
+      gst_caps_unref (out_caps);
     } else {
       gchar *caps_str = gst_caps_to_string (out_caps);
 
similarity index 94%
rename from libs/gst/base/gstdataqueue.c
rename to plugins/elements/gstdataqueue.c
index 2d325e3..c1b8820 100644 (file)
@@ -61,7 +61,7 @@ enum
     GST_CAT_LOG (data_queue_dataflow,                                   \
       "locking qlock from thread %p",                                   \
       g_thread_self ());                                                \
-  g_mutex_lock (q->qlock);                                              \
+  g_mutex_lock (&q->qlock);                                              \
   GST_CAT_LOG (data_queue_dataflow,                                     \
       "locked qlock from thread %p",                                    \
       g_thread_self ());                                                \
@@ -77,7 +77,7 @@ enum
     GST_CAT_LOG (data_queue_dataflow,                                   \
       "unlocking qlock from thread %p",                                 \
       g_thread_self ());                                                \
-  g_mutex_unlock (q->qlock);                                            \
+  g_mutex_unlock (&q->qlock);                                            \
 } G_STMT_END
 
 #define STATUS(q, msg)                                                  \
@@ -178,9 +178,9 @@ gst_data_queue_init (GstDataQueue * queue)
 
   queue->checkfull = NULL;
 
-  queue->qlock = g_mutex_new ();
-  queue->item_add = g_cond_new ();
-  queue->item_del = g_cond_new ();
+  g_mutex_init (&queue->qlock);
+  g_cond_init (&queue->item_add);
+  g_cond_init (&queue->item_del);
   queue->queue = g_queue_new ();
 
   GST_DEBUG ("initialized queue's not_empty & not_full conditions");
@@ -262,11 +262,11 @@ gst_data_queue_finalize (GObject * object)
   g_queue_free (queue->queue);
 
   GST_DEBUG ("free mutex");
-  g_mutex_free (queue->qlock);
+  g_mutex_clear (&queue->qlock);
   GST_DEBUG ("done free mutex");
 
-  g_cond_free (queue->item_add);
-  g_cond_free (queue->item_del);
+  g_cond_clear (&queue->item_add);
+  g_cond_clear (&queue->item_del);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -278,8 +278,8 @@ gst_data_queue_locked_flush (GstDataQueue * queue)
   gst_data_queue_cleanup (queue);
   STATUS (queue, "after flushing");
   /* we deleted something... */
-  if (queue->abidata.ABI.waiting_del)
-    g_cond_signal (queue->item_del);
+  if (queue->waiting_del)
+    g_cond_signal (&queue->item_del);
 }
 
 static inline gboolean
@@ -385,10 +385,10 @@ gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing)
   queue->flushing = flushing;
   if (flushing) {
     /* release push/pop functions */
-    if (queue->abidata.ABI.waiting_add)
-      g_cond_signal (queue->item_add);
-    if (queue->abidata.ABI.waiting_del)
-      g_cond_signal (queue->item_del);
+    if (queue->waiting_add)
+      g_cond_signal (&queue->item_add);
+    if (queue->waiting_del)
+      g_cond_signal (&queue->item_del);
   }
   GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
 }
@@ -433,9 +433,9 @@ gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
 
     /* signal might have removed some items */
     while (gst_data_queue_locked_is_full (queue)) {
-      queue->abidata.ABI.waiting_del = TRUE;
-      g_cond_wait (queue->item_del, queue->qlock);
-      queue->abidata.ABI.waiting_del = FALSE;
+      queue->waiting_del = TRUE;
+      g_cond_wait (&queue->item_del, &queue->qlock);
+      queue->waiting_del = FALSE;
       if (queue->flushing)
         goto flushing;
     }
@@ -449,8 +449,8 @@ gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
   queue->cur_level.time += item->duration;
 
   STATUS (queue, "after pushing");
-  if (queue->abidata.ABI.waiting_add)
-    g_cond_signal (queue->item_add);
+  if (queue->waiting_add)
+    g_cond_signal (&queue->item_add);
 
   GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
 
@@ -498,9 +498,9 @@ gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
     GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
 
     while (gst_data_queue_locked_is_empty (queue)) {
-      queue->abidata.ABI.waiting_add = TRUE;
-      g_cond_wait (queue->item_add, queue->qlock);
-      queue->abidata.ABI.waiting_add = FALSE;
+      queue->waiting_add = TRUE;
+      g_cond_wait (&queue->item_add, &queue->qlock);
+      queue->waiting_add = FALSE;
       if (queue->flushing)
         goto flushing;
     }
@@ -516,8 +516,8 @@ gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
   queue->cur_level.time -= (*item)->duration;
 
   STATUS (queue, "after popping");
-  if (queue->abidata.ABI.waiting_del)
-    g_cond_signal (queue->item_del);
+  if (queue->waiting_del)
+    g_cond_signal (&queue->item_del);
 
   GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
 
@@ -601,9 +601,9 @@ gst_data_queue_limits_changed (GstDataQueue * queue)
   g_return_if_fail (GST_IS_DATA_QUEUE (queue));
 
   GST_DATA_QUEUE_MUTEX_LOCK (queue);
-  if (queue->abidata.ABI.waiting_del) {
+  if (queue->waiting_del) {
     GST_DEBUG ("signal del");
-    g_cond_signal (queue->item_del);
+    g_cond_signal (&queue->item_del);
   }
   GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
 }
similarity index 93%
rename from libs/gst/base/gstdataqueue.h
rename to plugins/elements/gstdataqueue.h
index dea1954..36f4be7 100644 (file)
@@ -127,21 +127,17 @@ struct _GstDataQueue
   GstDataQueueCheckFullFunction checkfull;      /* Callback to check if the queue is full */
   gpointer *checkdata;
 
-  GMutex *qlock;                /* lock for queue (vs object lock) */
-  GCond *item_add;              /* signals buffers now available for reading */
-  GCond *item_del;              /* signals space now available for writing */
+  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;
 
-  union {
-    struct {
-      gboolean waiting_add;
-      gboolean waiting_del;
-    } ABI;
-    gpointer _gst_reserved[GST_PADDING - 2];
-  } abidata;
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstDataQueueClass
index 202d07b..09c213c 100644 (file)
@@ -111,11 +111,11 @@ gst_fake_sink_state_error_get_type (void)
   return fakesink_state_error_type;
 }
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_fake_sink_debug, "fakesink", 0, "fakesink element");
-
-GST_BOILERPLATE_FULL (GstFakeSink, gst_fake_sink, GstBaseSink,
-    GST_TYPE_BASE_SINK, _do_init);
+#define gst_fake_sink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFakeSink, gst_fake_sink, GST_TYPE_BASE_SINK,
+    _do_init);
 
 static void gst_fake_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -160,27 +160,11 @@ marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
       (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
       cc->callback);
 
-  callback (data1, gst_value_get_mini_object (param_values + 1),
+  callback (data1, g_value_get_boxed (param_values + 1),
       g_value_get_object (param_values + 2), data2);
 }
 
 static void
-gst_fake_sink_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Fake Sink",
-      "Sink",
-      "Black hole for data",
-      "Erik Walthinsen <omega@cse.ogi.edu>, "
-      "Wim Taymans <wim@fluendo.com>, "
-      "Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
-
-static void
 gst_fake_sink_class_init (GstFakeSinkClass * klass)
 {
   GObjectClass *gobject_class;
@@ -260,6 +244,16 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
       NULL, NULL, marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2,
       GST_TYPE_BUFFER, GST_TYPE_PAD);
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Fake Sink",
+      "Sink",
+      "Black hole for data",
+      "Erik Walthinsen <omega@cse.ogi.edu>, "
+      "Wim Taymans <wim@fluendo.com>, "
+      "Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_fake_sink_change_state);
 
@@ -269,7 +263,7 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
 }
 
 static void
-gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class)
+gst_fake_sink_init (GstFakeSink * fakesink)
 {
   fakesink->silent = DEFAULT_SILENT;
   fakesink->dump = DEFAULT_DUMP;
@@ -277,9 +271,6 @@ gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class)
   fakesink->state_error = DEFAULT_STATE_ERROR;
   fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
   fakesink->num_buffers = DEFAULT_NUM_BUFFERS;
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_static_rec_mutex_init (&fakesink->notify_lock);
-#endif
 
   gst_base_sink_set_sync (GST_BASE_SINK (fakesink), DEFAULT_SYNC);
 }
@@ -287,12 +278,6 @@ gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class)
 static void
 gst_fake_sink_finalize (GObject * obj)
 {
-#if !GLIB_CHECK_VERSION(2,26,0)
-  GstFakeSink *sink = GST_FAKE_SINK (obj);
-
-  g_static_rec_mutex_free (&sink->notify_lock);
-#endif
-
   G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
@@ -376,19 +361,7 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
 static void
 gst_fake_sink_notify_last_message (GstFakeSink * sink)
 {
-  /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent
-   * g_object_notify() on the same object might lead to crashes, see
-   * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups.
-   * So we really don't want to do a g_object_notify() here for out-of-band
-   * events with the streaming thread possibly also doing a g_object_notify()
-   * for an in-band buffer or event. This is fixed in GLib >= 2.26 */
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_static_rec_mutex_lock (&sink->notify_lock);
-  g_object_notify ((GObject *) sink, "last-message");
-  g_static_rec_mutex_unlock (&sink->notify_lock);
-#else
   g_object_notify_by_pspec ((GObject *) sink, pspec_last_message);
-#endif
 }
 
 static gboolean
@@ -405,9 +378,11 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
 
     if (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE) {
       GstMessage *msg;
+      const GstStructure *structure;
 
       gst_event_parse_sink_message (event, &msg);
-      sstr = gst_structure_to_string (msg->structure);
+      structure = gst_message_get_structure (msg);
+      sstr = gst_structure_to_string (structure);
       sink->last_message =
           g_strdup_printf ("message ******* (%s:%s) M (type: %d, %s) %p",
           GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad),
@@ -431,11 +406,7 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
     gst_fake_sink_notify_last_message (sink);
   }
 
-  if (GST_BASE_SINK_CLASS (parent_class)->event) {
-    return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
-  } else {
-    return TRUE;
-  }
+  return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
 }
 
 static GstFlowReturn
@@ -466,7 +437,7 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
 eos:
   {
     GST_DEBUG_OBJECT (sink, "we are EOS");
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
@@ -503,15 +474,14 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
     }
 
     {
-      const char *flag_list[12] = {
-        "ro", "media4", "", "",
-        "preroll", "discont", "incaps", "gap",
-        "delta_unit", "media1", "media2", "media3"
+      const char *flag_list[15] = {
+        "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted",
+        "marker", "header", "gap", "droppable", "delta-unit", "in-caps"
       };
       int i;
       char *end = flag_str;
       end[0] = '\0';
-      for (i = 0; i < 12; i++) {
+      for (i = 0; i < G_N_ELEMENTS (flag_list); i++) {
         if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
           strcpy (end, flag_list[i]);
           end += strlen (end);
@@ -527,7 +497,7 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
         ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
         G_GINT64_FORMAT ", flags: %d %s) %p",
         GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad),
-        GST_BUFFER_SIZE (buf), ts_str,
+        (guint) gst_buffer_get_size (buf), ts_str,
         dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
         GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf);
     GST_OBJECT_UNLOCK (sink);
@@ -539,7 +509,12 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
         bsink->sinkpad);
 
   if (sink->dump) {
-    gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+    guint8 *data;
+    gsize size;
+
+    data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+    gst_util_dump_mem (data, size);
+    gst_buffer_unmap (buf, data, size);
   }
   if (sink->num_buffers_left == 0)
     goto eos;
@@ -550,7 +525,7 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 eos:
   {
     GST_DEBUG_OBJECT (sink, "we are EOS");
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
index b1165af..2db98b9 100644 (file)
@@ -82,9 +82,6 @@ struct _GstFakeSink {
   gchar                        *last_message;
   gint                  num_buffers;
   gint                  num_buffers_left;
-#if !GLIB_CHECK_VERSION(2,26,0)
-  GStaticRecMutex       notify_lock;
-#endif
 };
 
 struct _GstFakeSinkClass {
index 8ba1b09..4cca62c 100644 (file)
@@ -201,11 +201,10 @@ gst_fake_src_filltype_get_type (void)
   return fakesrc_filltype_type;
 }
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element");
-
-GST_BOILERPLATE_FULL (GstFakeSrc, gst_fake_src, GstBaseSrc, GST_TYPE_BASE_SRC,
-    _do_init);
+#define gst_fake_src_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFakeSrc, gst_fake_src, GST_TYPE_BASE_SRC, _do_init);
 
 static void gst_fake_src_finalize (GObject * object);
 static void gst_fake_src_set_property (GObject * object, guint prop_id,
@@ -251,31 +250,19 @@ marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
       (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
       cc->callback);
 
-  callback (data1, gst_value_get_mini_object (param_values + 1),
+  callback (data1, g_value_get_boxed (param_values + 1),
       g_value_get_object (param_values + 2), data2);
 }
 
 static void
-gst_fake_src_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Fake Source",
-      "Source",
-      "Push empty (no data) buffers around",
-      "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-}
-
-static void
 gst_fake_src_class_init (GstFakeSrcClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbase_src_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbase_src_class = GST_BASE_SRC_CLASS (klass);
 
   gobject_class->finalize = gst_fake_src_finalize;
@@ -379,6 +366,14 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
       marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
       GST_TYPE_PAD);
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Fake Source",
+      "Source",
+      "Push empty (no data) buffers around",
+      "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+
   gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
   gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
   gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
@@ -388,7 +383,7 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
 }
 
 static void
-gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
+gst_fake_src_init (GstFakeSrc * fakesrc)
 {
   fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
   fakesrc->buffer_count = 0;
@@ -451,11 +446,7 @@ gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event)
     g_free (sstr);
     GST_OBJECT_UNLOCK (src);
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-    g_object_notify ((GObject *) src, "last-message");
-#else
     g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
-#endif
   }
 
   return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
@@ -466,10 +457,7 @@ gst_fake_src_alloc_parent (GstFakeSrc * src)
 {
   GstBuffer *buf;
 
-  buf = gst_buffer_new ();
-  GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
-  GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
-  GST_BUFFER_SIZE (buf) = src->parentsize;
+  buf = gst_buffer_new_allocate (NULL, src->parentsize, 0);
 
   src->parent = buf;
   src->parentoffset = 0;
@@ -535,11 +523,13 @@ gst_fake_src_set_property (GObject * object, guint prop_id,
       src->dump = g_value_get_boolean (value);
       break;
     case PROP_CAN_ACTIVATE_PUSH:
-      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
+      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object,
+              GST_BASE_SRC_FLAG_STARTED));
       GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
       break;
     case PROP_CAN_ACTIVATE_PULL:
-      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
+      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object,
+              GST_BASE_SRC_FLAG_STARTED));
       src->can_activate_pull = g_value_get_boolean (value);
       break;
     case PROP_IS_LIVE:
@@ -630,21 +620,21 @@ gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
 }
 
 static void
-gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
+gst_fake_src_prepare_buffer (GstFakeSrc * src, guint8 * data, gsize size)
 {
-  if (GST_BUFFER_SIZE (buf) == 0)
+  if (size == 0)
     return;
 
   switch (src->filltype) {
     case FAKE_SRC_FILLTYPE_ZERO:
-      memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
+      memset (data, 0, size);
       break;
     case FAKE_SRC_FILLTYPE_RANDOM:
     {
       gint i;
-      guint8 *ptr = GST_BUFFER_DATA (buf);
+      guint8 *ptr = data;
 
-      for (i = GST_BUFFER_SIZE (buf); i; i--) {
+      for (i = size; i; i--) {
         *ptr++ = g_random_int_range (0, 256);
       }
       break;
@@ -654,9 +644,9 @@ gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
     case FAKE_SRC_FILLTYPE_PATTERN_CONT:
     {
       gint i;
-      guint8 *ptr = GST_BUFFER_DATA (buf);
+      guint8 *ptr = data;
 
-      for (i = GST_BUFFER_SIZE (buf); i; i--) {
+      for (i = size; i; i--) {
         *ptr++ = src->pattern_byte++;
       }
       break;
@@ -671,29 +661,32 @@ static GstBuffer *
 gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
 {
   GstBuffer *buf;
+  gpointer data;
+  gboolean do_prepare = FALSE;
 
   buf = gst_buffer_new ();
-  GST_BUFFER_SIZE (buf) = size;
 
   if (size != 0) {
     switch (src->filltype) {
       case FAKE_SRC_FILLTYPE_NOTHING:
-        GST_BUFFER_DATA (buf) = g_malloc (size);
-        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
+        data = g_malloc (size);
         break;
       case FAKE_SRC_FILLTYPE_ZERO:
-        GST_BUFFER_DATA (buf) = g_malloc0 (size);
-        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
+        data = g_malloc0 (size);
         break;
       case FAKE_SRC_FILLTYPE_RANDOM:
       case FAKE_SRC_FILLTYPE_PATTERN:
       case FAKE_SRC_FILLTYPE_PATTERN_CONT:
       default:
-        GST_BUFFER_DATA (buf) = g_malloc (size);
-        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
-        gst_fake_src_prepare_buffer (src, buf);
+        data = g_malloc (size);
+        do_prepare = TRUE;
         break;
     }
+    if (do_prepare)
+      gst_fake_src_prepare_buffer (src, data, size);
+
+    gst_buffer_take_memory (buf, -1,
+        gst_memory_new_wrapped (0, data, g_free, size, 0, size));
   }
 
   return buf;
@@ -721,11 +714,14 @@ gst_fake_src_get_size (GstFakeSrc * src)
 }
 
 static GstBuffer *
-gst_fake_src_create_buffer (GstFakeSrc * src)
+gst_fake_src_create_buffer (GstFakeSrc * src, gsize * bufsize)
 {
   GstBuffer *buf;
-  guint size = gst_fake_src_get_size (src);
+  gsize size = gst_fake_src_get_size (src);
   gboolean dump = src->dump;
+  guint8 *data;
+
+  *bufsize = size;
 
   switch (src->data) {
     case FAKE_SRC_DATA_ALLOCATE:
@@ -738,17 +734,21 @@ gst_fake_src_create_buffer (GstFakeSrc * src)
         g_assert (src->parent);
       }
       /* see if it's large enough */
-      if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
-        buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
+      if ((src->parentsize - src->parentoffset) >= size) {
+        buf =
+            gst_buffer_copy_region (src->parent, GST_BUFFER_COPY_ALL,
+            src->parentoffset, size);
         src->parentoffset += size;
       } else {
         /* the parent is useless now */
         gst_buffer_unref (src->parent);
         src->parent = NULL;
         /* try again (this will allocate a new parent) */
-        return gst_fake_src_create_buffer (src);
+        return gst_fake_src_create_buffer (src, bufsize);
       }
-      gst_fake_src_prepare_buffer (src, buf);
+      data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
+      gst_fake_src_prepare_buffer (src, data, size);
+      gst_buffer_unmap (buf, data, size);
       break;
     default:
       g_warning ("fakesrc: dunno how to allocate buffers !");
@@ -756,7 +756,9 @@ gst_fake_src_create_buffer (GstFakeSrc * src)
       break;
   }
   if (dump) {
-    gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+    data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+    gst_util_dump_mem (data, size);
+    gst_buffer_unmap (buf, data, size);
   }
 
   return buf;
@@ -796,17 +798,17 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
   GstFakeSrc *src;
   GstBuffer *buf;
   GstClockTime time;
+  gsize size;
 
   src = GST_FAKE_SRC (basesrc);
 
-  buf = gst_fake_src_create_buffer (src);
+  buf = gst_fake_src_create_buffer (src, &size);
   GST_BUFFER_OFFSET (buf) = src->buffer_count++;
 
   if (src->datarate > 0) {
     time = (src->bytes_sent * GST_SECOND) / src->datarate;
 
-    GST_BUFFER_DURATION (buf) =
-        GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
+    GST_BUFFER_DURATION (buf) = size * GST_SECOND / src->datarate;
   } else if (gst_base_src_is_live (basesrc)) {
     GstClock *clock;
 
@@ -848,15 +850,14 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
     }
 
     {
-      const char *flag_list[12] = {
-        "ro", "media4", "", "",
-        "preroll", "discont", "incaps", "gap",
-        "delta_unit", "media1", "media2", "media3"
+      const char *flag_list[15] = {
+        "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted",
+        "marker", "header", "gap", "droppable", "delta-unit", "in-caps"
       };
       int i;
       char *end = flag_str;
       end[0] = '\0';
-      for (i = 0; i < 12; i++) {
+      for (i = 0; i < G_N_ELEMENTS (flag_list); i++) {
         if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
           strcpy (end, flag_list[i]);
           end += strlen (end);
@@ -871,17 +872,12 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
         g_strdup_printf ("create   ******* (%s:%s) (%u bytes, timestamp: %s"
         ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
         G_GINT64_FORMAT ", flags: %d %s) %p",
-        GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad),
-        GST_BUFFER_SIZE (buf), ts_str, dur_str, GST_BUFFER_OFFSET (buf),
-        GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT (buf)->flags, flag_str,
-        buf);
+        GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size,
+        ts_str, dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
+        GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf);
     GST_OBJECT_UNLOCK (src);
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-    g_object_notify ((GObject *) src, "last-message");
-#else
     g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
-#endif
   }
 
   if (src->signal_handoffs) {
@@ -891,7 +887,7 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
     GST_LOG_OBJECT (src, "post handoff emit");
   }
 
-  src->bytes_sent += GST_BUFFER_SIZE (buf);
+  src->bytes_sent += size;
 
   *ret = buf;
   return GST_FLOW_OK;
index 6383d2a..619b545 100644 (file)
@@ -94,23 +94,11 @@ enum
 static void gst_fd_sink_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 
-static void
-_do_init (GType gst_fd_sink_type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_fd_sink_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  g_type_add_interface_static (gst_fd_sink_type, GST_TYPE_URI_HANDLER,
-      &urihandler_info);
-
+#define _do_init \
+  G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_fd_sink_uri_handler_init); \
   GST_DEBUG_CATEGORY_INIT (gst_fd_sink__debug, "fdsink", 0, "fdsink element");
-}
-
-GST_BOILERPLATE_FULL (GstFdSink, gst_fd_sink, GstBaseSink, GST_TYPE_BASE_SINK,
-    _do_init);
+#define gst_fd_sink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFdSink, gst_fd_sink, GST_TYPE_BASE_SINK, _do_init);
 
 static void gst_fd_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -118,7 +106,7 @@ static void gst_fd_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_fd_sink_dispose (GObject * obj);
 
-static gboolean gst_fd_sink_query (GstPad * pad, GstQuery * query);
+static gboolean gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query);
 static GstFlowReturn gst_fd_sink_render (GstBaseSink * sink,
     GstBuffer * buffer);
 static gboolean gst_fd_sink_start (GstBaseSink * basesink);
@@ -130,37 +118,34 @@ static gboolean gst_fd_sink_event (GstBaseSink * sink, GstEvent * event);
 static gboolean gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset);
 
 static void
-gst_fd_sink_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Filedescriptor Sink",
-      "Sink/File",
-      "Write data to a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
-
-static void
 gst_fd_sink_class_init (GstFdSinkClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseSinkClass *gstbasesink_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesink_class = GST_BASE_SINK_CLASS (klass);
 
   gobject_class->set_property = gst_fd_sink_set_property;
   gobject_class->get_property = gst_fd_sink_get_property;
   gobject_class->dispose = gst_fd_sink_dispose;
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Filedescriptor Sink",
+      "Sink/File",
+      "Write data to a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_fd_sink_render);
   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_fd_sink_start);
   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
   gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
   gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event);
+  gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_fd_sink_query);
 
   g_object_class_install_property (gobject_class, ARG_FD,
       g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
@@ -168,13 +153,8 @@ gst_fd_sink_class_init (GstFdSinkClass * klass)
 }
 
 static void
-gst_fd_sink_init (GstFdSink * fdsink, GstFdSinkClass * klass)
+gst_fd_sink_init (GstFdSink * fdsink)
 {
-  GstPad *pad;
-
-  pad = GST_BASE_SINK_PAD (fdsink);
-  gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_fd_sink_query));
-
   fdsink->fd = 1;
   fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
   fdsink->bytes_written = 0;
@@ -195,44 +175,53 @@ gst_fd_sink_dispose (GObject * obj)
 }
 
 static gboolean
-gst_fd_sink_query (GstPad * pad, GstQuery * query)
+gst_fd_sink_query (GstBaseSink * bsink, GstQuery * query)
 {
+  gboolean res = FALSE;
   GstFdSink *fdsink;
-  GstFormat format;
 
-  fdsink = GST_FD_SINK (GST_PAD_PARENT (pad));
+  fdsink = GST_FD_SINK (bsink);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
+    {
+      GstFormat format;
+
       gst_query_parse_position (query, &format, NULL);
+
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
           gst_query_set_position (query, GST_FORMAT_BYTES, fdsink->current_pos);
-          return TRUE;
+          res = TRUE;
+          break;
         default:
-          return FALSE;
+          break;
       }
-
+      break;
+    }
     case GST_QUERY_FORMATS:
       gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
-      return TRUE;
-
+      res = TRUE;
+      break;
     case GST_QUERY_URI:
       gst_query_set_uri (query, fdsink->uri);
-      return TRUE;
-
+      res = TRUE;
+      break;
     default:
-      return gst_pad_query_default (pad, query);
+      res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
+      break;
+
   }
+  return res;
 }
 
 static GstFlowReturn
 gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 {
   GstFdSink *fdsink;
-  guint8 *data;
-  guint size;
+  guint8 *data, *ptr;
+  gsize size, left;
   gint written;
 
 #ifndef HAVE_WIN32
@@ -243,14 +232,16 @@ gst_fd_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 
   g_return_val_if_fail (fdsink->fd >= 0, GST_FLOW_ERROR);
 
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+
+  ptr = data;
+  left = size;
 
 again:
 #ifndef HAVE_WIN32
   do {
-    GST_DEBUG_OBJECT (fdsink, "going into select, have %d bytes to write",
-        size);
+    GST_DEBUG_OBJECT (fdsink, "going into select, have %" G_GSIZE_FORMAT
+        " bytes to write", size);
     retval = gst_poll_wait (fdsink->fdset, GST_CLOCK_TIME_NONE);
   } while (retval == -1 && (errno == EINTR || errno == EAGAIN));
 
@@ -262,10 +253,10 @@ again:
   }
 #endif
 
-  GST_DEBUG_OBJECT (fdsink, "writing %d bytes to file descriptor %d", size,
-      fdsink->fd);
+  GST_DEBUG_OBJECT (fdsink, "writing %" G_GSIZE_FORMAT " bytes to"
+      " file descriptor %d", size, fdsink->fd);
 
-  written = write (fdsink->fd, data, size);
+  written = write (fdsink->fd, ptr, left);
 
   /* check for errors */
   if (G_UNLIKELY (written < 0)) {
@@ -278,17 +269,20 @@ again:
   }
 
   /* all is fine when we get here */
-  size -= written;
-  data += written;
+  left -= written;
+  ptr += written;
   fdsink->bytes_written += written;
   fdsink->current_pos += written;
 
-  GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
+  GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %" G_GSIZE_FORMAT " left", written,
+      left);
 
   /* short write, select and try to write the remainder */
-  if (G_UNLIKELY (size > 0))
+  if (G_UNLIKELY (left > 0))
     goto again;
 
+  gst_buffer_unmap (buffer, data, size);
+
   return GST_FLOW_OK;
 
 #ifndef HAVE_WIN32
@@ -297,11 +291,13 @@ select_error:
     GST_ELEMENT_ERROR (fdsink, RESOURCE, READ, (NULL),
         ("select on file descriptor: %s.", g_strerror (errno)));
     GST_DEBUG_OBJECT (fdsink, "Error during select");
+    gst_buffer_unmap (buffer, data, size);
     return GST_FLOW_ERROR;
   }
 stopped:
   {
     GST_DEBUG_OBJECT (fdsink, "Select stopped");
+    gst_buffer_unmap (buffer, data, size);
     return GST_FLOW_WRONG_STATE;
   }
 #endif
@@ -318,12 +314,13 @@ write_error:
                 fdsink->fd, g_strerror (errno)));
       }
     }
+    gst_buffer_unmap (buffer, data, size);
     return GST_FLOW_ERROR;
   }
 }
 
 static gboolean
-gst_fd_sink_check_fd (GstFdSink * fdsink, int fd)
+gst_fd_sink_check_fd (GstFdSink * fdsink, int fd, GError ** error)
 {
   struct stat stat_results;
   off_t result;
@@ -355,6 +352,8 @@ invalid:
   {
     GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL),
         ("File descriptor %d is not valid: %s", fd, g_strerror (errno)));
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE,
+        "File descriptor %d is not valid: %s", fd, g_strerror (errno));
     return FALSE;
   }
 not_seekable:
@@ -371,7 +370,7 @@ gst_fd_sink_start (GstBaseSink * basesink)
   GstPollFD fd = GST_POLL_FD_INIT;
 
   fdsink = GST_FD_SINK (basesink);
-  if (!gst_fd_sink_check_fd (fdsink, fdsink->fd))
+  if (!gst_fd_sink_check_fd (fdsink, fdsink->fd, NULL))
     return FALSE;
 
   if ((fdsink->fdset = gst_poll_new (TRUE)) == NULL)
@@ -435,12 +434,15 @@ gst_fd_sink_unlock_stop (GstBaseSink * basesink)
 }
 
 static gboolean
-gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd)
+gst_fd_sink_update_fd (GstFdSink * fdsink, int new_fd, GError ** error)
 {
-  if (new_fd < 0)
+  if (new_fd < 0) {
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_REFERENCE,
+        "File descriptor %d is not valid", new_fd);
     return FALSE;
+  }
 
-  if (!gst_fd_sink_check_fd (fdsink, new_fd))
+  if (!gst_fd_sink_check_fd (fdsink, new_fd, error))
     goto invalid;
 
   /* assign the fd */
@@ -482,7 +484,7 @@ gst_fd_sink_set_property (GObject * object, guint prop_id,
       int fd;
 
       fd = g_value_get_int (value);
-      gst_fd_sink_update_fd (fdsink, fd);
+      gst_fd_sink_update_fd (fdsink, fd, NULL);
       break;
     }
     default:
@@ -546,28 +548,27 @@ gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
   type = GST_EVENT_TYPE (event);
 
   switch (type) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gint64 start, stop, pos;
-      GstFormat format;
-      gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
-          &stop, &pos);
+      const GstSegment *segment;
+
+      gst_event_parse_segment (event, &segment);
 
-      if (format == GST_FORMAT_BYTES) {
+      if (segment->format == GST_FORMAT_BYTES) {
         /* only try to seek and fail when we are going to a different
          * position */
-        if (fdsink->current_pos != start) {
+        if (fdsink->current_pos != segment->start) {
           /* FIXME, the seek should be performed on the pos field, start/stop are
            * just boundaries for valid bytes offsets. We should also fill the file
            * with zeroes if the new position extends the current EOF (sparse streams
            * and segment accumulation). */
-          if (!gst_fd_sink_do_seek (fdsink, (guint64) start))
+          if (!gst_fd_sink_do_seek (fdsink, (guint64) segment->start))
             goto seek_failed;
         }
       } else {
         GST_DEBUG_OBJECT (fdsink,
-            "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
-            gst_format_get_name (format));
+            "Ignored SEGMENT event of format %u (%s)", (guint) segment->format,
+            gst_format_get_name (segment->format));
       }
       break;
     }
@@ -575,13 +576,14 @@ gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
       break;
   }
 
-  return TRUE;
+  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
 
 seek_failed:
   {
     GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL),
         ("Error while seeking on file descriptor %d: %s",
             fdsink->fd, g_strerror (errno)));
+    gst_event_unref (event);
     return FALSE;
   }
 
@@ -590,45 +592,42 @@ seek_failed:
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
-gst_fd_sink_uri_get_type (void)
+gst_fd_sink_uri_get_type (GType type)
 {
   return GST_URI_SINK;
 }
 
-static gchar **
-gst_fd_sink_uri_get_protocols (void)
+static const gchar *const *
+gst_fd_sink_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "fd", NULL };
+  static const gchar *protocols[] = { "fd", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_fd_sink_uri_get_uri (GstURIHandler * handler)
 {
   GstFdSink *sink = GST_FD_SINK (handler);
 
-  return sink->uri;
+  /* FIXME: make thread-safe */
+  return g_strdup (sink->uri);
 }
 
 static gboolean
-gst_fd_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_fd_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** error)
 {
-  gchar *protocol;
   GstFdSink *sink = GST_FD_SINK (handler);
   gint fd;
 
-  protocol = gst_uri_get_protocol (uri);
-  if (strcmp (protocol, "fd") != 0) {
-    g_free (protocol);
+  if (sscanf (uri, "fd://%d", &fd) != 1) {
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "File descriptor URI could not be parsed");
     return FALSE;
   }
-  g_free (protocol);
-
-  if (sscanf (uri, "fd://%d", &fd) != 1)
-    return FALSE;
 
-  return gst_fd_sink_update_fd (sink, fd);
+  return gst_fd_sink_update_fd (sink, fd, error);
 }
 
 static void
index 715f107..0ca9115 100644 (file)
@@ -113,23 +113,11 @@ enum
 
 static void gst_fd_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
 
-static void
-_do_init (GType fd_src_type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_fd_src_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  g_type_add_interface_static (fd_src_type, GST_TYPE_URI_HANDLER,
-      &urihandler_info);
-
+#define _do_init \
+  G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_fd_src_uri_handler_init); \
   GST_DEBUG_CATEGORY_INIT (gst_fd_src_debug, "fdsrc", 0, "fdsrc element");
-}
-
-GST_BOILERPLATE_FULL (GstFdSrc, gst_fd_src, GstPushSrc, GST_TYPE_PUSH_SRC,
-    _do_init);
+#define gst_fd_src_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFdSrc, gst_fd_src, GST_TYPE_PUSH_SRC, _do_init);
 
 static void gst_fd_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -149,26 +137,15 @@ static gboolean gst_fd_src_query (GstBaseSrc * src, GstQuery * query);
 static GstFlowReturn gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf);
 
 static void
-gst_fd_src_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Filedescriptor Source",
-      "Source/File",
-      "Read from a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-}
-
-static void
 gst_fd_src_class_init (GstFdSrcClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbasesrc_class;
   GstPushSrcClass *gstpush_src_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
   gstpush_src_class = GST_PUSH_SRC_CLASS (klass);
 
@@ -192,6 +169,13 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
           G_MAXUINT64, DEFAULT_TIMEOUT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Filedescriptor Source",
+      "Source/File",
+      "Read from a file descriptor", "Erik Walthinsen <omega@cse.ogi.edu>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fd_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fd_src_stop);
   gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_src_unlock);
@@ -205,7 +189,7 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
 }
 
 static void
-gst_fd_src_init (GstFdSrc * fdsrc, GstFdSrcClass * klass)
+gst_fd_src_init (GstFdSrc * fdsrc)
 {
   fdsrc->new_fd = DEFAULT_FD;
   fdsrc->seekable_fd = FALSE;
@@ -409,6 +393,8 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
   gssize readbytes;
   guint blocksize;
   GstClockTime timeout;
+  guint8 *data;
+  gsize maxsize;
 
 #ifndef HAVE_WIN32
   gboolean try_again;
@@ -456,25 +442,26 @@ gst_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
   blocksize = GST_BASE_SRC (src)->blocksize;
 
   /* create the buffer */
-  buf = gst_buffer_try_new_and_alloc (blocksize);
-  if (G_UNLIKELY (buf == NULL)) {
-    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize);
-    return GST_FLOW_ERROR;
-  }
+  buf = gst_buffer_new_allocate (NULL, blocksize, 0);
+  if (G_UNLIKELY (buf == NULL))
+    goto alloc_failed;
+
+  data = gst_buffer_map (buf, NULL, &maxsize, GST_MAP_WRITE);
 
   do {
-    readbytes = read (src->fd, GST_BUFFER_DATA (buf), blocksize);
+    readbytes = read (src->fd, data, blocksize);
     GST_LOG_OBJECT (src, "read %" G_GSSIZE_FORMAT, readbytes);
   } while (readbytes == -1 && errno == EINTR);  /* retry if interrupted */
 
   if (readbytes < 0)
     goto read_error;
 
+  gst_buffer_unmap (buf, data, readbytes);
+
   if (readbytes == 0)
     goto eos;
 
   GST_BUFFER_OFFSET (buf) = src->curoffset;
-  GST_BUFFER_SIZE (buf) = readbytes;
   GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
   src->curoffset += readbytes;
 
@@ -500,17 +487,23 @@ stopped:
     return GST_FLOW_WRONG_STATE;
   }
 #endif
+alloc_failed:
+  {
+    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", blocksize);
+    return GST_FLOW_ERROR;
+  }
 eos:
   {
     GST_DEBUG_OBJECT (psrc, "Read 0 bytes. EOS.");
     gst_buffer_unref (buf);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 read_error:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
         ("read on file descriptor: %s.", g_strerror (errno)));
     GST_DEBUG_OBJECT (psrc, "Error reading from fd");
+    gst_buffer_unmap (buf, data, 0);
     gst_buffer_unref (buf);
     return GST_FLOW_ERROR;
   }
@@ -594,7 +587,7 @@ gst_fd_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
   if (G_UNLIKELY (res < 0 || res != offset))
     goto seek_failed;
 
-  segment->last_stop = segment->start;
+  segment->position = segment->start;
   segment->time = segment->start;
 
   return TRUE;
@@ -607,29 +600,31 @@ seek_failed:
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
-gst_fd_src_uri_get_type (void)
+gst_fd_src_uri_get_type (GType type)
 {
   return GST_URI_SRC;
 }
 
-static gchar **
-gst_fd_src_uri_get_protocols (void)
+static const gchar *const *
+gst_fd_src_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "fd", NULL };
+  static const gchar *protocols[] = { "fd", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_fd_src_uri_get_uri (GstURIHandler * handler)
 {
   GstFdSrc *src = GST_FD_SRC (handler);
 
-  return src->uri;
+  /* FIXME: make thread-safe */
+  return g_strdup (src->uri);
 }
 
 static gboolean
-gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_fd_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** err)
 {
   gchar *protocol, *q;
   GstFdSrc *src = GST_FD_SRC (handler);
index 9356c0f..5fc305a 100644 (file)
@@ -173,42 +173,18 @@ static gboolean gst_file_sink_query (GstBaseSink * bsink, GstQuery * query);
 static void gst_file_sink_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 
-
-static void
-_do_init (GType filesink_type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_file_sink_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER,
-      &urihandler_info);
-  GST_DEBUG_CATEGORY_INIT (gst_file_sink_debug, "filesink", 0,
-      "filesink element");
-}
-
-GST_BOILERPLATE_FULL (GstFileSink, gst_file_sink, GstBaseSink,
-    GST_TYPE_BASE_SINK, _do_init);
-
-static void
-gst_file_sink_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "File Sink",
-      "Sink/File", "Write stream to a file",
-      "Thomas Vander Stichele <thomas at apestaart dot org>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
+#define _do_init \
+  G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_file_sink_uri_handler_init); \
+  GST_DEBUG_CATEGORY_INIT (gst_file_sink_debug, "filesink", 0, "filesink element");
+#define gst_file_sink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFileSink, gst_file_sink, GST_TYPE_BASE_SINK,
+    _do_init);
 
 static void
 gst_file_sink_class_init (GstFileSinkClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
   GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
 
   gobject_class->dispose = gst_file_sink_dispose;
@@ -244,6 +220,13 @@ gst_file_sink_class_init (GstFileSinkClass * klass)
           "Append to an already existing file", DEFAULT_APPEND,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "File Sink",
+      "Sink/File", "Write stream to a file",
+      "Thomas Vander Stichele <thomas at apestaart dot org>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_file_sink_start);
   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_file_sink_stop);
   gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_file_sink_query);
@@ -257,7 +240,7 @@ gst_file_sink_class_init (GstFileSinkClass * klass)
 }
 
 static void
-gst_file_sink_init (GstFileSink * filesink, GstFileSinkClass * g_class)
+gst_file_sink_init (GstFileSink * filesink)
 {
   filesink->filename = NULL;
   filesink->file = NULL;
@@ -286,7 +269,8 @@ gst_file_sink_dispose (GObject * object)
 }
 
 static gboolean
-gst_file_sink_set_location (GstFileSink * sink, const gchar * location)
+gst_file_sink_set_location (GstFileSink * sink, const gchar * location,
+    GError ** error)
 {
   if (sink->file)
     goto was_open;
@@ -312,6 +296,9 @@ was_open:
   {
     g_warning ("Changing the `location' property on filesink when a file is "
         "open is not supported.");
+    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE,
+        "Changing the 'location' property on filesink when a file is "
+        "open is not supported");
     return FALSE;
   }
 }
@@ -324,7 +311,7 @@ gst_file_sink_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_LOCATION:
-      gst_file_sink_set_location (sink, g_value_get_string (value));
+      gst_file_sink_set_location (sink, g_value_get_string (value), NULL);
       break;
     case PROP_BUFFER_MODE:
       sink->buffer_mode = g_value_get_enum (value);
@@ -562,31 +549,29 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
   type = GST_EVENT_TYPE (event);
 
   switch (type) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gint64 start, stop, pos;
-      GstFormat format;
+      const GstSegment *segment;
 
-      gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
-          &stop, &pos);
+      gst_event_parse_segment (event, &segment);
 
-      if (format == GST_FORMAT_BYTES) {
+      if (segment->format == GST_FORMAT_BYTES) {
         /* only try to seek and fail when we are going to a different
          * position */
-        if (filesink->current_pos != start) {
+        if (filesink->current_pos != segment->start) {
           /* FIXME, the seek should be performed on the pos field, start/stop are
            * just boundaries for valid bytes offsets. We should also fill the file
            * with zeroes if the new position extends the current EOF (sparse streams
            * and segment accumulation). */
-          if (!gst_file_sink_do_seek (filesink, (guint64) start))
+          if (!gst_file_sink_do_seek (filesink, (guint64) segment->start))
             goto seek_failed;
         } else {
-          GST_DEBUG_OBJECT (filesink, "Ignored NEWSEGMENT, no seek needed");
+          GST_DEBUG_OBJECT (filesink, "Ignored SEGMENT, no seek needed");
         }
       } else {
         GST_DEBUG_OBJECT (filesink,
-            "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
-            gst_format_get_name (format));
+            "Ignored SEGMENT event of format %u (%s)", (guint) segment->format,
+            gst_format_get_name (segment->format));
       }
       break;
     }
@@ -598,7 +583,7 @@ gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
       break;
   }
 
-  return TRUE;
+  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
 
   /* ERRORS */
 seek_failed:
@@ -606,6 +591,7 @@ seek_failed:
     GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK,
         (_("Error while seeking in file \"%s\"."), filesink->filename),
         GST_ERROR_SYSTEM);
+    gst_event_unref (event);
     return FALSE;
   }
 flush_failed:
@@ -613,6 +599,7 @@ flush_failed:
     GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
         (_("Error while writing to file \"%s\"."), filesink->filename),
         GST_ERROR_SYSTEM);
+    gst_event_unref (event);
     return FALSE;
   }
 }
@@ -644,15 +631,15 @@ static GstFlowReturn
 gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 {
   GstFileSink *filesink;
-  guint size;
+  gsize size;
   guint8 *data;
 
   filesink = GST_FILE_SINK (sink);
 
-  size = GST_BUFFER_SIZE (buffer);
-  data = GST_BUFFER_DATA (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 
-  GST_DEBUG_OBJECT (filesink, "writing %u bytes at %" G_GUINT64_FORMAT,
+  GST_DEBUG_OBJECT (filesink,
+      "writing %" G_GSIZE_FORMAT " bytes at %" G_GUINT64_FORMAT,
       size, filesink->current_pos);
 
   if (size > 0 && data != NULL) {
@@ -661,6 +648,7 @@ gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
 
     filesink->current_pos += size;
   }
+  gst_buffer_unmap (buffer, data, size);
 
   return GST_FLOW_OK;
 
@@ -677,6 +665,7 @@ handle_error:
             ("%s", g_strerror (errno)));
       }
     }
+    gst_buffer_unmap (buffer, data, size);
     return GST_FLOW_ERROR;
   }
 }
@@ -697,41 +686,36 @@ gst_file_sink_stop (GstBaseSink * basesink)
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
-gst_file_sink_uri_get_type (void)
+gst_file_sink_uri_get_type (GType type)
 {
   return GST_URI_SINK;
 }
 
-static gchar **
-gst_file_sink_uri_get_protocols (void)
+static const gchar *const *
+gst_file_sink_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "file", NULL };
+  static const gchar *protocols[] = { "file", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_file_sink_uri_get_uri (GstURIHandler * handler)
 {
   GstFileSink *sink = GST_FILE_SINK (handler);
 
-  return sink->uri;
+  /* FIXME: make thread-safe */
+  return g_strdup (sink->uri);
 }
 
 static gboolean
-gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** error)
 {
-  gchar *protocol, *location;
+  gchar *location;
   gboolean ret;
   GstFileSink *sink = GST_FILE_SINK (handler);
 
-  protocol = gst_uri_get_protocol (uri);
-  if (strcmp (protocol, "file") != 0) {
-    g_free (protocol);
-    return FALSE;
-  }
-  g_free (protocol);
-
   /* allow file://localhost/foo/bar by stripping localhost but fail
    * for every other hostname */
   if (g_str_has_prefix (uri, "file://localhost/")) {
@@ -747,20 +731,26 @@ gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
     /* Special case for "file://" as this is used by some applications
      *  to test with gst_element_make_from_uri if there's an element
      *  that supports the URI protocol. */
-    gst_file_sink_set_location (sink, NULL);
+    gst_file_sink_set_location (sink, NULL, NULL);
     return TRUE;
   } else {
     location = gst_uri_get_location (uri);
   }
 
-  if (!location)
+  if (!location) {
+    g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "File URI without location");
     return FALSE;
+  }
+
   if (!g_path_is_absolute (location)) {
+    g_set_error_literal (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "File URI location must be an absolute path");
     g_free (location);
     return FALSE;
   }
 
-  ret = gst_file_sink_set_location (sink, location);
+  ret = gst_file_sink_set_location (sink, location, error);
   g_free (location);
 
   return ret;
index 87402c8..9ed4406 100644 (file)
 #  include <unistd.h>
 #endif
 
-#ifdef HAVE_MMAP
-# include <sys/mman.h>
-#endif
-
 #include <errno.h>
 #include <string.h>
 
@@ -119,46 +115,6 @@ gst_open (const gchar * filename, int flags, int mode)
 #endif
 }
 
-
-/**********************************************************************
- * GStreamer Default File Source
- * Theory of Operation
- *
- * Update: see GstFileSrc:use-mmap property documentation below
- *         for why use of mmap() is disabled by default.
- *
- * This source uses mmap(2) to efficiently load data from a file.
- * To do this without seriously polluting the applications' memory
- * space, it must do so in smaller chunks, say 1-4MB at a time.
- * Buffers are then subdivided from these mmap'd chunks, to directly
- * make use of the mmap.
- *
- * To handle refcounting so that the mmap can be freed at the appropriate
- * time, a buffer will be created for each mmap'd region, and all new
- * buffers will be sub-buffers of this top-level buffer.  As they are
- * freed, the refcount goes down on the mmap'd buffer and its free()
- * function is called, which will call munmap(2) on itself.
- *
- * If a buffer happens to cross the boundaries of an mmap'd region, we
- * have to decide whether it's more efficient to copy the data into a
- * new buffer, or mmap() just that buffer.  There will have to be a
- * breakpoint size to determine which will be done.  The mmap() size
- * has a lot to do with this as well, because you end up in double-
- * jeopardy: the larger the outgoing buffer, the more data to copy when
- * it overlaps, *and* the more frequently you'll have buffers that *do*
- * overlap.
- *
- * Seeking is another tricky aspect to do efficiently.  The initial
- * implementation of this source won't make use of these features, however.
- * The issue is that if an application seeks backwards in a file, *and*
- * that region of the file is covered by an mmap that hasn't been fully
- * deallocated, we really should re-use it.  But keeping track of these
- * regions is tricky because we have to lock the structure that holds
- * them.  We need to settle on a locking primitive (GMutex seems to be
- * a really good option...), then we can do that.
- */
-
-
 GST_DEBUG_CATEGORY_STATIC (gst_file_src_debug);
 #define GST_CAT_DEFAULT gst_file_src_debug
 
@@ -170,20 +126,11 @@ enum
 };
 
 #define DEFAULT_BLOCKSIZE       4*1024
-#define DEFAULT_MMAPSIZE        4*1024*1024
-#define DEFAULT_TOUCH           TRUE
-#define DEFAULT_USEMMAP         FALSE
-#define DEFAULT_SEQUENTIAL      FALSE
 
 enum
 {
-  ARG_0,
-  ARG_LOCATION,
-  ARG_FD,
-  ARG_MMAPSIZE,
-  ARG_SEQUENTIAL,
-  ARG_TOUCH,
-  ARG_USEMMAP
+  PROP_0,
+  PROP_LOCATION
 };
 
 static void gst_file_src_finalize (GObject * object);
@@ -198,113 +145,54 @@ static gboolean gst_file_src_stop (GstBaseSrc * basesrc);
 
 static gboolean gst_file_src_is_seekable (GstBaseSrc * src);
 static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size);
-static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
-    guint length, GstBuffer ** buffer);
+static GstFlowReturn gst_file_src_fill (GstBaseSrc * src, guint64 offset,
+    guint length, GstBuffer * buf);
 static gboolean gst_file_src_query (GstBaseSrc * src, GstQuery * query);
 
 static void gst_file_src_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 
-static void
-_do_init (GType filesrc_type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_file_src_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER,
-      &urihandler_info);
+#define _do_init \
+  G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_file_src_uri_handler_init); \
   GST_DEBUG_CATEGORY_INIT (gst_file_src_debug, "filesrc", 0, "filesrc element");
-}
-
-GST_BOILERPLATE_FULL (GstFileSrc, gst_file_src, GstBaseSrc, GST_TYPE_BASE_SRC,
-    _do_init);
-
-static void
-gst_file_src_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "File Source",
-      "Source/File",
-      "Read from arbitrary point in a file",
-      "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-}
+#define gst_file_src_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFileSrc, gst_file_src, GST_TYPE_BASE_SRC, _do_init);
 
 static void
 gst_file_src_class_init (GstFileSrcClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbasesrc_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
+  gstelement_class = GST_ELEMENT_CLASS (klass);
   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
 
   gobject_class->set_property = gst_file_src_set_property;
   gobject_class->get_property = gst_file_src_get_property;
 
-  g_object_class_install_property (gobject_class, ARG_FD,
-      g_param_spec_int ("fd", "File-descriptor",
-          "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
-          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, ARG_LOCATION,
+  g_object_class_install_property (gobject_class, PROP_LOCATION,
       g_param_spec_string ("location", "File Location",
           "Location of the file to read", NULL,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_READY));
-  g_object_class_install_property (gobject_class, ARG_MMAPSIZE,
-      g_param_spec_ulong ("mmapsize", "mmap() Block Size",
-          "Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
-          GST_PARAM_MUTABLE_PLAYING));
-  g_object_class_install_property (gobject_class, ARG_TOUCH,
-      g_param_spec_boolean ("touch", "Touch mapped region read data",
-          "Touch mmapped data regions to force them to be read from disk",
-          DEFAULT_TOUCH,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
-          GST_PARAM_MUTABLE_PLAYING));
-  /**
-   * GstFileSrc:use-mmap
-   *
-   * Whether to use mmap(). Set to TRUE to force use of mmap() instead of
-   * read() for reading data.
-   *
-   * Use of mmap() is disabled by default since with mmap() there are a
-   * number of occasions where the process/application will be notified of
-   * read errors via a SIGBUS signal from the kernel, which will lead to
-   * the application being killed if not handled by the application. This
-   * is something that is difficult to work around for a library like
-   * GStreamer, hence use of mmap() is disabled by default. Said errors
-   * can occur for example when an external device (e.g. an external hard
-   * drive or a portable music player) are unplugged while in use, or when
-   * a CD/DVD medium cannot be be read because the medium is scratched or
-   * otherwise damaged.
-   *
-   **/
-  g_object_class_install_property (gobject_class, ARG_USEMMAP,
-      g_param_spec_boolean ("use-mmap", "Use mmap to read data",
-          "Whether to use mmap() instead of read()",
-          DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
-          GST_PARAM_MUTABLE_READY));
-  g_object_class_install_property (gobject_class, ARG_SEQUENTIAL,
-      g_param_spec_boolean ("sequential", "Optimise for sequential mmap access",
-          "Whether to use madvise to hint to the kernel that access to "
-          "mmap pages will be sequential",
-          DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
-          GST_PARAM_MUTABLE_PLAYING));
 
   gobject_class->finalize = gst_file_src_finalize;
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "File Source",
+      "Source/File",
+      "Read from arbitrary point in a file",
+      "Erik Walthinsen <omega@cse.ogi.edu>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop);
   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
-  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
+  gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_file_src_fill);
   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_file_src_query);
 
   if (sizeof (off_t) < 8) {
@@ -314,23 +202,12 @@ gst_file_src_class_init (GstFileSrcClass * klass)
 }
 
 static void
-gst_file_src_init (GstFileSrc * src, GstFileSrcClass * g_class)
+gst_file_src_init (GstFileSrc * src)
 {
-#ifdef HAVE_MMAP
-  src->pagesize = getpagesize ();
-#endif
-
   src->filename = NULL;
   src->fd = 0;
   src->uri = NULL;
 
-  src->touch = DEFAULT_TOUCH;
-
-  src->mapbuf = NULL;
-  src->mapsize = DEFAULT_MMAPSIZE;      /* default is 4MB */
-  src->use_mmap = DEFAULT_USEMMAP;
-  src->sequential = DEFAULT_SEQUENTIAL;
-
   src->is_regular = FALSE;
 }
 
@@ -375,7 +252,7 @@ gst_file_src_set_location (GstFileSrc * src, const gchar * location)
     GST_INFO ("uri      : %s", src->uri);
   }
   g_object_notify (G_OBJECT (src), "location");
-  gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
+  /* FIXME 0.11: notify "uri" property once there is one */
 
   return TRUE;
 
@@ -400,27 +277,9 @@ gst_file_src_set_property (GObject * object, guint prop_id,
   src = GST_FILE_SRC (object);
 
   switch (prop_id) {
-    case ARG_LOCATION:
+    case PROP_LOCATION:
       gst_file_src_set_location (src, g_value_get_string (value));
       break;
-    case ARG_MMAPSIZE:
-      if ((src->mapsize % src->pagesize) == 0) {
-        src->mapsize = g_value_get_ulong (value);
-      } else {
-        GST_INFO_OBJECT (src,
-            "invalid mapsize, must be a multiple of pagesize, which is %d",
-            src->pagesize);
-      }
-      break;
-    case ARG_TOUCH:
-      src->touch = g_value_get_boolean (value);
-      break;
-    case ARG_SEQUENTIAL:
-      src->sequential = g_value_get_boolean (value);
-      break;
-    case ARG_USEMMAP:
-      src->use_mmap = g_value_get_boolean (value);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -438,24 +297,9 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value,
   src = GST_FILE_SRC (object);
 
   switch (prop_id) {
-    case ARG_LOCATION:
+    case PROP_LOCATION:
       g_value_set_string (value, src->filename);
       break;
-    case ARG_FD:
-      g_value_set_int (value, src->fd);
-      break;
-    case ARG_MMAPSIZE:
-      g_value_set_ulong (value, src->mapsize);
-      break;
-    case ARG_TOUCH:
-      g_value_set_boolean (value, src->touch);
-      break;
-    case ARG_SEQUENTIAL:
-      g_value_set_boolean (value, src->sequential);
-      break;
-    case ARG_USEMMAP:
-      g_value_set_boolean (value, src->use_mmap);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -463,327 +307,6 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value,
 }
 
 /***
- * mmap code below
- */
-
-#ifdef HAVE_MMAP
-
-/* GstMmapBuffer */
-
-typedef struct _GstMmapBuffer GstMmapBuffer;
-typedef struct _GstMmapBufferClass GstMmapBufferClass;
-
-#define GST_TYPE_MMAP_BUFFER                         (gst_mmap_buffer_get_type())
-
-#define GST_IS_MMAP_BUFFER(obj)  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MMAP_BUFFER))
-#define GST_IS_MMAP_BUFFER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MMAP_BUFFER))
-#define GST_MMAP_BUFFER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MMAP_BUFFER, GstMmapBufferClass))
-#define GST_MMAP_BUFFER(obj)     (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MMAP_BUFFER, GstMmapBuffer))
-#define GST_MMAP_BUFFER_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MMAP_BUFFER, GstMmapBufferClass))
-
-
-
-struct _GstMmapBuffer
-{
-  GstBuffer buffer;
-
-  GstFileSrc *filesrc;
-};
-
-struct _GstMmapBufferClass
-{
-  GstBufferClass buffer_class;
-};
-
-static void gst_mmap_buffer_finalize (GstMmapBuffer * mmap_buffer);
-
-GType gst_mmap_buffer_get_type (void);
-
-G_DEFINE_TYPE (GstMmapBuffer, gst_mmap_buffer, GST_TYPE_BUFFER);
-
-static void
-gst_mmap_buffer_class_init (GstMmapBufferClass * g_class)
-{
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
-  mini_object_class->finalize =
-      (GstMiniObjectFinalizeFunction) gst_mmap_buffer_finalize;
-}
-
-static void
-gst_mmap_buffer_init (GstMmapBuffer * buf)
-{
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
-  /* before we re-enable this flag, we probably need to fix _copy()
-   * _make_writable(), etc. in GstMiniObject/GstBuffer as well */
-  /* GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_ORIGINAL); */
-}
-
-static void
-gst_mmap_buffer_finalize (GstMmapBuffer * mmap_buffer)
-{
-  guint size;
-  gpointer data;
-  guint64 offset;
-  GstFileSrc *src;
-  GstBuffer *buffer = GST_BUFFER (mmap_buffer);
-
-  /* get info */
-  size = GST_BUFFER_SIZE (buffer);
-  offset = GST_BUFFER_OFFSET (buffer);
-  data = GST_BUFFER_DATA (buffer);
-  src = mmap_buffer->filesrc;
-
-  GST_LOG ("freeing mmap()d buffer at %" G_GUINT64_FORMAT "+%u", offset, size);
-
-#ifdef MADV_DONTNEED
-  /* madvise to tell the kernel what to do with it */
-  if (madvise (data, size, MADV_DONTNEED) < 0) {
-    GST_WARNING_OBJECT (src, "warning: madvise failed: %s", g_strerror (errno));
-  }
-#endif
-
-  /* now unmap the memory */
-  if (munmap (data, size) < 0) {
-    GST_WARNING_OBJECT (src, "warning: munmap failed: %s", g_strerror (errno));
-  }
-
-  /* cast to unsigned long, since there's no gportable way to print
-   * guint64 as hex */
-  GST_LOG ("unmapped region %08lx+%08lx at %p",
-      (gulong) offset, (gulong) size, data);
-
-  GST_MINI_OBJECT_CLASS (gst_mmap_buffer_parent_class)->finalize
-      (GST_MINI_OBJECT (mmap_buffer));
-}
-
-static GstBuffer *
-gst_file_src_map_region (GstFileSrc * src, off_t offset, gsize size,
-    gboolean testonly)
-{
-  GstBuffer *buf;
-  void *mmapregion;
-
-  g_return_val_if_fail (offset >= 0, NULL);
-
-  /* FIXME ? use goffset and friends if we require glib >= 2.20 */
-  GST_LOG_OBJECT (src, "mapping region %08" G_GINT64_MODIFIER "x+%08lx "
-      "from file into memory", (gint64) offset, (gulong) size);
-
-  mmapregion = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
-
-  if (mmapregion == NULL || mmapregion == MAP_FAILED)
-    goto mmap_failed;
-
-  GST_LOG_OBJECT (src, "mapped region %08lx+%08lx from file into memory at %p",
-      (gulong) offset, (gulong) size, mmapregion);
-
-  /* time to allocate a new mapbuf */
-  buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_MMAP_BUFFER);
-  /* mmap() the data into this new buffer */
-  GST_BUFFER_DATA (buf) = mmapregion;
-  GST_MMAP_BUFFER (buf)->filesrc = src;
-
-#ifdef MADV_SEQUENTIAL
-  if (src->sequential) {
-    /* madvise to tell the kernel what to do with it */
-    if (madvise (mmapregion, size, MADV_SEQUENTIAL) < 0) {
-      GST_WARNING_OBJECT (src, "warning: madvise failed: %s",
-          g_strerror (errno));
-    }
-  }
-#endif
-
-  /* fill in the rest of the fields */
-  GST_BUFFER_SIZE (buf) = size;
-  GST_BUFFER_OFFSET (buf) = offset;
-  GST_BUFFER_OFFSET_END (buf) = offset + size;
-  GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
-
-  return buf;
-
-  /* ERROR */
-mmap_failed:
-  {
-    if (!testonly) {
-      GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-          ("mmap (0x%08lx, %d, 0x%" G_GINT64_MODIFIER "x) failed: %s",
-              (gulong) size, src->fd, (guint64) offset, g_strerror (errno)));
-    }
-    return NULL;
-  }
-}
-
-static GstBuffer *
-gst_file_src_map_small_region (GstFileSrc * src, off_t offset, gsize size)
-{
-  GstBuffer *ret;
-  off_t mod;
-  guint pagesize;
-
-  GST_LOG_OBJECT (src,
-      "attempting to map a small buffer at %" G_GUINT64_FORMAT "+%d",
-      (guint64) offset, (gint) size);
-
-  pagesize = src->pagesize;
-
-  mod = offset % pagesize;
-
-  /* if the offset starts at a non-page boundary, we have to special case */
-  if (mod != 0) {
-    gsize mapsize;
-    off_t mapbase;
-    GstBuffer *map;
-
-    mapbase = offset - mod;
-    mapsize = ((size + mod + pagesize - 1) / pagesize) * pagesize;
-
-    GST_LOG_OBJECT (src,
-        "not on page boundaries, resizing to map to %" G_GUINT64_FORMAT "+%d",
-        (guint64) mapbase, (gint) mapsize);
-
-    map = gst_file_src_map_region (src, mapbase, mapsize, FALSE);
-    if (map == NULL)
-      return NULL;
-
-    ret = gst_buffer_create_sub (map, offset - mapbase, size);
-    GST_BUFFER_OFFSET (ret) = GST_BUFFER_OFFSET (map) + offset - mapbase;
-
-    gst_buffer_unref (map);
-  } else {
-    ret = gst_file_src_map_region (src, offset, size, FALSE);
-  }
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_file_src_create_mmap (GstFileSrc * src, guint64 offset, guint length,
-    GstBuffer ** buffer)
-{
-  GstBuffer *buf = NULL;
-  gsize readsize, mapsize;
-  off_t readend, mapstart, mapend;
-  int i;
-
-  /* calculate end pointers so we don't have to do so repeatedly later */
-  readsize = length;
-  readend = offset + readsize;  /* note this is the byte *after* the read */
-
-  mapstart = GST_BUFFER_OFFSET (src->mapbuf);
-  mapsize = GST_BUFFER_SIZE (src->mapbuf);
-  mapend = mapstart + mapsize;  /* note this is the byte *after* the map */
-
-  GST_LOG ("attempting to read %08lx, %08lx, %08lx, %08lx",
-      (unsigned long) readsize, (unsigned long) readend,
-      (unsigned long) mapstart, (unsigned long) mapend);
-
-  /* if the start is past the mapstart */
-  if (offset >= mapstart) {
-    /* if the end is before the mapend, the buffer is in current mmap region... */
-    /* ('cause by definition if readend is in the buffer, so's readstart) */
-    if (readend <= mapend) {
-      GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%u lives in "
-          "current mapbuf %u+%u, creating subbuffer of mapbuf",
-          offset, (guint) readsize, (guint) mapstart, (guint) mapsize);
-      buf = gst_buffer_create_sub (src->mapbuf, offset - mapstart, readsize);
-      GST_BUFFER_OFFSET (buf) = offset;
-
-      /* if the start actually is within the current mmap region, map an overlap buffer */
-    } else if (offset < mapend) {
-      GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%u starts in "
-          "mapbuf %u+%u but ends outside, creating new mmap",
-          offset, (guint) readsize, (guint) mapstart, (guint) mapsize);
-      buf = gst_file_src_map_small_region (src, offset, readsize);
-      if (buf == NULL)
-        goto could_not_mmap;
-    }
-
-    /* the only other option is that buffer is totally outside, which means we search for it */
-
-    /* now we can assume that the start is *before* the current mmap region */
-    /* if the readend is past mapstart, we have two options */
-  } else if (readend >= mapstart) {
-    /* either the read buffer overlaps the start of the mmap region */
-    /* or the read buffer fully contains the current mmap region    */
-    /* either way, it's really not relevant, we just create a new region anyway */
-    GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d starts before "
-        "mapbuf %d+%d, but overlaps it", (guint64) offset, (gint) readsize,
-        (gint) mapstart, (gint) mapsize);
-    buf = gst_file_src_map_small_region (src, offset, readsize);
-    if (buf == NULL)
-      goto could_not_mmap;
-  }
-
-  /* then deal with the case where the read buffer is totally outside */
-  if (buf == NULL) {
-    /* first check to see if there's a map that covers the right region already */
-    GST_LOG_OBJECT (src, "searching for mapbuf to cover %" G_GUINT64_FORMAT
-        "+%d", offset, (int) readsize);
-
-    /* if the read buffer crosses a mmap region boundary, create a one-off region */
-    if ((offset / src->mapsize) != (readend / src->mapsize)) {
-      GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d crosses a "
-          "%d-byte boundary, creating a one-off", offset, (int) readsize,
-          (int) src->mapsize);
-      buf = gst_file_src_map_small_region (src, offset, readsize);
-      if (buf == NULL)
-        goto could_not_mmap;
-
-      /* otherwise we will create a new mmap region and set it to the default */
-    } else {
-      gsize mapsize;
-
-      off_t nextmap = offset - (offset % src->mapsize);
-
-      GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d in new mapbuf "
-          "at %" G_GUINT64_FORMAT "+%d, mapping and subbuffering",
-          offset, (gint) readsize, (guint64) nextmap, (gint) src->mapsize);
-      /* first, we're done with the old mapbuf */
-      gst_buffer_unref (src->mapbuf);
-      mapsize = src->mapsize;
-
-      /* double the mapsize as long as the readsize is smaller */
-      while (readsize + offset > nextmap + mapsize) {
-        GST_LOG_OBJECT (src, "readsize smaller then mapsize %08x %d",
-            (guint) readsize, (gint) mapsize);
-        mapsize <<= 1;
-      }
-      /* create a new one */
-      src->mapbuf = gst_file_src_map_region (src, nextmap, mapsize, FALSE);
-      if (src->mapbuf == NULL)
-        goto could_not_mmap;
-
-      /* subbuffer it */
-      buf = gst_buffer_create_sub (src->mapbuf, offset - nextmap, readsize);
-      GST_BUFFER_OFFSET (buf) =
-          GST_BUFFER_OFFSET (src->mapbuf) + offset - nextmap;
-    }
-  }
-
-  /* if we need to touch the buffer (to bring it into memory), do so */
-  if (src->touch) {
-    volatile guchar *p = GST_BUFFER_DATA (buf);
-
-    /* read first byte of each page */
-    for (i = 0; i < GST_BUFFER_SIZE (buf); i += src->pagesize)
-      (void) p[i];
-  }
-
-  /* we're done, return the buffer */
-  *buffer = buf;
-
-  return GST_FLOW_OK;
-
-  /* ERROR */
-could_not_mmap:
-  {
-    return GST_FLOW_ERROR;
-  }
-}
-#endif
-
-/***
  * read code below
  * that is to say, you shouldn't read the code below, but the code that reads
  * stuff is below.  Well, you shouldn't not read the code below, feel free
@@ -793,14 +316,16 @@ could_not_mmap:
  * the sort of attitude we want to be advertising.  No sir.
  *
  */
-
 static GstFlowReturn
-gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
-    GstBuffer ** buffer)
+gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
+    GstBuffer * buf)
 {
-  int ret;
-  GstBuffer *buf;
+  GstFileSrc *src;
   guint to_read, bytes_read;
+  int ret;
+  guint8 *data;
+
+  src = GST_FILE_SRC_CAST (basesrc);
 
   if (G_UNLIKELY (src->read_position != offset)) {
     off_t res;
@@ -812,23 +337,15 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
     src->read_position = offset;
   }
 
-  buf = gst_buffer_try_new_and_alloc (length);
-  if (G_UNLIKELY (buf == NULL && length > 0)) {
-    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
-    return GST_FLOW_ERROR;
-  }
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
 
-  /* No need to read anything if length is 0 */
-  GST_BUFFER_SIZE (buf) = 0;
-  GST_BUFFER_OFFSET (buf) = offset;
-  GST_BUFFER_OFFSET_END (buf) = offset;
   bytes_read = 0;
   to_read = length;
   while (to_read > 0) {
     GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
         to_read, offset + bytes_read);
     errno = 0;
-    ret = read (src->fd, GST_BUFFER_DATA (buf) + bytes_read, to_read);
+    ret = read (src->fd, data + bytes_read, to_read);
     if (G_UNLIKELY (ret < 0)) {
       if (errno == EAGAIN || errno == EINTR)
         continue;
@@ -849,10 +366,10 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
     src->read_position += ret;
   }
 
-  GST_BUFFER_SIZE (buf) = bytes_read;
-  GST_BUFFER_OFFSET_END (buf) = offset + bytes_read;
+  gst_buffer_unmap (buf, data, bytes_read);
 
-  *buffer = buf;
+  GST_BUFFER_OFFSET (buf) = offset;
+  GST_BUFFER_OFFSET_END (buf) = offset + bytes_read;
 
   return GST_FLOW_OK;
 
@@ -865,37 +382,15 @@ seek_failed:
 could_not_read:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-    gst_buffer_unref (buf);
+    gst_buffer_unmap (buf, data, 0);
     return GST_FLOW_ERROR;
   }
 eos:
   {
     GST_DEBUG ("EOS");
-    gst_buffer_unref (buf);
-    return GST_FLOW_UNEXPECTED;
-  }
-}
-
-static GstFlowReturn
-gst_file_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
-    GstBuffer ** buffer)
-{
-  GstFileSrc *src;
-  GstFlowReturn ret;
-
-  src = GST_FILE_SRC_CAST (basesrc);
-
-#ifdef HAVE_MMAP
-  if (src->using_mmap) {
-    ret = gst_file_src_create_mmap (src, offset, length, buffer);
-  } else {
-    ret = gst_file_src_create_read (src, offset, length, buffer);
+    gst_buffer_unmap (buf, data, 0);
+    return GST_FLOW_EOS;
   }
-#else
-  ret = gst_file_src_create_read (src, offset, length, buffer);
-#endif
-
-  return ret;
 }
 
 static gboolean
@@ -984,29 +479,14 @@ gst_file_src_start (GstBaseSrc * basesrc)
   if (S_ISSOCK (stat_results.st_mode))
     goto was_socket;
 
-  src->using_mmap = FALSE;
   src->read_position = 0;
 
   /* record if it's a regular (hence seekable and lengthable) file */
   if (S_ISREG (stat_results.st_mode))
     src->is_regular = TRUE;
 
-#ifdef HAVE_MMAP
-  if (src->use_mmap) {
-    /* FIXME: maybe we should only try to mmap if it's a regular file */
-    /* allocate the first mmap'd region if it's a regular file ? */
-    src->mapbuf = gst_file_src_map_region (src, 0, src->mapsize, TRUE);
-    if (src->mapbuf != NULL) {
-      GST_DEBUG_OBJECT (src, "using mmap for file");
-      src->using_mmap = TRUE;
-      src->seekable = TRUE;
-    }
-  }
-  if (src->mapbuf == NULL)
-#endif
+  /* We need to check if the underlying file is seekable. */
   {
-    /* If not in mmap mode, we need to check if the underlying file is
-     * seekable. */
     off_t res = lseek (src->fd, 0, SEEK_END);
 
     if (res < 0) {
@@ -1032,7 +512,7 @@ no_filename:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
         (_("No file name specified for reading.")), (NULL));
-    return FALSE;
+    goto error_exit;
   }
 open_failed:
   {
@@ -1047,29 +527,30 @@ open_failed:
             GST_ERROR_SYSTEM);
         break;
     }
-    return FALSE;
+    goto error_exit;
   }
 no_stat:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         (_("Could not get info on \"%s\"."), src->filename), (NULL));
-    close (src->fd);
-    return FALSE;
+    goto error_close;
   }
 was_directory:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         (_("\"%s\" is a directory."), src->filename), (NULL));
-    close (src->fd);
-    return FALSE;
+    goto error_close;
   }
 was_socket:
   {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
         (_("File \"%s\" is a socket."), src->filename), (NULL));
-    close (src->fd);
-    return FALSE;
+    goto error_close;
   }
+error_close:
+  close (src->fd);
+error_exit:
+  return FALSE;
 }
 
 /* unmap and close the file */
@@ -1085,45 +566,41 @@ gst_file_src_stop (GstBaseSrc * basesrc)
   src->fd = 0;
   src->is_regular = FALSE;
 
-  if (src->mapbuf) {
-    gst_buffer_unref (src->mapbuf);
-    src->mapbuf = NULL;
-  }
-
   return TRUE;
 }
 
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
-gst_file_src_uri_get_type (void)
+gst_file_src_uri_get_type (GType type)
 {
   return GST_URI_SRC;
 }
 
-static gchar **
-gst_file_src_uri_get_protocols (void)
+static const gchar *const *
+gst_file_src_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "file", NULL };
+  static const gchar *protocols[] = { "file", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_file_src_uri_get_uri (GstURIHandler * handler)
 {
   GstFileSrc *src = GST_FILE_SRC (handler);
 
-  return src->uri;
+  /* FIXME: make thread-safe */
+  return g_strdup (src->uri);
 }
 
 static gboolean
-gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** err)
 {
   gchar *location, *hostname = NULL;
   gboolean ret = FALSE;
   GstFileSrc *src = GST_FILE_SRC (handler);
-  GError *error = NULL;
 
   if (strcmp (uri, "file://") == 0) {
     /* Special case for "file://" as this is used by some applications
@@ -1133,22 +610,19 @@ gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
     return TRUE;
   }
 
-  location = g_filename_from_uri (uri, &hostname, &error);
+  location = g_filename_from_uri (uri, &hostname, err);
 
-  if (!location || error) {
-    if (error) {
-      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
-          error->message);
-      g_error_free (error);
-    } else {
-      GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
-    }
+  if (!location || (err != NULL && *err != NULL)) {
+    GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
+        (err != NULL && *err != NULL) ? (*err)->message : "unknown error");
     goto beach;
   }
 
   if ((hostname) && (strcmp (hostname, "localhost"))) {
     /* Only 'localhost' is permitted */
     GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
+    g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
+        "File URI with invalid hostname '%s'", hostname);
     goto beach;
   }
 #ifdef G_OS_WIN32
index dbd6fe4..5aa9f87 100644 (file)
@@ -55,23 +55,14 @@ struct _GstFileSrc {
   GstBaseSrc element;
 
   /*< private >*/
-  guint pagesize;                      /* system page size */
-
   gchar *filename;                     /* filename */
   gchar *uri;                          /* caching the URI */
   gint fd;                             /* open file descriptor */
   guint64 read_position;               /* position of fd */
 
-  gboolean touch;                      /* whether to touch every page */
-  gboolean using_mmap;                  /* whether we opened it with mmap */
-  gboolean sequential;                  /* Whether to madvise (MADV_SEQUENTIAL) 
-                                           for mmap pages */
   gboolean seekable;                    /* whether the file is seekable */
   gboolean is_regular;                  /* whether it's a (symlink to a)
                                            regular file */
-  GstBuffer *mapbuf;
-  size_t mapsize;
-  gboolean use_mmap;
 };
 
 struct _GstFileSrcClass {
index 4cb8c35..8222910 100644 (file)
@@ -94,7 +94,7 @@ gst_funnel_pad_init (GstFunnelPad * pad)
 }
 
 static GstStaticPadTemplate funnel_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink%d",
+GST_STATIC_PAD_TEMPLATE ("sink_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS_ANY);
@@ -105,43 +105,26 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS_ANY);
 
-static void
-_do_init (GType type)
-{
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (gst_funnel_debug, "funnel", 0, "funnel element");
-}
-
-GST_BOILERPLATE_FULL (GstFunnel, gst_funnel, GstElement, GST_TYPE_ELEMENT,
-    _do_init);
+#define gst_funnel_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstFunnel, gst_funnel, GST_TYPE_ELEMENT, _do_init);
 
 static GstStateChangeReturn gst_funnel_change_state (GstElement * element,
     GstStateChange transition);
 static GstPad *gst_funnel_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name);
+    GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
 static void gst_funnel_release_pad (GstElement * element, GstPad * pad);
 
-static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_funnel_sink_buffer_alloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf);
-static gboolean gst_funnel_sink_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_funnel_sink_getcaps (GstPad * pad);
-
-static gboolean gst_funnel_src_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static gboolean gst_funnel_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_funnel_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-static void
-gst_funnel_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Funnel pipe fitting", "Generic", "N-to-1 pipe fitting",
-      "Olivier Crete <olivier.crete@collabora.co.uk>");
-
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&funnel_sink_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&funnel_src_template));
-}
+static gboolean gst_funnel_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
 static void
 gst_funnel_dispose (GObject * object)
@@ -169,6 +152,15 @@ gst_funnel_class_init (GstFunnelClass * klass)
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_funnel_dispose);
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Funnel pipe fitting", "Generic", "N-to-1 pipe fitting",
+      "Olivier Crete <olivier.crete@collabora.co.uk>");
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&funnel_sink_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&funnel_src_template));
+
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_funnel_request_new_pad);
   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_funnel_release_pad);
@@ -176,7 +168,7 @@ gst_funnel_class_init (GstFunnelClass * klass)
 }
 
 static void
-gst_funnel_init (GstFunnel * funnel, GstFunnelClass * g_class)
+gst_funnel_init (GstFunnel * funnel)
 {
   funnel->srcpad = gst_pad_new_from_static_template (&funnel_src_template,
       "src");
@@ -185,26 +177,9 @@ gst_funnel_init (GstFunnel * funnel, GstFunnelClass * g_class)
   gst_element_add_pad (GST_ELEMENT (funnel), funnel->srcpad);
 }
 
-static GstFlowReturn
-gst_funnel_sink_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent_element (pad));
-  GstFlowReturn ret;
-
-  if (G_UNLIKELY (funnel == NULL))
-    return GST_FLOW_WRONG_STATE;
-
-  ret = gst_pad_alloc_buffer (funnel->srcpad, offset, size, caps, buf);
-
-  gst_object_unref (funnel);
-
-  return ret;
-}
-
 static GstPad *
 gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ,
-    const gchar * name)
+    const gchar * name, const GstCaps * caps)
 {
   GstPad *sinkpad;
 
@@ -218,10 +193,8 @@ gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ,
       GST_DEBUG_FUNCPTR (gst_funnel_sink_chain));
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_funnel_sink_event));
-  gst_pad_set_getcaps_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_funnel_sink_getcaps));
-  gst_pad_set_bufferalloc_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_funnel_sink_buffer_alloc));
+  gst_pad_set_query_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_funnel_sink_query));
 
   gst_pad_set_active (sinkpad, TRUE);
 
@@ -242,33 +215,17 @@ gst_funnel_release_pad (GstElement * element, GstPad * pad)
   gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad);
 }
 
-static GstCaps *
-gst_funnel_sink_getcaps (GstPad * pad)
-{
-  GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
-  GstCaps *caps;
-
-  if (G_UNLIKELY (funnel == NULL))
-    return gst_caps_new_any ();
-
-  caps = gst_pad_peer_get_caps_reffed (funnel->srcpad);
-  if (caps == NULL)
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
-
-  gst_object_unref (funnel);
-
-  return caps;
-}
-
 static GstFlowReturn
-gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
+gst_funnel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstFlowReturn res;
-  GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
+  GstFunnel *funnel = GST_FUNNEL (parent);
   GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
   GstEvent *event = NULL;
   GstClockTime newts;
+#if 0
   GstCaps *padcaps;
+#endif
 
   GST_DEBUG_OBJECT (funnel, "received buffer %p", buffer);
 
@@ -276,24 +233,24 @@ gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
   if (fpad->segment.format == GST_FORMAT_UNDEFINED) {
     GST_WARNING_OBJECT (funnel, "Got buffer without segment,"
         " setting segment [0,inf[");
-    gst_segment_set_newsegment_full (&fpad->segment, FALSE, 1.0, 1.0,
-        GST_FORMAT_TIME, 0, -1, 0);
+    gst_segment_init (&fpad->segment, GST_FORMAT_TIME);
   }
 
   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
-    gst_segment_set_last_stop (&fpad->segment, fpad->segment.format,
-        GST_BUFFER_TIMESTAMP (buffer));
+    fpad->segment.position = GST_BUFFER_TIMESTAMP (buffer);
 
   newts = gst_segment_to_running_time (&fpad->segment,
       fpad->segment.format, GST_BUFFER_TIMESTAMP (buffer));
   if (newts != GST_BUFFER_TIMESTAMP (buffer)) {
-    buffer = gst_buffer_make_metadata_writable (buffer);
+    buffer = gst_buffer_make_writable (buffer);
     GST_BUFFER_TIMESTAMP (buffer) = newts;
   }
 
   if (!funnel->has_segment) {
-    event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
-        0, -1, 0);
+    GstSegment segment;
+
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    event = gst_event_new_segment (&segment);
     funnel->has_segment = TRUE;
   }
   GST_OBJECT_UNLOCK (funnel);
@@ -302,7 +259,7 @@ gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
     if (!gst_pad_push_event (funnel->srcpad, event))
       GST_WARNING_OBJECT (funnel, "Could not push out newsegment event");
   }
-
+#if 0
   GST_OBJECT_LOCK (pad);
   padcaps = GST_PAD_CAPS (funnel->srcpad);
   GST_OBJECT_UNLOCK (pad);
@@ -313,59 +270,45 @@ gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
       goto out;
     }
   }
+#endif
 
   res = gst_pad_push (funnel->srcpad, buffer);
 
   GST_LOG_OBJECT (funnel, "handled buffer %s", gst_flow_get_name (res));
 
+#if 0
 out:
-  gst_object_unref (funnel);
+#endif
 
   return res;
 }
 
 static gboolean
-gst_funnel_sink_event (GstPad * pad, GstEvent * event)
+gst_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
+  GstFunnel *funnel = GST_FUNNEL (parent);
   GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
   gboolean forward = TRUE;
   gboolean res = TRUE;
 
-  if (G_UNLIKELY (funnel == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
-
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gboolean update;
-      gdouble rate, arate;
-      GstFormat format;
-      gint64 start;
-      gint64 stop;
-      gint64 time;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate,
-          &format, &start, &stop, &time);
-
       GST_OBJECT_LOCK (funnel);
-      gst_segment_set_newsegment_full (&fpad->segment, update, rate, arate,
-          format, start, stop, time);
+      gst_event_copy_segment (event, &fpad->segment);
       GST_OBJECT_UNLOCK (funnel);
 
       forward = FALSE;
-    }
       break;
+    }
     case GST_EVENT_FLUSH_STOP:
     {
       GST_OBJECT_LOCK (funnel);
       gst_segment_init (&fpad->segment, GST_FORMAT_UNDEFINED);
       funnel->has_segment = FALSE;
       GST_OBJECT_UNLOCK (funnel);
-    }
       break;
+    }
     default:
       break;
   }
@@ -375,34 +318,43 @@ gst_funnel_sink_event (GstPad * pad, GstEvent * event)
   else
     gst_event_unref (event);
 
-  gst_object_unref (funnel);
+  return res;
+}
+
+static gboolean
+gst_funnel_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  GstFunnel *funnel = GST_FUNNEL (parent);
+  gboolean forward = TRUE;
+  gboolean res = TRUE;
+
+  if (forward)
+    res = gst_pad_peer_query (funnel->srcpad, query);
 
   return res;
 }
 
 static gboolean
-gst_funnel_src_event (GstPad * pad, GstEvent * event)
+gst_funnel_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstElement *funnel;
   GstIterator *iter;
   GstPad *sinkpad;
   gboolean result = FALSE;
   gboolean done = FALSE;
+  GValue value = { 0, };
 
-  funnel = gst_pad_get_parent_element (pad);
-  if (G_UNLIKELY (funnel == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  funnel = GST_ELEMENT_CAST (parent);
 
   iter = gst_element_iterate_sink_pads (funnel);
 
   while (!done) {
-    switch (gst_iterator_next (iter, (gpointer) & sinkpad)) {
+    switch (gst_iterator_next (iter, &value)) {
       case GST_ITERATOR_OK:
+        sinkpad = g_value_get_object (&value);
         gst_event_ref (event);
         result |= gst_pad_push_event (sinkpad, event);
-        gst_object_unref (sinkpad);
+        g_value_reset (&value);
         break;
       case GST_ITERATOR_RESYNC:
         gst_iterator_resync (iter);
@@ -415,23 +367,22 @@ gst_funnel_src_event (GstPad * pad, GstEvent * event)
         break;
     }
   }
+  g_value_unset (&value);
   gst_iterator_free (iter);
-  gst_object_unref (funnel);
   gst_event_unref (event);
 
   return result;
 }
 
 static void
-reset_pad (gpointer data, gpointer user_data)
+reset_pad (const GValue * data, gpointer user_data)
 {
-  GstPad *pad = data;
+  GstPad *pad = g_value_get_object (data);
   GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
 
   GST_OBJECT_LOCK (pad);
   gst_funnel_pad_reset (fpad);
   GST_OBJECT_UNLOCK (pad);
-  gst_object_unref (pad);
 }
 
 static GstStateChangeReturn
index 39c94dc..aa4873e 100644 (file)
@@ -92,11 +92,11 @@ enum
 };
 
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element");
-
-GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM, _do_init);
+#define gst_identity_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstIdentity, gst_identity, GST_TYPE_BASE_TRANSFORM,
+    _do_init);
 
 static void gst_identity_finalize (GObject * object);
 static void gst_identity_set_property (GObject * object, guint prop_id,
@@ -104,12 +104,12 @@ static void gst_identity_set_property (GObject * object, guint prop_id,
 static void gst_identity_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
+static gboolean gst_identity_sink_event (GstBaseTransform * trans,
+    GstEvent * event);
 static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans,
     GstBuffer * buf);
-static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform
-    * trans, GstBuffer * in_buf, gint out_size, GstCaps * out_caps,
-    GstBuffer ** out_buf);
+static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform *
+    trans, GstBuffer * in_buf, GstBuffer ** out_buf);
 static gboolean gst_identity_start (GstBaseTransform * trans);
 static gboolean gst_identity_stop (GstBaseTransform * trans);
 static GstStateChangeReturn gst_identity_change_state (GstElement * element,
@@ -120,21 +120,6 @@ static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *pspec_last_message = NULL;
 
 static void
-gst_identity_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Identity",
-      "Generic",
-      "Pass data without modification", "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
-
-static void
 gst_identity_finalize (GObject * object)
 {
   GstIdentity *identity;
@@ -143,10 +128,6 @@ gst_identity_finalize (GObject * object)
 
   g_free (identity->last_message);
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_static_rec_mutex_free (&identity->notify_lock);
-#endif
-
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -175,7 +156,7 @@ marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
       (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data :
       cc->callback);
 
-  callback (data1, gst_value_get_mini_object (param_values + 1), data2);
+  callback (data1, g_value_get_boxed (param_values + 1), data2);
 }
 
 static void
@@ -215,7 +196,7 @@ gst_identity_class_init (GstIdentityClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SINGLE_SEGMENT,
       g_param_spec_boolean ("single-segment", "Single Segment",
-          "Timestamp buffers and eat newsegments so as to appear as one segment",
+          "Timestamp buffers and eat segments so as to appear as one segment",
           DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   pspec_last_message = g_param_spec_string ("last-message", "last-message",
       "last-message", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
@@ -276,10 +257,18 @@ gst_identity_class_init (GstIdentityClass * klass)
 
   gobject_class->finalize = gst_identity_finalize;
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Identity",
+      "Generic",
+      "Pass data without modification", "Erik Walthinsen <omega@cse.ogi.edu>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_identity_change_state);
-
-  gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event);
+  gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_identity_sink_event);
   gstbasetrans_class->transform_ip =
       GST_DEBUG_FUNCPTR (gst_identity_transform_ip);
   gstbasetrans_class->prepare_output_buffer =
@@ -289,7 +278,7 @@ gst_identity_class_init (GstIdentityClass * klass)
 }
 
 static void
-gst_identity_init (GstIdentity * identity, GstIdentityClass * g_class)
+gst_identity_init (GstIdentity * identity)
 {
   identity->sleep_time = DEFAULT_SLEEP_TIME;
   identity->error_after = DEFAULT_ERROR_AFTER;
@@ -305,33 +294,17 @@ gst_identity_init (GstIdentity * identity, GstIdentityClass * g_class)
   identity->last_message = NULL;
   identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_static_rec_mutex_init (&identity->notify_lock);
-#endif
-
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE);
 }
 
 static void
 gst_identity_notify_last_message (GstIdentity * identity)
 {
-  /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent
-   * g_object_notify() on the same object might lead to crashes, see
-   * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups.
-   * So we really don't want to do a g_object_notify() here for out-of-band
-   * events with the streaming thread possibly also doing a g_object_notify()
-   * for an in-band buffer or event. This is fixed in GLib >= 2.26 */
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_static_rec_mutex_lock (&identity->notify_lock);
-  g_object_notify ((GObject *) identity, "last-message");
-  g_static_rec_mutex_unlock (&identity->notify_lock);
-#else
   g_object_notify_by_pspec ((GObject *) identity, pspec_last_message);
-#endif
 }
 
 static gboolean
-gst_identity_event (GstBaseTransform * trans, GstEvent * event)
+gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event)
 {
   GstIdentity *identity;
   gboolean ret = TRUE;
@@ -360,46 +333,47 @@ gst_identity_event (GstBaseTransform * trans, GstEvent * event)
     gst_identity_notify_last_message (identity);
   }
 
-  if (identity->single_segment
-      && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
-    if (trans->have_newsegment == FALSE) {
+  if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) {
+    if (trans->have_segment == FALSE) {
       GstEvent *news;
-      GstFormat format;
+      GstSegment segment;
 
-      gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
-          NULL);
+      gst_event_copy_segment (event, &segment);
+      gst_event_copy_segment (event, &trans->segment);
+      trans->have_segment = TRUE;
 
-      /* This is the first newsegment, send out a (0, -1) newsegment */
-      news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);
+      /* This is the first segment, send out a (0, -1) segment */
+      gst_segment_init (&segment, segment.format);
+      news = gst_event_new_segment (&segment);
 
-      gst_pad_event_default (trans->sinkpad, news);
+      gst_pad_event_default (trans->sinkpad, GST_OBJECT_CAST (trans), news);
     }
   }
 
   /* Reset previous timestamp, duration and offsets on NEWSEGMENT
    * to prevent false warnings when checking for perfect streams */
-  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
     identity->prev_timestamp = identity->prev_duration = GST_CLOCK_TIME_NONE;
     identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE;
   }
 
-  ret = parent_class->event (trans, event);
-
-  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) {
-    GST_OBJECT_LOCK (identity);
-    if (identity->clock_id) {
-      GST_DEBUG_OBJECT (identity, "unlock clock wait");
-      gst_clock_id_unschedule (identity->clock_id);
-      gst_clock_id_unref (identity->clock_id);
-      identity->clock_id = NULL;
+  if (identity->single_segment && GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+    /* eat up segments */
+    gst_event_unref (event);
+    ret = TRUE;
+  } else {
+    if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) {
+      GST_OBJECT_LOCK (identity);
+      if (identity->clock_id) {
+        GST_DEBUG_OBJECT (identity, "unlock clock wait");
+        gst_clock_id_unschedule (identity->clock_id);
+        gst_clock_id_unref (identity->clock_id);
+        identity->clock_id = NULL;
+      }
+      GST_OBJECT_UNLOCK (identity);
     }
-    GST_OBJECT_UNLOCK (identity);
-  }
 
-  if (identity->single_segment
-      && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
-    /* eat up segments */
-    ret = FALSE;
+    ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
   }
 
   return ret;
@@ -407,22 +381,21 @@ gst_identity_event (GstBaseTransform * trans, GstEvent * event)
 
 static GstFlowReturn
 gst_identity_prepare_output_buffer (GstBaseTransform * trans,
-    GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf)
+    GstBuffer * in_buf, GstBuffer ** out_buf)
 {
   GstIdentity *identity = GST_IDENTITY (trans);
 
   /* only bother if we may have to alter metadata */
   if (identity->datarate > 0 || identity->single_segment) {
-    if (gst_buffer_is_metadata_writable (in_buf))
-      *out_buf = gst_buffer_ref (in_buf);
+    if (gst_buffer_is_writable (in_buf))
+      /* reuse */
+      *out_buf = in_buf;
     else {
-      /* make even less writable */
-      gst_buffer_ref (in_buf);
-      /* extra ref is dropped going through the official process */
-      *out_buf = gst_buffer_make_metadata_writable (in_buf);
+      /* copy */
+      *out_buf = gst_buffer_copy (in_buf);
     }
   } else
-    *out_buf = gst_buffer_ref (in_buf);
+    *out_buf = in_buf;
 
   return GST_FLOW_OK;
 }
@@ -579,7 +552,7 @@ print_pretty_time (gchar * ts_str, gsize ts_str_len, GstClockTime ts)
 
 static void
 gst_identity_update_last_message_for_buffer (GstIdentity * identity,
-    const gchar * action, GstBuffer * buf)
+    const gchar * action, GstBuffer * buf, gsize size)
 {
   gchar ts_str[64], dur_str[64];
   gchar flag_str[100];
@@ -587,15 +560,14 @@ gst_identity_update_last_message_for_buffer (GstIdentity * identity,
   GST_OBJECT_LOCK (identity);
 
   {
-    const char *flag_list[12] = {
-      "ro", "media4", "", "",
-      "preroll", "discont", "incaps", "gap",
-      "delta_unit", "media1", "media2", "media3"
+    const char *flag_list[15] = {
+      "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted",
+      "marker", "header", "gap", "droppable", "delta-unit", "in-caps"
     };
     int i;
     char *end = flag_str;
     end[0] = '\0';
-    for (i = 0; i < 12; i++) {
+    for (i = 0; i < G_N_ELEMENTS (flag_list); i++) {
       if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
         strcpy (end, flag_list[i]);
         end += strlen (end);
@@ -608,10 +580,10 @@ gst_identity_update_last_message_for_buffer (GstIdentity * identity,
 
   g_free (identity->last_message);
   identity->last_message = g_strdup_printf ("%s   ******* (%s:%s) "
-      "(%u bytes, timestamp: %s, duration: %s, offset: %" G_GINT64_FORMAT ", "
-      "offset_end: % " G_GINT64_FORMAT ", flags: %d %s) %p", action,
-      GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad),
-      GST_BUFFER_SIZE (buf),
+      "(%" G_GSIZE_FORMAT " bytes, timestamp: %s, duration: %s, offset: %"
+      G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT
+      ", flags: %d %s) %p", action,
+      GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size,
       print_pretty_time (ts_str, sizeof (ts_str), GST_BUFFER_TIMESTAMP (buf)),
       print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)),
       GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
@@ -628,6 +600,10 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
   GstFlowReturn ret = GST_FLOW_OK;
   GstIdentity *identity = GST_IDENTITY (trans);
   GstClockTime runtimestamp = G_GINT64_CONSTANT (0);
+  guint8 *data;
+  gsize size;
+
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 
   if (identity->check_perfect)
     gst_identity_check_perfect (identity, buf);
@@ -644,29 +620,21 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
 
   if (identity->error_after >= 0) {
     identity->error_after--;
-    if (identity->error_after == 0) {
-      GST_ELEMENT_ERROR (identity, CORE, FAILED,
-          (_("Failed after iterations as requested.")), (NULL));
-      return GST_FLOW_ERROR;
-    }
+    if (identity->error_after == 0)
+      goto error_after;
   }
 
   if (identity->drop_probability > 0.0) {
-    if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
-      if (!identity->silent) {
-        gst_identity_update_last_message_for_buffer (identity, "dropping", buf);
-      }
-      /* return DROPPED to basetransform. */
-      return GST_BASE_TRANSFORM_FLOW_DROPPED;
-    }
+    if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability)
+      goto dropped;
   }
 
   if (identity->dump) {
-    gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+    gst_util_dump_mem (data, size);
   }
 
   if (!identity->silent) {
-    gst_identity_update_last_message_for_buffer (identity, "chain", buf);
+    gst_identity_update_last_message_for_buffer (identity, "chain", buf, size);
   }
 
   if (identity->datarate > 0) {
@@ -674,8 +642,7 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
         GST_SECOND, identity->datarate);
 
     GST_BUFFER_TIMESTAMP (buf) = time;
-    GST_BUFFER_DURATION (buf) =
-        GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
+    GST_BUFFER_DURATION (buf) = size * GST_SECOND / identity->datarate;
   }
 
   if (identity->signal_handoffs)
@@ -707,12 +674,12 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
         identity->clock_id = NULL;
       }
       if (cret == GST_CLOCK_UNSCHEDULED)
-        ret = GST_FLOW_UNEXPECTED;
+        ret = GST_FLOW_EOS;
     }
     GST_OBJECT_UNLOCK (identity);
   }
 
-  identity->offset += GST_BUFFER_SIZE (buf);
+  identity->offset += size;
 
   if (identity->sleep_time && ret == GST_FLOW_OK)
     g_usleep (identity->sleep_time);
@@ -724,7 +691,28 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
     GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE;
   }
 
+  gst_buffer_unmap (buf, data, size);
+
   return ret;
+
+  /* ERRORS */
+error_after:
+  {
+    GST_ELEMENT_ERROR (identity, CORE, FAILED,
+        (_("Failed after iterations as requested.")), (NULL));
+    gst_buffer_unmap (buf, data, size);
+    return GST_FLOW_ERROR;
+  }
+dropped:
+  {
+    if (!identity->silent) {
+      gst_identity_update_last_message_for_buffer (identity, "dropping", buf,
+          size);
+    }
+    gst_buffer_unmap (buf, data, size);
+    /* return DROPPED to basetransform. */
+    return GST_BASE_TRANSFORM_FLOW_DROPPED;
+  }
 }
 
 static void
index a608d2b..fabc667 100644 (file)
@@ -73,10 +73,6 @@ struct _GstIdentity {
   gchar        *last_message;
   guint64        offset;
   gboolean       signal_handoffs;
-
-#if !GLIB_CHECK_VERSION(2,26,0)
-  GStaticRecMutex  notify_lock;
-#endif
 };
 
 struct _GstIdentityClass {
index 4da4735..3bd4f22 100644 (file)
 GST_DEBUG_CATEGORY_STATIC (input_selector_debug);
 #define GST_CAT_DEFAULT input_selector_debug
 
-#if GLIB_CHECK_VERSION(2, 26, 0)
-#define NOTIFY_MUTEX_LOCK()
-#define NOTIFY_MUTEX_UNLOCK()
-#else
-static GStaticRecMutex notify_mutex = G_STATIC_REC_MUTEX_INIT;
-#define NOTIFY_MUTEX_LOCK() g_static_rec_mutex_lock (&notify_mutex)
-#define NOTIFY_MUTEX_UNLOCK() g_static_rec_mutex_unlock (&notify_mutex)
-#endif
-
-#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock)
-#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond)
-#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
-#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
-#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \
-                       GST_INPUT_SELECTOR_GET_LOCK(sel)))
-#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel)))
-
 static GstStaticPadTemplate gst_input_selector_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink%d",
+GST_STATIC_PAD_TEMPLATE ("sink_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS_ANY);
@@ -157,9 +140,12 @@ struct _GstSelectorPad
   gboolean discont;             /* after switching we create a discont */
   gboolean flushing;            /* set after flush-start and before flush-stop */
   gboolean always_ok;
-  GstSegment segment;           /* the current segment on the pad */
   GstTagList *tags;             /* last tags received on the pad */
 
+  GstClockTime position;        /* the current position in the segment */
+  GstSegment segment;           /* the current segment on the pad */
+  guint32 segment_seqnum;       /* sequence number of the current segment */
+
   gboolean segment_pending;
 };
 
@@ -168,50 +154,25 @@ struct _GstSelectorPadClass
   GstPadClass parent;
 };
 
-static void gst_selector_pad_class_init (GstSelectorPadClass * klass);
-static void gst_selector_pad_init (GstSelectorPad * pad);
+GType gst_selector_pad_get_type (void);
 static void gst_selector_pad_finalize (GObject * object);
 static void gst_selector_pad_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 static void gst_selector_pad_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
 
-static GstPadClass *selector_pad_parent_class = NULL;
-
 static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad);
 static void gst_selector_pad_reset (GstSelectorPad * pad);
-static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_selector_pad_getcaps (GstPad * pad);
-static gboolean gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps);
-static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad);
-static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf);
-static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
-
-static GType
-gst_selector_pad_get_type (void)
-{
-  static volatile gsize selector_pad_type = 0;
-  static const GTypeInfo selector_pad_info = {
-    sizeof (GstSelectorPadClass),
-    NULL,
-    NULL,
-    (GClassInitFunc) gst_selector_pad_class_init,
-    NULL,
-    NULL,
-    sizeof (GstSelectorPad),
-    0,
-    (GInstanceInitFunc) gst_selector_pad_init,
-  };
-
-  if (g_once_init_enter (&selector_pad_type)) {
-    GType tmp = g_type_register_static (GST_TYPE_PAD, "GstSelectorPad",
-        &selector_pad_info, 0);
-    g_once_init_leave (&selector_pad_type, tmp);
-  }
+static gboolean gst_selector_pad_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_selector_pad_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad,
+    GstObject * parent);
+static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buf);
 
-  return (GType) selector_pad_type;
-}
+G_DEFINE_TYPE (GstSelectorPad, gst_selector_pad, GST_TYPE_PAD);
 
 static void
 gst_selector_pad_class_init (GstSelectorPadClass * klass)
@@ -220,8 +181,6 @@ gst_selector_pad_class_init (GstSelectorPadClass * klass)
 
   gobject_class = (GObjectClass *) klass;
 
-  selector_pad_parent_class = g_type_class_peek_parent (klass);
-
   gobject_class->finalize = gst_selector_pad_finalize;
 
   gobject_class->get_property = gst_selector_pad_get_property;
@@ -263,7 +222,7 @@ gst_selector_pad_finalize (GObject * object)
   if (pad->tags)
     gst_tag_list_free (pad->tags);
 
-  G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object);
+  G_OBJECT_CLASS (gst_selector_pad_parent_class)->finalize (object);
 }
 
 static void
@@ -327,11 +286,10 @@ gst_selector_pad_get_running_time (GstSelectorPad * pad)
 
   GST_OBJECT_LOCK (pad);
   if (pad->active) {
-    gint64 last_stop = pad->segment.last_stop;
+    guint64 position = pad->position;
+    GstFormat format = pad->segment.format;
 
-    if (last_stop >= 0)
-      ret = gst_segment_to_running_time (&pad->segment, GST_FORMAT_TIME,
-          last_stop);
+    ret = gst_segment_to_running_time (&pad->segment, format, position);
   }
   GST_OBJECT_UNLOCK (pad);
 
@@ -352,6 +310,7 @@ gst_selector_pad_reset (GstSelectorPad * pad)
   pad->segment_pending = FALSE;
   pad->discont = FALSE;
   pad->flushing = FALSE;
+  pad->position = GST_CLOCK_TIME_NONE;
   gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED);
   GST_OBJECT_UNLOCK (pad);
 }
@@ -359,29 +318,29 @@ gst_selector_pad_reset (GstSelectorPad * pad)
 /* strictly get the linked pad from the sinkpad. If the pad is active we return
  * the srcpad else we return NULL */
 static GstIterator *
-gst_selector_pad_iterate_linked_pads (GstPad * pad)
+gst_selector_pad_iterate_linked_pads (GstPad * pad, GstObject * parent)
 {
   GstInputSelector *sel;
   GstPad *otherpad;
-  GstIterator *it;
+  GstIterator *it = NULL;
+  GValue val = { 0, };
 
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return NULL;
+  sel = GST_INPUT_SELECTOR (parent);
 
   otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE);
-  it = gst_iterator_new_single (GST_TYPE_PAD, otherpad,
-      (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
-
-  if (otherpad)
+  if (otherpad) {
+    g_value_init (&val, GST_TYPE_PAD);
+    g_value_set_object (&val, otherpad);
+    it = gst_iterator_new_single (GST_TYPE_PAD, &val);
+    g_value_unset (&val);
     gst_object_unref (otherpad);
-  gst_object_unref (sel);
+  }
 
   return it;
 }
 
 static gboolean
-gst_selector_pad_event (GstPad * pad, GstEvent * event)
+gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
   gboolean forward;
@@ -390,11 +349,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
   GstPad *prev_active_sinkpad;
   GstPad *active_sinkpad;
 
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  sel = GST_INPUT_SELECTOR (parent);
   selpad = GST_SELECTOR_PAD_CAST (pad);
 
   GST_INPUT_SELECTOR_LOCK (sel);
@@ -406,9 +361,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
   GST_INPUT_SELECTOR_UNLOCK (sel);
 
   if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) {
-    NOTIFY_MUTEX_LOCK ();
     g_object_notify (G_OBJECT (sel), "active-pad");
-    NOTIFY_MUTEX_UNLOCK ();
   }
 
   switch (GST_EVENT_TYPE (event)) {
@@ -422,30 +375,31 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
       GST_INPUT_SELECTOR_LOCK (sel);
       gst_selector_pad_reset (selpad);
-      sel->pending_close = FALSE;
       GST_INPUT_SELECTOR_UNLOCK (sel);
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gboolean update;
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      GST_DEBUG_OBJECT (pad,
-          "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-          "format %d, "
-          "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-          G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
-
       GST_INPUT_SELECTOR_LOCK (sel);
       GST_OBJECT_LOCK (selpad);
-      gst_segment_set_newsegment_full (&selpad->segment, update,
-          rate, arate, format, start, stop, time);
-      GST_OBJECT_UNLOCK (selpad);
+      gst_event_copy_segment (event, &selpad->segment);
+      selpad->segment_seqnum = gst_event_get_seqnum (event);
+
+      /* Update the position */
+      if (selpad->position == GST_CLOCK_TIME_NONE
+          || selpad->segment.position > selpad->position) {
+        selpad->position = selpad->segment.position;
+      } else if (selpad->position != GST_CLOCK_TIME_NONE
+          && selpad->position > selpad->segment.position) {
+        selpad->segment.position = selpad->position;
+
+        if (forward) {
+          gst_event_unref (event);
+          event = gst_event_new_segment (&selpad->segment);
+          gst_event_set_seqnum (event, selpad->segment_seqnum);
+        }
+      }
+      GST_DEBUG_OBJECT (pad, "configured SEGMENT %" GST_SEGMENT_FORMAT,
+          &selpad->segment);
 
       /* If we aren't forwarding the event because the pad is not the
        * active_sinkpad, then set the flag on the pad
@@ -456,6 +410,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
       if (!forward)
         selpad->segment_pending = TRUE;
 
+      GST_OBJECT_UNLOCK (selpad);
       GST_INPUT_SELECTOR_UNLOCK (sel);
       break;
     }
@@ -510,110 +465,21 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
   } else
     gst_event_unref (event);
 
-  gst_object_unref (sel);
-
   return res;
 }
 
-static GstCaps *
-gst_selector_pad_getcaps (GstPad * pad)
-{
-  GstInputSelector *sel;
-  GstCaps *caps;
-
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return gst_caps_new_any ();
-
-  GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer");
-  caps = gst_pad_peer_get_caps_reffed (sel->srcpad);
-  if (caps == NULL)
-    caps = gst_caps_new_any ();
-
-  gst_object_unref (sel);
-
-  return caps;
-}
-
 static gboolean
-gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps)
+gst_selector_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstInputSelector *sel;
-  gboolean res;
-
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return FALSE;
-
-  GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer");
-  res = gst_pad_peer_accept_caps (sel->srcpad, caps);
-  gst_object_unref (sel);
-
-  return res;
-}
-
-static GstFlowReturn
-gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf)
-{
-  GstInputSelector *sel;
-  GstFlowReturn result;
-  GstPad *active_sinkpad;
-  GstPad *prev_active_sinkpad;
-  GstSelectorPad *selpad;
-
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return GST_FLOW_WRONG_STATE;
-
-  selpad = GST_SELECTOR_PAD_CAST (pad);
-
-  GST_LOG_OBJECT (pad, "received alloc");
-
-  GST_INPUT_SELECTOR_LOCK (sel);
-  prev_active_sinkpad = sel->active_sinkpad;
-  active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
-
-  if (pad != active_sinkpad)
-    goto not_active;
-
-  GST_INPUT_SELECTOR_UNLOCK (sel);
+  gboolean res = FALSE;
 
-  if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) {
-    NOTIFY_MUTEX_LOCK ();
-    g_object_notify (G_OBJECT (sel), "active-pad");
-    NOTIFY_MUTEX_UNLOCK ();
+  switch (GST_QUERY_TYPE (query)) {
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
   }
 
-  result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf);
-
-done:
-  gst_object_unref (sel);
-
-  return result;
-
-  /* ERRORS */
-not_active:
-  {
-    gboolean active_pad_pushed = GST_SELECTOR_PAD_CAST (active_sinkpad)->pushed;
-
-    GST_INPUT_SELECTOR_UNLOCK (sel);
-
-    /* unselected pad, perform fallback alloc or return unlinked when
-     * asked */
-    GST_OBJECT_LOCK (selpad);
-    if (selpad->always_ok || !active_pad_pushed) {
-      GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation");
-      *buf = NULL;
-      result = GST_FLOW_OK;
-    } else {
-      GST_DEBUG_OBJECT (pad, "Not selected, return NOT_LINKED");
-      result = GST_FLOW_NOT_LINKED;
-    }
-    GST_OBJECT_UNLOCK (selpad);
-
-    goto done;
-  }
+  return res;
 }
 
 /* must be called with the SELECTOR_LOCK, will block while the pad is blocked 
@@ -674,7 +540,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel,
   if (active_seg->format == GST_FORMAT_TIME)
     active_running_time =
         gst_segment_to_running_time (active_seg, GST_FORMAT_TIME,
-        active_seg->last_stop);
+        active_selpad->position);
 
   /* Wait until
    *   a) this is the active pad
@@ -711,7 +577,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel,
     if (active_seg->format == GST_FORMAT_TIME)
       active_running_time =
           gst_segment_to_running_time (active_seg, GST_FORMAT_TIME,
-          active_seg->last_stop);
+          active_selpad->position);
     else
       active_running_time = -1;
 
@@ -729,7 +595,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel,
 
 
 static GstFlowReturn
-gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
+gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
   GstInputSelector *sel;
   GstFlowReturn res;
@@ -738,10 +604,9 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
   GstSelectorPad *selpad;
   GstClockTime start_time;
   GstSegment *seg;
-  GstEvent *close_event = NULL, *start_event = NULL;
-  GstCaps *caps;
+  GstEvent *start_event = NULL;
 
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+  sel = GST_INPUT_SELECTOR (parent);
   selpad = GST_SELECTOR_PAD_CAST (pad);
   seg = &selpad->segment;
 
@@ -775,7 +640,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
           GST_TIME_ARGS (start_time + GST_BUFFER_DURATION (buf)));
 
     GST_OBJECT_LOCK (pad);
-    gst_segment_set_last_stop (seg, seg->format, start_time);
+    selpad->position = start_time;
     GST_OBJECT_UNLOCK (pad);
   }
 
@@ -787,56 +652,34 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
   if (sel->sync_streams)
     GST_INPUT_SELECTOR_BROADCAST (sel);
 
-  if (G_UNLIKELY (sel->pending_close)) {
-    GstSegment *cseg = &sel->segment;
-
-    GST_DEBUG_OBJECT (sel,
-        "pushing close NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-        "format %d, "
-        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-        G_GINT64_FORMAT, TRUE, cseg->rate, cseg->applied_rate, cseg->format,
-        cseg->start, cseg->stop, cseg->time);
-
-    /* create update segment */
-    close_event = gst_event_new_new_segment_full (TRUE, cseg->rate,
-        cseg->applied_rate, cseg->format, cseg->start, cseg->stop, cseg->time);
-
-    sel->pending_close = FALSE;
-  }
   /* if we have a pending segment, push it out now */
-  if (G_UNLIKELY (selpad->segment_pending)) {
+  if (G_UNLIKELY (prev_active_sinkpad != active_sinkpad
+          || selpad->segment_pending)) {
     if (G_UNLIKELY (seg->format == GST_FORMAT_UNDEFINED)) {
       GST_ERROR_OBJECT (pad, "Buffers arrived before NEWSEGMENT event");
-
     } else {
       GST_DEBUG_OBJECT (pad,
           "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-          "format %d, "
-          "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+          "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
           G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format,
           seg->start, seg->stop, seg->time);
 
-      start_event = gst_event_new_new_segment_full (FALSE, seg->rate,
-          seg->applied_rate, seg->format, seg->start, seg->stop, seg->time);
+      start_event = gst_event_new_segment (seg);
+      gst_event_set_seqnum (start_event, selpad->segment_seqnum);
       selpad->segment_pending = FALSE;
     }
   }
   GST_INPUT_SELECTOR_UNLOCK (sel);
 
   if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) {
-    NOTIFY_MUTEX_LOCK ();
     g_object_notify (G_OBJECT (sel), "active-pad");
-    NOTIFY_MUTEX_UNLOCK ();
   }
 
-  if (close_event)
-    gst_pad_push_event (sel->srcpad, close_event);
-
   if (start_event)
     gst_pad_push_event (sel->srcpad, start_event);
 
   if (selpad->discont) {
-    buf = gst_buffer_make_metadata_writable (buf);
+    buf = gst_buffer_make_writable (buf);
 
     GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf);
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
@@ -846,16 +689,10 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
   /* forward */
   GST_LOG_OBJECT (pad, "Forwarding buffer %p", buf);
 
-  if ((caps = GST_BUFFER_CAPS (buf))) {
-    if (GST_PAD_CAPS (sel->srcpad) != caps)
-      gst_pad_set_caps (sel->srcpad, caps);
-  }
-
   res = gst_pad_push (sel->srcpad, buf);
   selpad->pushed = TRUE;
 
 done:
-  gst_object_unref (sel);
   return res;
 
   /* dropped buffers */
@@ -890,6 +727,7 @@ flushing:
 }
 
 static void gst_input_selector_dispose (GObject * object);
+static void gst_input_selector_finalize (GObject * object);
 
 static void gst_input_selector_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -897,23 +735,19 @@ static void gst_input_selector_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
 static GstPad *gst_input_selector_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * unused);
+    GstPadTemplate * templ, const gchar * unused, const GstCaps * caps);
 static void gst_input_selector_release_pad (GstElement * element, GstPad * pad);
 
 static GstStateChangeReturn gst_input_selector_change_state (GstElement *
     element, GstStateChange transition);
 
-static GstCaps *gst_input_selector_getcaps (GstPad * pad);
-static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event);
-static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query);
+static gboolean gst_input_selector_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_input_selector_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static gint64 gst_input_selector_block (GstInputSelector * self);
-static void gst_input_selector_switch (GstInputSelector * self,
-    GstPad * pad, gint64 stop_time, gint64 start_time);
 
 /* FIXME: create these marshallers using glib-genmarshal */
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-
 static void
 gst_input_selector_marshal_INT64__VOID (GClosure * closure,
     GValue * return_value G_GNUC_UNUSED,
@@ -945,60 +779,12 @@ gst_input_selector_marshal_INT64__VOID (GClosure * closure,
   g_value_set_int64 (return_value, v_return);
 }
 
-static void
-gst_input_selector_marshal_VOID__OBJECT_INT64_INT64 (GClosure * closure,
-    GValue * return_value G_GNUC_UNUSED,
-    guint n_param_values,
-    const GValue * param_values,
-    gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__OBJECT_INT64_INT64) (gpointer data1,
-      gpointer arg_1, gint64 arg_2, gint64 arg_3, gpointer data2);
-  register GMarshalFunc_VOID__OBJECT_INT64_INT64 callback;
-  register GCClosure *cc = (GCClosure *) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure)) {
-    data1 = closure->data;
-    data2 = g_value_peek_pointer (param_values + 0);
-  } else {
-    data1 = g_value_peek_pointer (param_values + 0);
-    data2 = closure->data;
-  }
-  callback =
-      (GMarshalFunc_VOID__OBJECT_INT64_INT64) (marshal_data ? marshal_data :
-      cc->callback);
-
-  callback (data1,
-      g_marshal_value_peek_object (param_values + 1),
-      g_marshal_value_peek_int64 (param_values + 2),
-      g_marshal_value_peek_int64 (param_values + 3), data2);
-}
-
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (input_selector_debug, \
         "input-selector", 0, "An input stream selector element");
-
-GST_BOILERPLATE_FULL (GstInputSelector, gst_input_selector, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
-
-static void
-gst_input_selector_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (element_class, "Input selector",
-      "Generic", "N-to-1 input stream selector",
-      "Julien Moutte <julien@moutte.net>, "
-      "Jan Schmidt <thaytan@mad.scientist.com>, "
-      "Wim Taymans <wim.taymans@gmail.com>");
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_input_selector_sink_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_input_selector_src_factory));
-}
+#define gst_input_selector_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstInputSelector, gst_input_selector, GST_TYPE_ELEMENT,
+    _do_init);
 
 static void
 gst_input_selector_class_init (GstInputSelectorClass * klass)
@@ -1007,6 +793,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
   gobject_class->dispose = gst_input_selector_dispose;
+  gobject_class->finalize = gst_input_selector_finalize;
 
   gobject_class->set_property = gst_input_selector_set_property;
   gobject_class->get_property = gst_input_selector_get_property;
@@ -1049,89 +836,43 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
       G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL,
       gst_input_selector_marshal_INT64__VOID, G_TYPE_INT64, 0);
-  /**
-   * GstInputSelector::switch:
-   * @inputselector: the #GstInputSelector
-   * @pad:            the pad to switch to
-   * @stop_time:      running time at which to close the previous segment, or -1
-   *                  to use the running time of the previously active sink pad
-   * @start_time:     running time at which to start the new segment, or -1 to
-   *                  use the running time of the newly active sink pad
-   *
-   * Switch to a new feed. The segment opened by the previously active pad, if
-   * any, will be closed, and a new segment opened before data flows again.
-   *
-   * This signal must be emitted when the element has been blocked via the <link
-   * linkend="GstInputSelector-block">block</link> signal.
-   *
-   * If you have a stream with only one switch element, such as an audio-only
-   * stream, a stream switch should be performed by first emitting the block
-   * signal, and then emitting the switch signal with -1 for the stop and start
-   * time values.
-   *
-   * The intention of the @stop_time and @start_time arguments is to allow
-   * multiple switch elements to switch and maintain stream synchronization.
-   * When switching a stream with multiple feeds, you will need as many switch
-   * elements as you have feeds. For example, a feed with audio and video will
-   * have one switch element between the audio feeds and one for video.
-   *
-   * A switch over multiple switch elements should be performed as follows:
-   * First, emit the <link linkend="GstInputSelector-block">block</link>
-   * signal, collecting the returned values. The maximum running time returned
-   * by block should then be used as the time at which to close the previous
-   * segment.
-   *
-   * Then, query the running times of the new audio and video pads that you will
-   * switch to. Naturally, these pads are on separate switch elements. Take the
-   * minimum running time for those streams and use it for the time at which to
-   * open the new segment.
-   *
-   * If @pad is the same as the current active pad, the element will cancel any
-   * previous block without adjusting segments.
-   *
-   * <note><simpara>
-   * the signal changed from accepting the pad name to the pad object.
-   * </simpara></note>
-   *
-   * Since: 0.10.7
-   */
-  gst_input_selector_signals[SIGNAL_SWITCH] =
-      g_signal_new ("switch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstInputSelectorClass, switch_),
-      NULL, NULL, gst_input_selector_marshal_VOID__OBJECT_INT64_INT64,
-      G_TYPE_NONE, 3, GST_TYPE_PAD, G_TYPE_INT64, G_TYPE_INT64);
+
+  gst_element_class_set_details_simple (gstelement_class, "Input selector",
+      "Generic", "N-to-1 input stream selector",
+      "Julien Moutte <julien@moutte.net>, "
+      "Jan Schmidt <thaytan@mad.scientist.com>, "
+      "Wim Taymans <wim.taymans@gmail.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_input_selector_sink_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_input_selector_src_factory));
 
   gstelement_class->request_new_pad = gst_input_selector_request_new_pad;
   gstelement_class->release_pad = gst_input_selector_release_pad;
   gstelement_class->change_state = gst_input_selector_change_state;
 
   klass->block = GST_DEBUG_FUNCPTR (gst_input_selector_block);
-  /* note the underscore because switch is a keyword otherwise */
-  klass->switch_ = GST_DEBUG_FUNCPTR (gst_input_selector_switch);
 }
 
 static void
-gst_input_selector_init (GstInputSelector * sel,
-    GstInputSelectorClass * g_class)
+gst_input_selector_init (GstInputSelector * sel)
 {
   sel->srcpad = gst_pad_new ("src", GST_PAD_SRC);
   gst_pad_set_iterate_internal_links_function (sel->srcpad,
       GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads));
-  gst_pad_set_getcaps_function (sel->srcpad,
-      GST_DEBUG_FUNCPTR (gst_input_selector_getcaps));
   gst_pad_set_query_function (sel->srcpad,
       GST_DEBUG_FUNCPTR (gst_input_selector_query));
   gst_pad_set_event_function (sel->srcpad,
       GST_DEBUG_FUNCPTR (gst_input_selector_event));
+  GST_OBJECT_FLAG_SET (sel->srcpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
   /* sinkpad management */
   sel->active_sinkpad = NULL;
   sel->padcount = 0;
-  gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
   sel->sync_streams = DEFAULT_SYNC_STREAMS;
 
-  sel->lock = g_mutex_new ();
-  sel->cond = g_cond_new ();
+  g_mutex_init (&sel->lock);
+  g_cond_init (&sel->cond);
   sel->blocked = FALSE;
 }
 
@@ -1144,59 +885,24 @@ gst_input_selector_dispose (GObject * object)
     gst_object_unref (sel->active_sinkpad);
     sel->active_sinkpad = NULL;
   }
-  if (sel->lock) {
-    g_mutex_free (sel->lock);
-    sel->lock = NULL;
-  }
-  if (sel->cond) {
-    g_cond_free (sel->cond);
-    sel->cond = NULL;
-  }
-
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
-/* Solve the following equation for B.timestamp, and set that as the segment
- * stop:
- * B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
- */
-static gint64
-gst_segment_get_timestamp (GstSegment * segment, gint64 running_time)
-{
-  if (running_time <= segment->accum)
-    return segment->start;
-  else
-    return (running_time - segment->accum) * segment->abs_rate + segment->start;
-}
-
 static void
-gst_segment_set_stop (GstSegment * segment, gint64 running_time)
+gst_input_selector_finalize (GObject * object)
 {
-  segment->stop = gst_segment_get_timestamp (segment, running_time);
-  segment->last_stop = -1;
-}
-
-static void
-gst_segment_set_start (GstSegment * segment, gint64 running_time)
-{
-  gint64 new_start, duration;
+  GstInputSelector *sel = GST_INPUT_SELECTOR (object);
 
-  new_start = gst_segment_get_timestamp (segment, running_time);
+  g_mutex_clear (&sel->lock);
+  g_cond_clear (&sel->cond);
 
-  /* this is the duration we skipped */
-  duration = new_start - segment->start;
-  /* add the duration to the accumulated segment time */
-  segment->accum += duration;
-  /* move position in the segment */
-  segment->time += duration;
-  segment->start += duration;
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /* this function must be called with the SELECTOR_LOCK. It returns TRUE when the
  * active pad changed. */
 static gboolean
-gst_input_selector_set_active_pad (GstInputSelector * self,
-    GstPad * pad, gint64 stop_time, gint64 start_time)
+gst_input_selector_set_active_pad (GstInputSelector * self, GstPad * pad)
 {
   GstSelectorPad *old, *new;
   GstPad **active_pad_p;
@@ -1210,37 +916,15 @@ gst_input_selector_set_active_pad (GstInputSelector * self,
   GST_DEBUG_OBJECT (self, "setting active pad to %s:%s",
       GST_DEBUG_PAD_NAME (new));
 
-  if (!GST_CLOCK_TIME_IS_VALID (stop_time) && old) {
-    /* no stop time given, get the latest running_time on the active pad to 
-     * close and open the new segment */
-    stop_time = start_time = gst_selector_pad_get_running_time (old);
-    GST_DEBUG_OBJECT (self, "using start/stop of %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (start_time));
-  }
-
-  if (old && old->active && !self->pending_close && stop_time >= 0) {
-    /* schedule a last_stop update if one isn't already scheduled, and a
-       segment has been pushed before. */
-    memcpy (&self->segment, &old->segment, sizeof (self->segment));
-
-    GST_DEBUG_OBJECT (self, "setting stop_time to %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (stop_time));
-    gst_segment_set_stop (&self->segment, stop_time);
-    self->pending_close = TRUE;
-  }
   if (old)
     old->pushed = FALSE;
-
-  if (new && new->active && start_time >= 0) {
-    GST_DEBUG_OBJECT (self, "setting start_time to %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (start_time));
-    /* schedule a new segment push */
-    gst_segment_set_start (&new->segment, start_time);
-    new->segment_pending = TRUE;
-  }
   if (new)
     new->pushed = FALSE;
 
+  /* Send a new SEGMENT event on the new pad next */
+  if (old != new && new)
+    new->segment_pending = TRUE;
+
   active_pad_p = &self->active_sinkpad;
   gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad));
 
@@ -1269,8 +953,7 @@ gst_input_selector_set_property (GObject * object, guint prop_id,
       pad = g_value_get_object (value);
 
       GST_INPUT_SELECTOR_LOCK (sel);
-      gst_input_selector_set_active_pad (sel, pad,
-          GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
+      gst_input_selector_set_active_pad (sel, pad);
       GST_INPUT_SELECTOR_UNLOCK (sel);
       break;
     }
@@ -1334,44 +1017,72 @@ gst_input_selector_get_linked_pad (GstInputSelector * sel, GstPad * pad,
 }
 
 static gboolean
-gst_input_selector_event (GstPad * pad, GstEvent * event)
+gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstInputSelector *sel;
-  gboolean res = FALSE;
-  GstPad *otherpad;
+  gboolean result = FALSE;
+  GstIterator *iter;
+  gboolean done = FALSE;
+  GValue item = { 0, };
+  GstPad *eventpad;
+  GList *pushed_pads = NULL;
+
+  sel = GST_INPUT_SELECTOR (parent);
+  /* Send upstream events to all sinkpads */
+  iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel));
+
+  /* This is now essentially a copy of gst_pad_event_default_dispatch
+   * with a different iterator */
+  while (!done) {
+    switch (gst_iterator_next (iter, &item)) {
+      case GST_ITERATOR_OK:
+        eventpad = g_value_get_object (&item);
+
+        /* if already pushed,  skip */
+        if (g_list_find (pushed_pads, eventpad)) {
+          g_value_reset (&item);
+          break;
+        }
 
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
+        gst_event_ref (event);
+        result |= gst_pad_push_event (eventpad, event);
+
+        g_value_reset (&item);
+        break;
+      case GST_ITERATOR_RESYNC:
+        /* We don't reset the result here because we don't push the event
+         * again on pads that got the event already and because we need
+         * to consider the result of the previous pushes */
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_ERROR_OBJECT (pad, "Could not iterate over sinkpads");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+    }
   }
+  g_value_unset (&item);
+  gst_iterator_free (iter);
 
-  otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE);
-  if (otherpad) {
-    res = gst_pad_push_event (otherpad, event);
+  g_list_free (pushed_pads);
 
-    gst_object_unref (otherpad);
-  } else
-    gst_event_unref (event);
+  gst_event_unref (event);
 
-  gst_object_unref (sel);
-  return res;
+  return result;
 }
 
 /* query on the srcpad. We override this function because by default it will
  * only forward the query to one random sinkpad */
 static gboolean
-gst_input_selector_query (GstPad * pad, GstQuery * query)
+gst_input_selector_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  gboolean res = TRUE;
+  gboolean res = FALSE;
   GstInputSelector *sel;
-  GstPad *otherpad;
-
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return FALSE;
 
-  otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE);
+  sel = GST_INPUT_SELECTOR (parent);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:
@@ -1384,9 +1095,6 @@ gst_input_selector_query (GstPad * pad, GstQuery * query)
       resmax = -1;
       reslive = FALSE;
 
-      /* assume FALSE, we become TRUE if one query succeeds */
-      res = FALSE;
-
       /* perform the query on all sinkpads and combine the results. We take the
        * max of min and the min of max for the result latency. */
       GST_INPUT_SELECTOR_LOCK (sel);
@@ -1432,47 +1140,13 @@ gst_input_selector_query (GstPad * pad, GstQuery * query)
       break;
     }
     default:
-      if (otherpad)
-        res = gst_pad_peer_query (otherpad, query);
+      res = gst_pad_query_default (pad, parent, query);
       break;
   }
-  if (otherpad)
-    gst_object_unref (otherpad);
-  gst_object_unref (sel);
 
   return res;
 }
 
-static GstCaps *
-gst_input_selector_getcaps (GstPad * pad)
-{
-  GstPad *otherpad;
-  GstInputSelector *sel;
-  GstCaps *caps;
-
-  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return gst_caps_new_any ();
-
-  otherpad = gst_input_selector_get_linked_pad (sel, pad, FALSE);
-
-  if (!otherpad) {
-    GST_DEBUG_OBJECT (pad, "Pad not linked, returning ANY");
-    caps = gst_caps_new_any ();
-  } else {
-    GST_DEBUG_OBJECT (pad, "Pad is linked (to %s:%s), returning peer caps",
-        GST_DEBUG_PAD_NAME (otherpad));
-    /* if the peer has caps, use those. If the pad is not linked, this function
-     * returns NULL and we return ANY */
-    if (!(caps = gst_pad_peer_get_caps_reffed (otherpad)))
-      caps = gst_caps_new_any ();
-    gst_object_unref (otherpad);
-  }
-
-  gst_object_unref (sel);
-  return caps;
-}
-
 /* check if the pad is the active sinkpad */
 static inline gboolean
 gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad)
@@ -1510,7 +1184,7 @@ gst_input_selector_activate_sinkpad (GstInputSelector * sel, GstPad * pad)
 
 static GstPad *
 gst_input_selector_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * unused)
+    GstPadTemplate * templ, const gchar * unused, const GstCaps * caps)
 {
   GstInputSelector *sel;
   gchar *name = NULL;
@@ -1523,7 +1197,7 @@ gst_input_selector_request_new_pad (GstElement * element,
   GST_INPUT_SELECTOR_LOCK (sel);
 
   GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
-  name = g_strdup_printf ("sink%d", sel->padcount++);
+  name = g_strdup_printf ("sink_%u", sel->padcount++);
   sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
       "name", name, "direction", templ->direction, "template", templ, NULL);
   g_free (name);
@@ -1532,17 +1206,14 @@ gst_input_selector_request_new_pad (GstElement * element,
 
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_selector_pad_event));
-  gst_pad_set_getcaps_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps));
-  gst_pad_set_acceptcaps_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_selector_pad_acceptcaps));
+  gst_pad_set_query_function (sinkpad,
+      GST_DEBUG_FUNCPTR (gst_selector_pad_query));
   gst_pad_set_chain_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_selector_pad_chain));
   gst_pad_set_iterate_internal_links_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads));
-  gst_pad_set_bufferalloc_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_selector_pad_bufferalloc));
 
+  GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_pad_set_active (sinkpad, TRUE);
   gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
   GST_INPUT_SELECTOR_UNLOCK (sel);
@@ -1583,9 +1254,6 @@ gst_input_selector_reset (GstInputSelector * sel)
     gst_object_unref (sel->active_sinkpad);
     sel->active_sinkpad = NULL;
   }
-  /* reset segment */
-  gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
-  sel->pending_close = FALSE;
   /* reset each of our sinkpads state */
   for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) {
     GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data);
@@ -1663,27 +1331,3 @@ gst_input_selector_block (GstInputSelector * self)
 
   return ret;
 }
-
-/* stop_time and start_time are running times */
-static void
-gst_input_selector_switch (GstInputSelector * self, GstPad * pad,
-    gint64 stop_time, gint64 start_time)
-{
-  gboolean changed;
-
-  g_return_if_fail (self->blocked == TRUE);
-
-  GST_INPUT_SELECTOR_LOCK (self);
-  changed =
-      gst_input_selector_set_active_pad (self, pad, stop_time, start_time);
-
-  self->blocked = FALSE;
-  GST_INPUT_SELECTOR_BROADCAST (self);
-  GST_INPUT_SELECTOR_UNLOCK (self);
-
-  if (changed) {
-    NOTIFY_MUTEX_LOCK ();
-    g_object_notify (G_OBJECT (self), "active-pad");
-    NOTIFY_MUTEX_UNLOCK ();
-  }
-}
index f370999..8a5248a 100644 (file)
@@ -40,8 +40,8 @@ G_BEGIN_DECLS
 typedef struct _GstInputSelector GstInputSelector;
 typedef struct _GstInputSelectorClass GstInputSelectorClass;
 
-#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock)
-#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond)
+#define GST_INPUT_SELECTOR_GET_LOCK(sel) (&((GstInputSelector*)(sel))->lock)
+#define GST_INPUT_SELECTOR_GET_COND(sel) (&((GstInputSelector*)(sel))->cond)
 #define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
 #define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
 #define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \
@@ -58,11 +58,8 @@ struct _GstInputSelector {
   guint padcount;
   gboolean sync_streams;
 
-  GstSegment segment;      /* the output segment */
-  gboolean pending_close;  /* if we should push a close first */
-
-  GMutex *lock;
-  GCond *cond;
+  GMutex lock;
+  GCond cond;
   gboolean blocked;
   gboolean flushing;
 };
@@ -71,8 +68,6 @@ struct _GstInputSelectorClass {
   GstElementClass parent_class;
 
   gint64 (*block)      (GstInputSelector *self);
-  void (*switch_)      (GstInputSelector *self, GstPad *pad,
-                         gint64 stop_time, gint64 start_time);
 };
 
 GType gst_input_selector_get_type (void);
index 0054715..c5b24e0 100644 (file)
 #  include "config.h"
 #endif
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
-
 #include <gst/gst.h>
 #include <stdio.h>
 #include "gstmultiqueue.h"
@@ -163,7 +159,7 @@ struct _GstSingleQueue
   guint32 last_oldid;           /* Previously observed old_id, reset to MAXUINT32 on flush */
   GstClockTime next_time;       /* End running time of next buffer to be pushed */
   GstClockTime last_time;       /* Start running time of last pushed buffer */
-  GCond *turn;                  /* SingleQueue turn waiting conditional */
+  GCond turn;                   /* SingleQueue turn waiting conditional */
 };
 
 
@@ -181,7 +177,7 @@ struct _GstMultiQueueItem
   guint32 posid;
 };
 
-static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, gint id);
+static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, guint id);
 static void gst_single_queue_free (GstSingleQueue * squeue);
 
 static void wake_up_next_non_linked (GstMultiQueue * mq);
@@ -190,12 +186,12 @@ static void compute_high_time (GstMultiQueue * mq);
 static void single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq);
 static void single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq);
 
-static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink%d",
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS_ANY);
 
-static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
     GST_STATIC_CAPS_ANY);
@@ -251,11 +247,11 @@ enum
 };
 
 #define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START {                          \
-  g_mutex_lock (q->qlock);                                              \
+  g_mutex_lock (&q->qlock);                                              \
 } G_STMT_END
 
 #define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START {                        \
-  g_mutex_unlock (q->qlock);                                            \
+  g_mutex_unlock (&q->qlock);                                            \
 } G_STMT_END
 
 static void gst_multi_queue_finalize (GObject * object);
@@ -265,36 +261,22 @@ static void gst_multi_queue_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
 static GstPad *gst_multi_queue_request_new_pad (GstElement * element,
-    GstPadTemplate * temp, const gchar * name);
+    GstPadTemplate * temp, const gchar * name, const GstCaps * caps);
 static void gst_multi_queue_release_pad (GstElement * element, GstPad * pad);
 static GstStateChangeReturn gst_multi_queue_change_state (GstElement *
     element, GstStateChange transition);
 
 static void gst_multi_queue_loop (GstPad * pad);
 
-#define _do_init(bla) \
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (multi_queue_debug, "multiqueue", 0, "multiqueue element");
-
-GST_BOILERPLATE_FULL (GstMultiQueue, gst_multi_queue, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
+#define gst_multi_queue_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstMultiQueue, gst_multi_queue, GST_TYPE_ELEMENT,
+    _do_init);
 
 static guint gst_multi_queue_signals[LAST_SIGNAL] = { 0 };
 
 static void
-gst_multi_queue_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "MultiQueue",
-      "Generic", "Multiple data queue", "Edward Hervey <edward@fluendo.com>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-}
-
-static void
 gst_multi_queue_class_init (GstMultiQueueClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -425,6 +407,14 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
 
   gobject_class->finalize = gst_multi_queue_finalize;
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "MultiQueue",
+      "Generic", "Multiple data queue", "Edward Hervey <edward@fluendo.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_multi_queue_request_new_pad);
   gstelement_class->release_pad =
@@ -434,7 +424,7 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
 }
 
 static void
-gst_multi_queue_init (GstMultiQueue * mqueue, GstMultiQueueClass * klass)
+gst_multi_queue_init (GstMultiQueue * mqueue)
 {
   mqueue->nbqueues = 0;
   mqueue->queues = NULL;
@@ -457,7 +447,7 @@ gst_multi_queue_init (GstMultiQueue * mqueue, GstMultiQueueClass * klass)
   mqueue->highid = -1;
   mqueue->high_time = GST_CLOCK_TIME_NONE;
 
-  mqueue->qlock = g_mutex_new ();
+  g_mutex_init (&mqueue->qlock);
 }
 
 static void
@@ -471,7 +461,7 @@ gst_multi_queue_finalize (GObject * object)
   mqueue->queues_cookie++;
 
   /* free/unref instance data */
-  g_mutex_free (mqueue->qlock);
+  g_mutex_clear (&mqueue->qlock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -585,12 +575,13 @@ gst_multi_queue_get_property (GObject * object, guint prop_id,
 }
 
 static GstIterator *
-gst_multi_queue_iterate_internal_links (GstPad * pad)
+gst_multi_queue_iterate_internal_links (GstPad * pad, GstObject * parent)
 {
   GstIterator *it = NULL;
   GstPad *opad;
   GstSingleQueue *squeue;
-  GstMultiQueue *mq = GST_MULTI_QUEUE (gst_pad_get_parent (pad));
+  GstMultiQueue *mq = GST_MULTI_QUEUE (parent);
+  GValue val = { 0, };
 
   GST_MULTI_QUEUE_MUTEX_LOCK (mq);
   squeue = gst_pad_get_element_private (pad);
@@ -604,14 +595,15 @@ gst_multi_queue_iterate_internal_links (GstPad * pad)
   else
     goto out;
 
-  it = gst_iterator_new_single (GST_TYPE_PAD, opad,
-      (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
+  g_value_init (&val, GST_TYPE_PAD);
+  g_value_set_object (&val, opad);
+  it = gst_iterator_new_single (GST_TYPE_PAD, &val);
+  g_value_unset (&val);
 
   gst_object_unref (opad);
 
 out:
   GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
-  gst_object_unref (mq);
 
   return it;
 }
@@ -623,14 +615,14 @@ out:
 
 static GstPad *
 gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp,
-    const gchar * name)
+    const gchar * name, const GstCaps * caps)
 {
   GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
   GstSingleQueue *squeue;
-  gint temp_id = -1;
+  guint temp_id = -1;
 
   if (name) {
-    sscanf (name + 4, "%d", &temp_id);
+    sscanf (name + 4, "_%u", &temp_id);
     GST_LOG_OBJECT (element, "name : %s (id %d)", GST_STR_NULL (name), temp_id);
   }
 
@@ -717,7 +709,7 @@ gst_multi_queue_change_state (GstElement * element, GstStateChange transition)
       for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
         sq = (GstSingleQueue *) tmp->data;
         sq->flushing = TRUE;
-        g_cond_signal (sq->turn);
+        g_cond_signal (&sq->turn);
       }
       GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
       break;
@@ -757,7 +749,7 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
     GST_LOG_OBJECT (mq, "SingleQueue %d : waking up eventually waiting task",
         sq->id);
     GST_MULTI_QUEUE_MUTEX_LOCK (mq);
-    g_cond_signal (sq->turn);
+    g_cond_signal (&sq->turn);
     GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
 
     GST_LOG_OBJECT (mq, "SingleQueue %d : pausing task", sq->id);
@@ -877,7 +869,7 @@ update_time_level (GstMultiQueue * mq, GstSingleQueue * sq)
   if (sq->sink_tainted) {
     sink_time = sq->sinktime =
         gst_segment_to_running_time (&sq->sink_segment, GST_FORMAT_TIME,
-        sq->sink_segment.last_stop);
+        sq->sink_segment.position);
 
     if (G_UNLIKELY (sink_time != GST_CLOCK_TIME_NONE))
       /* if we have a time, we become untainted and use the time */
@@ -888,7 +880,7 @@ update_time_level (GstMultiQueue * mq, GstSingleQueue * sq)
   if (sq->src_tainted) {
     src_time = sq->srctime =
         gst_segment_to_running_time (&sq->src_segment, GST_FORMAT_TIME,
-        sq->src_segment.last_stop);
+        sq->src_segment.position);
     /* if we have a time, we become untainted and use the time */
     if (G_UNLIKELY (src_time != GST_CLOCK_TIME_NONE))
       sq->src_tainted = FALSE;
@@ -912,44 +904,33 @@ update_time_level (GstMultiQueue * mq, GstSingleQueue * sq)
   return;
 }
 
-/* take a NEWSEGMENT event and apply the values to segment, updating the time
+/* take a SEGMENT event and apply the values to segment, updating the time
  * level of queue. */
 static void
 apply_segment (GstMultiQueue * mq, GstSingleQueue * sq, GstEvent * event,
     GstSegment * segment)
 {
-  gboolean update;
-  GstFormat format;
-  gdouble rate, arate;
-  gint64 start, stop, time;
-
-  gst_event_parse_new_segment_full (event, &update, &rate, &arate,
-      &format, &start, &stop, &time);
+  gst_event_copy_segment (event, segment);
 
   /* now configure the values, we use these to track timestamps on the
    * sinkpad. */
-  if (format != GST_FORMAT_TIME) {
+  if (segment->format != GST_FORMAT_TIME) {
     /* non-time format, pretent the current time segment is closed with a
      * 0 start and unknown stop time. */
-    update = FALSE;
-    format = GST_FORMAT_TIME;
-    start = 0;
-    stop = -1;
-    time = 0;
+    segment->format = GST_FORMAT_TIME;
+    segment->start = 0;
+    segment->stop = -1;
+    segment->time = 0;
   }
-
   GST_MULTI_QUEUE_MUTEX_LOCK (mq);
 
-  gst_segment_set_newsegment_full (segment, update,
-      rate, arate, format, start, stop, time);
-
   if (segment == &sq->sink_segment)
     sq->sink_tainted = TRUE;
   else
     sq->src_tainted = TRUE;
 
   GST_DEBUG_OBJECT (mq,
-      "queue %d, configured NEWSEGMENT %" GST_SEGMENT_FORMAT, sq->id, segment);
+      "queue %d, configured SEGMENT %" GST_SEGMENT_FORMAT, sq->id, segment);
 
   /* segment can update the time level of the queue */
   update_time_level (mq, sq);
@@ -967,16 +948,16 @@ apply_buffer (GstMultiQueue * mq, GstSingleQueue * sq, GstClockTime timestamp,
   /* if no timestamp is set, assume it's continuous with the previous 
    * time */
   if (timestamp == GST_CLOCK_TIME_NONE)
-    timestamp = segment->last_stop;
+    timestamp = segment->position;
 
   /* add duration */
   if (duration != GST_CLOCK_TIME_NONE)
     timestamp += duration;
 
-  GST_DEBUG_OBJECT (mq, "queue %d, last_stop updated to %" GST_TIME_FORMAT,
+  GST_DEBUG_OBJECT (mq, "queue %d, position updated to %" GST_TIME_FORMAT,
       sq->id, GST_TIME_ARGS (timestamp));
 
-  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, timestamp);
+  segment->position = timestamp;
 
   if (segment == &sq->sink_segment)
     sq->sink_tainted = TRUE;
@@ -1006,45 +987,37 @@ get_running_time (GstSegment * segment, GstMiniObject * object, gboolean end)
     }
   } else if (GST_IS_BUFFER_LIST (object)) {
     GstBufferList *list = GST_BUFFER_LIST_CAST (object);
-    GstBufferListIterator *it = gst_buffer_list_iterate (list);
+    gint i, n;
     GstBuffer *buf;
 
-    do {
-      while ((buf = gst_buffer_list_iterator_next (it))) {
-        if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
-          time = GST_BUFFER_TIMESTAMP (buf);
-          if (end && GST_BUFFER_DURATION_IS_VALID (buf))
-            time += GST_BUFFER_DURATION (buf);
-          if (time > segment->stop)
-            time = segment->stop;
-          time = gst_segment_to_running_time (segment, GST_FORMAT_TIME, time);
-          if (!end)
-            goto done;
-        } else if (!end) {
+    n = gst_buffer_list_length (list);
+    for (i = 0; i < n; i++) {
+      buf = gst_buffer_list_get (list, i);
+      if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+        time = GST_BUFFER_TIMESTAMP (buf);
+        if (end && GST_BUFFER_DURATION_IS_VALID (buf))
+          time += GST_BUFFER_DURATION (buf);
+        if (time > segment->stop)
+          time = segment->stop;
+        time = gst_segment_to_running_time (segment, GST_FORMAT_TIME, time);
+        if (!end)
           goto done;
-        }
+      } else if (!end) {
+        goto done;
       }
-    } while (gst_buffer_list_iterator_next_group (it));
+    }
   } else if (GST_IS_EVENT (object)) {
     GstEvent *event = GST_EVENT_CAST (object);
 
     /* For newsegment events return the running time of the start position */
-    if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
-      GstSegment new_segment = *segment;
-      gboolean update;
-      gdouble rate, applied_rate;
-      GstFormat format;
-      gint64 start, stop, position;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-          &format, &start, &stop, &position);
-      if (format == GST_FORMAT_TIME) {
-        gst_segment_set_newsegment_full (&new_segment, update, rate,
-            applied_rate, format, start, stop, position);
+    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+      const GstSegment *new_segment;
 
+      gst_event_parse_segment (event, &new_segment);
+      if (new_segment->format == GST_FORMAT_TIME) {
         time =
-            gst_segment_to_running_time (&new_segment, GST_FORMAT_TIME,
-            new_segment.start);
+            gst_segment_to_running_time (new_segment, GST_FORMAT_TIME,
+            new_segment->start);
       }
     }
   }
@@ -1062,12 +1035,10 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
   if (GST_IS_BUFFER (object)) {
     GstBuffer *buffer;
     GstClockTime timestamp, duration;
-    GstCaps *caps;
 
     buffer = GST_BUFFER_CAST (object);
     timestamp = GST_BUFFER_TIMESTAMP (buffer);
     duration = GST_BUFFER_DURATION (buffer);
-    caps = GST_BUFFER_CAPS (buffer);
 
     apply_buffer (mq, sq, timestamp, duration, &sq->src_segment);
 
@@ -1078,12 +1049,6 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
         "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT,
         sq->id, buffer, GST_TIME_ARGS (timestamp));
 
-    /* Set caps on pad before pushing, this avoids core calling the acceptcaps
-     * function on the srcpad, which will call acceptcaps upstream, which might
-     * not accept these caps (anymore). */
-    if (caps && caps != GST_PAD_CAPS (sq->srcpad))
-      gst_pad_set_caps (sq->srcpad, caps);
-
     result = gst_pad_push (sq->srcpad, buffer);
   } else if (GST_IS_EVENT (object)) {
     GstEvent *event;
@@ -1092,9 +1057,9 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
 
     switch (GST_EVENT_TYPE (event)) {
       case GST_EVENT_EOS:
-        result = GST_FLOW_UNEXPECTED;
+        result = GST_FLOW_EOS;
         break;
-      case GST_EVENT_NEWSEGMENT:
+      case GST_EVENT_SEGMENT:
         apply_segment (mq, sq, event, &sq->src_segment);
         /* Applying the segment may have made the queue non-full again, unblock it if needed */
         gst_data_queue_limits_changed (sq->queue);
@@ -1147,7 +1112,7 @@ gst_multi_queue_buffer_item_new (GstMiniObject * object, guint32 curid)
   item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy;
   item->posid = curid;
 
-  item->size = GST_BUFFER_SIZE (object);
+  item->size = gst_buffer_get_size (GST_BUFFER_CAST (object));
   item->duration = GST_BUFFER_DURATION (object);
   if (item->duration == GST_CLOCK_TIME_NONE)
     item->duration = 0;
@@ -1265,7 +1230,7 @@ gst_multi_queue_loop (GstPad * pad)
         wake_up_next_non_linked (mq);
 
         mq->numwaiting++;
-        g_cond_wait (sq->turn, mq->qlock);
+        g_cond_wait (&sq->turn, &mq->qlock);
         mq->numwaiting--;
 
         if (sq->flushing) {
@@ -1320,7 +1285,7 @@ gst_multi_queue_loop (GstPad * pad)
   object = NULL;
 
   if (result != GST_FLOW_OK && result != GST_FLOW_NOT_LINKED
-      && result != GST_FLOW_UNEXPECTED)
+      && result != GST_FLOW_EOS)
     goto out_flushing;
 
   GST_LOG_OBJECT (mq, "AFTER PUSHING sq->srcresult: %s",
@@ -1345,7 +1310,7 @@ out_flushing:
      * but might be stuck in one of our other full queues;
      * so empty this one and trigger dynamic queue growth. At
      * this point the srcresult is not OK, NOT_LINKED
-     * or UNEXPECTED, i.e. a real failure */
+     * or EOS, i.e. a real failure */
     gst_data_queue_flush (sq->queue);
     single_queue_underrun_cb (sq->queue, sq);
     gst_data_queue_set_flushing (sq->queue, TRUE);
@@ -1365,7 +1330,7 @@ out_flushing:
  * _ we push with a unique id (curid)
  */
 static GstFlowReturn
-gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer)
+gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstSingleQueue *sq;
   GstMultiQueue *mq;
@@ -1381,7 +1346,7 @@ gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer)
     goto was_eos;
 
   /* Get a unique incrementing id */
-  curid = G_ATOMIC_INT_ADD ((gint *) & mq->counter, 1);
+  curid = g_atomic_int_add ((gint *) & mq->counter, 1);
 
   GST_LOG_OBJECT (mq, "SingleQueue %d : about to enqueue buffer %p with id %d",
       sq->id, buffer, curid);
@@ -1411,31 +1376,41 @@ flushing:
   }
 was_eos:
   {
-    GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return UNEXPECTED");
+    GST_DEBUG_OBJECT (mq, "we are EOS, dropping buffer, return EOS");
     gst_buffer_unref (buffer);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
 static gboolean
-gst_multi_queue_sink_activate_push (GstPad * pad, gboolean active)
+gst_multi_queue_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
+  gboolean res;
   GstSingleQueue *sq;
 
   sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
 
-  if (active) {
-    /* All pads start off linked until they push one buffer */
-    sq->srcresult = GST_FLOW_OK;
-  } else {
-    sq->srcresult = GST_FLOW_WRONG_STATE;
-    gst_data_queue_flush (sq->queue);
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        /* All pads start off linked until they push one buffer */
+        sq->srcresult = GST_FLOW_OK;
+      } else {
+        sq->srcresult = GST_FLOW_WRONG_STATE;
+        gst_data_queue_flush (sq->queue);
+      }
+      res = TRUE;
+      break;
+    default:
+      res = FALSE;
+      break;
   }
-  return TRUE;
+  return res;
 }
 
 static gboolean
-gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
+gst_multi_queue_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstSingleQueue *sq;
   GstMultiQueue *mq;
@@ -1446,7 +1421,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
   GstEvent *sref = NULL;
 
   sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
-  mq = (GstMultiQueue *) gst_pad_get_parent (pad);
+  mq = (GstMultiQueue *) parent;
 
   type = GST_EVENT_TYPE (event);
 
@@ -1468,7 +1443,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
 
       gst_single_queue_flush (mq, sq, FALSE);
       goto done;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       /* take ref because the queue will take ownership and we need the event
        * afterwards to update the segment */
       sref = gst_event_ref (event);
@@ -1487,7 +1462,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
     goto was_eos;
 
   /* Get an unique incrementing id. */
-  curid = G_ATOMIC_INT_ADD ((gint *) & mq->counter, 1);
+  curid = g_atomic_int_add ((gint *) & mq->counter, 1);
 
   item = gst_multi_queue_event_item_new ((GstMiniObject *) event, curid);
 
@@ -1509,7 +1484,7 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
       update_buffering (mq, sq);
       single_queue_overrun_cb (sq->queue, sq);
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       apply_segment (mq, sq, sref, &sq->sink_segment);
       gst_event_unref (sref);
       break;
@@ -1517,7 +1492,6 @@ gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
       break;
   }
 done:
-  gst_object_unref (mq);
   return res;
 
 flushing:
@@ -1538,73 +1512,54 @@ was_eos:
   }
 }
 
-static GstCaps *
-gst_multi_queue_getcaps (GstPad * pad)
-{
-  GstSingleQueue *sq = gst_pad_get_element_private (pad);
-  GstPad *otherpad;
-  GstCaps *result;
-
-  otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad;
-
-  GST_LOG_OBJECT (otherpad, "Getting caps from the peer of this pad");
-
-  result = gst_pad_peer_get_caps (otherpad);
-  if (result == NULL)
-    result = gst_caps_new_any ();
-
-  return result;
-}
-
 static gboolean
-gst_multi_queue_acceptcaps (GstPad * pad, GstCaps * caps)
+gst_multi_queue_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstSingleQueue *sq = gst_pad_get_element_private (pad);
-  GstPad *otherpad;
-  gboolean result;
-
-  otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad;
-
-  GST_LOG_OBJECT (otherpad, "Accept caps from the peer of this pad");
-
-  result = gst_pad_peer_accept_caps (otherpad, caps);
-
-  return result;
-}
-
-static GstFlowReturn
-gst_multi_queue_bufferalloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstSingleQueue *sq = gst_pad_get_element_private (pad);
+  gboolean res;
 
-  return gst_pad_alloc_buffer (sq->srcpad, offset, size, caps, buf);
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ACCEPT_CAPS:
+    case GST_QUERY_CAPS:
+    default:
+      /* default handling */
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
+  return res;
 }
 
 static gboolean
-gst_multi_queue_src_activate_push (GstPad * pad, gboolean active)
+gst_multi_queue_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
   GstMultiQueue *mq;
   GstSingleQueue *sq;
-  gboolean result = FALSE;
+  gboolean result;
 
   sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
   mq = sq->mqueue;
 
   GST_DEBUG_OBJECT (mq, "SingleQueue %d", sq->id);
 
-  if (active) {
-    result = gst_single_queue_flush (mq, sq, FALSE);
-  } else {
-    result = gst_single_queue_flush (mq, sq, TRUE);
-    /* make sure streaming finishes */
-    result |= gst_pad_stop_task (pad);
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        result = gst_single_queue_flush (mq, sq, FALSE);
+      } else {
+        result = gst_single_queue_flush (mq, sq, TRUE);
+        /* make sure streaming finishes */
+        result |= gst_pad_stop_task (pad);
+      }
+      break;
+    default:
+      result = FALSE;
+      break;
   }
   return result;
 }
 
 static gboolean
-gst_multi_queue_src_event (GstPad * pad, GstEvent * event)
+gst_multi_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstSingleQueue *sq = gst_pad_get_element_private (pad);
 
@@ -1612,30 +1567,18 @@ gst_multi_queue_src_event (GstPad * pad, GstEvent * event)
 }
 
 static gboolean
-gst_multi_queue_src_query (GstPad * pad, GstQuery * query)
+gst_multi_queue_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstSingleQueue *sq = gst_pad_get_element_private (pad);
-  GstPad *peerpad;
   gboolean res;
 
   /* FIXME, Handle position offset depending on queue size */
-
-  /* default handling */
-  if (!(peerpad = gst_pad_get_peer (sq->sinkpad)))
-    goto no_peer;
-
-  res = gst_pad_query (peerpad, query);
-
-  gst_object_unref (peerpad);
-
-  return res;
-
-  /* ERRORS */
-no_peer:
-  {
-    GST_LOG_OBJECT (sq->sinkpad, "Couldn't send query because we have no peer");
-    return FALSE;
+  switch (GST_QUERY_TYPE (query)) {
+    default:
+      /* default handling */
+      res = gst_pad_query_default (pad, parent, query);
+      break;
   }
+  return res;
 }
 
 /*
@@ -1662,7 +1605,7 @@ wake_up_next_non_linked (GstMultiQueue * mq)
               && sq->next_time >= mq->high_time)
           || (sq->nextid != 0 && sq->nextid <= mq->highid)) {
         GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id);
-        g_cond_signal (sq->turn);
+        g_cond_signal (&sq->turn);
       }
     }
   }
@@ -1693,10 +1636,10 @@ compute_high_id (GstMultiQueue * mq)
 
       if (sq->nextid < lowest)
         lowest = sq->nextid;
-    } else if (sq->srcresult != GST_FLOW_UNEXPECTED) {
+    } else if (sq->srcresult != GST_FLOW_EOS) {
       /* If we don't have a global highid, or the global highid is lower than
        * this single queue's last outputted id, store the queue's one, 
-       * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */
+       * unless the singlequeue is at EOS (srcresult = EOS) */
       if ((highid == G_MAXUINT32) || (sq->oldid > highid))
         highid = sq->oldid;
     }
@@ -1738,10 +1681,10 @@ compute_high_time (GstMultiQueue * mq)
 
       if (lowest == GST_CLOCK_TIME_NONE || sq->next_time < lowest)
         lowest = sq->next_time;
-    } else if (sq->srcresult != GST_FLOW_UNEXPECTED) {
+    } else if (sq->srcresult != GST_FLOW_EOS) {
       /* If we don't have a global highid, or the global highid is lower than
        * this single queue's last outputted id, store the queue's one, 
-       * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */
+       * unless the singlequeue is at EOS (srcresult = EOS) */
       if (highest == GST_CLOCK_TIME_NONE || sq->last_time > highest)
         highest = sq->last_time;
     }
@@ -1892,17 +1835,17 @@ gst_single_queue_free (GstSingleQueue * sq)
   /* DRAIN QUEUE */
   gst_data_queue_flush (sq->queue);
   g_object_unref (sq->queue);
-  g_cond_free (sq->turn);
+  g_cond_clear (&sq->turn);
   g_free (sq);
 }
 
 static GstSingleQueue *
-gst_single_queue_new (GstMultiQueue * mqueue, gint id)
+gst_single_queue_new (GstMultiQueue * mqueue, guint id)
 {
   GstSingleQueue *sq;
   gchar *name;
   GList *tmp;
-  gint temp_id = (id == -1) ? 0 : id;
+  guint temp_id = (id == -1) ? 0 : id;
 
   GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
 
@@ -1956,48 +1899,42 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id)
   sq->oldid = 0;
   sq->next_time = GST_CLOCK_TIME_NONE;
   sq->last_time = GST_CLOCK_TIME_NONE;
-  sq->turn = g_cond_new ();
+  g_cond_init (&sq->turn);
 
   sq->sinktime = GST_CLOCK_TIME_NONE;
   sq->srctime = GST_CLOCK_TIME_NONE;
   sq->sink_tainted = TRUE;
   sq->src_tainted = TRUE;
 
-  name = g_strdup_printf ("sink%d", sq->id);
+  name = g_strdup_printf ("sink_%u", sq->id);
   sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, name);
   g_free (name);
 
   gst_pad_set_chain_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
-  gst_pad_set_activatepush_function (sq->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_push));
+  gst_pad_set_activatemode_function (sq->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_mode));
   gst_pad_set_event_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
-  gst_pad_set_getcaps_function (sq->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
-  gst_pad_set_acceptcaps_function (sq->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps));
-  gst_pad_set_bufferalloc_function (sq->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_bufferalloc));
+  gst_pad_set_query_function (sq->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
   gst_pad_set_iterate_internal_links_function (sq->sinkpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
+  GST_OBJECT_FLAG_SET (sq->sinkpad, GST_PAD_FLAG_PROXY_CAPS);
 
-  name = g_strdup_printf ("src%d", sq->id);
+  name = g_strdup_printf ("src_%u", sq->id);
   sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name);
   g_free (name);
 
-  gst_pad_set_activatepush_function (sq->srcpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push));
-  gst_pad_set_getcaps_function (sq->srcpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
-  gst_pad_set_acceptcaps_function (sq->srcpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps));
+  gst_pad_set_activatemode_function (sq->srcpad,
+      GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_mode));
   gst_pad_set_event_function (sq->srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_event));
   gst_pad_set_query_function (sq->srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_query));
   gst_pad_set_iterate_internal_links_function (sq->srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
+  GST_OBJECT_FLAG_SET (sq->srcpad, GST_PAD_FLAG_PROXY_CAPS);
 
   gst_pad_set_element_private (sq->sinkpad, (gpointer) sq);
   gst_pad_set_element_private (sq->srcpad, (gpointer) sq);
@@ -2007,14 +1944,14 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id)
   /* only activate the pads when we are not in the NULL state
    * and add the pad under the state_lock to prevend state changes
    * between activating and adding */
-  g_static_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue));
+  g_rec_mutex_lock (GST_STATE_GET_LOCK (mqueue));
   if (GST_STATE_TARGET (mqueue) != GST_STATE_NULL) {
     gst_pad_set_active (sq->srcpad, TRUE);
     gst_pad_set_active (sq->sinkpad, TRUE);
   }
   gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad);
   gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad);
-  g_static_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue));
+  g_rec_mutex_unlock (GST_STATE_GET_LOCK (mqueue));
 
   GST_DEBUG_OBJECT (mqueue, "GstSingleQueue [%d] created and pads added",
       sq->id);
index bb3d840..04c7501 100644 (file)
@@ -24,7 +24,7 @@
 #define __GST_MULTI_QUEUE_H__
 
 #include <gst/gst.h>
-#include <gst/base/gstdataqueue.h>
+#include "gstdataqueue.h"
 
 G_BEGIN_DECLS
 
@@ -65,11 +65,11 @@ struct _GstMultiQueue {
   gboolean buffering;
   gint percent;
 
-  guint32  counter;    /* incoming object counter, use atomic accesses */
+  guint    counter;    /* incoming object counter, use atomic accesses */
   guint32  highid;     /* contains highest id of last outputted object */
   GstClockTime high_time; /* highest start running time */
 
-  GMutex * qlock;      /* Global queue lock (vs object lock or individual */
+  GMutex   qlock;      /* Global queue lock (vs object lock or individual */
                        /* queues lock). Protects nbqueues, queues, global */
                        /* GstMultiQueueSize, counter and highid */
 
index b3b6c36..ba30a46 100644 (file)
@@ -44,7 +44,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS_ANY);
 
 static GstStaticPadTemplate gst_output_selector_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src%d",
+GST_STATIC_PAD_TEMPLATE ("src_%u",
     GST_PAD_SRC,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS_ANY);
@@ -86,11 +86,11 @@ enum
 
 #define DEFAULT_PAD_NEGOTIATION_MODE GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL
 
-#define _do_init(bla) \
+#define _do_init \
 GST_DEBUG_CATEGORY_INIT (output_selector_debug, \
         "output-selector", 0, "Output stream selector");
-
-GST_BOILERPLATE_FULL (GstOutputSelector, gst_output_selector, GstElement,
+#define gst_output_selector_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstOutputSelector, gst_output_selector,
     GST_TYPE_ELEMENT, _do_init);
 
 static void gst_output_selector_dispose (GObject * object);
@@ -99,34 +99,21 @@ static void gst_output_selector_set_property (GObject * object,
 static void gst_output_selector_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 static GstPad *gst_output_selector_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * unused);
+    GstPadTemplate * templ, const gchar * unused, const GstCaps * caps);
 static void gst_output_selector_release_pad (GstElement * element,
     GstPad * pad);
-static GstFlowReturn gst_output_selector_chain (GstPad * pad, GstBuffer * buf);
-static GstFlowReturn gst_output_selector_buffer_alloc (GstPad * pad,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+static GstFlowReturn gst_output_selector_chain (GstPad * pad,
+    GstObject * parent, GstBuffer * buf);
 static GstStateChangeReturn gst_output_selector_change_state (GstElement *
     element, GstStateChange transition);
-static gboolean gst_output_selector_handle_sink_event (GstPad * pad,
+static gboolean gst_output_selector_event (GstPad * pad, GstObject * parent,
     GstEvent * event);
+static gboolean gst_output_selector_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static void gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector *
     sel, gint mode);
 
 static void
-gst_output_selector_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (element_class, "Output selector",
-      "Generic", "1-to-N output stream selector",
-      "Stefan Kost <stefan.kost@nokia.com>");
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_output_selector_sink_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_output_selector_src_factory));
-}
-
-static void
 gst_output_selector_class_init (GstOutputSelectorClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -152,6 +139,14 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass)
           DEFAULT_PAD_NEGOTIATION_MODE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_set_details_simple (gstelement_class, "Output selector",
+      "Generic", "1-to-N output stream selector",
+      "Stefan Kost <stefan.kost@nokia.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_output_selector_sink_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_output_selector_src_factory));
+
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_output_selector_request_new_pad);
   gstelement_class->release_pad =
@@ -161,8 +156,7 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass)
 }
 
 static void
-gst_output_selector_init (GstOutputSelector * sel,
-    GstOutputSelectorClass * g_class)
+gst_output_selector_init (GstOutputSelector * sel)
 {
   sel->sinkpad =
       gst_pad_new_from_static_template (&gst_output_selector_sink_factory,
@@ -170,9 +164,9 @@ gst_output_selector_init (GstOutputSelector * sel,
   gst_pad_set_chain_function (sel->sinkpad,
       GST_DEBUG_FUNCPTR (gst_output_selector_chain));
   gst_pad_set_event_function (sel->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_output_selector_handle_sink_event));
-  gst_pad_set_bufferalloc_function (sel->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_output_selector_buffer_alloc));
+      GST_DEBUG_FUNCPTR (gst_output_selector_event));
+  gst_pad_set_query_function (sel->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_output_selector_query));
 
   gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad);
 
@@ -291,41 +285,10 @@ gst_output_selector_get_property (GObject * object, guint prop_id,
   }
 }
 
-static GstCaps *
-gst_output_selector_sink_getcaps (GstPad * pad)
-{
-  GstOutputSelector *sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
-  GstPad *active = NULL;
-  GstCaps *caps = NULL;
-
-  if (G_UNLIKELY (sel == NULL))
-    return gst_caps_new_any ();
-
-  GST_OBJECT_LOCK (sel);
-  if (sel->pending_srcpad)
-    active = gst_object_ref (sel->pending_srcpad);
-  else if (sel->active_srcpad)
-    active = gst_object_ref (sel->active_srcpad);
-  GST_OBJECT_UNLOCK (sel);
-
-  if (active) {
-    caps = gst_pad_peer_get_caps_reffed (active);
-    gst_object_unref (active);
-  }
-  if (caps == NULL) {
-    caps = gst_caps_new_any ();
-  }
-
-  gst_object_unref (sel);
-  return caps;
-}
-
-static gboolean
-gst_output_selector_sink_setcaps (GstPad * pad, GstCaps * caps)
+static GstPad *
+gst_output_selector_get_active (GstOutputSelector * sel)
 {
-  GstOutputSelector *sel = GST_OUTPUT_SELECTOR (GST_PAD_PARENT (pad));
   GstPad *active = NULL;
-  gboolean ret = TRUE;
 
   GST_OBJECT_LOCK (sel);
   if (sel->pending_srcpad)
@@ -334,11 +297,7 @@ gst_output_selector_sink_setcaps (GstPad * pad, GstCaps * caps)
     active = gst_object_ref (sel->active_srcpad);
   GST_OBJECT_UNLOCK (sel);
 
-  if (active) {
-    ret = gst_pad_set_caps (active, caps);
-    gst_object_unref (active);
-  }
-  return ret;
+  return active;
 }
 
 static void
@@ -346,63 +305,21 @@ gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * sel,
     gint mode)
 {
   sel->pad_negotiation_mode = mode;
-  if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL) {
-    gst_pad_set_getcaps_function (sel->sinkpad, gst_pad_proxy_getcaps);
-    gst_pad_set_setcaps_function (sel->sinkpad, gst_pad_proxy_setcaps);
-  } else if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE) {
-    gst_pad_set_getcaps_function (sel->sinkpad, NULL);
-    gst_pad_set_setcaps_function (sel->sinkpad, NULL);
-  } else {                      /* active */
-    gst_pad_set_getcaps_function (sel->sinkpad,
-        gst_output_selector_sink_getcaps);
-    gst_pad_set_setcaps_function (sel->sinkpad,
-        gst_output_selector_sink_setcaps);
-  }
 }
 
-static GstFlowReturn
-gst_output_selector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
+static gboolean
+forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
 {
-  GstOutputSelector *sel;
-  GstFlowReturn res;
-  GstPad *allocpad;
+  GstPad *srcpad = GST_PAD_CAST (user_data);
 
-  sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL))
-    return GST_FLOW_WRONG_STATE;
+  gst_pad_push_event (srcpad, gst_event_ref (*event));
 
-  GST_OBJECT_LOCK (sel);
-  allocpad = sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad;
-  if (allocpad) {
-    /* if we had a previous pad we used for allocating a buffer, continue using
-     * it. */
-    GST_DEBUG_OBJECT (sel, "using pad %s:%s for alloc",
-        GST_DEBUG_PAD_NAME (allocpad));
-    gst_object_ref (allocpad);
-    GST_OBJECT_UNLOCK (sel);
-
-    res = gst_pad_alloc_buffer (allocpad, offset, size, caps, buf);
-    gst_object_unref (allocpad);
-
-    GST_OBJECT_LOCK (sel);
-  } else {
-    /* fallback case, allocate a buffer of our own, add pad caps. */
-    GST_DEBUG_OBJECT (pad, "fallback buffer alloc");
-    *buf = NULL;
-    res = GST_FLOW_OK;
-  }
-  GST_OBJECT_UNLOCK (sel);
-
-  GST_DEBUG_OBJECT (sel, "buffer alloc finished: %s", gst_flow_get_name (res));
-
-  gst_object_unref (sel);
-  return res;
+  return TRUE;
 }
 
 static GstPad *
 gst_output_selector_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name)
+    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
 {
   gchar *padname;
   GstPad *srcpad;
@@ -413,11 +330,15 @@ gst_output_selector_request_new_pad (GstElement * element,
   GST_DEBUG_OBJECT (osel, "requesting pad");
 
   GST_OBJECT_LOCK (osel);
-  padname = g_strdup_printf ("src%d", osel->nb_srcpads++);
+  padname = g_strdup_printf ("src_%u", osel->nb_srcpads++);
   srcpad = gst_pad_new_from_template (templ, padname);
   GST_OBJECT_UNLOCK (osel);
 
   gst_pad_set_active (srcpad, TRUE);
+
+  /* Forward sticky events to the new srcpad */
+  gst_pad_sticky_events_foreach (osel->sinkpad, forward_sticky_events, srcpad);
+
   gst_element_add_pad (GST_ELEMENT (osel), srcpad);
 
   /* Set the first requested src pad as active by default */
@@ -463,22 +384,24 @@ gst_output_selector_switch (GstOutputSelector * osel)
   osel->pending_srcpad = NULL;
   GST_OBJECT_UNLOCK (GST_OBJECT (osel));
 
-  /* Send NEWSEGMENT event and latest buffer if switching succeeded
+  /* Send SEGMENT event and latest buffer if switching succeeded
    * and we already have a valid segment configured */
   if (res) {
     if (osel->segment.format != GST_FORMAT_UNDEFINED) {
-      /* Send NEWSEGMENT to the pad we are going to switch to */
+      /* Send SEGMENT to the pad we are going to switch to */
       seg = &osel->segment;
-
-      /* If resending then mark newsegment start and position accordingly */
+      /* If resending then mark segment start and position accordingly */
       if (osel->resend_latest && osel->latest_buffer &&
           GST_BUFFER_TIMESTAMP_IS_VALID (osel->latest_buffer)) {
         start = position = GST_BUFFER_TIMESTAMP (osel->latest_buffer);
       } else {
-        start = position = seg->last_stop;
+        start = position = seg->position;
       }
-      ev = gst_event_new_new_segment (TRUE, seg->rate,
-          seg->format, start, seg->stop, position);
+
+      seg->start = start;
+      seg->position = position;
+      ev = gst_event_new_segment (seg);
+
       if (!gst_pad_push_event (osel->active_srcpad, ev)) {
         GST_WARNING_OBJECT (osel,
             "newsegment handling failed in %" GST_PTR_FORMAT,
@@ -499,13 +422,13 @@ gst_output_selector_switch (GstOutputSelector * osel)
 }
 
 static GstFlowReturn
-gst_output_selector_chain (GstPad * pad, GstBuffer * buf)
+gst_output_selector_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
   GstFlowReturn res;
   GstOutputSelector *osel;
-  GstClockTime last_stop, duration;
+  GstClockTime position, duration;
 
-  osel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
+  osel = GST_OUTPUT_SELECTOR (parent);
 
   /*
    * The _switch function might push a buffer if 'resend-latest' is true.
@@ -535,21 +458,20 @@ gst_output_selector_chain (GstPad * pad, GstBuffer * buf)
 
   /* Keep track of last stop and use it in NEWSEGMENT start after 
      switching to a new src pad */
-  last_stop = GST_BUFFER_TIMESTAMP (buf);
-  if (GST_CLOCK_TIME_IS_VALID (last_stop)) {
+  position = GST_BUFFER_TIMESTAMP (buf);
+  if (GST_CLOCK_TIME_IS_VALID (position)) {
     duration = GST_BUFFER_DURATION (buf);
     if (GST_CLOCK_TIME_IS_VALID (duration)) {
-      last_stop += duration;
+      position += duration;
     }
     GST_LOG_OBJECT (osel, "setting last stop %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (last_stop));
-    gst_segment_set_last_stop (&osel->segment, osel->segment.format, last_stop);
+        GST_TIME_ARGS (position));
+    osel->segment.position = position;
   }
 
   GST_LOG_OBJECT (osel, "pushing buffer to %" GST_PTR_FORMAT,
       osel->active_srcpad);
   res = gst_pad_push (osel->active_srcpad, buf);
-  gst_object_unref (osel);
 
   return res;
 }
@@ -584,54 +506,104 @@ gst_output_selector_change_state (GstElement * element,
 }
 
 static gboolean
-gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event)
+gst_output_selector_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
   GstOutputSelector *sel;
-  GstPad *output_pad = NULL;
+  GstPad *active = NULL;
 
-  sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (sel == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  sel = GST_OUTPUT_SELECTOR (parent);
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_CAPS:
     {
-      gboolean update;
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-
-      GST_DEBUG_OBJECT (sel,
-          "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-          "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-          G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
+      switch (sel->pad_negotiation_mode) {
+        case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL:
+          /* Send caps to all src pads */
+          res = gst_pad_event_default (pad, parent, event);
+          break;
+        case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE:
+          gst_event_unref (event);
+          break;
+        default:
+          active = gst_output_selector_get_active (sel);
+          if (active) {
+            res = gst_pad_push_event (active, event);
+            gst_object_unref (active);
+          } else {
+            gst_event_unref (event);
+          }
+          break;
+      }
+      break;
+    }
+    case GST_EVENT_SEGMENT:
+    {
+      gst_event_copy_segment (event, &sel->segment);
 
-      gst_segment_set_newsegment_full (&sel->segment, update,
-          rate, arate, format, start, stop, time);
+      GST_DEBUG_OBJECT (sel, "configured SEGMENT %" GST_SEGMENT_FORMAT,
+          &sel->segment);
 
       /* Send newsegment to all src pads */
-      gst_pad_event_default (pad, event);
+      res = gst_pad_event_default (pad, parent, event);
       break;
     }
     case GST_EVENT_EOS:
       /* Send eos to all src pads */
-      gst_pad_event_default (pad, event);
+      res = gst_pad_event_default (pad, parent, event);
       break;
     default:
+    {
       /* Send other events to pending or active src pad */
-      output_pad =
-          sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad;
-      res = gst_pad_push_event (output_pad, event);
+      active = gst_output_selector_get_active (sel);
+      if (active) {
+        res = gst_pad_push_event (active, event);
+        gst_object_unref (active);
+      } else {
+        gst_event_unref (event);
+      }
       break;
+    }
   }
 
-  gst_object_unref (sel);
+  return res;
+}
 
+static gboolean
+gst_output_selector_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  gboolean res = TRUE;
+  GstOutputSelector *sel;
+  GstPad *active = NULL;
+
+  sel = GST_OUTPUT_SELECTOR (parent);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+    {
+      switch (sel->pad_negotiation_mode) {
+        case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL:
+          /* Send caps to all src pads */
+          res = gst_pad_proxy_query_caps (pad, query);
+          break;
+        case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE:
+          res = FALSE;
+          break;
+        default:
+          active = gst_output_selector_get_active (sel);
+          if (active) {
+            res = gst_pad_peer_query (active, query);
+            gst_object_unref (active);
+          } else {
+            res = FALSE;
+          }
+          break;
+      }
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
   return res;
 }
index 25829d8..274017d 100644 (file)
@@ -128,7 +128,7 @@ enum
 #define DEFAULT_MAX_SIZE_TIME     GST_SECOND    /* 1 second    */
 
 #define GST_QUEUE_MUTEX_LOCK(q) G_STMT_START {                          \
-  g_mutex_lock (q->qlock);                                              \
+  g_mutex_lock (&q->qlock);                                              \
 } G_STMT_END
 
 #define GST_QUEUE_MUTEX_LOCK_CHECK(q,label) G_STMT_START {              \
@@ -138,13 +138,13 @@ enum
 } G_STMT_END
 
 #define GST_QUEUE_MUTEX_UNLOCK(q) G_STMT_START {                        \
-  g_mutex_unlock (q->qlock);                                            \
+  g_mutex_unlock (&q->qlock);                                            \
 } G_STMT_END
 
 #define GST_QUEUE_WAIT_DEL_CHECK(q, label) G_STMT_START {               \
   STATUS (q, q->sinkpad, "wait for DEL");                               \
   q->waiting_del = TRUE;                                                \
-  g_cond_wait (q->item_del, q->qlock);                                  \
+  g_cond_wait (&q->item_del, &q->qlock);                                  \
   q->waiting_del = FALSE;                                               \
   if (q->srcresult != GST_FLOW_OK) {                                    \
     STATUS (q, q->srcpad, "received DEL wakeup");                       \
@@ -156,7 +156,7 @@ enum
 #define GST_QUEUE_WAIT_ADD_CHECK(q, label) G_STMT_START {               \
   STATUS (q, q->srcpad, "wait for ADD");                                \
   q->waiting_add = TRUE;                                                \
-  g_cond_wait (q->item_add, q->qlock);                                  \
+  g_cond_wait (&q->item_add, &q->qlock);                                  \
   q->waiting_add = FALSE;                                               \
   if (q->srcresult != GST_FLOW_OK) {                                    \
     STATUS (q, q->srcpad, "received ADD wakeup");                       \
@@ -168,24 +168,23 @@ enum
 #define GST_QUEUE_SIGNAL_DEL(q) G_STMT_START {                          \
   if (q->waiting_del) {                                                 \
     STATUS (q, q->srcpad, "signal DEL");                                \
-    g_cond_signal (q->item_del);                                        \
+    g_cond_signal (&q->item_del);                                        \
   }                                                                     \
 } G_STMT_END
 
 #define GST_QUEUE_SIGNAL_ADD(q) G_STMT_START {                          \
   if (q->waiting_add) {                                                 \
     STATUS (q, q->sinkpad, "signal ADD");                               \
-    g_cond_signal (q->item_add);                                        \
+    g_cond_signal (&q->item_add);                                        \
   }                                                                     \
 } G_STMT_END
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (queue_debug, "queue", 0, "queue element"); \
     GST_DEBUG_CATEGORY_INIT (queue_dataflow, "queue_dataflow", 0, \
         "dataflow inside the queue element");
-
-GST_BOILERPLATE_FULL (GstQueue, gst_queue, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
+#define gst_queue_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstQueue, gst_queue, GST_TYPE_ELEMENT, _do_init);
 
 static void gst_queue_finalize (GObject * object);
 
@@ -194,25 +193,29 @@ static void gst_queue_set_property (GObject * object,
 static void gst_queue_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_queue_bufferalloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf);
+static GstFlowReturn gst_queue_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
 static GstFlowReturn gst_queue_push_one (GstQueue * queue);
 static void gst_queue_loop (GstPad * pad);
 
-static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_queue_handle_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_queue_handle_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_queue_handle_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_queue_handle_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-static gboolean gst_queue_acceptcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_queue_getcaps (GstPad * pad);
 static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
 static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer);
 static void gst_queue_locked_flush (GstQueue * queue);
 
-static gboolean gst_queue_src_activate_push (GstPad * pad, gboolean active);
-static gboolean gst_queue_sink_activate_push (GstPad * pad, gboolean active);
+static gboolean gst_queue_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
+static gboolean gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
 
 static gboolean gst_queue_is_empty (GstQueue * queue);
 static gboolean gst_queue_is_filled (GstQueue * queue);
@@ -240,23 +243,10 @@ queue_leaky_get_type (void)
 static guint gst_queue_signals[LAST_SIGNAL] = { 0 };
 
 static void
-gst_queue_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Queue",
-      "Generic", "Simple data queue", "Erik Walthinsen <omega@cse.ogi.edu>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-}
-
-static void
 gst_queue_class_init (GstQueueClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
   gobject_class->set_property = gst_queue_set_property;
   gobject_class->get_property = gst_queue_get_property;
@@ -375,44 +365,47 @@ gst_queue_class_init (GstQueueClass * klass)
 
   gobject_class->finalize = gst_queue_finalize;
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Queue",
+      "Generic", "Simple data queue", "Erik Walthinsen <omega@cse.ogi.edu>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   /* Registering debug symbols for function pointers */
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_sink_activate_push);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_mode);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_sink);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_getcaps);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_acceptcaps);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_bufferalloc);
-  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_push);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_src);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_query);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_event);
   GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain);
 }
 
 static void
-gst_queue_init (GstQueue * queue, GstQueueClass * g_class)
+gst_queue_init (GstQueue * queue)
 {
   queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
 
   gst_pad_set_chain_function (queue->sinkpad, gst_queue_chain);
-  gst_pad_set_activatepush_function (queue->sinkpad,
-      gst_queue_sink_activate_push);
+  gst_pad_set_activatemode_function (queue->sinkpad,
+      gst_queue_sink_activate_mode);
   gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event);
+  gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query);
   gst_pad_set_link_function (queue->sinkpad, gst_queue_link_sink);
-  gst_pad_set_getcaps_function (queue->sinkpad, gst_queue_getcaps);
-  gst_pad_set_acceptcaps_function (queue->sinkpad, gst_queue_acceptcaps);
-  gst_pad_set_bufferalloc_function (queue->sinkpad, gst_queue_bufferalloc);
+  GST_PAD_SET_PROXY_CAPS (queue->sinkpad);
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
 
   queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
 
-  gst_pad_set_activatepush_function (queue->srcpad,
-      gst_queue_src_activate_push);
+  gst_pad_set_activatemode_function (queue->srcpad,
+      gst_queue_src_activate_mode);
   gst_pad_set_link_function (queue->srcpad, gst_queue_link_src);
-  gst_pad_set_acceptcaps_function (queue->srcpad, gst_queue_acceptcaps);
-  gst_pad_set_getcaps_function (queue->srcpad, gst_queue_getcaps);
   gst_pad_set_event_function (queue->srcpad, gst_queue_handle_src_event);
   gst_pad_set_query_function (queue->srcpad, gst_queue_handle_src_query);
+  GST_PAD_SET_PROXY_CAPS (queue->srcpad);
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
 
   GST_QUEUE_CLEAR_LEVEL (queue->cur_level);
@@ -428,9 +421,9 @@ gst_queue_init (GstQueue * queue, GstQueueClass * g_class)
   queue->leaky = GST_QUEUE_NO_LEAK;
   queue->srcresult = GST_FLOW_WRONG_STATE;
 
-  queue->qlock = g_mutex_new ();
-  queue->item_add = g_cond_new ();
-  queue->item_del = g_cond_new ();
+  g_mutex_init (&queue->qlock);
+  g_cond_init (&queue->item_add);
+  g_cond_init (&queue->item_del);
 
   g_queue_init (&queue->queue);
 
@@ -459,53 +452,13 @@ gst_queue_finalize (GObject * object)
     gst_mini_object_unref (data);
 
   g_queue_clear (&queue->queue);
-  g_mutex_free (queue->qlock);
-  g_cond_free (queue->item_add);
-  g_cond_free (queue->item_del);
+  g_mutex_clear (&queue->qlock);
+  g_cond_clear (&queue->item_add);
+  g_cond_clear (&queue->item_del);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static gboolean
-gst_queue_acceptcaps (GstPad * pad, GstCaps * caps)
-{
-  gboolean result;
-  GstQueue *queue;
-  GstPad *otherpad;
-
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL))
-    return FALSE;
-
-  otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
-  result = gst_pad_peer_accept_caps (otherpad, caps);
-
-  gst_object_unref (queue);
-
-  return result;
-}
-
-static GstCaps *
-gst_queue_getcaps (GstPad * pad)
-{
-  GstQueue *queue;
-  GstPad *otherpad;
-  GstCaps *result;
-
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL))
-    return gst_caps_new_any ();
-
-  otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
-  result = gst_pad_peer_get_caps (otherpad);
-  if (result == NULL)
-    result = gst_caps_new_any ();
-
-  gst_object_unref (queue);
-
-  return result;
-}
-
 static GstPadLinkReturn
 gst_queue_link_sink (GstPad * pad, GstPad * peer)
 {
@@ -518,7 +471,7 @@ gst_queue_link_src (GstPad * pad, GstPad * peer)
   GstPadLinkReturn result = GST_PAD_LINK_OK;
   GstQueue *queue;
 
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
+  queue = GST_QUEUE (GST_PAD_PARENT (pad));
 
   GST_DEBUG_OBJECT (queue, "queue linking source pad");
 
@@ -538,26 +491,7 @@ gst_queue_link_src (GstPad * pad, GstPad * peer)
     }
     GST_QUEUE_MUTEX_UNLOCK (queue);
   }
-  gst_object_unref (queue);
-
-  return result;
-}
-
-static GstFlowReturn
-gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
-    GstBuffer ** buf)
-{
-  GstQueue *queue;
-  GstFlowReturn result;
-
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL))
-    return GST_FLOW_WRONG_STATE;
-
-  /* Forward to src pad, without setting caps on the src pad */
-  result = gst_pad_alloc_buffer (queue->srcpad, offset, size, caps, buf);
 
-  gst_object_unref (queue);
   return result;
 }
 
@@ -569,17 +503,19 @@ update_time_level (GstQueue * queue)
   gint64 sink_time, src_time;
 
   if (queue->sink_tainted) {
+    GST_LOG_OBJECT (queue, "update sink time");
     queue->sinktime =
         gst_segment_to_running_time (&queue->sink_segment, GST_FORMAT_TIME,
-        queue->sink_segment.last_stop);
+        queue->sink_segment.position);
     queue->sink_tainted = FALSE;
   }
   sink_time = queue->sinktime;
 
   if (queue->src_tainted) {
+    GST_LOG_OBJECT (queue, "update src time");
     queue->srctime =
         gst_segment_to_running_time (&queue->src_segment, GST_FORMAT_TIME,
-        queue->src_segment.last_stop);
+        queue->src_segment.position);
     queue->src_tainted = FALSE;
   }
   src_time = queue->srctime;
@@ -593,41 +529,30 @@ update_time_level (GstQueue * queue)
     queue->cur_level.time = 0;
 }
 
-/* take a NEWSEGMENT event and apply the values to segment, updating the time
+/* take a SEGMENT event and apply the values to segment, updating the time
  * level of queue. */
 static void
 apply_segment (GstQueue * queue, GstEvent * event, GstSegment * segment,
     gboolean sink)
 {
-  gboolean update;
-  GstFormat format;
-  gdouble rate, arate;
-  gint64 start, stop, time;
-
-  gst_event_parse_new_segment_full (event, &update, &rate, &arate,
-      &format, &start, &stop, &time);
+  gst_event_copy_segment (event, segment);
 
   /* now configure the values, we use these to track timestamps on the
    * sinkpad. */
-  if (format != GST_FORMAT_TIME) {
+  if (segment->format != GST_FORMAT_TIME) {
     /* non-time format, pretent the current time segment is closed with a
      * 0 start and unknown stop time. */
-    update = FALSE;
-    format = GST_FORMAT_TIME;
-    start = 0;
-    stop = -1;
-    time = 0;
+    segment->format = GST_FORMAT_TIME;
+    segment->start = 0;
+    segment->stop = -1;
+    segment->time = 0;
   }
-  gst_segment_set_newsegment_full (segment, update,
-      rate, arate, format, start, stop, time);
-
   if (sink)
     queue->sink_tainted = TRUE;
   else
     queue->src_tainted = TRUE;
 
-  GST_DEBUG_OBJECT (queue,
-      "configured NEWSEGMENT %" GST_SEGMENT_FORMAT, segment);
+  GST_DEBUG_OBJECT (queue, "configured SEGMENT %" GST_SEGMENT_FORMAT, segment);
 
   /* segment can update the time level of the queue */
   update_time_level (queue);
@@ -646,16 +571,16 @@ apply_buffer (GstQueue * queue, GstBuffer * buffer, GstSegment * segment,
   /* if no timestamp is set, assume it's continuous with the previous
    * time */
   if (timestamp == GST_CLOCK_TIME_NONE)
-    timestamp = segment->last_stop;
+    timestamp = segment->position;
 
   /* add duration */
   if (with_duration && duration != GST_CLOCK_TIME_NONE)
     timestamp += duration;
 
-  GST_LOG_OBJECT (queue, "last_stop updated to %" GST_TIME_FORMAT,
+  GST_LOG_OBJECT (queue, "position updated to %" GST_TIME_FORMAT,
       GST_TIME_ARGS (timestamp));
 
-  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, timestamp);
+  segment->position = timestamp;
   if (sink)
     queue->sink_tainted = TRUE;
   else
@@ -699,7 +624,7 @@ gst_queue_locked_enqueue_buffer (GstQueue * queue, gpointer item)
 
   /* add buffer to the statistics */
   queue->cur_level.buffers++;
-  queue->cur_level.bytes += GST_BUFFER_SIZE (buffer);
+  queue->cur_level.bytes += gst_buffer_get_size (buffer);
   apply_buffer (queue, buffer, &queue->sink_segment, TRUE, TRUE);
 
   g_queue_push_tail (&queue->queue, item);
@@ -720,7 +645,7 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item)
       GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from upstream");
       queue->eos = TRUE;
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       apply_segment (queue, event, &queue->sink_segment, TRUE);
       /* if the queue is empty, apply sink segment on the source */
       if (queue->queue.length == 0) {
@@ -728,7 +653,7 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item)
         apply_segment (queue, event, &queue->src_segment, FALSE);
         queue->newseg_applied_to_src = TRUE;
       }
-      /* a new segment allows us to accept more buffers if we got UNEXPECTED
+      /* a new segment allows us to accept more buffers if we got EOS
        * from downstream */
       queue->unexpected = FALSE;
       break;
@@ -757,7 +682,7 @@ gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer)
         "retrieved buffer %p from queue", buffer);
 
     queue->cur_level.buffers--;
-    queue->cur_level.bytes -= GST_BUFFER_SIZE (buffer);
+    queue->cur_level.bytes -= gst_buffer_get_size (buffer);
     apply_buffer (queue, buffer, &queue->src_segment, TRUE, FALSE);
 
     /* if the queue is empty now, update the other side */
@@ -776,7 +701,7 @@ gst_queue_locked_dequeue (GstQueue * queue, gboolean * is_buffer)
         /* queue is empty now that we dequeued the EOS */
         GST_QUEUE_CLEAR_LEVEL (queue->cur_level);
         break;
-      case GST_EVENT_NEWSEGMENT:
+      case GST_EVENT_SEGMENT:
         /* apply newsegment if it has not already been applied */
         if (G_LIKELY (!queue->newseg_applied_to_src)) {
           apply_segment (queue, event, &queue->src_segment, FALSE);
@@ -808,15 +733,11 @@ no_item:
 }
 
 static gboolean
-gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
+gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstQueue *queue;
 
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  queue = GST_QUEUE (parent);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_START:
@@ -877,7 +798,6 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
       break;
   }
 done:
-  gst_object_unref (queue);
   return TRUE;
 
   /* ERRORS */
@@ -886,7 +806,6 @@ out_flushing:
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
         "refusing event, we are flushing");
     GST_QUEUE_MUTEX_UNLOCK (queue);
-    gst_object_unref (queue);
     gst_event_unref (event);
     return FALSE;
   }
@@ -894,13 +813,25 @@ out_eos:
   {
     GST_CAT_LOG_OBJECT (queue_dataflow, queue, "refusing event, we are EOS");
     GST_QUEUE_MUTEX_UNLOCK (queue);
-    gst_object_unref (queue);
     gst_event_unref (event);
     return FALSE;
   }
 }
 
 static gboolean
+gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  gboolean res;
+
+  switch (GST_QUERY_TYPE (query)) {
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
+  return res;
+}
+
+static gboolean
 gst_queue_is_empty (GstQueue * queue)
 {
   if (queue->queue.length == 0)
@@ -951,12 +882,12 @@ gst_queue_leak_downstream (GstQueue * queue)
 }
 
 static GstFlowReturn
-gst_queue_chain (GstPad * pad, GstBuffer * buffer)
+gst_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstQueue *queue;
   GstClockTime duration, timestamp;
 
-  queue = (GstQueue *) GST_OBJECT_PARENT (pad);
+  queue = GST_QUEUE_CAST (parent);
 
   /* we have to lock the queue since we span threads */
   GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing);
@@ -969,9 +900,9 @@ gst_queue_chain (GstPad * pad, GstBuffer * buffer)
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   duration = GST_BUFFER_DURATION (buffer);
 
-  GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-      "received buffer %p of size %d, time %" GST_TIME_FORMAT ", duration %"
-      GST_TIME_FORMAT, buffer, GST_BUFFER_SIZE (buffer),
+  GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of size %"
+      G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %"
+      GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer),
       GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
 
   /* We make space available if we're "full" according to whatever
@@ -1027,7 +958,7 @@ gst_queue_chain (GstPad * pad, GstBuffer * buffer)
   }
 
   if (queue->tail_needs_discont) {
-    GstBuffer *subbuffer = gst_buffer_make_metadata_writable (buffer);
+    GstBuffer *subbuffer = gst_buffer_make_writable (buffer);
 
     if (subbuffer) {
       buffer = subbuffer;
@@ -1071,38 +1002,25 @@ out_eos:
 
     gst_buffer_unref (buffer);
 
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 out_unexpected:
   {
-    GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because we received UNEXPECTED");
+    GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS");
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
     gst_buffer_unref (buffer);
 
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
 static void
 gst_queue_push_newsegment (GstQueue * queue)
 {
-  GstSegment *s;
   GstEvent *event;
 
-  s = &queue->src_segment;
-
-  if (s->accum != 0) {
-    event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, s->format, 0,
-        s->accum, 0);
-    GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "pushing accum newsegment event");
-    gst_pad_push_event (queue->srcpad, event);
-  }
-
-  event = gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
-      s->format, s->start, s->stop, s->time);
+  event = gst_event_new_segment (&queue->src_segment);
   GST_CAT_LOG_OBJECT (queue_dataflow, queue, "pushing real newsegment event");
   gst_pad_push_event (queue->srcpad, event);
 }
@@ -1123,12 +1041,11 @@ gst_queue_push_one (GstQueue * queue)
 next:
   if (is_buffer) {
     GstBuffer *buffer;
-    GstCaps *caps;
 
     buffer = GST_BUFFER_CAST (data);
 
     if (queue->head_needs_discont) {
-      GstBuffer *subbuffer = gst_buffer_make_metadata_writable (buffer);
+      GstBuffer *subbuffer = gst_buffer_make_writable (buffer);
 
       if (subbuffer) {
         buffer = subbuffer;
@@ -1139,17 +1056,7 @@ next:
       queue->head_needs_discont = FALSE;
     }
 
-    caps = GST_BUFFER_CAPS (buffer);
-
     GST_QUEUE_MUTEX_UNLOCK (queue);
-    /* set the right caps on the pad now. We do this before pushing the buffer
-     * because the pad_push call will check (using acceptcaps) if the buffer can
-     * be set on the pad, which might fail because this will be propagated
-     * upstream. Also note that if the buffer has NULL caps, it means that the
-     * caps did not change, so we don't have to change caps on the pad. */
-    if (caps && caps != GST_PAD_CAPS (queue->srcpad))
-      gst_pad_set_caps (queue->srcpad, caps);
-
     if (queue->push_newsegment) {
       gst_queue_push_newsegment (queue);
     }
@@ -1158,37 +1065,36 @@ next:
     /* need to check for srcresult here as well */
     GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing);
 
-    if (result == GST_FLOW_UNEXPECTED) {
-      GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "got UNEXPECTED from downstream");
+    if (result == GST_FLOW_EOS) {
+      GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream");
       /* stop pushing buffers, we dequeue all items until we see an item that we
-       * can push again, which is EOS or NEWSEGMENT. If there is nothing in the
+       * can push again, which is EOS or SEGMENT. If there is nothing in the
        * queue we can push, we set a flag to make the sinkpad refuse more
-       * buffers with an UNEXPECTED return value. */
+       * buffers with an EOS return value. */
       while ((data = gst_queue_locked_dequeue (queue, &is_buffer))) {
         if (is_buffer) {
           GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-              "dropping UNEXPECTED buffer %p", data);
+              "dropping EOS buffer %p", data);
           gst_buffer_unref (GST_BUFFER_CAST (data));
         } else {
           GstEvent *event = GST_EVENT_CAST (data);
           GstEventType type = GST_EVENT_TYPE (event);
 
-          if (type == GST_EVENT_EOS || type == GST_EVENT_NEWSEGMENT) {
+          if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT) {
             /* we found a pushable item in the queue, push it out */
             GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-                "pushing pushable event %s after UNEXPECTED",
+                "pushing pushable event %s after EOS",
                 GST_EVENT_TYPE_NAME (event));
             goto next;
           }
           GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-              "dropping UNEXPECTED event %p", event);
+              "dropping EOS event %p", event);
           gst_event_unref (event);
         }
       }
       /* no more items in the queue. Set the unexpected flag so that upstream
        * make us refuse any more buffers on the sinkpad. Since we will still
-       * accept EOS and NEWSEGMENT we return _FLOW_OK to the caller so that the
+       * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the
        * task function does not shut down. */
       queue->unexpected = TRUE;
       result = GST_FLOW_OK;
@@ -1199,17 +1105,17 @@ next:
 
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
-    if (queue->push_newsegment && type != GST_EVENT_NEWSEGMENT) {
+    if (queue->push_newsegment && type != GST_EVENT_SEGMENT) {
       gst_queue_push_newsegment (queue);
     }
     gst_pad_push_event (queue->srcpad, event);
 
     GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing);
-    /* if we're EOS, return UNEXPECTED so that the task pauses. */
+    /* if we're EOS, return EOS so that the task pauses. */
     if (type == GST_EVENT_EOS) {
       GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "pushed EOS event %p, return UNEXPECTED", event);
-      result = GST_FLOW_UNEXPECTED;
+          "pushed EOS event %p, return EOS", event);
+      result = GST_FLOW_EOS;
     }
   }
   return result;
@@ -1283,8 +1189,8 @@ out_flushing:
     GST_QUEUE_SIGNAL_DEL (queue);
     GST_QUEUE_MUTEX_UNLOCK (queue);
     /* let app know about us giving up if upstream is not expected to do so */
-    /* UNEXPECTED is already taken care of elsewhere */
-    if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED)) {
+    /* EOS is already taken care of elsewhere */
+    if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) {
       GST_ELEMENT_ERROR (queue, STREAM, FAILED,
           (_("Internal data flow error.")),
           ("streaming task paused, reason %s (%d)",
@@ -1296,15 +1202,11 @@ out_flushing:
 }
 
 static gboolean
-gst_queue_handle_src_event (GstPad * pad, GstEvent * event)
+gst_queue_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
-  GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
+  GstQueue *queue = GST_QUEUE (parent);
 
-  if (G_UNLIKELY (queue == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
 #ifndef GST_DISABLE_GST_DEBUG
   GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%d)",
       event, GST_EVENT_TYPE (event));
@@ -1312,31 +1214,18 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event)
 
   res = gst_pad_push_event (queue->sinkpad, event);
 
-  gst_object_unref (queue);
   return res;
 }
 
 static gboolean
-gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
+gst_queue_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
-  GstPad *peer;
+  GstQueue *queue = GST_QUEUE (parent);
   gboolean res;
 
-  if (G_UNLIKELY (queue == NULL))
-    return FALSE;
-
-  if (!(peer = gst_pad_get_peer (queue->sinkpad))) {
-    gst_object_unref (queue);
+  res = gst_pad_peer_query (queue->sinkpad, query);
+  if (!res)
     return FALSE;
-  }
-
-  res = gst_pad_query (peer, query);
-  gst_object_unref (peer);
-  if (!res) {
-    gst_object_unref (queue);
-    return FALSE;
-  }
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
@@ -1392,72 +1281,83 @@ gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
       break;
   }
 
-  gst_object_unref (queue);
   return TRUE;
 }
 
 static gboolean
-gst_queue_sink_activate_push (GstPad * pad, gboolean active)
+gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
+    gboolean active)
 {
-  gboolean result = TRUE;
+  gboolean result;
   GstQueue *queue;
 
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
+  queue = GST_QUEUE (parent);
 
-  if (active) {
-    GST_QUEUE_MUTEX_LOCK (queue);
-    queue->srcresult = GST_FLOW_OK;
-    queue->eos = FALSE;
-    queue->unexpected = FALSE;
-    GST_QUEUE_MUTEX_UNLOCK (queue);
-  } else {
-    /* step 1, unblock chain function */
-    GST_QUEUE_MUTEX_LOCK (queue);
-    queue->srcresult = GST_FLOW_WRONG_STATE;
-    gst_queue_locked_flush (queue);
-    GST_QUEUE_MUTEX_UNLOCK (queue);
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        GST_QUEUE_MUTEX_LOCK (queue);
+        queue->srcresult = GST_FLOW_OK;
+        queue->eos = FALSE;
+        queue->unexpected = FALSE;
+        GST_QUEUE_MUTEX_UNLOCK (queue);
+      } else {
+        /* step 1, unblock chain function */
+        GST_QUEUE_MUTEX_LOCK (queue);
+        queue->srcresult = GST_FLOW_WRONG_STATE;
+        gst_queue_locked_flush (queue);
+        GST_QUEUE_MUTEX_UNLOCK (queue);
+      }
+      result = TRUE;
+      break;
+    default:
+      result = FALSE;
+      break;
   }
-
-  gst_object_unref (queue);
-
   return result;
 }
 
 static gboolean
-gst_queue_src_activate_push (GstPad * pad, gboolean active)
+gst_queue_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
+    gboolean active)
 {
-  gboolean result = FALSE;
+  gboolean result;
   GstQueue *queue;
 
-  queue = GST_QUEUE (gst_pad_get_parent (pad));
-
-  if (active) {
-    GST_QUEUE_MUTEX_LOCK (queue);
-    queue->srcresult = GST_FLOW_OK;
-    queue->eos = FALSE;
-    queue->unexpected = FALSE;
-    /* we do not start the task yet if the pad is not connected */
-    if (gst_pad_is_linked (pad))
-      result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
-    else {
-      GST_INFO_OBJECT (queue, "not starting task as pad is not linked");
-      result = TRUE;
-    }
-    GST_QUEUE_MUTEX_UNLOCK (queue);
-  } else {
-    /* step 1, unblock loop function */
-    GST_QUEUE_MUTEX_LOCK (queue);
-    queue->srcresult = GST_FLOW_WRONG_STATE;
-    /* the item add signal will unblock */
-    g_cond_signal (queue->item_add);
-    GST_QUEUE_MUTEX_UNLOCK (queue);
+  queue = GST_QUEUE (parent);
+
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        GST_QUEUE_MUTEX_LOCK (queue);
+        queue->srcresult = GST_FLOW_OK;
+        queue->eos = FALSE;
+        queue->unexpected = FALSE;
+        /* we do not start the task yet if the pad is not connected */
+        if (gst_pad_is_linked (pad))
+          result =
+              gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+        else {
+          GST_INFO_OBJECT (queue, "not starting task as pad is not linked");
+          result = TRUE;
+        }
+        GST_QUEUE_MUTEX_UNLOCK (queue);
+      } else {
+        /* step 1, unblock loop function */
+        GST_QUEUE_MUTEX_LOCK (queue);
+        queue->srcresult = GST_FLOW_WRONG_STATE;
+        /* the item add signal will unblock */
+        g_cond_signal (&queue->item_add);
+        GST_QUEUE_MUTEX_UNLOCK (queue);
 
-    /* step 2, make sure streaming finishes */
-    result = gst_pad_stop_task (pad);
+        /* step 2, make sure streaming finishes */
+        result = gst_pad_stop_task (pad);
+      }
+      break;
+    default:
+      result = FALSE;
+      break;
   }
-
-  gst_object_unref (queue);
-
   return result;
 }
 
index 9af6e14..3b0752c 100644 (file)
@@ -38,6 +38,8 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QUEUE))
 #define GST_IS_QUEUE_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE))
+#define GST_QUEUE_CAST(obj) \
+  ((GstQueue *)(obj))
 
 typedef struct _GstQueue GstQueue;
 typedef struct _GstQueueSize GstQueueSize;
@@ -116,11 +118,11 @@ struct _GstQueue {
   /* whether we leak data, and at which end */
   gint leaky;
 
-  GMutex *qlock;        /* lock for queue (vs object lock) */
+  GMutex qlock;        /* lock for queue (vs object lock) */
   gboolean waiting_add;
-  GCond *item_add;      /* signals buffers now available for reading */
+  GCond item_add;      /* signals buffers now available for reading */
   gboolean waiting_del;
-  GCond *item_del;      /* signals space now available for writing */
+  GCond item_del;      /* signals space now available for writing */
 
   gboolean head_needs_discont, tail_needs_discont;
   gboolean push_newsegment;
index 8c4e4cc..6b761fc 100644 (file)
@@ -159,7 +159,7 @@ enum
                         queue->queue.length))
 
 #define GST_QUEUE2_MUTEX_LOCK(q) G_STMT_START {                          \
-  g_mutex_lock (q->qlock);                                              \
+  g_mutex_lock (&q->qlock);                                              \
 } G_STMT_END
 
 #define GST_QUEUE2_MUTEX_LOCK_CHECK(q,res,label) G_STMT_START {         \
@@ -169,13 +169,13 @@ enum
 } G_STMT_END
 
 #define GST_QUEUE2_MUTEX_UNLOCK(q) G_STMT_START {                        \
-  g_mutex_unlock (q->qlock);                                            \
+  g_mutex_unlock (&q->qlock);                                            \
 } G_STMT_END
 
 #define GST_QUEUE2_WAIT_DEL_CHECK(q, res, label) G_STMT_START {         \
   STATUS (queue, q->sinkpad, "wait for DEL");                           \
   q->waiting_del = TRUE;                                                \
-  g_cond_wait (q->item_del, queue->qlock);                              \
+  g_cond_wait (&q->item_del, &queue->qlock);                              \
   q->waiting_del = FALSE;                                               \
   if (res != GST_FLOW_OK) {                                             \
     STATUS (queue, q->srcpad, "received DEL wakeup");                   \
@@ -187,7 +187,7 @@ enum
 #define GST_QUEUE2_WAIT_ADD_CHECK(q, res, label) G_STMT_START {         \
   STATUS (queue, q->srcpad, "wait for ADD");                            \
   q->waiting_add = TRUE;                                                \
-  g_cond_wait (q->item_add, q->qlock);                                  \
+  g_cond_wait (&q->item_add, &q->qlock);                                  \
   q->waiting_add = FALSE;                                               \
   if (res != GST_FLOW_OK) {                                             \
     STATUS (queue, q->srcpad, "received ADD wakeup");                   \
@@ -199,24 +199,23 @@ enum
 #define GST_QUEUE2_SIGNAL_DEL(q) G_STMT_START {                          \
   if (q->waiting_del) {                                                 \
     STATUS (q, q->srcpad, "signal DEL");                                \
-    g_cond_signal (q->item_del);                                        \
+    g_cond_signal (&q->item_del);                                        \
   }                                                                     \
 } G_STMT_END
 
 #define GST_QUEUE2_SIGNAL_ADD(q) G_STMT_START {                          \
   if (q->waiting_add) {                                                 \
     STATUS (q, q->sinkpad, "signal ADD");                               \
-    g_cond_signal (q->item_add);                                        \
+    g_cond_signal (&q->item_add);                                        \
   }                                                                     \
 } G_STMT_END
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (queue_debug, "queue2", 0, "queue element"); \
     GST_DEBUG_CATEGORY_INIT (queue_dataflow, "queue2_dataflow", 0, \
         "dataflow inside the queue element");
-
-GST_BOILERPLATE_FULL (GstQueue2, gst_queue2, GstElement, GST_TYPE_ELEMENT,
-    _do_init);
+#define gst_queue2_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstQueue2, gst_queue2, GST_TYPE_ELEMENT, _do_init);
 
 static void gst_queue2_finalize (GObject * object);
 
@@ -225,31 +224,32 @@ static void gst_queue2_set_property (GObject * object,
 static void gst_queue2_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-static GstFlowReturn gst_queue2_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_queue2_chain_list (GstPad * pad,
+static GstFlowReturn gst_queue2_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static GstFlowReturn gst_queue2_chain_list (GstPad * pad, GstObject * parent,
     GstBufferList * buffer_list);
-static GstFlowReturn gst_queue2_bufferalloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf);
 static GstFlowReturn gst_queue2_push_one (GstQueue2 * queue);
 static void gst_queue2_loop (GstPad * pad);
 
-static gboolean gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-static gboolean gst_queue2_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_queue2_handle_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_queue2_handle_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_queue2_handle_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static gboolean gst_queue2_handle_query (GstElement * element,
     GstQuery * query);
 
-static GstCaps *gst_queue2_getcaps (GstPad * pad);
-static gboolean gst_queue2_acceptcaps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_queue2_get_range (GstPad * pad, GstObject * parent,
+    guint64 offset, guint length, GstBuffer ** buffer);
 
-static GstFlowReturn gst_queue2_get_range (GstPad * pad, guint64 offset,
-    guint length, GstBuffer ** buffer);
-static gboolean gst_queue2_src_checkgetrange_function (GstPad * pad);
-
-static gboolean gst_queue2_src_activate_pull (GstPad * pad, gboolean active);
-static gboolean gst_queue2_src_activate_push (GstPad * pad, gboolean active);
-static gboolean gst_queue2_sink_activate_push (GstPad * pad, gboolean active);
+static gboolean gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
+static gboolean gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
 static GstStateChangeReturn gst_queue2_change_state (GstElement * element,
     GstStateChange transition);
 
@@ -269,23 +269,6 @@ typedef enum
 /* static guint gst_queue2_signals[LAST_SIGNAL] = { 0 }; */
 
 static void
-gst_queue2_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-
-  gst_element_class_set_details_simple (gstelement_class, "Queue 2",
-      "Generic",
-      "Simple data queue",
-      "Erik Walthinsen <omega@cse.ogi.edu>, "
-      "Wim Taymans <wim.taymans@gmail.com>");
-}
-
-static void
 gst_queue2_class_init (GstQueue2Class * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -385,12 +368,23 @@ gst_queue2_class_init (GstQueue2Class * klass)
   /* set several parent class virtual functions */
   gobject_class->finalize = gst_queue2_finalize;
 
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
+  gst_element_class_set_details_simple (gstelement_class, "Queue 2",
+      "Generic",
+      "Simple data queue",
+      "Erik Walthinsen <omega@cse.ogi.edu>, "
+      "Wim Taymans <wim.taymans@gmail.com>");
+
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_queue2_change_state);
   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_queue2_handle_query);
 }
 
 static void
-gst_queue2_init (GstQueue2 * queue, GstQueue2Class * g_class)
+gst_queue2_init (GstQueue2 * queue)
 {
   queue->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
 
@@ -398,36 +392,26 @@ gst_queue2_init (GstQueue2 * queue, GstQueue2Class * g_class)
       GST_DEBUG_FUNCPTR (gst_queue2_chain));
   gst_pad_set_chain_list_function (queue->sinkpad,
       GST_DEBUG_FUNCPTR (gst_queue2_chain_list));
-  gst_pad_set_activatepush_function (queue->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_push));
+  gst_pad_set_activatemode_function (queue->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_mode));
   gst_pad_set_event_function (queue->sinkpad,
       GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event));
-  gst_pad_set_getcaps_function (queue->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_getcaps));
-  gst_pad_set_acceptcaps_function (queue->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_acceptcaps));
-  gst_pad_set_bufferalloc_function (queue->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_bufferalloc));
+  gst_pad_set_query_function (queue->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query));
+  GST_OBJECT_FLAG_SET (queue->sinkpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
 
   queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
 
-  gst_pad_set_activatepull_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_src_activate_pull));
-  gst_pad_set_activatepush_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_src_activate_push));
+  gst_pad_set_activatemode_function (queue->srcpad,
+      GST_DEBUG_FUNCPTR (gst_queue2_src_activate_mode));
   gst_pad_set_getrange_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue2_get_range));
-  gst_pad_set_checkgetrange_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_src_checkgetrange_function));
-  gst_pad_set_getcaps_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_getcaps));
-  gst_pad_set_acceptcaps_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue2_acceptcaps));
   gst_pad_set_event_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue2_handle_src_event));
   gst_pad_set_query_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue2_handle_src_query));
+  GST_OBJECT_FLAG_SET (queue->srcpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
 
   /* levels */
@@ -455,11 +439,11 @@ gst_queue2_init (GstQueue2 * queue, GstQueue2Class * g_class)
   queue->in_timer = g_timer_new ();
   queue->out_timer = g_timer_new ();
 
-  queue->qlock = g_mutex_new ();
+  g_mutex_init (&queue->qlock);
   queue->waiting_add = FALSE;
-  queue->item_add = g_cond_new ();
+  g_cond_init (&queue->item_add);
   queue->waiting_del = FALSE;
-  queue->item_del = g_cond_new ();
+  g_cond_init (&queue->item_del);
   g_queue_init (&queue->queue);
 
   queue->buffering_percent = 100;
@@ -492,9 +476,9 @@ gst_queue2_finalize (GObject * object)
   }
 
   g_queue_clear (&queue->queue);
-  g_mutex_free (queue->qlock);
-  g_cond_free (queue->item_add);
-  g_cond_free (queue->item_del);
+  g_mutex_clear (&queue->qlock);
+  g_cond_clear (&queue->item_add);
+  g_cond_clear (&queue->item_del);
   g_timer_destroy (queue->in_timer);
   g_timer_destroy (queue->out_timer);
 
@@ -638,57 +622,6 @@ init_ranges (GstQueue2 * queue)
   queue->current = add_range (queue, 0);
 }
 
-static gboolean
-gst_queue2_acceptcaps (GstPad * pad, GstCaps * caps)
-{
-  GstQueue2 *queue;
-  GstPad *otherpad;
-  gboolean result;
-
-  queue = GST_QUEUE2 (GST_PAD_PARENT (pad));
-
-  otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
-  result = gst_pad_peer_accept_caps (otherpad, caps);
-
-  return result;
-}
-
-static GstCaps *
-gst_queue2_getcaps (GstPad * pad)
-{
-  GstQueue2 *queue;
-  GstPad *otherpad;
-  GstCaps *result;
-
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL))
-    return gst_caps_new_any ();
-
-  otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
-  result = gst_pad_peer_get_caps (otherpad);
-  if (result == NULL)
-    result = gst_caps_new_any ();
-
-  gst_object_unref (queue);
-
-  return result;
-}
-
-static GstFlowReturn
-gst_queue2_bufferalloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstQueue2 *queue;
-  GstFlowReturn result;
-
-  queue = GST_QUEUE2 (GST_PAD_PARENT (pad));
-
-  /* Forward to src pad, without setting caps on the src pad */
-  result = gst_pad_alloc_buffer (queue->srcpad, offset, size, caps, buf);
-
-  return result;
-}
-
 /* calculate the diff between running time on the sink and src of the queue.
  * This is the total amount of time in the queue. */
 static void
@@ -697,14 +630,14 @@ update_time_level (GstQueue2 * queue)
   if (queue->sink_tainted) {
     queue->sinktime =
         gst_segment_to_running_time (&queue->sink_segment, GST_FORMAT_TIME,
-        queue->sink_segment.last_stop);
+        queue->sink_segment.position);
     queue->sink_tainted = FALSE;
   }
 
   if (queue->src_tainted) {
     queue->srctime =
         gst_segment_to_running_time (&queue->src_segment, GST_FORMAT_TIME,
-        queue->src_segment.last_stop);
+        queue->src_segment.position);
     queue->src_tainted = FALSE;
   }
 
@@ -719,30 +652,18 @@ update_time_level (GstQueue2 * queue)
     queue->cur_level.time = 0;
 }
 
-/* take a NEWSEGMENT event and apply the values to segment, updating the time
+/* take a SEGMENT event and apply the values to segment, updating the time
  * level of queue. */
 static void
 apply_segment (GstQueue2 * queue, GstEvent * event, GstSegment * segment,
     gboolean is_sink)
 {
-  gboolean update;
-  GstFormat format;
-  gdouble rate, arate;
-  gint64 start, stop, time;
-
-  gst_event_parse_new_segment_full (event, &update, &rate, &arate,
-      &format, &start, &stop, &time);
-
-  GST_DEBUG_OBJECT (queue,
-      "received NEWSEGMENT update %d, rate %lf, applied rate %lf, "
-      "format %d, "
-      "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-      G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
+  gst_event_copy_segment (event, segment);
 
-  if (format == GST_FORMAT_BYTES) {
+  if (segment->format == GST_FORMAT_BYTES) {
     if (QUEUE_IS_USING_TEMP_FILE (queue)) {
       /* start is where we'll be getting from and as such writing next */
-      queue->current = add_range (queue, start);
+      queue->current = add_range (queue, segment->start);
       /* update the stats for this range */
       update_cur_level (queue, queue->current);
     }
@@ -750,20 +671,16 @@ apply_segment (GstQueue2 * queue, GstEvent * event, GstSegment * segment,
 
   /* now configure the values, we use these to track timestamps on the
    * sinkpad. */
-  if (format != GST_FORMAT_TIME) {
+  if (segment->format != GST_FORMAT_TIME) {
     /* non-time format, pretent the current time segment is closed with a
      * 0 start and unknown stop time. */
-    update = FALSE;
-    format = GST_FORMAT_TIME;
-    start = 0;
-    stop = -1;
-    time = 0;
+    segment->format = GST_FORMAT_TIME;
+    segment->start = 0;
+    segment->stop = -1;
+    segment->time = 0;
   }
-  gst_segment_set_newsegment_full (segment, update,
-      rate, arate, format, start, stop, time);
 
-  GST_DEBUG_OBJECT (queue,
-      "configured NEWSEGMENT %" GST_SEGMENT_FORMAT, segment);
+  GST_DEBUG_OBJECT (queue, "configured SEGMENT %" GST_SEGMENT_FORMAT, segment);
 
   if (is_sink)
     queue->sink_tainted = TRUE;
@@ -787,16 +704,16 @@ apply_buffer (GstQueue2 * queue, GstBuffer * buffer, GstSegment * segment,
   /* if no timestamp is set, assume it's continuous with the previous
    * time */
   if (timestamp == GST_CLOCK_TIME_NONE)
-    timestamp = segment->last_stop;
+    timestamp = segment->position;
 
   /* add duration */
   if (duration != GST_CLOCK_TIME_NONE)
     timestamp += duration;
 
-  GST_DEBUG_OBJECT (queue, "last_stop updated to %" GST_TIME_FORMAT,
+  GST_DEBUG_OBJECT (queue, "position updated to %" GST_TIME_FORMAT,
       GST_TIME_ARGS (timestamp));
 
-  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, timestamp);
+  segment->position = timestamp;
 
   if (is_sink)
     queue->sink_tainted = TRUE;
@@ -807,13 +724,13 @@ apply_buffer (GstQueue2 * queue, GstBuffer * buffer, GstSegment * segment,
   update_time_level (queue);
 }
 
-static GstBufferListItem
-buffer_list_apply_time (GstBuffer ** buf, guint group, guint idx, gpointer data)
+static gboolean
+buffer_list_apply_time (GstBuffer ** buf, guint idx, gpointer data)
 {
   GstClockTime *timestamp = data;
 
-  GST_TRACE ("buffer %u in group %u has ts %" GST_TIME_FORMAT
-      " duration %" GST_TIME_FORMAT, idx, group,
+  GST_TRACE ("buffer %u has ts %" GST_TIME_FORMAT
+      " duration %" GST_TIME_FORMAT, idx,
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (*buf)));
 
@@ -824,7 +741,7 @@ buffer_list_apply_time (GstBuffer ** buf, guint group, guint idx, gpointer data)
     *timestamp += GST_BUFFER_DURATION (*buf);
 
   GST_TRACE ("ts now %" GST_TIME_FORMAT, GST_TIME_ARGS (*timestamp));
-  return GST_BUFFER_LIST_CONTINUE;
+  return TRUE;
 }
 
 /* take a buffer list and update segment, updating the time level of the queue */
@@ -835,14 +752,14 @@ apply_buffer_list (GstQueue2 * queue, GstBufferList * buffer_list,
   GstClockTime timestamp;
 
   /* if no timestamp is set, assume it's continuous with the previous time */
-  timestamp = segment->last_stop;
+  timestamp = segment->position;
 
   gst_buffer_list_foreach (buffer_list, buffer_list_apply_time, &timestamp);
 
   GST_DEBUG_OBJECT (queue, "last_stop updated to %" GST_TIME_FORMAT,
       GST_TIME_ARGS (timestamp));
 
-  gst_segment_set_last_stop (segment, GST_FORMAT_TIME, timestamp);
+  segment->position = timestamp;
 
   if (is_sink)
     queue->sink_tainted = TRUE;
@@ -915,7 +832,6 @@ update_buffering (GstQueue2 * queue)
       queue->buffering_percent = percent;
 
       if (!QUEUE_IS_USING_QUEUE (queue)) {
-        GstFormat fmt = GST_FORMAT_BYTES;
         gint64 duration;
 
         if (QUEUE_IS_USING_RING_BUFFER (queue))
@@ -924,10 +840,12 @@ update_buffering (GstQueue2 * queue)
           mode = GST_BUFFERING_DOWNLOAD;
 
         if (queue->byte_in_rate > 0) {
-          if (gst_pad_query_peer_duration (queue->sinkpad, &fmt, &duration))
+          if (gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES,
+                  &duration)) {
             buffering_left =
                 (gdouble) ((duration -
                     queue->current->writing_pos) * 1000) / queue->byte_in_rate;
+          }
         } else {
           buffering_left = G_MAXINT64;
         }
@@ -1174,9 +1092,9 @@ gst_queue2_have_data (GstQueue2 * queue, guint64 offset, guint length)
 #define FSEEK_FILE(file,offset)  (fseek (file, offset, SEEK_SET) != 0)
 #endif
 
-static gint64
+static GstFlowReturn
 gst_queue2_read_data_at_offset (GstQueue2 * queue, guint64 offset, guint length,
-    guint8 * dst)
+    guint8 * dst, gint64 * read_return)
 {
   guint8 *ring_buffer;
   size_t res;
@@ -1208,7 +1126,9 @@ gst_queue2_read_data_at_offset (GstQueue2 * queue, guint64 offset, guint length,
       goto eos;
   }
 
-  return res;
+  *read_return = res;
+
+  return GST_FLOW_OK;
 
 seek_failed:
   {
@@ -1223,7 +1143,7 @@ could_not_read:
 eos:
   {
     GST_DEBUG ("non-regular file hits EOS");
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
@@ -1232,16 +1152,16 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length,
     GstBuffer ** buffer)
 {
   GstBuffer *buf;
-  guint8 *data;
+  guint8 *data, *orig;
   guint64 file_offset;
   guint block_length, remaining, read_length;
-  gint64 read_return;
   guint64 rb_size;
   guint64 rpos;
+  GstFlowReturn ret = GST_FLOW_OK;
 
   /* allocate the output buffer of the requested size */
-  buf = gst_buffer_new_and_alloc (length);
-  data = GST_BUFFER_DATA (buf);
+  buf = gst_buffer_new_allocate (NULL, length, 0);
+  orig = data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
 
   GST_DEBUG_OBJECT (queue, "Reading %u bytes from %" G_GUINT64_FORMAT, length,
       offset);
@@ -1283,12 +1203,8 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length,
                 "EOS hit but read %" G_GUINT64_FORMAT " bytes that we have",
                 level);
             read_length = level;
-          } else {
-            GST_DEBUG_OBJECT (queue,
-                "EOS hit and we don't have any requested data");
-            gst_buffer_unref (buf);
-            return GST_FLOW_UNEXPECTED;
-          }
+          } else
+            goto hit_eos;
         }
       }
 
@@ -1332,10 +1248,12 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length,
 
     /* while we still have data to read, we loop */
     while (read_length > 0) {
-      read_return =
+      gint64 read_return;
+
+      ret =
           gst_queue2_read_data_at_offset (queue, file_offset, block_length,
-          data);
-      if (read_return < 0)
+          data, &read_return);
+      if (ret != GST_FLOW_OK)
         goto read_error;
 
       file_offset += read_return;
@@ -1354,15 +1272,22 @@ gst_queue2_create_read (GstQueue2 * queue, guint64 offset, guint length,
     GST_DEBUG_OBJECT (queue, "%u bytes left to read", remaining);
   }
 
-  GST_BUFFER_SIZE (buf) = length;
+  gst_buffer_unmap (buf, orig, length);
+
   GST_BUFFER_OFFSET (buf) = offset;
   GST_BUFFER_OFFSET_END (buf) = offset + length;
 
   *buffer = buf;
 
-  return GST_FLOW_OK;
+  return ret;
 
   /* ERRORS */
+hit_eos:
+  {
+    GST_DEBUG_OBJECT (queue, "EOS hit and we don't have any requested data");
+    gst_buffer_unref (buf);
+    return GST_FLOW_EOS;
+  }
 out_flushing:
   {
     GST_DEBUG_OBJECT (queue, "we are flushing");
@@ -1372,8 +1297,9 @@ out_flushing:
 read_error:
   {
     GST_DEBUG_OBJECT (queue, "we have a read error");
+    gst_buffer_unmap (buf, data, 0);
     gst_buffer_unref (buf);
-    return read_return;
+    return ret;
   }
 }
 
@@ -1401,7 +1327,7 @@ gst_queue2_read_item_from_file (GstQueue2 * queue)
       case GST_FLOW_OK:
         item = GST_MINI_OBJECT_CAST (buffer);
         break;
-      case GST_FLOW_UNEXPECTED:
+      case GST_FLOW_EOS:
         item = GST_MINI_OBJECT_CAST (gst_event_new_eos ());
         break;
       default:
@@ -1597,8 +1523,9 @@ out_flushing:
 static gboolean
 gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer)
 {
-  guint8 *data, *ring_buffer;
+  guint8 *odata, *data, *ring_buffer;
   guint size, rb_size;
+  gsize osize;
   guint64 writing_pos, new_writing_pos;
   GstQueue2Range *range, *prev, *next;
 
@@ -1609,8 +1536,10 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer)
   ring_buffer = queue->ring_buffer;
   rb_size = queue->ring_buffer_max_size;
 
-  size = GST_BUFFER_SIZE (buffer);
-  data = GST_BUFFER_DATA (buffer);
+  odata = gst_buffer_map (buffer, &osize, NULL, GST_MAP_READ);
+
+  size = osize;
+  data = odata;
 
   GST_DEBUG_OBJECT (queue, "Writing %u bytes to %" G_GUINT64_FORMAT, size,
       GST_BUFFER_OFFSET (buffer));
@@ -1832,7 +1761,9 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer)
         queue->cur_level.bytes, QUEUE_MAX_BYTES (queue));
 
     GST_QUEUE2_SIGNAL_ADD (queue);
-  };
+  }
+
+  gst_buffer_unmap (buffer, odata, osize);
 
   return TRUE;
 
@@ -1840,12 +1771,14 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer)
 out_flushing:
   {
     GST_DEBUG_OBJECT (queue, "we are flushing");
-    /* FIXME - GST_FLOW_UNEXPECTED ? */
+    gst_buffer_unmap (buffer, odata, osize);
+    /* FIXME - GST_FLOW_EOS ? */
     return FALSE;
   }
 seek_failed:
   {
     GST_ELEMENT_ERROR (queue, RESOURCE, SEEK, (NULL), GST_ERROR_SYSTEM);
+    gst_buffer_unmap (buffer, odata, osize);
     return FALSE;
   }
 handle_error:
@@ -1861,37 +1794,37 @@ handle_error:
             ("%s", g_strerror (errno)));
       }
     }
+    gst_buffer_unmap (buffer, odata, osize);
     return FALSE;
   }
 }
 
-static GstBufferListItem
-buffer_list_create_write (GstBuffer ** buf, guint group, guint idx, gpointer q)
+static gboolean
+buffer_list_create_write (GstBuffer ** buf, guint idx, gpointer q)
 {
   GstQueue2 *queue = q;
 
-  GST_TRACE_OBJECT (queue, "writing buffer %u in group %u of size %u bytes",
-      idx, group, GST_BUFFER_SIZE (*buf));
+  GST_TRACE_OBJECT (queue,
+      "writing buffer %u of size %" G_GSIZE_FORMAT " bytes", idx,
+      gst_buffer_get_size (*buf));
 
   if (!gst_queue2_create_write (queue, *buf)) {
     GST_INFO_OBJECT (queue, "create_write() returned FALSE, bailing out");
-    return GST_BUFFER_LIST_END;
+    return FALSE;
   }
-
-  return GST_BUFFER_LIST_CONTINUE;
+  return TRUE;
 }
 
-static GstBufferListItem
-buffer_list_calc_size (GstBuffer ** buf, guint group, guint idx, gpointer data)
+static gboolean
+buffer_list_calc_size (GstBuffer ** buf, guint idx, gpointer data)
 {
   guint *p_size = data;
-  guint buf_size;
+  gsize buf_size;
 
-  buf_size = GST_BUFFER_SIZE (*buf);
-  GST_TRACE ("buffer %u in group %u has size %u", idx, group, buf_size);
+  buf_size = gst_buffer_get_size (*buf);
+  GST_TRACE ("buffer %u in has size %" G_GSIZE_FORMAT, idx, buf_size);
   *p_size += buf_size;
-
-  return GST_BUFFER_LIST_CONTINUE;
+  return TRUE;
 }
 
 /* enqueue an item an update the level stats */
@@ -1904,7 +1837,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item,
     guint size;
 
     buffer = GST_BUFFER_CAST (item);
-    size = GST_BUFFER_SIZE (buffer);
+    size = gst_buffer_get_size (buffer);
 
     /* add buffer to the statistics */
     if (QUEUE_IS_USING_QUEUE (queue)) {
@@ -1959,7 +1892,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item,
         GST_DEBUG_OBJECT (queue, "we have EOS");
         queue->is_eos = TRUE;
         break;
-      case GST_EVENT_NEWSEGMENT:
+      case GST_EVENT_SEGMENT:
         apply_segment (queue, event, &queue->sink_segment, TRUE);
         /* This is our first new segment, we hold it
          * as we can't save it on the temp file */
@@ -1973,7 +1906,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item,
           queue->starting_segment = event;
           item = NULL;
         }
-        /* a new segment allows us to accept more buffers if we got UNEXPECTED
+        /* a new segment allows us to accept more buffers if we got EOS
          * from downstream */
         queue->unexpected = FALSE;
         break;
@@ -2036,7 +1969,7 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, GstQueue2ItemType * item_type)
     guint size;
 
     buffer = GST_BUFFER_CAST (item);
-    size = GST_BUFFER_SIZE (buffer);
+    size = gst_buffer_get_size (buffer);
     *item_type = GST_QUEUE2_ITEM_TYPE_BUFFER;
 
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
@@ -2068,7 +2001,7 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, GstQueue2ItemType * item_type)
         /* queue is empty now that we dequeued the EOS */
         GST_QUEUE2_CLEAR_LEVEL (queue->cur_level);
         break;
-      case GST_EVENT_NEWSEGMENT:
+      case GST_EVENT_SEGMENT:
         apply_segment (queue, event, &queue->src_segment, FALSE);
         break;
       default:
@@ -2118,11 +2051,12 @@ no_item:
 }
 
 static gboolean
-gst_queue2_handle_sink_event (GstPad * pad, GstEvent * event)
+gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (GST_OBJECT_PARENT (pad));
+  queue = GST_QUEUE2 (parent);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_START:
@@ -2223,6 +2157,20 @@ out_eos:
 }
 
 static gboolean
+gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query)
+{
+  gboolean res;
+
+  switch (GST_QUERY_TYPE (query)) {
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
+  return res;
+}
+
+static gboolean
 gst_queue2_is_empty (GstQueue2 * queue)
 {
   /* never empty on EOS */
@@ -2323,29 +2271,28 @@ out_eos:
     GST_QUEUE2_MUTEX_UNLOCK (queue);
     gst_mini_object_unref (item);
 
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 out_unexpected:
   {
-    GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because we received UNEXPECTED");
+    GST_CAT_LOG_OBJECT (queue_dataflow, queue, "exit because we received EOS");
     GST_QUEUE2_MUTEX_UNLOCK (queue);
     gst_mini_object_unref (item);
 
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
 static GstFlowReturn
-gst_queue2_chain (GstPad * pad, GstBuffer * buffer)
+gst_queue2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (GST_OBJECT_PARENT (pad));
+  queue = GST_QUEUE2 (parent);
 
-  GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-      "received buffer %p of size %d, time %" GST_TIME_FORMAT ", duration %"
-      GST_TIME_FORMAT, buffer, GST_BUFFER_SIZE (buffer),
+  GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received buffer %p of "
+      "size %" G_GSIZE_FORMAT ", time %" GST_TIME_FORMAT ", duration %"
+      GST_TIME_FORMAT, buffer, gst_buffer_get_size (buffer),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
 
@@ -2354,11 +2301,12 @@ gst_queue2_chain (GstPad * pad, GstBuffer * buffer)
 }
 
 static GstFlowReturn
-gst_queue2_chain_list (GstPad * pad, GstBufferList * buffer_list)
+gst_queue2_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * buffer_list)
 {
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (GST_OBJECT_PARENT (pad));
+  queue = GST_QUEUE2 (parent);
 
   GST_CAT_LOG_OBJECT (queue_dataflow, queue,
       "received buffer list %p", buffer_list);
@@ -2368,46 +2316,44 @@ gst_queue2_chain_list (GstPad * pad, GstBufferList * buffer_list)
 }
 
 static GstMiniObject *
-gst_queue2_dequeue_on_unexpected (GstQueue2 * queue,
-    GstQueue2ItemType * item_type)
+gst_queue2_dequeue_on_eos (GstQueue2 * queue, GstQueue2ItemType * item_type)
 {
   GstMiniObject *data;
 
-  GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got UNEXPECTED from downstream");
+  GST_CAT_LOG_OBJECT (queue_dataflow, queue, "got EOS from downstream");
 
   /* stop pushing buffers, we dequeue all items until we see an item that we
-   * can push again, which is EOS or NEWSEGMENT. If there is nothing in the
+   * can push again, which is EOS or SEGMENT. If there is nothing in the
    * queue we can push, we set a flag to make the sinkpad refuse more
-   * buffers with an UNEXPECTED return value until we receive something
+   * buffers with an EOS return value until we receive something
    * pushable again or we get flushed. */
   while ((data = gst_queue2_locked_dequeue (queue, item_type))) {
     if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) {
       GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "dropping UNEXPECTED buffer %p", data);
+          "dropping EOS buffer %p", data);
       gst_buffer_unref (GST_BUFFER_CAST (data));
     } else if (*item_type == GST_QUEUE2_ITEM_TYPE_EVENT) {
       GstEvent *event = GST_EVENT_CAST (data);
       GstEventType type = GST_EVENT_TYPE (event);
 
-      if (type == GST_EVENT_EOS || type == GST_EVENT_NEWSEGMENT) {
+      if (type == GST_EVENT_EOS || type == GST_EVENT_SEGMENT) {
         /* we found a pushable item in the queue, push it out */
         GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-            "pushing pushable event %s after UNEXPECTED",
-            GST_EVENT_TYPE_NAME (event));
+            "pushing pushable event %s after EOS", GST_EVENT_TYPE_NAME (event));
         return data;
       }
       GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "dropping UNEXPECTED event %p", event);
+          "dropping EOS event %p", event);
       gst_event_unref (event);
     } else if (*item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) {
       GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "dropping UNEXPECTED buffer list %p", data);
+          "dropping EOS buffer list %p", data);
       gst_buffer_list_unref (GST_BUFFER_LIST_CAST (data));
     }
   }
   /* no more items in the queue. Set the unexpected flag so that upstream
    * make us refuse any more buffers on the sinkpad. Since we will still
-   * accept EOS and NEWSEGMENT we return _FLOW_OK to the caller so that the
+   * accept EOS and SEGMENT we return _FLOW_OK to the caller so that the
    * task function does not shut down. */
   queue->unexpected = TRUE;
   return NULL;
@@ -2431,25 +2377,31 @@ next:
 
   if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER) {
     GstBuffer *buffer;
+#if 0
     GstCaps *caps;
+#endif
 
     buffer = GST_BUFFER_CAST (data);
+#if 0
     caps = GST_BUFFER_CAPS (buffer);
+#endif
 
+#if 0
     /* set caps before pushing the buffer so that core does not try to do
      * something fancy to check if this is possible. */
     if (caps && caps != GST_PAD_CAPS (queue->srcpad))
       gst_pad_set_caps (queue->srcpad, caps);
+#endif
 
     result = gst_pad_push (queue->srcpad, buffer);
 
     /* need to check for srcresult here as well */
     GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing);
-    if (result == GST_FLOW_UNEXPECTED) {
-      data = gst_queue2_dequeue_on_unexpected (queue, &item_type);
+    if (result == GST_FLOW_EOS) {
+      data = gst_queue2_dequeue_on_eos (queue, &item_type);
       if (data != NULL)
         goto next;
-      /* Since we will still accept EOS and NEWSEGMENT we return _FLOW_OK
+      /* Since we will still accept EOS and SEGMENT we return _FLOW_OK
        * to the caller so that the task function does not shut down */
       result = GST_FLOW_OK;
     }
@@ -2459,38 +2411,42 @@ next:
 
     gst_pad_push_event (queue->srcpad, event);
 
-    /* if we're EOS, return UNEXPECTED so that the task pauses. */
+    /* if we're EOS, return EOS so that the task pauses. */
     if (type == GST_EVENT_EOS) {
       GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-          "pushed EOS event %p, return UNEXPECTED", event);
-      result = GST_FLOW_UNEXPECTED;
+          "pushed EOS event %p, return EOS", event);
+      result = GST_FLOW_EOS;
     }
 
     GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing);
   } else if (item_type == GST_QUEUE2_ITEM_TYPE_BUFFER_LIST) {
     GstBufferList *buffer_list;
+#if 0
     GstBuffer *first_buf;
     GstCaps *caps;
+#endif
 
     buffer_list = GST_BUFFER_LIST_CAST (data);
 
-    first_buf = gst_buffer_list_get (buffer_list, 0, 0);
+#if 0
+    first_buf = gst_buffer_list_get (buffer_list, 0);
     caps = (first_buf != NULL) ? GST_BUFFER_CAPS (first_buf) : NULL;
 
     /* set caps before pushing the buffer so that core does not try to do
      * something fancy to check if this is possible. */
     if (caps && caps != GST_PAD_CAPS (queue->srcpad))
       gst_pad_set_caps (queue->srcpad, caps);
+#endif
 
     result = gst_pad_push_list (queue->srcpad, buffer_list);
 
     /* need to check for srcresult here as well */
     GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing);
-    if (result == GST_FLOW_UNEXPECTED) {
-      data = gst_queue2_dequeue_on_unexpected (queue, &item_type);
+    if (result == GST_FLOW_EOS) {
+      data = gst_queue2_dequeue_on_eos (queue, &item_type);
       if (data != NULL)
         goto next;
-      /* Since we will still accept EOS and NEWSEGMENT we return _FLOW_OK
+      /* Since we will still accept EOS and SEGMENT we return _FLOW_OK
        * to the caller so that the task function does not shut down */
       result = GST_FLOW_OK;
     }
@@ -2565,8 +2521,8 @@ out_flushing:
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
         "pause task, reason:  %s", gst_flow_get_name (queue->srcresult));
     /* let app know about us giving up if upstream is not expected to do so */
-    /* UNEXPECTED is already taken care of elsewhere */
-    if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED)) {
+    /* EOS is already taken care of elsewhere */
+    if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) {
       GST_ELEMENT_ERROR (queue, STREAM, FAILED,
           (_("Internal data flow error.")),
           ("streaming task paused, reason %s (%d)",
@@ -2578,15 +2534,11 @@ out_flushing:
 }
 
 static gboolean
-gst_queue2_handle_src_event (GstPad * pad, GstEvent * event)
+gst_queue2_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
-  GstQueue2 *queue = GST_QUEUE2 (gst_pad_get_parent (pad));
+  GstQueue2 *queue = GST_QUEUE2 (parent);
 
-  if (G_UNLIKELY (queue == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
 #ifndef GST_DISABLE_GST_DEBUG
   GST_CAT_DEBUG_OBJECT (queue_dataflow, queue, "got event %p (%s)",
       event, GST_EVENT_TYPE_NAME (event));
@@ -2636,31 +2588,15 @@ gst_queue2_handle_src_event (GstPad * pad, GstEvent * event)
       break;
   }
 
-  gst_object_unref (queue);
   return res;
 }
 
 static gboolean
-gst_queue2_peer_query (GstQueue2 * queue, GstPad * pad, GstQuery * query)
-{
-  gboolean ret = FALSE;
-  GstPad *peer;
-
-  if ((peer = gst_pad_get_peer (pad))) {
-    ret = gst_pad_query (peer, query);
-    gst_object_unref (peer);
-  }
-  return ret;
-}
-
-static gboolean
-gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
+gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (queue == NULL))
-    return FALSE;
+  queue = GST_QUEUE2 (parent);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
@@ -2668,7 +2604,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
       gint64 peer_pos;
       GstFormat format;
 
-      if (!gst_queue2_peer_query (queue, queue->sinkpad, query))
+      if (!gst_pad_peer_query (queue->sinkpad, query))
         goto peer_failed;
 
       /* get peer position */
@@ -2695,7 +2631,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
     {
       GST_DEBUG_OBJECT (queue, "doing peer query");
 
-      if (!gst_queue2_peer_query (queue, queue->sinkpad, query))
+      if (!gst_pad_peer_query (queue->sinkpad, query))
         goto peer_failed;
 
       GST_DEBUG_OBJECT (queue, "peer query success");
@@ -2710,7 +2646,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
       /* FIXME - is this condition correct? what should ring buffer do? */
       if (QUEUE_IS_USING_QUEUE (queue)) {
         /* no temp file, just forward to the peer */
-        if (!gst_queue2_peer_query (queue, queue->sinkpad, query))
+        if (!gst_pad_peer_query (queue->sinkpad, query))
           goto peer_failed;
         GST_DEBUG_OBJECT (queue, "buffering forwarded to peer");
       } else {
@@ -2718,7 +2654,6 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
         guint64 writing_pos;
         gint percent;
         gint64 estimated_total, buffering_left;
-        GstFormat peer_fmt;
         gint64 duration;
         gboolean peer_res, is_buffering, is_eos;
         gdouble byte_in_rate, byte_out_rate;
@@ -2741,9 +2676,8 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
           duration = writing_pos;
         } else {
           /* get duration of upstream in bytes */
-          peer_fmt = GST_FORMAT_BYTES;
-          peer_res = gst_pad_query_peer_duration (queue->sinkpad, &peer_fmt,
-              &duration);
+          peer_res = gst_pad_peer_query_duration (queue->sinkpad,
+              GST_FORMAT_BYTES, &duration);
         }
 
         /* calculate remaining and total download time */
@@ -2824,21 +2758,35 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
       }
       break;
     }
+    case GST_QUERY_SCHEDULING:
+    {
+      gboolean pull_mode;
+      GstSchedulingFlags flags = 0;
+
+      /* we can operate in pull mode when we are using a tempfile */
+      pull_mode = !QUEUE_IS_USING_QUEUE (queue);
+
+      if (pull_mode)
+        flags |= GST_SCHEDULING_FLAG_SEEKABLE;
+      gst_query_set_scheduling (query, flags, 0, -1, 0);
+      if (pull_mode)
+        gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
+      gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
+      break;
+    }
     default:
       /* peer handled other queries */
-      if (!gst_queue2_peer_query (queue, queue->sinkpad, query))
+      if (!gst_pad_query_default (pad, parent, query))
         goto peer_failed;
       break;
   }
 
-  gst_object_unref (queue);
   return TRUE;
 
   /* ERRORS */
 peer_failed:
   {
     GST_DEBUG_OBJECT (queue, "failed peer query");
-    gst_object_unref (queue);
     return FALSE;
   }
 }
@@ -2846,30 +2794,33 @@ peer_failed:
 static gboolean
 gst_queue2_handle_query (GstElement * element, GstQuery * query)
 {
+  GstQueue2 *queue = GST_QUEUE2 (element);
+
   /* simply forward to the srcpad query function */
-  return gst_queue2_handle_src_query (GST_QUEUE2_CAST (element)->srcpad, query);
+  return gst_queue2_handle_src_query (queue->srcpad, GST_OBJECT_CAST (element),
+      query);
 }
 
 static void
 gst_queue2_update_upstream_size (GstQueue2 * queue)
 {
-  GstFormat fmt = GST_FORMAT_BYTES;
   gint64 upstream_size = -1;
 
-  if (gst_pad_query_peer_duration (queue->sinkpad, &fmt, &upstream_size)) {
+  if (gst_pad_peer_query_duration (queue->sinkpad, GST_FORMAT_BYTES,
+          &upstream_size)) {
     GST_INFO_OBJECT (queue, "upstream size: %" G_GINT64_FORMAT, upstream_size);
     queue->upstream_size = upstream_size;
   }
 }
 
 static GstFlowReturn
-gst_queue2_get_range (GstPad * pad, guint64 offset, guint length,
-    GstBuffer ** buffer)
+gst_queue2_get_range (GstPad * pad, GstObject * parent, guint64 offset,
+    guint length, GstBuffer ** buffer)
 {
   GstQueue2 *queue;
   GstFlowReturn ret;
 
-  queue = GST_QUEUE2_CAST (gst_pad_get_parent (pad));
+  queue = GST_QUEUE2_CAST (parent);
 
   length = (length == -1) ? DEFAULT_BUFFER_SIZE : length;
   GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->srcresult, out_flushing);
@@ -2901,8 +2852,6 @@ gst_queue2_get_range (GstPad * pad, guint64 offset, guint length,
   ret = gst_queue2_create_read (queue, offset, length, buffer);
   GST_QUEUE2_MUTEX_UNLOCK (queue);
 
-  gst_object_unref (queue);
-
   return ret;
 
   /* ERRORS */
@@ -2912,76 +2861,64 @@ out_flushing:
 
     GST_DEBUG_OBJECT (queue, "we are flushing");
     GST_QUEUE2_MUTEX_UNLOCK (queue);
-    gst_object_unref (queue);
     return ret;
   }
 out_unexpected:
   {
     GST_DEBUG_OBJECT (queue, "read beyond end of file");
     GST_QUEUE2_MUTEX_UNLOCK (queue);
-    gst_object_unref (queue);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 }
 
-static gboolean
-gst_queue2_src_checkgetrange_function (GstPad * pad)
-{
-  GstQueue2 *queue;
-  gboolean ret;
-
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
-
-  /* we can operate in pull mode when we are using a tempfile */
-  ret = !QUEUE_IS_USING_QUEUE (queue);
-
-  gst_object_unref (GST_OBJECT (queue));
-
-  return ret;
-}
-
 /* sink currently only operates in push mode */
 static gboolean
-gst_queue2_sink_activate_push (GstPad * pad, gboolean active)
+gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
-  gboolean result = TRUE;
+  gboolean result;
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
+  queue = GST_QUEUE2 (parent);
 
-  if (active) {
-    GST_QUEUE2_MUTEX_LOCK (queue);
-    GST_DEBUG_OBJECT (queue, "activating push mode");
-    queue->srcresult = GST_FLOW_OK;
-    queue->sinkresult = GST_FLOW_OK;
-    queue->is_eos = FALSE;
-    queue->unexpected = FALSE;
-    reset_rate_timer (queue);
-    GST_QUEUE2_MUTEX_UNLOCK (queue);
-  } else {
-    /* unblock chain function */
-    GST_QUEUE2_MUTEX_LOCK (queue);
-    GST_DEBUG_OBJECT (queue, "deactivating push mode");
-    queue->srcresult = GST_FLOW_WRONG_STATE;
-    queue->sinkresult = GST_FLOW_WRONG_STATE;
-    gst_queue2_locked_flush (queue);
-    GST_QUEUE2_MUTEX_UNLOCK (queue);
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        GST_QUEUE2_MUTEX_LOCK (queue);
+        GST_DEBUG_OBJECT (queue, "activating push mode");
+        queue->srcresult = GST_FLOW_OK;
+        queue->sinkresult = GST_FLOW_OK;
+        queue->is_eos = FALSE;
+        queue->unexpected = FALSE;
+        reset_rate_timer (queue);
+        GST_QUEUE2_MUTEX_UNLOCK (queue);
+      } else {
+        /* unblock chain function */
+        GST_QUEUE2_MUTEX_LOCK (queue);
+        GST_DEBUG_OBJECT (queue, "deactivating push mode");
+        queue->srcresult = GST_FLOW_WRONG_STATE;
+        queue->sinkresult = GST_FLOW_WRONG_STATE;
+        gst_queue2_locked_flush (queue);
+        GST_QUEUE2_MUTEX_UNLOCK (queue);
+      }
+      result = TRUE;
+      break;
+    default:
+      result = FALSE;
+      break;
   }
-
-  gst_object_unref (queue);
-
   return result;
 }
 
 /* src operating in push mode, we start a task on the source pad that pushes out
  * buffers from the queue */
 static gboolean
-gst_queue2_src_activate_push (GstPad * pad, gboolean active)
+gst_queue2_src_activate_push (GstPad * pad, GstObject * parent, gboolean active)
 {
   gboolean result = FALSE;
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
+  queue = GST_QUEUE2 (parent);
 
   if (active) {
     GST_QUEUE2_MUTEX_LOCK (queue);
@@ -3006,19 +2943,17 @@ gst_queue2_src_activate_push (GstPad * pad, gboolean active)
     result = gst_pad_stop_task (pad);
   }
 
-  gst_object_unref (queue);
-
   return result;
 }
 
 /* pull mode, downstream will call our getrange function */
 static gboolean
-gst_queue2_src_activate_pull (GstPad * pad, gboolean active)
+gst_queue2_src_activate_pull (GstPad * pad, GstObject * parent, gboolean active)
 {
   gboolean result;
   GstQueue2 *queue;
 
-  queue = GST_QUEUE2 (gst_pad_get_parent (pad));
+  queue = GST_QUEUE2 (parent);
 
   if (active) {
     GST_QUEUE2_MUTEX_LOCK (queue);
@@ -3059,11 +2994,31 @@ gst_queue2_src_activate_pull (GstPad * pad, gboolean active)
     result = TRUE;
     GST_QUEUE2_MUTEX_UNLOCK (queue);
   }
-  gst_object_unref (queue);
 
   return result;
 }
 
+static gboolean
+gst_queue2_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
+    gboolean active)
+{
+  gboolean res;
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_queue2_src_activate_pull (pad, parent, active);
+      break;
+    case GST_PAD_MODE_PUSH:
+      res = gst_queue2_src_activate_push (pad, parent, active);
+      break;
+    default:
+      GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
+      res = FALSE;
+      break;
+  }
+  return res;
+}
+
 static GstStateChangeReturn
 gst_queue2_change_state (GstElement * element, GstStateChange transition)
 {
index 02a38f2..66947a7 100644 (file)
@@ -124,11 +124,11 @@ struct _GstQueue2
   guint64 bytes_out;
   gdouble byte_out_rate;
 
-  GMutex *qlock;                /* lock for queue (vs object lock) */
+  GMutex qlock;                /* lock for queue (vs object lock) */
   gboolean waiting_add;
-  GCond *item_add;              /* signals buffers now available for reading */
+  GCond item_add;              /* signals buffers now available for reading */
   gboolean waiting_del;
-  GCond *item_del;              /* signals space now available for writing */
+  GCond item_del;              /* signals space now available for writing */
 
   /* temp location stuff */
   gchar *temp_template;
index 6b875a7..f4633e8 100644 (file)
@@ -79,8 +79,8 @@ gst_tee_pull_mode_get_type (void)
 }
 
 /* lock to protect request pads from being removed while downstream */
-#define GST_TEE_DYN_LOCK(tee) g_mutex_lock ((tee)->dyn_lock)
-#define GST_TEE_DYN_UNLOCK(tee) g_mutex_unlock ((tee)->dyn_lock)
+#define GST_TEE_DYN_LOCK(tee) g_mutex_lock (&(tee)->dyn_lock)
+#define GST_TEE_DYN_UNLOCK(tee) g_mutex_unlock (&(tee)->dyn_lock)
 
 #define DEFAULT_PROP_NUM_SRC_PADS      0
 #define DEFAULT_PROP_HAS_SINK_LOOP     FALSE
@@ -101,19 +101,21 @@ enum
   PROP_ALLOC_PAD,
 };
 
-static GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
+static GstStaticPadTemplate tee_src_template =
+GST_STATIC_PAD_TEMPLATE ("src_%u",
     GST_PAD_SRC,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS_ANY);
 
-#define _do_init(bla) \
-    GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element");
-
-GST_BOILERPLATE_FULL (GstTee, gst_tee, GstElement, GST_TYPE_ELEMENT, _do_init);
-
 /* structure and quark to keep track of which pads have been pushed */
 static GQuark push_data;
 
+#define _do_init \
+    GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element"); \
+    push_data = g_quark_from_static_string ("tee-push-data");
+#define gst_tee_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstTee, gst_tee, GST_TYPE_ELEMENT, _do_init);
+
 static GParamSpec *pspec_last_message = NULL;
 static GParamSpec *pspec_alloc_pad = NULL;
 
@@ -125,7 +127,7 @@ typedef struct
 } PushData;
 
 static GstPad *gst_tee_request_new_pad (GstElement * element,
-    GstPadTemplate * temp, const gchar * unused);
+    GstPadTemplate * temp, const gchar * unused, const GstCaps * caps);
 static void gst_tee_release_pad (GstElement * element, GstPad * pad);
 
 static void gst_tee_finalize (GObject * object);
@@ -135,35 +137,22 @@ static void gst_tee_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_tee_dispose (GObject * object);
 
-static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list);
-static GstFlowReturn gst_tee_buffer_alloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf);
-static gboolean gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
-static gboolean gst_tee_src_check_get_range (GstPad * pad);
-static gboolean gst_tee_src_activate_pull (GstPad * pad, gboolean active);
-static GstFlowReturn gst_tee_src_get_range (GstPad * pad, guint64 offset,
-    guint length, GstBuffer ** buf);
-
-
-static void
-gst_tee_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "Tee pipe fitting",
-      "Generic",
-      "1-to-N pipe fitting",
-      "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&sinktemplate));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&tee_src_template));
-
-  push_data = g_quark_from_static_string ("tee-push-data");
-}
+static GstFlowReturn gst_tee_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstObject * parent,
+    GstBufferList * list);
+static gboolean gst_tee_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_tee_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static gboolean gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
+static gboolean gst_tee_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static gboolean gst_tee_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active);
+static GstFlowReturn gst_tee_src_get_range (GstPad * pad, GstObject * parent,
+    guint64 offset, guint length, GstBuffer ** buf);
 
 static void
 gst_tee_dispose (GObject * object)
@@ -191,7 +180,7 @@ gst_tee_finalize (GObject * object)
 
   g_free (tee->last_message);
 
-  g_mutex_free (tee->dyn_lock);
+  g_mutex_clear (&tee->dyn_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -243,32 +232,39 @@ gst_tee_class_init (GstTeeClass * klass)
   g_object_class_install_property (gobject_class, PROP_ALLOC_PAD,
       pspec_alloc_pad);
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Tee pipe fitting",
+      "Generic",
+      "1-to-N pipe fitting",
+      "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&tee_src_template));
+
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_tee_release_pad);
 }
 
 static void
-gst_tee_init (GstTee * tee, GstTeeClass * g_class)
+gst_tee_init (GstTee * tee)
 {
-  tee->dyn_lock = g_mutex_new ();
+  g_mutex_init (&tee->dyn_lock);
 
   tee->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
-  tee->sink_mode = GST_ACTIVATE_NONE;
-
-  gst_pad_set_setcaps_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
-  gst_pad_set_getcaps_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
-  gst_pad_set_acceptcaps_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_tee_sink_acceptcaps));
-  gst_pad_set_bufferalloc_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_tee_buffer_alloc));
-  gst_pad_set_activatepush_function (tee->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
+  tee->sink_mode = GST_PAD_MODE_NONE;
+
+  gst_pad_set_event_function (tee->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tee_sink_event));
+  gst_pad_set_query_function (tee->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tee_sink_query));
+  gst_pad_set_activatemode_function (tee->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tee_sink_activate_mode));
   gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
   gst_pad_set_chain_list_function (tee->sinkpad,
       GST_DEBUG_FUNCPTR (gst_tee_chain_list));
+  GST_OBJECT_FLAG_SET (tee->sinkpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
 
   tee->last_message = NULL;
@@ -277,21 +273,27 @@ gst_tee_init (GstTee * tee, GstTeeClass * g_class)
 static void
 gst_tee_notify_alloc_pad (GstTee * tee)
 {
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_object_notify ((GObject *) tee, "alloc-pad");
-#else
   g_object_notify_by_pspec ((GObject *) tee, pspec_alloc_pad);
-#endif
+}
+
+static gboolean
+forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
+{
+  GstPad *srcpad = GST_PAD_CAST (user_data);
+
+  gst_pad_push_event (srcpad, gst_event_ref (*event));
+
+  return TRUE;
 }
 
 static GstPad *
 gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
-    const gchar * unused)
+    const gchar * unused, const GstCaps * caps)
 {
   gchar *name;
   GstPad *srcpad;
   GstTee *tee;
-  GstActivateMode mode;
+  GstPadMode mode;
   gboolean res;
   PushData *data;
 
@@ -300,7 +302,7 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
   GST_DEBUG_OBJECT (tee, "requesting pad");
 
   GST_OBJECT_LOCK (tee);
-  name = g_strdup_printf ("src%d", tee->pad_counter++);
+  name = g_strdup_printf ("src_%u", tee->pad_counter++);
 
   srcpad = gst_pad_new_from_template (templ, name);
   g_free (name);
@@ -318,11 +320,11 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
   GST_OBJECT_UNLOCK (tee);
 
   switch (mode) {
-    case GST_ACTIVATE_PULL:
+    case GST_PAD_MODE_PULL:
       /* we already have a src pad in pull mode, and our pull mode can only be
          SINGLE, so fall through to activate this new pad in push mode */
-    case GST_ACTIVATE_PUSH:
-      res = gst_pad_activate_push (srcpad, TRUE);
+    case GST_PAD_MODE_PUSH:
+      res = gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE);
       break;
     default:
       res = TRUE;
@@ -332,16 +334,14 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
   if (!res)
     goto activate_failed;
 
-  gst_pad_set_setcaps_function (srcpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
-  gst_pad_set_getcaps_function (srcpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
-  gst_pad_set_activatepull_function (srcpad,
-      GST_DEBUG_FUNCPTR (gst_tee_src_activate_pull));
-  gst_pad_set_checkgetrange_function (srcpad,
-      GST_DEBUG_FUNCPTR (gst_tee_src_check_get_range));
+  gst_pad_set_activatemode_function (srcpad,
+      GST_DEBUG_FUNCPTR (gst_tee_src_activate_mode));
+  gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query));
   gst_pad_set_getrange_function (srcpad,
       GST_DEBUG_FUNCPTR (gst_tee_src_get_range));
+  /* Forward sticky events to the new srcpad */
+  gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad);
+  GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS);
   gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad);
 
   return srcpad;
@@ -390,11 +390,14 @@ gst_tee_release_pad (GstElement * element, GstPad * pad)
   }
   GST_OBJECT_UNLOCK (tee);
 
-  gst_pad_set_active (pad, FALSE);
-
+  gst_object_ref (pad);
   gst_element_remove_pad (GST_ELEMENT_CAST (tee), pad);
+
+  gst_pad_set_active (pad, FALSE);
   GST_TEE_DYN_UNLOCK (tee);
 
+  gst_object_unref (pad);
+
   if (changed) {
     gst_tee_notify_alloc_pad (tee);
   }
@@ -478,159 +481,30 @@ gst_tee_get_property (GObject * object, guint prop_id, GValue * value,
   GST_OBJECT_UNLOCK (tee);
 }
 
-/* we have no previous source pad we can use to proxy the pad alloc. Loop over
- * the source pads, try to alloc a buffer on each one of them. Keep a reference
- * to the first pad that succeeds, we will be using it to alloc more buffers
- * later.  must be called with the OBJECT_LOCK on tee. */
-static GstFlowReturn
-gst_tee_find_buffer_alloc (GstTee * tee, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
+static gboolean
+gst_tee_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstFlowReturn res;
-  GList *pads;
-  guint32 cookie;
-
-  res = GST_FLOW_NOT_LINKED;
-
-retry:
-  pads = GST_ELEMENT_CAST (tee)->srcpads;
-  cookie = GST_ELEMENT_CAST (tee)->pads_cookie;
-
-  while (pads) {
-    GstPad *pad;
-    PushData *data;
-
-    pad = GST_PAD_CAST (pads->data);
-    gst_object_ref (pad);
-    GST_DEBUG_OBJECT (tee, "try alloc on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
-    GST_OBJECT_UNLOCK (tee);
-
-    GST_TEE_DYN_LOCK (tee);
-    data = g_object_get_qdata ((GObject *) pad, push_data);
-    if (!data->removed)
-      res = gst_pad_alloc_buffer (pad, offset, size, caps, buf);
-    else
-      res = GST_FLOW_NOT_LINKED;
-    GST_TEE_DYN_UNLOCK (tee);
-
-    GST_DEBUG_OBJECT (tee, "got return value %d", res);
-
-    gst_object_unref (pad);
+  gboolean res;
 
-    GST_OBJECT_LOCK (tee);
-    if (GST_ELEMENT_CAST (tee)->pads_cookie != cookie) {
-      GST_DEBUG_OBJECT (tee, "pad list changed, restart");
-      /* pad list changed, restart. If the pad alloc function returned OK we
-       * need to unref the buffer */
-      if (res == GST_FLOW_OK)
-        gst_buffer_unref (*buf);
-      *buf = NULL;
-      goto retry;
-    }
-    if (!data->removed && res == GST_FLOW_OK) {
-      GST_DEBUG_OBJECT (tee, "we have a buffer on pad %s:%s",
-          GST_DEBUG_PAD_NAME (pad));
-      /* we have a buffer, keep the pad for later and exit the loop. */
-      tee->allocpad = pad;
-      GST_OBJECT_UNLOCK (tee);
-      gst_tee_notify_alloc_pad (tee);
-      GST_OBJECT_LOCK (tee);
+  switch (GST_EVENT_TYPE (event)) {
+    default:
+      res = gst_pad_event_default (pad, parent, event);
       break;
-    }
-    /* no valid buffer, try another pad */
-    pads = g_list_next (pads);
   }
 
   return res;
 }
 
-static GstFlowReturn
-gst_tee_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstTee *tee;
-  GstFlowReturn res;
-  GstPad *allocpad;
-
-  tee = GST_TEE_CAST (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (tee == NULL))
-    return GST_FLOW_WRONG_STATE;
-
-  res = GST_FLOW_NOT_LINKED;
-
-  GST_OBJECT_LOCK (tee);
-  if ((allocpad = tee->allocpad)) {
-    PushData *data;
-
-    /* if we had a previous pad we used for allocating a buffer, continue using
-     * it. */
-    GST_DEBUG_OBJECT (tee, "using pad %s:%s for alloc",
-        GST_DEBUG_PAD_NAME (allocpad));
-    gst_object_ref (allocpad);
-    GST_OBJECT_UNLOCK (tee);
-
-    GST_TEE_DYN_LOCK (tee);
-    data = g_object_get_qdata ((GObject *) allocpad, push_data);
-    if (!data->removed)
-      res = gst_pad_alloc_buffer (allocpad, offset, size, caps, buf);
-    else
-      res = GST_FLOW_NOT_LINKED;
-    GST_TEE_DYN_UNLOCK (tee);
-
-    gst_object_unref (allocpad);
-
-    GST_OBJECT_LOCK (tee);
-  }
-  /* either we failed to alloc on the previous pad or we did not have a
-   * previous pad. */
-  if (res == GST_FLOW_NOT_LINKED) {
-    /* find a new pad to alloc a buffer on */
-    GST_DEBUG_OBJECT (tee, "finding pad for alloc");
-    res = gst_tee_find_buffer_alloc (tee, offset, size, caps, buf);
-  }
-  GST_OBJECT_UNLOCK (tee);
-
-  gst_object_unref (tee);
-  return res;
-}
-
-/* on the sink we accept caps that are acceptable to all srcpads */
 static gboolean
-gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps)
+gst_tee_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstTee *tee;
-  gboolean res, done;
-  GstIterator *it;
-
-  tee = GST_TEE_CAST (GST_PAD_PARENT (pad));
-
-  it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (tee));
-
-  res = TRUE;
-  done = FALSE;
-  while (!done && res) {
-    gpointer item;
+  gboolean res;
 
-    switch (gst_iterator_next (it, &item)) {
-      case GST_ITERATOR_OK:
-        res &= gst_pad_peer_accept_caps (GST_PAD_CAST (item), caps);
-        gst_object_unref (item);
-        break;
-      case GST_ITERATOR_RESYNC:
-        res = TRUE;
-        gst_iterator_resync (it);
-        break;
-      case GST_ITERATOR_ERROR:
-        res = FALSE;
-        done = TRUE;
-        break;
-      case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
-    }
+  switch (GST_QUERY_TYPE (query)) {
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
   }
-  gst_iterator_free (it);
-
   return res;
 }
 
@@ -645,17 +519,13 @@ gst_tee_do_message (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list)
         GST_DEBUG_PAD_NAME (pad), data);
   } else {
     tee->last_message =
-        g_strdup_printf ("chain        ******* (%s:%s)t (%d bytes, %"
-        G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
-        GST_BUFFER_SIZE (data), GST_BUFFER_TIMESTAMP (data), data);
+        g_strdup_printf ("chain        ******* (%s:%s)t (%" G_GSIZE_FORMAT
+        " bytes, %" G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
+        gst_buffer_get_size (data), GST_BUFFER_TIMESTAMP (data), data);
   }
   GST_OBJECT_UNLOCK (tee);
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-  g_object_notify ((GObject *) tee, "last-message");
-#else
   g_object_notify_by_pspec ((GObject *) tee, pspec_last_message);
-#endif
 }
 
 static GstFlowReturn
@@ -816,12 +686,12 @@ error:
 }
 
 static GstFlowReturn
-gst_tee_chain (GstPad * pad, GstBuffer * buffer)
+gst_tee_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstFlowReturn res;
   GstTee *tee;
 
-  tee = GST_TEE_CAST (GST_OBJECT_PARENT (pad));
+  tee = GST_TEE_CAST (parent);
 
   GST_DEBUG_OBJECT (tee, "received buffer %p", buffer);
 
@@ -833,12 +703,12 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer)
 }
 
 static GstFlowReturn
-gst_tee_chain_list (GstPad * pad, GstBufferList * list)
+gst_tee_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
 {
   GstFlowReturn res;
   GstTee *tee;
 
-  tee = GST_TEE_CAST (gst_pad_get_parent (pad));
+  tee = GST_TEE_CAST (parent);
 
   GST_DEBUG_OBJECT (tee, "received list %p", list);
 
@@ -846,26 +716,35 @@ gst_tee_chain_list (GstPad * pad, GstBufferList * list)
 
   GST_DEBUG_OBJECT (tee, "handled list %s", gst_flow_get_name (res));
 
-  gst_object_unref (tee);
-
   return res;
 }
 
 static gboolean
-gst_tee_sink_activate_push (GstPad * pad, gboolean active)
+gst_tee_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
+    gboolean active)
 {
+  gboolean res;
   GstTee *tee;
 
-  tee = GST_TEE (GST_OBJECT_PARENT (pad));
+  tee = GST_TEE (parent);
 
-  GST_OBJECT_LOCK (tee);
-  tee->sink_mode = active && GST_ACTIVATE_PUSH;
-
-  if (active && !tee->has_chain)
-    goto no_chain;
-  GST_OBJECT_UNLOCK (tee);
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+    {
+      GST_OBJECT_LOCK (tee);
+      tee->sink_mode = active ? mode : GST_PAD_MODE_NONE;
 
-  return TRUE;
+      if (active && !tee->has_chain)
+        goto no_chain;
+      GST_OBJECT_UNLOCK (tee);
+      res = TRUE;
+      break;
+    }
+    default:
+      res = FALSE;
+      break;
+  }
+  return res;
 
   /* ERRORS */
 no_chain:
@@ -878,45 +757,52 @@ no_chain:
 }
 
 static gboolean
-gst_tee_src_activate_pull (GstPad * pad, gboolean active)
+gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
+    gboolean active)
 {
   GstTee *tee;
   gboolean res;
   GstPad *sinkpad;
 
-  tee = GST_TEE (gst_pad_get_parent (pad));
+  tee = GST_TEE (parent);
 
-  GST_OBJECT_LOCK (tee);
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+    {
+      GST_OBJECT_LOCK (tee);
 
-  if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER)
-    goto cannot_pull;
+      if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER)
+        goto cannot_pull;
 
-  if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad)
-    goto cannot_pull_multiple_srcs;
+      if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad)
+        goto cannot_pull_multiple_srcs;
 
-  sinkpad = gst_object_ref (tee->sinkpad);
+      sinkpad = gst_object_ref (tee->sinkpad);
 
-  GST_OBJECT_UNLOCK (tee);
+      GST_OBJECT_UNLOCK (tee);
 
-  res = gst_pad_activate_pull (sinkpad, active);
-  gst_object_unref (sinkpad);
+      res = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, active);
+      gst_object_unref (sinkpad);
 
-  if (!res)
-    goto sink_activate_failed;
+      if (!res)
+        goto sink_activate_failed;
 
-  GST_OBJECT_LOCK (tee);
-  if (active) {
-    if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE)
-      tee->pull_pad = pad;
-  } else {
-    if (pad == tee->pull_pad)
-      tee->pull_pad = NULL;
+      GST_OBJECT_LOCK (tee);
+      if (active) {
+        if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE)
+          tee->pull_pad = pad;
+      } else {
+        if (pad == tee->pull_pad)
+          tee->pull_pad = NULL;
+      }
+      tee->sink_mode = active & GST_PAD_MODE_PULL;
+      GST_OBJECT_UNLOCK (tee);
+      break;
+    }
+    default:
+      res = TRUE;
+      break;
   }
-  tee->sink_mode = active && GST_ACTIVATE_PULL;
-  GST_OBJECT_UNLOCK (tee);
-
-  gst_object_unref (tee);
-
   return res;
 
   /* ERRORS */
@@ -925,7 +811,6 @@ cannot_pull:
     GST_OBJECT_UNLOCK (tee);
     GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode "
         "set to NEVER");
-    gst_object_unref (tee);
     return FALSE;
   }
 cannot_pull_multiple_srcs:
@@ -933,71 +818,69 @@ cannot_pull_multiple_srcs:
     GST_OBJECT_UNLOCK (tee);
     GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, "
         "pull-mode set to SINGLE");
-    gst_object_unref (tee);
     return FALSE;
   }
 sink_activate_failed:
   {
     GST_INFO_OBJECT (tee, "Failed to %sactivate sink pad in pull mode",
         active ? "" : "de");
-    gst_object_unref (tee);
     return FALSE;
   }
 }
 
 static gboolean
-gst_tee_src_check_get_range (GstPad * pad)
+gst_tee_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstTee *tee;
   gboolean res;
   GstPad *sinkpad;
 
-  tee = GST_TEE (gst_pad_get_parent (pad));
-
-  GST_OBJECT_LOCK (tee);
-
-  if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER)
-    goto cannot_pull;
+  tee = GST_TEE (parent);
 
-  if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && tee->pull_pad)
-    goto cannot_pull_multiple_srcs;
-
-  sinkpad = gst_object_ref (tee->sinkpad);
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_SCHEDULING:
+    {
+      gboolean pull_mode;
 
-  GST_OBJECT_UNLOCK (tee);
+      GST_OBJECT_LOCK (tee);
+      pull_mode = TRUE;
+      if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) {
+        GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode "
+            "set to NEVER");
+        pull_mode = FALSE;
+      } else if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && tee->pull_pad) {
+        GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, "
+            "pull-mode set to SINGLE");
+        pull_mode = FALSE;
+      }
 
-  res = gst_pad_check_pull_range (sinkpad);
-  gst_object_unref (sinkpad);
+      sinkpad = gst_object_ref (tee->sinkpad);
+      GST_OBJECT_UNLOCK (tee);
 
-  gst_object_unref (tee);
+      if (pull_mode) {
+        /* ask peer if we can operate in pull mode */
+        res = gst_pad_peer_query (sinkpad, query);
+      } else {
+        res = TRUE;
+      }
+      gst_object_unref (sinkpad);
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
 
   return res;
-
-  /* ERRORS */
-cannot_pull:
-  {
-    GST_OBJECT_UNLOCK (tee);
-    GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode "
-        "set to NEVER");
-    gst_object_unref (tee);
-    return FALSE;
-  }
-cannot_pull_multiple_srcs:
-  {
-    GST_OBJECT_UNLOCK (tee);
-    GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, "
-        "pull-mode set to SINGLE");
-    gst_object_unref (tee);
-    return FALSE;
-  }
 }
 
 static void
-gst_tee_push_eos (GstPad * pad, GstTee * tee)
+gst_tee_push_eos (const GValue * vpad, GstTee * tee)
 {
+  GstPad *pad = g_value_get_object (vpad);
+
   if (pad != tee->pull_pad)
     gst_pad_push_event (pad, gst_event_new_eos ());
-  gst_object_unref (pad);
 }
 
 static void
@@ -1006,27 +889,26 @@ gst_tee_pull_eos (GstTee * tee)
   GstIterator *iter;
 
   iter = gst_element_iterate_src_pads (GST_ELEMENT (tee));
-  gst_iterator_foreach (iter, (GFunc) gst_tee_push_eos, tee);
+  gst_iterator_foreach (iter, (GstIteratorForeachFunction) gst_tee_push_eos,
+      tee);
   gst_iterator_free (iter);
 }
 
 static GstFlowReturn
-gst_tee_src_get_range (GstPad * pad, guint64 offset, guint length,
-    GstBuffer ** buf)
+gst_tee_src_get_range (GstPad * pad, GstObject * parent, guint64 offset,
+    guint length, GstBuffer ** buf)
 {
   GstTee *tee;
   GstFlowReturn ret;
 
-  tee = GST_TEE (gst_pad_get_parent (pad));
+  tee = GST_TEE (parent);
 
   ret = gst_pad_pull_range (tee->sinkpad, offset, length, buf);
 
   if (ret == GST_FLOW_OK)
     ret = gst_tee_handle_data (tee, gst_buffer_ref (*buf), FALSE);
-  else if (ret == GST_FLOW_UNEXPECTED)
+  else if (ret == GST_FLOW_EOS)
     gst_tee_pull_eos (tee);
 
-  gst_object_unref (tee);
-
   return ret;
 }
index 626d750..5d6cc51 100644 (file)
@@ -67,18 +67,18 @@ struct _GstTee {
 
   /*< private >*/
   /* lock protecting dynamic pads */
-  GMutex         *dyn_lock;
+  GMutex          dyn_lock;
 
   GstPad         *sinkpad;
   GstPad         *allocpad;
-  gint            pad_counter;
+  guint           pad_counter;
 
   gboolean        has_chain;
   gboolean        has_sink_loop;
   gboolean        silent;
   gchar          *last_message;
 
-  GstActivateMode sink_mode;
+  GstPadMode      sink_mode;
   GstTeePullMode  pull_mode;
   GstPad         *pull_pad;
 };
@@ -87,7 +87,7 @@ struct _GstTeeClass {
   GstElementClass parent_class;
 };
 
-GType  gst_tee_get_type        (void);
+GType  gst_tee_get_type        (void);
 
 G_END_DECLS
 
index b6675a6..1f7e03a 100644 (file)
@@ -123,11 +123,11 @@ enum
 };
 
 
-#define _do_init(bla) \
+#define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind",           \
         GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
-
-GST_BOILERPLATE_FULL (GstTypeFindElement, gst_type_find_element, GstElement,
+#define gst_type_find_element_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstTypeFindElement, gst_type_find_element,
     GST_TYPE_ELEMENT, _do_init);
 
 static void gst_type_find_element_dispose (GObject * object);
@@ -141,28 +141,31 @@ static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
 #endif
 
 static gboolean gst_type_find_element_src_event (GstPad * pad,
-    GstEvent * event);
-static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
-
-static gboolean gst_type_find_element_handle_event (GstPad * pad,
-    GstEvent * event);
-static gboolean gst_type_find_element_setcaps (GstPad * pad, GstCaps * caps);
+    GstObject * parent, GstEvent * event);
+static gboolean gst_type_find_handle_src_query (GstPad * pad,
+    GstObject * parent, GstQuery * query);
+
+static gboolean gst_type_find_element_sink_event (GstPad * pad,
+    GstObject * parent, GstEvent * event);
+static gboolean gst_type_find_element_setcaps (GstTypeFindElement * typefind,
+    GstCaps * caps);
 static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad,
-    GstBuffer * buffer);
+    GstObject * parent, GstBuffer * buffer);
 static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad,
-    guint64 offset, guint length, GstBuffer ** buffer);
-static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad);
+    GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
 
 static GstStateChangeReturn
 gst_type_find_element_change_state (GstElement * element,
     GstStateChange transition);
-static gboolean gst_type_find_element_activate (GstPad * pad);
-static gboolean
-gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
+static gboolean gst_type_find_element_activate (GstPad * pad,
+    GstObject * parent);
+static gboolean gst_type_find_element_activate_src_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
 static GstFlowReturn
-gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind);
-static void
-gst_type_find_element_send_cached_events (GstTypeFindElement * typefind);
+gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
+    gboolean check_avail);
+static void gst_type_find_element_send_cached_events (GstTypeFindElement *
+    typefind);
 
 static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
 
@@ -184,27 +187,11 @@ gst_type_find_element_have_type (GstTypeFindElement * typefind,
   copy = gst_caps_ref (typefind->caps);
   GST_OBJECT_UNLOCK (typefind);
 
-  gst_pad_set_caps (typefind->src, copy);
+  gst_pad_push_event (typefind->src, gst_event_new_caps (copy));
   gst_caps_unref (copy);
 }
 
 static void
-gst_type_find_element_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (gstelement_class,
-      "TypeFind",
-      "Generic",
-      "Finds the media type of a stream",
-      "Benjamin Otte <in7y118@public.uni-hamburg.de>");
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&type_find_element_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&type_find_element_sink_template));
-}
-
-static void
 gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
@@ -216,7 +203,7 @@ gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
 
   g_object_class_install_property (gobject_class, PROP_CAPS,
       g_param_spec_boxed ("caps", _("caps"),
-          _("detected capabilities in stream"), gst_caps_get_type (),
+          _("detected capabilities in stream"), GST_TYPE_CAPS,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_MINIMUM,
       g_param_spec_uint ("minimum", _("minimum"),
@@ -230,7 +217,7 @@ gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_FORCE_CAPS,
       g_param_spec_boxed ("force-caps", _("force caps"),
-          _("force caps without doing a typefind"), gst_caps_get_type (),
+          _("force caps without doing a typefind"), GST_TYPE_CAPS,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstTypeFindElement::have-type:
@@ -250,13 +237,22 @@ gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
   typefind_class->have_type =
       GST_DEBUG_FUNCPTR (gst_type_find_element_have_type);
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "TypeFind",
+      "Generic",
+      "Finds the media type of a stream",
+      "Benjamin Otte <in7y118@public.uni-hamburg.de>");
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&type_find_element_src_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&type_find_element_sink_template));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
 }
 
 static void
-gst_type_find_element_init (GstTypeFindElement * typefind,
-    GstTypeFindElementClass * g_class)
+gst_type_find_element_init (GstTypeFindElement * typefind)
 {
   /* sinkpad */
   typefind->sink =
@@ -265,22 +261,18 @@ gst_type_find_element_init (GstTypeFindElement * typefind,
 
   gst_pad_set_activate_function (typefind->sink,
       GST_DEBUG_FUNCPTR (gst_type_find_element_activate));
-  gst_pad_set_setcaps_function (typefind->sink,
-      GST_DEBUG_FUNCPTR (gst_type_find_element_setcaps));
   gst_pad_set_chain_function (typefind->sink,
       GST_DEBUG_FUNCPTR (gst_type_find_element_chain));
   gst_pad_set_event_function (typefind->sink,
-      GST_DEBUG_FUNCPTR (gst_type_find_element_handle_event));
+      GST_DEBUG_FUNCPTR (gst_type_find_element_sink_event));
   gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
 
   /* srcpad */
   typefind->src =
       gst_pad_new_from_static_template (&type_find_element_src_template, "src");
 
-  gst_pad_set_activatepull_function (typefind->src,
-      GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_pull));
-  gst_pad_set_checkgetrange_function (typefind->src,
-      GST_DEBUG_FUNCPTR (gst_type_find_element_checkgetrange));
+  gst_pad_set_activatemode_function (typefind->src,
+      GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_mode));
   gst_pad_set_getrange_function (typefind->src,
       GST_DEBUG_FUNCPTR (gst_type_find_element_getrange));
   gst_pad_set_event_function (typefind->src,
@@ -295,7 +287,7 @@ gst_type_find_element_init (GstTypeFindElement * typefind,
   typefind->min_probability = 1;
   typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
 
-  typefind->store = NULL;
+  typefind->adapter = gst_adapter_new ();
 }
 
 static void
@@ -303,9 +295,9 @@ gst_type_find_element_dispose (GObject * object)
 {
   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
 
-  if (typefind->store) {
-    gst_buffer_unref (typefind->store);
-    typefind->store = NULL;
+  if (typefind->adapter) {
+    g_object_unref (typefind->adapter);
+    typefind->adapter = NULL;
   }
 
   if (typefind->force_caps) {
@@ -376,19 +368,15 @@ gst_type_find_element_get_property (GObject * object, guint prop_id,
 }
 
 static gboolean
-gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
+gst_type_find_handle_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query)
 {
   GstTypeFindElement *typefind;
   gboolean res = FALSE;
-  GstPad *peer;
-
-  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
 
-  peer = gst_pad_get_peer (typefind->sink);
-  if (peer == NULL)
-    return FALSE;
+  typefind = GST_TYPE_FIND_ELEMENT (parent);
 
-  res = gst_pad_query (peer, query);
+  res = gst_pad_peer_query (typefind->sink, query);
   if (!res)
     goto out;
 
@@ -398,18 +386,13 @@ gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
       gint64 peer_pos;
       GstFormat format;
 
-      GST_OBJECT_LOCK (typefind);
-      if (typefind->store == NULL) {
-        GST_OBJECT_UNLOCK (typefind);
-        goto out;
-      }
-
       gst_query_parse_position (query, &format, &peer_pos);
 
+      GST_OBJECT_LOCK (typefind);
       /* FIXME: this code assumes that there's no discont in the queue */
       switch (format) {
         case GST_FORMAT_BYTES:
-          peer_pos -= GST_BUFFER_SIZE (typefind->store);
+          peer_pos -= gst_adapter_available (typefind->adapter);
           break;
         default:
           /* FIXME */
@@ -424,7 +407,6 @@ gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
   }
 
 out:
-  gst_object_unref (peer);
   return res;
 }
 
@@ -445,13 +427,14 @@ gst_type_find_element_src_event_mask (GstPad * pad)
 #endif
 
 static gboolean
-gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
+gst_type_find_element_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
-  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
+  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
 
   if (typefind->mode != MODE_NORMAL) {
     /* need to do more? */
-    gst_mini_object_unref (GST_MINI_OBJECT (event));
+    gst_mini_object_unref (GST_MINI_OBJECT_CAST (event));
     return FALSE;
   }
   return gst_pad_push_event (typefind->sink, event);
@@ -461,7 +444,6 @@ static void
 start_typefinding (GstTypeFindElement * typefind)
 {
   GST_DEBUG_OBJECT (typefind, "starting typefinding");
-  gst_pad_set_caps (typefind->src, NULL);
 
   GST_OBJECT_LOCK (typefind);
   if (typefind->caps)
@@ -476,6 +458,8 @@ stop_typefinding (GstTypeFindElement * typefind)
 {
   GstState state;
   gboolean push_cached_buffers;
+  gsize avail;
+  GstBuffer *buffer;
 
   gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);
 
@@ -485,54 +469,58 @@ stop_typefinding (GstTypeFindElement * typefind)
       push_cached_buffers ? " and pushing cached buffers" : "");
 
   GST_OBJECT_LOCK (typefind);
-  if (typefind->store) {
-    GstBuffer *store;
+  avail = gst_adapter_available (typefind->adapter);
+  if (avail == 0)
+    goto no_data;
 
-    store = gst_buffer_make_metadata_writable (typefind->store);
-    typefind->store = NULL;
-    gst_buffer_set_caps (store, typefind->caps);
-    GST_OBJECT_UNLOCK (typefind);
+  buffer = gst_adapter_take_buffer (typefind->adapter, avail);
+  GST_OBJECT_UNLOCK (typefind);
 
-    if (!push_cached_buffers) {
-      gst_buffer_unref (store);
-    } else {
-      GstPad *peer = gst_pad_get_peer (typefind->src);
-
-      typefind->mode = MODE_NORMAL;
-
-      /* make sure the user gets a meaningful error message in this case,
-       * which is not a core bug or bug of any kind (as the default error
-       * message emitted by gstpad.c otherwise would make you think) */
-      if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
-        GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
-            "downstream element only works in pull mode, erroring out");
-        GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
-            ("%s cannot work in push mode. The operation is not supported "
-                "with this source element or protocol.",
-                G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
-            ("Downstream pad %s:%s has no chainfunction, and the upstream "
-                "element does not support pull mode",
-                GST_DEBUG_PAD_NAME (peer)));
-        typefind->mode = MODE_ERROR;    /* make the chain function error out */
-        gst_buffer_unref (store);
-      } else {
-        gst_type_find_element_send_cached_events (typefind);
-        gst_pad_push (typefind->src, store);
-      }
+  if (!push_cached_buffers) {
+    gst_buffer_unref (buffer);
+  } else {
+    GstPad *peer = gst_pad_get_peer (typefind->src);
 
-      if (peer)
-        gst_object_unref (peer);
+    typefind->mode = MODE_NORMAL;
+
+    /* make sure the user gets a meaningful error message in this case,
+     * which is not a core bug or bug of any kind (as the default error
+     * message emitted by gstpad.c otherwise would make you think) */
+    if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
+      GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
+          "downstream element only works in pull mode, erroring out");
+      GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
+          ("%s cannot work in push mode. The operation is not supported "
+              "with this source element or protocol.",
+              G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
+          ("Downstream pad %s:%s has no chainfunction, and the upstream "
+              "element does not support pull mode", GST_DEBUG_PAD_NAME (peer)));
+      typefind->mode = MODE_ERROR;      /* make the chain function error out */
+      gst_buffer_unref (buffer);
+    } else {
+      gst_type_find_element_send_cached_events (typefind);
+      gst_pad_push (typefind->src, buffer);
     }
-  } else {
+    if (peer)
+      gst_object_unref (peer);
+  }
+  return;
+
+  /* ERRORS */
+no_data:
+  {
+    GST_DEBUG_OBJECT (typefind, "we have no data to typefind");
     GST_OBJECT_UNLOCK (typefind);
+    return;
   }
 }
 
 static gboolean
-gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
+gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   gboolean res = FALSE;
-  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
+  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
 
   GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
       GST_EVENT_TYPE_NAME (event), typefind->mode);
@@ -540,37 +528,25 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
   switch (typefind->mode) {
     case MODE_TYPEFIND:
       switch (GST_EVENT_TYPE (event)) {
-        case GST_EVENT_EOS:{
-          GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
-          GstCaps *caps = NULL;
+        case GST_EVENT_CAPS:
+        {
+          GstCaps *caps;
 
+          /* first pass the caps event downstream */
+          res = gst_pad_push_event (typefind->src, gst_event_ref (event));
+
+          /* then parse and push out our data */
+          gst_event_parse_caps (event, &caps);
+          res = gst_type_find_element_setcaps (typefind, caps);
+
+          gst_event_unref (event);
+          break;
+        }
+        case GST_EVENT_EOS:
+        {
           GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
+          gst_type_find_element_chain_do_typefinding (typefind, FALSE);
 
-          /* we might not have started typefinding yet because there was not
-           * enough data so far; just give it a shot now and see what we get */
-          GST_OBJECT_LOCK (typefind);
-          if (typefind->store) {
-            caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
-                typefind->store, &prob);
-            GST_OBJECT_UNLOCK (typefind);
-
-            if (caps && prob >= typefind->min_probability) {
-              g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
-                  0, prob, caps);
-            } else {
-              GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
-                  (NULL), (NULL));
-            }
-            gst_caps_replace (&caps, NULL);
-          } else {
-            GST_OBJECT_UNLOCK (typefind);
-            /* keep message in sync with the one in the pad activate function */
-            GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
-                (_("Stream contains no data.")),
-                ("Can't typefind empty stream"));
-          }
-
-          stop_typefinding (typefind);
           res = gst_pad_push_event (typefind->src, event);
           break;
         }
@@ -580,7 +556,7 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
               (GFunc) gst_mini_object_unref, NULL);
           g_list_free (typefind->cached_events);
           typefind->cached_events = NULL;
-          gst_buffer_replace (&typefind->store, NULL);
+          gst_adapter_clear (typefind->adapter);
           GST_OBJECT_UNLOCK (typefind);
           /* fall through */
         case GST_EVENT_FLUSH_START:
@@ -629,12 +605,8 @@ gst_type_find_element_send_cached_events (GstTypeFindElement * typefind)
 }
 
 static gboolean
-gst_type_find_element_setcaps (GstPad * pad, GstCaps * caps)
+gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps)
 {
-  GstTypeFindElement *typefind;
-
-  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
-
   /* don't operate on ANY caps */
   if (gst_caps_is_any (caps))
     return TRUE;
@@ -644,28 +616,34 @@ gst_type_find_element_setcaps (GstPad * pad, GstCaps * caps)
 
   /* Shortcircuit typefinding if we get caps */
   if (typefind->mode == MODE_TYPEFIND) {
+    GstBuffer *buffer;
+    gsize avail;
+
     GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
         "upstream buffer: %" GST_PTR_FORMAT, caps);
     typefind->mode = MODE_NORMAL;
 
     gst_type_find_element_send_cached_events (typefind);
     GST_OBJECT_LOCK (typefind);
-    if (typefind->store) {
-      GstBuffer *store;
+    avail = gst_adapter_available (typefind->adapter);
+    if (avail == 0)
+      goto no_data;
 
-      store = gst_buffer_make_metadata_writable (typefind->store);
-      typefind->store = NULL;
-      gst_buffer_set_caps (store, typefind->caps);
-      GST_OBJECT_UNLOCK (typefind);
+    buffer = gst_adapter_take_buffer (typefind->adapter, avail);
+    GST_OBJECT_UNLOCK (typefind);
 
-      GST_DEBUG_OBJECT (typefind, "Pushing store: %d", GST_BUFFER_SIZE (store));
-      gst_pad_push (typefind->src, store);
-    } else {
-      GST_OBJECT_UNLOCK (typefind);
-    }
+    GST_DEBUG_OBJECT (typefind, "Pushing buffer: %" G_GSIZE_FORMAT, avail);
+    gst_pad_push (typefind->src, buffer);
   }
 
   return TRUE;
+
+no_data:
+  {
+    GST_DEBUG_OBJECT (typefind, "no data to push");
+    GST_OBJECT_UNLOCK (typefind);
+    return TRUE;
+  }
 }
 
 static gchar *
@@ -751,12 +729,13 @@ gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad,
 }
 
 static GstFlowReturn
-gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
+gst_type_find_element_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer)
 {
   GstTypeFindElement *typefind;
   GstFlowReturn res = GST_FLOW_OK;
 
-  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
+  typefind = GST_TYPE_FIND_ELEMENT (parent);
 
   GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode);
 
@@ -766,18 +745,14 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
       return GST_FLOW_ERROR;
     case MODE_NORMAL:
       /* don't take object lock as typefind->caps should not change anymore */
-      buffer = gst_buffer_make_metadata_writable (buffer);
-      gst_buffer_set_caps (buffer, typefind->caps);
       return gst_pad_push (typefind->src, buffer);
-    case MODE_TYPEFIND:{
+    case MODE_TYPEFIND:
+    {
       GST_OBJECT_LOCK (typefind);
-      if (typefind->store)
-        typefind->store = gst_buffer_join (typefind->store, buffer);
-      else
-        typefind->store = buffer;
+      gst_adapter_push (typefind->adapter, buffer);
       GST_OBJECT_UNLOCK (typefind);
 
-      res = gst_type_find_element_chain_do_typefinding (typefind);
+      res = gst_type_find_element_chain_do_typefinding (typefind, TRUE);
 
       if (typefind->mode == MODE_ERROR)
         res = GST_FLOW_ERROR;
@@ -793,112 +768,147 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
 }
 
 static GstFlowReturn
-gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind)
+gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
+    gboolean check_avail)
 {
   GstTypeFindProbability probability;
   GstCaps *caps;
+  gsize avail;
+  const guint8 *data;
+  gboolean have_min, have_max;
 
   GST_OBJECT_LOCK (typefind);
-  if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
+  avail = gst_adapter_available (typefind->adapter);
+
+  if (check_avail) {
+    have_min = avail >= TYPE_FIND_MIN_SIZE;
+    have_max = avail >= TYPE_FIND_MAX_SIZE;
+  } else {
+    have_min = TRUE;
+    have_max = TRUE;
+  }
+
+  if (!have_min)
+    goto not_enough_data;
+
+  /* map all available data */
+  data = gst_adapter_map (typefind->adapter, avail);
+  caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
+      data, avail, &probability);
+  gst_adapter_unmap (typefind->adapter);
+
+  if (caps == NULL && have_max)
+    goto no_type_found;
+  else if (caps == NULL)
+    goto wait_for_data;
+
+  /* found a type */
+  if (probability < typefind->min_probability)
+    goto low_probability;
+  GST_OBJECT_UNLOCK (typefind);
+
+  /* probability is good enough too, so let's make it known ... emiting this
+   * signal calls our object handler which sets the caps. */
+  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
+      probability, caps);
+
+  /* .. and send out the accumulated data */
+  stop_typefinding (typefind);
+  gst_caps_unref (caps);
+
+  return GST_FLOW_OK;
+
+not_enough_data:
+  {
     GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
-        "(%u bytes)", GST_BUFFER_SIZE (typefind->store));
+        "(%" G_GSIZE_FORMAT " bytes)", avail);
     GST_OBJECT_UNLOCK (typefind);
     return GST_FLOW_OK;
   }
-
-  caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
-      typefind->store, &probability);
-  if (caps == NULL && GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
+no_type_found:
+  {
     GST_OBJECT_UNLOCK (typefind);
     GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
     stop_typefinding (typefind);
     return GST_FLOW_ERROR;
-  } else if (caps == NULL) {
+  }
+wait_for_data:
+  {
+    GST_DEBUG_OBJECT (typefind,
+        "no caps found with %" G_GSIZE_FORMAT " bytes of data, "
+        "waiting for more data", avail);
     GST_OBJECT_UNLOCK (typefind);
-    GST_DEBUG_OBJECT (typefind, "no caps found with %u bytes of data, "
-        "waiting for more data", GST_BUFFER_SIZE (typefind->store));
     return GST_FLOW_OK;
   }
-
-  /* found a type */
-  if (probability < typefind->min_probability) {
+low_probability:
+  {
     GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
         "probability is %u which is lower than the required minimum of %u",
         caps, probability, typefind->min_probability);
 
-    gst_caps_replace (&caps, NULL);
+    gst_caps_unref (caps);
 
-    if (GST_BUFFER_SIZE (typefind->store) >= TYPE_FIND_MAX_SIZE) {
-      GST_OBJECT_UNLOCK (typefind);
-      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
-      stop_typefinding (typefind);
-      return GST_FLOW_ERROR;
-    }
+    if (have_max)
+      goto no_type_found;
 
     GST_OBJECT_UNLOCK (typefind);
     GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
     return GST_FLOW_OK;
   }
-  GST_OBJECT_UNLOCK (typefind);
-
-  /* probability is good enough too, so let's make it known ... */
-  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
-      probability, caps);
-
-  /* .. and send out the accumulated data */
-  stop_typefinding (typefind);
-  gst_caps_unref (caps);
-  return GST_FLOW_OK;
-}
-
-static gboolean
-gst_type_find_element_checkgetrange (GstPad * srcpad)
-{
-  GstTypeFindElement *typefind;
-
-  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
-
-  return gst_pad_check_pull_range (typefind->sink);
 }
 
 static GstFlowReturn
-gst_type_find_element_getrange (GstPad * srcpad,
+gst_type_find_element_getrange (GstPad * srcpad, GstObject * parent,
     guint64 offset, guint length, GstBuffer ** buffer)
 {
   GstTypeFindElement *typefind;
   GstFlowReturn ret;
 
-  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
+  typefind = GST_TYPE_FIND_ELEMENT (parent);
 
   ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
 
-  if (ret == GST_FLOW_OK && buffer && *buffer) {
-    /* don't take object lock as typefind->caps should not change anymore */
-    /* we assume that pulled buffers are meta-data writable */
-    gst_buffer_set_caps (*buffer, typefind->caps);
-  }
-
   return ret;
 }
 
 static gboolean
-gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active)
+gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
+  gboolean res;
   GstTypeFindElement *typefind;
 
-  typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
+  typefind = GST_TYPE_FIND_ELEMENT (parent);
 
-  return gst_pad_activate_pull (typefind->sink, active);
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      res = gst_pad_activate_mode (typefind->sink, mode, active);
+      if (typefind->caps) {
+        GstCaps *caps;
+        GST_OBJECT_LOCK (typefind);
+        caps = gst_caps_ref (typefind->caps);
+        GST_OBJECT_UNLOCK (typefind);
+        gst_pad_push_event (typefind->src, gst_event_new_caps (caps));
+        gst_caps_unref (caps);
+      }
+      break;
+    default:
+      res = TRUE;
+      break;
+  }
+  return res;
 }
 
 static gboolean
-gst_type_find_element_activate (GstPad * pad)
+gst_type_find_element_activate (GstPad * pad, GstObject * parent)
 {
   GstTypeFindProbability probability = GST_TYPE_FIND_NONE;
   GstCaps *found_caps = NULL;
   GstTypeFindElement *typefind;
+  GstQuery *query;
+  gboolean pull_mode;
 
-  typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
+  typefind = GST_TYPE_FIND_ELEMENT (parent);
 
   /* if we have force caps, use those */
   GST_OBJECT_LOCK (typefind);
@@ -923,27 +933,37 @@ gst_type_find_element_activate (GstPad * pad)
    */
 
   /* 1 */
-  if (!gst_pad_check_pull_range (pad) || !gst_pad_activate_pull (pad, TRUE)) {
-    start_typefinding (typefind);
-    return gst_pad_activate_push (pad, TRUE);
+  query = gst_query_new_scheduling ();
+
+  if (!gst_pad_peer_query (pad, query)) {
+    gst_query_unref (query);
+    goto typefind_push;
   }
 
-  GST_DEBUG_OBJECT (typefind, "find type in pull mode");
+  pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
+  gst_query_unref (query);
+
+  if (!pull_mode)
+    goto typefind_push;
+
+  if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE))
+    goto typefind_push;
 
   /* 2 */
+  GST_DEBUG_OBJECT (typefind, "find type in pull mode");
+
   {
     GstPad *peer;
 
     peer = gst_pad_get_peer (pad);
     if (peer) {
       gint64 size;
-      GstFormat format = GST_FORMAT_BYTES;
       gchar *ext;
 
-      if (!gst_pad_query_duration (peer, &format, &size)) {
+      if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
         GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
         gst_object_unref (peer);
-        gst_pad_activate_pull (pad, FALSE);
+        gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, FALSE);
         return FALSE;
       }
 
@@ -953,16 +973,20 @@ gst_type_find_element_activate (GstPad * pad)
         GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
             (_("Stream contains no data.")), ("Can't typefind empty stream"));
         gst_object_unref (peer);
-        gst_pad_activate_pull (pad, FALSE);
+        gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, FALSE);
         return FALSE;
       }
       ext = gst_type_find_get_extension (typefind, pad);
 
-      found_caps = gst_type_find_helper_get_range_ext (GST_OBJECT_CAST (peer),
+      found_caps =
+          gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
+          GST_OBJECT_PARENT (peer),
           (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
           (guint64) size, ext, &probability);
       g_free (ext);
 
+      GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);
+
       gst_object_unref (peer);
     }
   }
@@ -981,13 +1005,18 @@ gst_type_find_element_activate (GstPad * pad)
   }
 
   /* 3 */
-  gst_pad_activate_pull (pad, FALSE);
+  GST_DEBUG ("Deactivate pull mode");
+  gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, FALSE);
 
+#if 0
   /* 4 */
-  gst_pad_activate_push (typefind->src, FALSE);
+  GST_DEBUG ("Deactivate push mode mode");
+  gst_pad_activate_mode (typefind->src, GST_PAD_MODE_PUSH, FALSE);
+#endif
 
   /* 5 */
   if (!found_caps || probability < typefind->min_probability) {
+    GST_DEBUG ("Trying to guess using extension");
     found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
   }
 
@@ -1000,9 +1029,11 @@ gst_type_find_element_activate (GstPad * pad)
 
 done:
   /* 7 */
+  GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
   g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
       0, probability, found_caps);
   typefind->mode = MODE_NORMAL;
+
 really_done:
   gst_caps_unref (found_caps);
 
@@ -1012,10 +1043,16 @@ really_done:
   else {
     gboolean ret;
 
-    ret = gst_pad_activate_push (typefind->src, TRUE);
-    ret &= gst_pad_activate_push (pad, TRUE);
+    GST_DEBUG ("Activating in push mode");
+    ret = gst_pad_activate_mode (typefind->src, GST_PAD_MODE_PUSH, TRUE);
+    ret &= gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
     return ret;
   }
+typefind_push:
+  {
+    start_typefinding (typefind);
+    return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
+  }
 }
 
 static GstStateChangeReturn
index dbce72f..5c34758 100644 (file)
 
 #include <gst/gstinfo.h>
 #include <gst/gstelement.h>
+#include <gst/base/gstadapter.h>
 
 G_BEGIN_DECLS
 
-
-
 #define GST_TYPE_TYPE_FIND_ELEMENT             (gst_type_find_element_get_type ())
 #define GST_TYPE_FIND_ELEMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElement))
 #define GST_IS_TYPE_FIND_ELEMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TYPE_FIND_ELEMENT))
@@ -56,7 +55,7 @@ struct _GstTypeFindElement {
   GstCaps *            caps;
 
   guint                        mode;
-  GstBuffer *          store;
+  GstAdapter *         adapter;
 
   GList *               cached_events;
   GstCaps *             force_caps;
index ae905f4..41bf207 100644 (file)
@@ -72,39 +72,26 @@ static void gst_valve_set_property (GObject * object,
 static void gst_valve_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-static gboolean gst_valve_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset,
-    guint size, GstCaps * caps, GstBuffer ** buf);
-static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer);
-static GstCaps *gst_valve_getcaps (GstPad * pad);
-
-#define _do_init(bla) \
+static GstFlowReturn gst_valve_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static gboolean gst_valve_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_valve_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+
+#define _do_init \
   GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
-
-GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
-
-static void
-gst_valve_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&srctemplate));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sinktemplate));
-
-  gst_element_class_set_details_simple (element_class, "Valve element",
-      "Filter", "Drops buffers and events or lets them through",
-      "Olivier Crete <olivier.crete@collabora.co.uk>");
-}
+#define gst_valve_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstValve, gst_valve, GST_TYPE_ELEMENT, _do_init);
 
 static void
 gst_valve_class_init (GstValveClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
 
   gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) (klass);
 
   gobject_class->set_property = gst_valve_set_property;
   gobject_class->get_property = gst_valve_get_property;
@@ -113,28 +100,35 @@ gst_valve_class_init (GstValveClass * klass)
       g_param_spec_boolean ("drop", "Drop buffers and events",
           "Whether to drop buffers and events or let them through",
           DEFAULT_DROP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&srctemplate));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sinktemplate));
+
+  gst_element_class_set_details_simple (gstelement_class, "Valve element",
+      "Filter", "Drops buffers and events or lets them through",
+      "Olivier Crete <olivier.crete@collabora.co.uk>");
 }
 
 static void
-gst_valve_init (GstValve * valve, GstValveClass * klass)
+gst_valve_init (GstValve * valve)
 {
   valve->drop = FALSE;
   valve->discont = FALSE;
 
   valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
-  gst_pad_set_getcaps_function (valve->srcpad,
-      GST_DEBUG_FUNCPTR (gst_valve_getcaps));
+  gst_pad_set_query_function (valve->srcpad,
+      GST_DEBUG_FUNCPTR (gst_valve_query));
   gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
 
   valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
   gst_pad_set_chain_function (valve->sinkpad,
       GST_DEBUG_FUNCPTR (gst_valve_chain));
   gst_pad_set_event_function (valve->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_valve_event));
-  gst_pad_set_bufferalloc_function (valve->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc));
-  gst_pad_set_getcaps_function (valve->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_valve_getcaps));
+      GST_DEBUG_FUNCPTR (gst_valve_sink_event));
+  gst_pad_set_query_function (valve->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_valve_query));
   gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
 }
 
@@ -172,9 +166,9 @@ gst_valve_get_property (GObject * object,
 }
 
 static GstFlowReturn
-gst_valve_chain (GstPad * pad, GstBuffer * buffer)
+gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
-  GstValve *valve = GST_VALVE (GST_OBJECT_PARENT (pad));
+  GstValve *valve = GST_VALVE (parent);
   GstFlowReturn ret = GST_FLOW_OK;
 
   if (g_atomic_int_get (&valve->drop)) {
@@ -182,7 +176,7 @@ gst_valve_chain (GstPad * pad, GstBuffer * buffer)
     valve->discont = TRUE;
   } else {
     if (valve->discont) {
-      buffer = gst_buffer_make_metadata_writable (buffer);
+      buffer = gst_buffer_make_writable (buffer);
       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
       valve->discont = FALSE;
     }
@@ -202,11 +196,13 @@ gst_valve_chain (GstPad * pad, GstBuffer * buffer)
 
 
 static gboolean
-gst_valve_event (GstPad * pad, GstEvent * event)
+gst_valve_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
-  GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
+  GstValve *valve;
   gboolean ret = TRUE;
 
+  valve = GST_VALVE (parent);
+
   if (g_atomic_int_get (&valve->drop))
     gst_event_unref (event);
   else
@@ -218,48 +214,29 @@ gst_valve_event (GstPad * pad, GstEvent * event)
   if (g_atomic_int_get (&valve->drop))
     ret = TRUE;
 
-  gst_object_unref (valve);
-  return ret;
-}
-
-static GstFlowReturn
-gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf)
-{
-  GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad));
-  GstFlowReturn ret = GST_FLOW_OK;
-
-  if (g_atomic_int_get (&valve->drop))
-    *buf = NULL;
-  else
-    ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf);
-
-  /* Ignore errors if "drop" was changed while the thread was blocked
-   * downwards
-   */
-  if (g_atomic_int_get (&valve->drop))
-    ret = GST_FLOW_OK;
-
-  gst_object_unref (valve);
-
   return ret;
 }
 
-static GstCaps *
-gst_valve_getcaps (GstPad * pad)
+static gboolean
+gst_valve_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstValve *valve = GST_VALVE (gst_pad_get_parent (pad));
-  GstCaps *caps;
+  GstValve *valve;
+  gboolean res;
+  GstPad *otherpad;
 
-  if (pad == valve->sinkpad)
-    caps = gst_pad_peer_get_caps (valve->srcpad);
-  else
-    caps = gst_pad_peer_get_caps (valve->sinkpad);
+  valve = GST_VALVE (parent);
 
-  if (caps == NULL)
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+  otherpad = (pad == valve->sinkpad ? valve->srcpad : valve->sinkpad);
 
-  gst_object_unref (valve);
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+      if (!(res = gst_pad_peer_query (otherpad, query)))
+        res = gst_pad_query_default (pad, parent, query);
+      break;
+    default:
+      res = gst_pad_peer_query (otherpad, query);
+      break;
+  }
 
-  return caps;
+  return res;
 }
diff --git a/plugins/indexers/.gitignore b/plugins/indexers/.gitignore
deleted file mode 100644 (file)
index 68e008e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-*.bb
-*.bbg
-*.da
-*.def
-*.gcno
-*.lo
-*.la
diff --git a/plugins/indexers/Makefile.am b/plugins/indexers/Makefile.am
deleted file mode 100644 (file)
index 1220671..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-plugin_LTLIBRARIES = libgstcoreindexers.la
-
-# file index uses xml
-if HAVE_MMAP
-if GST_DISABLE_LOADSAVE
-GST_LOADSAVE_SRC =
-GST_FILEINDEX_LIBS =
-else
-GST_LOADSAVE_SRC = gstfileindex.c
-GST_FILEINDEX_LIBS = $(XML_LIBS)
-endif
-else
-GST_LOADSAVE_SRC =
-GST_FILEINDEX_LIBS =
-endif
-
-noinst_HEADERS =               \
-       gstindexers.h
-
-libgstcoreindexers_la_DEPENDENCIES = $(top_builddir)/gst/libgstreamer-@GST_MAJORMINOR@.la
-libgstcoreindexers_la_SOURCES = gstindexers.c gstmemindex.c $(GST_LOADSAVE_SRC)
-libgstcoreindexers_la_CFLAGS = $(GST_OBJ_CFLAGS)
-libgstcoreindexers_la_LIBADD = $(GST_OBJ_LIBS) $(GST_FILEINDEX_LIBS)
-libgstcoreindexers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstcoreindexers_la_LIBTOOLFLAGS = --tag=disable-static
-
-%.c.gcov: .libs/libgstcoreindexers_la-%.gcda %.c
-       $(GCOV) -b -f -o $^ > $@.out
-
-gcov: $(libgstcoreindexers_la_SOURCES:=.gcov)
-
-Android.mk: Makefile.am
-       androgenizer -:PROJECT gstreamer -:SHARED libgstcoreindexers -:TAGS eng debug \
-        -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-        -:SOURCES $(libgstcoreindexers_la_SOURCES) \
-        -:CFLAGS $(DEFS) $(libgstcoreindexers_la_CFLAGS) \
-        -:LDFLAGS $(libgstcoreindexers_la_LDFLAGS) \
-                  $(libgstcoreindexers_la_LIBADD) \
-        -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-                      LOCAL_MODULE_PATH:=$$\(TARGET_OUT\)/lib/gstreamer-@GST_MAJORMINOR@ \
-       > $@
-
diff --git a/plugins/indexers/gstfileindex.c b/plugins/indexers/gstfileindex.c
deleted file mode 100644 (file)
index c8c8fb1..0000000
+++ /dev/null
@@ -1,990 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Erik Walthinsen <omega@cse.ogi.edu>
- *               2003 Joshua N Pritikin <jpritikin@pobox.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <gst/gst.h>
-
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#ifdef GST_DISABLE_DEPRECATED
-#include <libxml/parser.h>
-#endif
-
-#include "gstindexers.h"
-
-#define GST_TYPE_FILE_INDEX             \
-  (gst_file_index_get_type ())
-#define GST_FILE_INDEX(obj)             \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FILE_INDEX, GstFileIndex))
-#define GST_FILE_INDEX_CLASS(klass)     \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_FILE_INDEX, GstFileIndexClass))
-#define GST_IS_FILE_INDEX(obj)          \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FILE_INDEX))
-#define GST_IS_FILE_INDEX_CLASS(klass)    \
-  (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_FILE_INDEX))
-
-/*
- * Object model:
- *
- * We build an index to each entry for each id.
- *
- *
- *  fileindex
- *    -----------------------------...
- *    !                  !
- *   id1                 id2
- *    !
- *   GArray
- *
- * The fileindex creates a FileIndexId object for each writer id, a
- * Hashtable is kept to map the id to the FileIndexId
- *
- * The FileIndexId also keeps all the values in a sorted GArray.
- *
- * Finding a value for an id/format requires locating the correct GArray,
- * then do a binary search to get the required value.
- *
- * Unlike gstmemindex:  All formats are assumed to sort to the
- * same order.  All formats are assumed to be available from
- * any entry.
- */
-
-/*
- * Each array element is (32bits flags, nformats * 64bits)
- */
-typedef struct
-{
-  gint id;
-  gchar *id_desc;
-  gint nformats;
-  GstFormat *format;
-  GArray *array;
-}
-GstFileIndexId;
-
-typedef struct _GstFileIndex GstFileIndex;
-typedef struct _GstFileIndexClass GstFileIndexClass;
-
-#define ARRAY_ROW_SIZE(_ii) \
-  (sizeof (gint32) + (_ii)->nformats * sizeof (gint64))
-#define ARRAY_TOTAL_SIZE(_ii) \
-  (_ii->array->len * ARRAY_ROW_SIZE(_ii))
-
-/* don't forget to convert to/from BE byte-order */
-#define ARRAY_ROW_FLAGS(_row) \
-  (*((gint32*) (_row)))
-#define ARRAY_ROW_VALUE(_row,_vx) \
-  (*(gint64*) (((gchar*)(_row)) + sizeof (gint32) + (_vx) * sizeof (gint64)))
-
-GST_DEBUG_CATEGORY_STATIC (DC);
-#define GST_CAT_DEFAULT DC
-
-struct _GstFileIndex
-{
-  GstIndex parent;
-
-  gchar *location;
-  gboolean is_loaded;
-  GSList *unresolved;
-  gint next_id;
-  GHashTable *id_index;
-
-  GstIndexEntry *ret_entry;     /* hack to avoid leaking memory */
-};
-
-struct _GstFileIndexClass
-{
-  GstIndexClass parent_class;
-};
-
-enum
-{
-  ARG_0,
-  ARG_LOCATION,
-};
-
-static void gst_file_index_dispose (GObject * object);
-
-static void
-gst_file_index_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void
-gst_file_index_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-
-static gboolean
-gst_file_index_get_writer_id (GstIndex * _index, gint * id,
-    gchar * writer_string);
-
-static void gst_file_index_commit (GstIndex * index, gint writer_id);
-static void gst_file_index_add_entry (GstIndex * index, GstIndexEntry * entry);
-static GstIndexEntry *gst_file_index_get_assoc_entry (GstIndex * index, gint id,
-    GstIndexLookupMethod method,
-    GstAssocFlags flags,
-    GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data);
-
-#define CLASS(file_index)  GST_FILE_INDEX_CLASS (G_OBJECT_GET_CLASS (file_index))
-
-GType gst_file_index_get_type (void);
-
-G_DEFINE_TYPE (GstFileIndex, gst_file_index, GST_TYPE_INDEX);
-
-static void
-gst_file_index_class_init (GstFileIndexClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstIndexClass *gstindex_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstindex_class = (GstIndexClass *) klass;
-
-  gobject_class->dispose = gst_file_index_dispose;
-  gobject_class->set_property = gst_file_index_set_property;
-  gobject_class->get_property = gst_file_index_get_property;
-
-  gstindex_class->add_entry = gst_file_index_add_entry;
-  gstindex_class->get_assoc_entry = gst_file_index_get_assoc_entry;
-  gstindex_class->commit = gst_file_index_commit;
-  gstindex_class->get_writer_id = gst_file_index_get_writer_id;
-
-  g_object_class_install_property (gobject_class, ARG_LOCATION,
-      g_param_spec_string ("location", "File Location",
-          "Location of the index file", NULL,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-gst_file_index_init (GstFileIndex * index)
-{
-  GST_DEBUG ("created new file index");
-
-  index->id_index = g_hash_table_new (g_int_hash, g_int_equal);
-}
-
-static void
-_file_index_id_free (GstFileIndexId * index_id, gboolean is_mmapped)
-{
-  if (index_id->id_desc)
-    g_free (index_id->id_desc);
-  if (index_id->format)
-    g_free (index_id->format);
-  if (index_id->array) {
-    if (is_mmapped)
-      munmap (index_id->array->data, ARRAY_TOTAL_SIZE (index_id));
-    g_array_free (index_id->array, !is_mmapped);
-  }
-  g_slice_free (GstFileIndexId, index_id);
-}
-
-static gboolean
-_id_index_free_helper (gpointer _key, GstFileIndexId * index_id,
-    GstFileIndex * index)
-{
-  _file_index_id_free (index_id, index->is_loaded);
-  return TRUE;
-}
-
-static void
-gst_file_index_dispose (GObject * object)
-{
-  GstFileIndex *index = GST_FILE_INDEX (object);
-
-  if (index->location) {
-    g_free (index->location);
-    index->location = NULL;
-  }
-
-  {
-    GSList *elem;
-
-    for (elem = index->unresolved; elem; elem = g_slist_next (elem))
-      _file_index_id_free (elem->data, index->is_loaded);
-    g_slist_free (index->unresolved);
-    index->unresolved = NULL;
-  }
-
-  g_hash_table_foreach_steal (index->id_index,
-      (GHRFunc) _id_index_free_helper, index);
-  g_hash_table_destroy (index->id_index);
-  index->id_index = NULL;
-
-  gst_index_entry_free (index->ret_entry);      /* hack */
-
-  G_OBJECT_CLASS (gst_file_index_parent_class)->dispose (object);
-}
-
-struct fi_find_writer_context
-{
-  const gchar *writer_string;
-  GstFileIndexId *ii;
-};
-
-static void
-_fi_find_writer (gpointer key, gpointer val, gpointer data)
-{
-  struct fi_find_writer_context *cx = data;
-  GstFileIndexId *ii = val;
-
-  if (strcmp (ii->id_desc, cx->writer_string) == 0)
-    cx->ii = ii;
-}
-
-static gboolean
-gst_file_index_get_writer_id (GstIndex * _index,
-    gint * id, gchar * writer_string)
-{
-  GstFileIndex *index = GST_FILE_INDEX (_index);
-  GSList *pending = index->unresolved;
-  gboolean match = FALSE;
-  GSList *elem;
-
-  if (!index->is_loaded)
-    return FALSE;
-
-  g_return_val_if_fail (id, FALSE);
-  g_return_val_if_fail (writer_string, FALSE);
-
-  index->unresolved = NULL;
-
-  for (elem = pending; elem; elem = g_slist_next (elem)) {
-    GstFileIndexId *ii = elem->data;
-
-    if (strcmp (ii->id_desc, writer_string) != 0) {
-      index->unresolved = g_slist_prepend (index->unresolved, ii);
-      continue;
-    }
-
-    if (match) {
-      GST_WARNING_OBJECT (index, "Duplicate matches for writer '%s'",
-          writer_string);
-      continue;
-    }
-
-    ii->id = *id = ++index->next_id;
-    g_hash_table_insert (index->id_index, &ii->id, ii);
-    match = TRUE;
-  }
-
-  g_slist_free (pending);
-
-  if (!match) {
-    struct fi_find_writer_context cx;
-
-    cx.writer_string = writer_string;
-    cx.ii = NULL;
-    g_hash_table_foreach (index->id_index, _fi_find_writer, &cx);
-
-    if (cx.ii) {
-      match = TRUE;
-      GST_DEBUG_OBJECT (index, "Resolved writer '%s' again", writer_string);
-    } else
-      GST_WARNING_OBJECT (index, "Can't resolve writer '%s'", writer_string);
-  }
-
-  return match;
-}
-
-static void
-_fc_alloc_array (GstFileIndexId * id_index)
-{
-  g_assert (!id_index->array);
-  id_index->array =
-      g_array_sized_new (FALSE, FALSE, ARRAY_ROW_SIZE (id_index), 0);
-}
-
-static void
-gst_file_index_load (GstFileIndex * index)
-{
-  xmlDocPtr doc;
-  xmlNodePtr root, part;
-  xmlChar *val;
-
-  g_assert (index->location);
-  g_return_if_fail (!index->is_loaded);
-
-  {
-    gchar *path = g_strdup_printf ("%s/gstindex.xml", index->location);
-    GError *err = NULL;
-    gchar *buf;
-    gsize len;
-
-    g_file_get_contents (path, &buf, &len, &err);
-    g_free (path);
-    if (err) {
-      GST_ERROR_OBJECT (index, "%s", err->message);
-      return;
-    }
-
-    doc = xmlParseMemory (buf, len);
-    g_free (buf);
-  }
-
-  //xmlDocFormatDump (stderr, doc, TRUE);
-
-  root = doc->xmlRootNode;
-  if (strcmp ((char *) root->name, "gstfileindex") != 0) {
-    GST_ERROR_OBJECT (index, "root node isn't a gstfileindex");
-    return;
-  }
-
-  val = xmlGetProp (root, (xmlChar *) "version");
-  if (!val || atoi ((char *) val) != 1) {
-    GST_ERROR_OBJECT (index, "version != 1");
-    return;
-  }
-  free (val);
-
-  for (part = root->children; part; part = part->next) {
-    if (strcmp ((char *) part->name, "writers") == 0) {
-      xmlNodePtr writer;
-
-      for (writer = part->children; writer; writer = writer->next) {
-        xmlChar *datafile = xmlGetProp (writer, (xmlChar *) "datafile");
-        gchar *path = g_strdup_printf ("%s/%s", index->location, datafile);
-        int fd;
-        GstFileIndexId *id_index;
-        xmlNodePtr wpart;
-        xmlChar *entries_str;
-        gpointer array_data;
-
-        free (datafile);
-
-        fd = open (path, O_RDONLY);
-        g_free (path);
-        if (fd < 0) {
-          GST_ERROR_OBJECT (index,
-              "Can't open '%s': %s", path, g_strerror (errno));
-          continue;
-        }
-
-        id_index = g_slice_new0 (GstFileIndexId);
-        id_index->id_desc = (char *) xmlGetProp (writer, (xmlChar *) "id");
-
-        for (wpart = writer->children; wpart; wpart = wpart->next) {
-          if (strcmp ((char *) wpart->name, "formats") == 0) {
-            xmlChar *count_str = xmlGetProp (wpart, (xmlChar *) "count");
-            gint fx = 0;
-            xmlNodePtr format;
-
-            id_index->nformats = atoi ((char *) count_str);
-            free (count_str);
-
-            id_index->format = g_new (GstFormat, id_index->nformats);
-
-            for (format = wpart->children; format; format = format->next) {
-              xmlChar *nick = xmlGetProp (format, (xmlChar *) "nick");
-              GstFormat fmt = gst_format_get_by_nick ((gchar *) nick);
-
-              if (fmt == GST_FORMAT_UNDEFINED)
-                GST_ERROR_OBJECT (index, "format '%s' undefined", nick);
-              g_assert (fx < id_index->nformats);
-              id_index->format[fx++] = fmt;
-              free (nick);
-            }
-          } else
-            GST_INFO_OBJECT (index, "unknown wpart '%s'", wpart->name);
-        }
-
-        g_assert (id_index->nformats > 0);
-        _fc_alloc_array (id_index);
-        g_assert (id_index->array->data == NULL);       /* little bit risky */
-
-        entries_str = xmlGetProp (writer, (xmlChar *) "entries");
-        id_index->array->len = atoi ((char *) entries_str);
-        free (entries_str);
-
-        array_data =
-            mmap (NULL, ARRAY_TOTAL_SIZE (id_index), PROT_READ, MAP_SHARED, fd,
-            0);
-        close (fd);
-        if (array_data == MAP_FAILED) {
-          GST_ERROR_OBJECT (index,
-              "mmap %s failed: %s", path, g_strerror (errno));
-          continue;
-        }
-
-        id_index->array->data = array_data;
-
-        index->unresolved = g_slist_prepend (index->unresolved, id_index);
-      }
-    } else
-      GST_INFO_OBJECT (index, "unknown part '%s'", part->name);
-  }
-
-  xmlFreeDoc (doc);
-
-  GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE);
-  index->is_loaded = TRUE;
-  GST_LOG_OBJECT (index, "index %s loaded OK", index->location);
-}
-
-static void
-gst_file_index_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstFileIndex *index = GST_FILE_INDEX (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      if (index->location)
-        g_free (index->location);
-      index->location = g_value_dup_string (value);
-
-      if (index->location && !g_hash_table_size (index->id_index))
-        gst_file_index_load (index);
-      break;
-  }
-}
-
-static void
-gst_file_index_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstFileIndex *index = GST_FILE_INDEX (object);
-
-  switch (prop_id) {
-    case ARG_LOCATION:
-      g_value_set_string (value, index->location);
-      break;
-  }
-}
-
-static void
-_file_index_id_save_xml (gpointer _key, GstFileIndexId * ii, xmlNodePtr writers)
-{
-  const gint bufsize = 16;
-  gchar buf[16];
-  xmlNodePtr writer;
-  xmlNodePtr formats;
-  gint xx;
-
-  if (!ii->array) {
-    GST_INFO ("Index for %s is empty", ii->id_desc);
-    return;
-  }
-
-  writer = xmlNewChild (writers, NULL, (xmlChar *) "writer", NULL);
-  xmlSetProp (writer, (xmlChar *) "id", (xmlChar *) ii->id_desc);
-  g_snprintf (buf, bufsize, "%d", ii->array->len);
-  xmlSetProp (writer, (xmlChar *) "entries", (xmlChar *) buf);
-  g_snprintf (buf, bufsize, "%d", ii->id);      /* any unique number is OK */
-  xmlSetProp (writer, (xmlChar *) "datafile", (xmlChar *) buf);
-
-  formats = xmlNewChild (writer, NULL, (xmlChar *) "formats", NULL);
-  g_snprintf (buf, bufsize, "%d", ii->nformats);
-  xmlSetProp (formats, (xmlChar *) "count", (xmlChar *) buf);
-
-  for (xx = 0; xx < ii->nformats; xx++) {
-    xmlNodePtr format = xmlNewChild (formats, NULL, (xmlChar *) "format", NULL);
-    const GstFormatDefinition *def = gst_format_get_details (ii->format[xx]);
-
-    xmlSetProp (format, (xmlChar *) "nick", (xmlChar *) def->nick);
-  }
-}
-
-/*
-  We must save the binary data in separate files because
-  mmap wants getpagesize() alignment.  If we append all
-  the data to one file then we don't know the appropriate
-  padding since the page size isn't fixed.
-*/
-static void
-_file_index_id_save_entries (gpointer * _key,
-    GstFileIndexId * ii, gchar * prefix)
-{
-  GError *err;
-  gchar *path;
-  GIOChannel *chan;
-
-  if (!ii->array)
-    return;
-
-  err = NULL;
-  path = g_strdup_printf ("%s/%d", prefix, ii->id);
-  chan = g_io_channel_new_file (path, "w", &err);
-  g_free (path);
-  if (err)
-    goto fail;
-
-  g_io_channel_set_encoding (chan, NULL, &err);
-  if (err)
-    goto fail;
-
-  g_io_channel_write_chars (chan,
-      ii->array->data, ARRAY_TOTAL_SIZE (ii), NULL, &err);
-  if (err)
-    goto fail;
-
-  g_io_channel_shutdown (chan, TRUE, &err);
-  if (err)
-    goto fail;
-
-  g_io_channel_unref (chan);
-  return;
-
-fail:
-  GST_ERROR ("%s", err->message);
-}
-
-/*
-  We have to save the whole set of indexes into a single file
-  so it doesn't make sense to commit only a single writer.
-
-  i suggest:
-
-  gst_index_commit (index, -1);
-*/
-static void
-gst_file_index_commit (GstIndex * _index, gint _writer_id)
-{
-  GstFileIndex *index = GST_FILE_INDEX (_index);
-  xmlDocPtr doc;
-  xmlNodePtr writers;
-  GError *err = NULL;
-  gchar *path;
-  GIOChannel *tocfile;
-
-  g_return_if_fail (index->location);
-  g_return_if_fail (!index->is_loaded);
-
-  GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE);
-
-  doc = xmlNewDoc ((xmlChar *) "1.0");
-  doc->xmlRootNode =
-      xmlNewDocNode (doc, NULL, (xmlChar *) "gstfileindex", NULL);
-  xmlSetProp (doc->xmlRootNode, (xmlChar *) "version", (xmlChar *) "1");
-
-  writers = xmlNewChild (doc->xmlRootNode, NULL, (xmlChar *) "writers", NULL);
-  g_hash_table_foreach (index->id_index,
-      (GHFunc) _file_index_id_save_xml, writers);
-
-  if (mkdir (index->location, 0777) && errno != EEXIST) {
-    GST_ERROR_OBJECT (index, "mkdir %s: %s", index->location,
-        g_strerror (errno));
-    return;
-  }
-
-  path = g_strdup_printf ("%s/gstindex.xml", index->location);
-  tocfile = g_io_channel_new_file (path, "w", &err);
-  g_free (path);
-  if (err) {
-    GST_ERROR_OBJECT (index, "%s", err->message);
-    return;
-  }
-
-  g_io_channel_set_encoding (tocfile, NULL, &err);
-  if (err) {
-    GST_ERROR_OBJECT (index, "%s", err->message);
-    return;
-  }
-
-  {
-    xmlChar *xmlmem;
-    int xmlsize;
-
-    xmlDocDumpMemory (doc, &xmlmem, &xmlsize);
-    g_io_channel_write_chars (tocfile, (gchar *) xmlmem, xmlsize, NULL, &err);
-    if (err) {
-      GST_ERROR_OBJECT (index, "%s", err->message);
-      return;
-    }
-    xmlFreeDoc (doc);
-    free (xmlmem);
-  }
-
-  g_io_channel_shutdown (tocfile, TRUE, &err);
-  if (err) {
-    GST_ERROR_OBJECT (index, "%s", err->message);
-    return;
-  }
-
-  g_io_channel_unref (tocfile);
-
-  g_hash_table_foreach (index->id_index,
-      (GHFunc) _file_index_id_save_entries, index->location);
-}
-
-static void
-gst_file_index_add_id (GstIndex * index, GstIndexEntry * entry)
-{
-  GstFileIndex *fileindex = GST_FILE_INDEX (index);
-  GstFileIndexId *id_index;
-
-  id_index = g_hash_table_lookup (fileindex->id_index, &entry->id);
-
-  if (!id_index) {
-    id_index = g_slice_new0 (GstFileIndexId);
-
-    id_index->id = entry->id;
-    id_index->id_desc = g_strdup (entry->data.id.description);
-
-    /* It would be useful to know the GType of the writer so
-       we can try to cope with changes in the id_desc path. */
-
-    g_hash_table_insert (fileindex->id_index, &id_index->id, id_index);
-  }
-}
-
-/* This algorithm differs from libc bsearch in the handling
-   of non-exact matches. */
-
-static gboolean
-_fc_bsearch (GArray * ary,
-    gint stride,
-    gint * ret,
-    GCompareDataFunc compare, gconstpointer sample, gpointer user_data)
-{
-  gint first, last;
-  gint mid;
-  gint midsize;
-  gint cmp;
-  gint tx;
-
-  g_return_val_if_fail (compare, FALSE);
-
-  if (!ary->len) {
-    if (ret)
-      *ret = 0;
-    return FALSE;
-  }
-
-  first = 0;
-  last = ary->len - 1;
-
-  midsize = last - first;
-
-  while (midsize > 1) {
-    mid = first + midsize / 2;
-
-    cmp = (*compare) (sample, ary->data + mid * stride, user_data);
-
-    if (cmp == 0) {
-      /* if there are multiple matches then scan for the first match */
-      while (mid > 0 &&
-          (*compare) (sample, ary->data + (mid - 1) * stride, user_data) == 0)
-        --mid;
-
-      if (ret)
-        *ret = mid;
-      return TRUE;
-    }
-
-    if (cmp < 0)
-      last = mid - 1;
-    else
-      first = mid + 1;
-
-    midsize = last - first;
-  }
-
-  for (tx = first; tx <= last; tx++) {
-    cmp = (*compare) (sample, ary->data + tx * stride, user_data);
-
-    if (cmp < 0) {
-      if (ret)
-        *ret = tx;
-      return FALSE;
-    }
-    if (cmp == 0) {
-      if (ret)
-        *ret = tx;
-      return TRUE;
-    }
-  }
-
-  if (ret)
-    *ret = last + 1;
-  return FALSE;
-}
-
-static gint
-file_index_compare (gconstpointer sample, gconstpointer row, gpointer user_data)
-{
-  //GstFileIndexId *id_index = user_data;
-  const GstIndexAssociation *ca = sample;
-  gint64 val1 = ca->value;
-  gint64 val2_be = ARRAY_ROW_VALUE (row, ca->format);
-  gint64 val2 = GINT64_FROM_BE (val2_be);
-  gint64 diff = val2 - val1;
-
-  return (diff == 0 ? 0 : (diff < 0 ? 1 : -1));
-}
-
-static void
-gst_file_index_add_association (GstIndex * index, GstIndexEntry * entry)
-{
-  GstFileIndex *fileindex = GST_FILE_INDEX (index);
-  GstFileIndexId *id_index;
-  gint mx;
-  GstIndexAssociation sample;
-  gboolean exact;
-
-  id_index = g_hash_table_lookup (fileindex->id_index, &entry->id);
-  if (!id_index)
-    return;
-
-  if (!id_index->nformats) {
-    gint fx;
-
-    id_index->nformats = GST_INDEX_NASSOCS (entry);
-    GST_LOG_OBJECT (fileindex, "creating %d formats for %d",
-        id_index->nformats, entry->id);
-    id_index->format = g_new (GstFormat, id_index->nformats);
-    for (fx = 0; fx < id_index->nformats; fx++)
-      id_index->format[fx] = GST_INDEX_ASSOC_FORMAT (entry, fx);
-    _fc_alloc_array (id_index);
-  } else {
-    /* only sanity checking */
-    if (id_index->nformats != GST_INDEX_NASSOCS (entry))
-      GST_WARNING_OBJECT (fileindex, "arity change %d -> %d",
-          id_index->nformats, GST_INDEX_NASSOCS (entry));
-    else {
-      gint fx;
-
-      for (fx = 0; fx < id_index->nformats; fx++)
-        if (id_index->format[fx] != GST_INDEX_ASSOC_FORMAT (entry, fx))
-          GST_WARNING_OBJECT (fileindex, "format[%d] changed %d -> %d",
-              fx, id_index->format[fx], GST_INDEX_ASSOC_FORMAT (entry, fx));
-    }
-  }
-
-  /* this is a hack, we should use a private structure instead */
-  sample.format = GST_FORMAT_UNDEFINED;
-  sample.value = GST_INDEX_ASSOC_VALUE (entry, 0);
-
-  exact =
-      _fc_bsearch (id_index->array, ARRAY_ROW_SIZE (id_index),
-      &mx, file_index_compare, &sample, id_index);
-
-  if (exact) {
-    /* maybe overwrite instead? */
-    GST_DEBUG_OBJECT (index,
-        "Ignoring duplicate index association at %" G_GINT64_FORMAT,
-        GST_INDEX_ASSOC_VALUE (entry, 0));
-    return;
-  }
-
-  {
-    gchar *row_data = (gchar *) g_malloc (ARRAY_ROW_SIZE (id_index));
-    gint fx;
-
-    gint32 flags_host = GST_INDEX_ASSOC_FLAGS (entry);
-
-    ARRAY_ROW_FLAGS (row_data) = GINT32_TO_BE (flags_host);
-
-    for (fx = 0; fx < id_index->nformats; fx++) {
-      gint64 val_host = GST_INDEX_ASSOC_VALUE (entry, fx);
-
-      ARRAY_ROW_VALUE (row_data, fx) = GINT64_TO_BE (val_host);
-    }
-
-    g_array_insert_vals (id_index->array, mx, row_data, 1);
-
-    g_free (row_data);
-  }
-}
-
-/*
-static void
-show_entry (GstIndexEntry *entry)
-{
-  switch (entry->type) {
-    case GST_INDEX_ENTRY_ID:
-      g_print ("id %d describes writer %s\n", entry->id,
-                      GST_INDEX_ID_DESCRIPTION (entry));
-      break;
-    case GST_INDEX_ENTRY_FORMAT:
-      g_print ("%d: registered format %d for %s\n", entry->id,
-                      GST_INDEX_FORMAT_FORMAT (entry),
-                      GST_INDEX_FORMAT_KEY (entry));
-      break;
-    case GST_INDEX_ENTRY_ASSOCIATION:
-    {
-      gint i;
-
-      g_print ("%d: %08x ", entry->id, GST_INDEX_ASSOC_FLAGS (entry));
-      for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
-        g_print ("%d %" G_GINT64_FORMAT, GST_INDEX_ASSOC_FORMAT (entry, i),
-                             GST_INDEX_ASSOC_VALUE (entry, i));
-      }
-      g_print ("\n");
-      break;
-    }
-    default:
-      break;
-  }
-}
-*/
-
-static void
-gst_file_index_add_entry (GstIndex * index, GstIndexEntry * entry)
-{
-  GST_LOG_OBJECT (index, "adding this entry");
-
-  switch (entry->type) {
-    case GST_INDEX_ENTRY_ID:
-      gst_file_index_add_id (index, entry);
-      break;
-    case GST_INDEX_ENTRY_ASSOCIATION:
-      gst_file_index_add_association (index, entry);
-      break;
-    case GST_INDEX_ENTRY_OBJECT:
-      GST_ERROR_OBJECT (index, "gst_file_index_add_object not implemented");
-      break;
-    case GST_INDEX_ENTRY_FORMAT:
-      /*
-         We infer the formats from the entry itself so this type of
-         GST_INDEX_ENTRY_* can probably go away.
-       */
-      GST_DEBUG_OBJECT (index, "gst_file_index_add_format not implemented");
-      break;
-    default:
-      break;
-  }
-}
-
-static GstIndexEntry *
-gst_file_index_get_assoc_entry (GstIndex * index,
-    gint id,
-    GstIndexLookupMethod method,
-    GstAssocFlags flags,
-    GstFormat format,
-    gint64 value, GCompareDataFunc _ignore_func, gpointer _ignore_user_data)
-{
-  GstFileIndex *fileindex = GST_FILE_INDEX (index);
-  GstFileIndexId *id_index;
-  gint formatx = -1;
-  gint fx;
-  GstIndexAssociation sample;
-  gint mx;
-  gboolean exact;
-  gpointer row_data;
-  GstIndexEntry *entry;
-  gint xx;
-
-  g_return_val_if_fail (id > 0, NULL);
-
-  id_index = g_hash_table_lookup (fileindex->id_index, &id);
-  if (!id_index) {
-    GST_WARNING_OBJECT (fileindex, "writer %d unavailable", id);
-    return NULL;
-  }
-
-  for (fx = 0; fx < id_index->nformats; fx++)
-    if (id_index->format[fx] == format) {
-      formatx = fx;
-      break;
-    }
-
-  if (formatx == -1) {
-    GST_WARNING_OBJECT (fileindex, "format %d not available", format);
-    return NULL;
-  }
-
-  /* this is a hack, we should use a private structure instead */
-  sample.format = (GstFormat) formatx;
-  sample.value = value;
-
-  exact = _fc_bsearch (id_index->array, ARRAY_ROW_SIZE (id_index),
-      &mx, file_index_compare, &sample, id_index);
-
-  if (!exact) {
-    if (method == GST_INDEX_LOOKUP_EXACT)
-      return NULL;
-    else if (method == GST_INDEX_LOOKUP_BEFORE) {
-      if (mx == 0)
-        return NULL;
-      mx -= 1;
-    } else if (method == GST_INDEX_LOOKUP_AFTER) {
-      if (mx == id_index->array->len)
-        return NULL;
-    }
-  }
-
-  row_data = id_index->array->data + mx * ARRAY_ROW_SIZE (id_index);
-
-  /* if exact then ignore flags (?) */
-  if (method != GST_INDEX_LOOKUP_EXACT)
-    while ((GINT32_FROM_BE (ARRAY_ROW_FLAGS (row_data)) & flags) != flags) {
-      if (method == GST_INDEX_LOOKUP_BEFORE)
-        mx -= 1;
-      else if (method == GST_INDEX_LOOKUP_AFTER)
-        mx += 1;
-      if (mx < 0 || mx >= id_index->array->len)
-        return NULL;
-      row_data = id_index->array->data + mx * ARRAY_ROW_SIZE (id_index);
-    }
-
-  /* entry memory management needs improvement FIXME */
-  if (!fileindex->ret_entry)
-    fileindex->ret_entry = g_slice_new0 (GstIndexEntry);
-  entry = fileindex->ret_entry;
-  if (entry->data.assoc.assocs) {
-    g_free (entry->data.assoc.assocs);
-    entry->data.assoc.assocs = NULL;
-  }
-
-  entry->type = GST_INDEX_ENTRY_ASSOCIATION;
-
-  GST_INDEX_NASSOCS (entry) = id_index->nformats;
-  entry->data.assoc.assocs = g_new (GstIndexAssociation, id_index->nformats);
-
-  {
-    gint32 flags_be = ARRAY_ROW_FLAGS (row_data);
-
-    GST_INDEX_ASSOC_FLAGS (entry) = (GstAssocFlags) GINT32_FROM_BE (flags_be);
-
-    for (xx = 0; xx < id_index->nformats; xx++) {
-      gint64 val_be = ARRAY_ROW_VALUE (row_data, xx);
-
-      GST_INDEX_ASSOC_FORMAT (entry, xx) = id_index->format[xx];
-      GST_INDEX_ASSOC_VALUE (entry, xx) = GINT64_FROM_BE (val_be);
-    }
-  }
-
-  return entry;
-}
-
-gboolean
-gst_file_index_plugin_init (GstPlugin * plugin)
-{
-  GstIndexFactory *factory;
-
-  factory = gst_index_factory_new ("fileindex",
-      "A index that stores entries in file", gst_file_index_get_type ());
-
-  if (factory == NULL) {
-    return FALSE;
-  }
-
-  GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name;
-  GST_PLUGIN_FEATURE (factory)->loaded = TRUE;
-
-  gst_registry_add_feature (gst_registry_get_default (),
-      GST_PLUGIN_FEATURE (factory));
-
-  GST_DEBUG_CATEGORY_INIT (DC, "GST_FILEINDEX", 0, NULL);
-
-  return TRUE;
-}
diff --git a/plugins/indexers/gstindexers.c b/plugins/indexers/gstindexers.c
deleted file mode 100644 (file)
index 9513f67..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <gst/gst_private.h>
-#include <gst/gstversion.h>
-#include <gst/gstplugin.h>
-
-#include "gstindexers.h"
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-  gboolean res = TRUE;
-
-  res &= gst_mem_index_plugin_init (plugin);
-#if defined(HAVE_MMAP) && !defined(GST_DISABLE_LOADSAVE)
-  res &= gst_file_index_plugin_init (plugin);
-#endif
-
-  return res;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "coreindexers",
-    "GStreamer core indexers",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/plugins/indexers/gstindexers.h b/plugins/indexers/gstindexers.h
deleted file mode 100644 (file)
index 03e8e46..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_INDEXERS_H__
-#define __GST_INDEXERS_H__
-
-G_BEGIN_DECLS
-
-
-gboolean gst_mem_index_plugin_init (GstPlugin * plugin);
-
-#ifndef GST_DISABLE_LOADSAVE
-gboolean gst_file_index_plugin_init (GstPlugin * plugin);
-#endif
-
-
-G_END_DECLS
-
-#endif /* __GST_INDEXERS_H__ */
index dfd93b8..a30959f 100644 (file)
--- a/po/af.po
+++ b/po/af.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.9.7\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2005-12-05 11:45+0200\n"
 "Last-Translator: Petri Jooste <rkwjpj@puk.ac.za>\n"
 "Language-Team: Afrikaans <i18n@af.org.za>\n"
@@ -561,9 +561,17 @@ msgstr ""
 msgid "language code"
 msgstr "taalkode"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "taalkode vir hierdie stroom, wat voldoen aan ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "taalkode"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr ""
 
@@ -1032,29 +1040,6 @@ msgstr "Kon nie lêer \"%s\" oopmaak om in te skryf nie."
 msgid "No such element or plugin '%s'\n"
 msgstr "geen bronelement vir URI \"%s\""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Gebruik so: gst-xmllaunch <lêer.xml> [ element.eienskap=waarde ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "FOUT: ontleding van xml-lêer '%s' het misluk.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "FOUT: geen topvlak pyplynelement in lêer '%s' nie.\n"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "WAARSKUWING: slegs een topvlak element word tans ondersteun."
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "FOUT: onverstaanbare bevellynparameter %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "WAARSKUWING: element genaamd '%s' nie gevind nie.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1151,19 +1136,9 @@ msgstr "Moenie statusinligting van TIPE wys nie"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPE1, TIPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Stoor xml-voorstelling van pyplyn na LÊER en stop"
-
-msgid "FILE"
-msgstr "LÊER"
-
 msgid "Do not install a fault handler"
 msgstr "Moenie 'n fouthanteerder installeer nie"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Moenie 'n fouthanteerder installeer nie"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Druk \"alloc trace\" (indien aangeskakel tydens kompilering)"
 
@@ -1237,6 +1212,36 @@ msgstr "Pyplyn word gestel na NULL ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Pyplyn word gestel na NULL ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Gebruik so: gst-xmllaunch <lêer.xml> [ element.eienskap=waarde ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "FOUT: ontleding van xml-lêer '%s' het misluk.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "FOUT: geen topvlak pyplynelement in lêer '%s' nie.\n"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "WAARSKUWING: slegs een topvlak element word tans ondersteun."
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "FOUT: onverstaanbare bevellynparameter %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "WAARSKUWING: element genaamd '%s' nie gevind nie.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Stoor xml-voorstelling van pyplyn na LÊER en stop"
+
+#~ msgid "FILE"
+#~ msgstr "LÊER"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Moenie 'n fouthanteerder installeer nie"
+
 #~ msgid "Internal GStreamer error: state change failed."
 #~ msgstr "Interne GStreamer-fout: state change failed."
 
index c022a6b..f6f74f9 100644 (file)
--- a/po/az.po
+++ b/po/az.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.8.0\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2004-03-19 18:40+0200\n"
 "Last-Translator: Metin Amiroff <metin@karegen.com>\n"
 "Language-Team: Azerbaijani <translation-team-az@lists.sourceforge.net>\n"
@@ -537,7 +537,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -983,28 +989,6 @@ msgstr ""
 msgid "No such element or plugin '%s'\n"
 msgstr ""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr ""
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1097,18 +1081,9 @@ msgstr ""
 msgid "TYPE1,TYPE2,..."
 msgstr ""
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-
-msgid "FILE"
-msgstr "FAYL"
-
 msgid "Do not install a fault handler"
 msgstr ""
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 
@@ -1180,6 +1155,9 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr ""
 
+#~ msgid "FILE"
+#~ msgstr "FAYL"
+
 #~ msgid "')"
 #~ msgstr "')"
 
index 6da856d..66dedfe 100644 (file)
--- a/po/be.po
+++ b/po/be.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.9.7\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2006-01-18 22:26+0200\n"
 "Last-Translator: Ales Nyakhaychyk <nab@mail.by>\n"
 "Language-Team: Belarusian <i18n@mova.org>\n"
@@ -541,7 +541,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -992,28 +998,6 @@ msgstr ""
 msgid "No such element or plugin '%s'\n"
 msgstr ""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr ""
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1106,18 +1090,9 @@ msgstr ""
 msgid "TYPE1,TYPE2,..."
 msgstr ""
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-
-msgid "FILE"
-msgstr ""
-
 msgid "Do not install a fault handler"
 msgstr ""
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 
index 29d96ef..17b4131 100644 (file)
--- a/po/bg.po
+++ b/po/bg.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-26 22:40+0300\n"
 "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
 "Language-Team: Bulgarian <dict@fsa-bg.org>\n"
@@ -553,9 +553,17 @@ msgstr "еталонно ниво на усилването на песните
 msgid "language code"
 msgstr "езиков код"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "езиковият код на този поток според ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "езиков код"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "изображение"
 
@@ -1030,30 +1038,6 @@ msgstr "Файлът на приставката не може да бъде з
 msgid "No such element or plugin '%s'\n"
 msgstr "Няма такъв елемент или приставка „%s“\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Употреба: gst-xmllaunch <файл.xml> [ елемент.свойство=стойност … ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ГРЕШКА: файлът с xml „%s“ не може да бъде анализиран.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ГРЕШКА: няма най-горен елемент за конвейер във файла „%s“.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "ПРЕДУПРЕЖДЕНИЕ: засега е позволен само един най-горен елемент.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ГРЕШКА: аргументът подаден на командния ред не може да бъде анализиран %d: "
-"%s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ПРЕДУПРЕЖДЕНИЕ: елементът на име „%s“ не е открит.\n"
-
 msgid "Index statistics"
 msgstr "Статистика на индекса"
 
@@ -1148,18 +1132,9 @@ msgstr "Да не се дават изходни съобщения от сле
 msgid "TYPE1,TYPE2,..."
 msgstr "ВИД1,ВИД2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Запазване на конвейера във вид на XML във ФАЙЛа и изход"
-
-msgid "FILE"
-msgstr "ФАЙЛ"
-
 msgid "Do not install a fault handler"
 msgstr "Да не се инсталира модул за обработка на грешки"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Да не се включват функции за обработка на сигналите SIGUSR1 и SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 "Отпечатване на заделянето на памет (ако е било включено при компилиране на "
@@ -1233,3 +1208,34 @@ msgstr "Конвейерът се ЗАНУЛЯВА…\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Конвейерът се освобождава…\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Употреба: gst-xmllaunch <файл.xml> [ елемент.свойство=стойност … ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ГРЕШКА: файлът с xml „%s“ не може да бъде анализиран.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ГРЕШКА: няма най-горен елемент за конвейер във файла „%s“.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: засега е позволен само един най-горен елемент.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ГРЕШКА: аргументът подаден на командния ред не може да бъде анализиран "
+#~ "%d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: елементът на име „%s“ не е открит.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Запазване на конвейера във вид на XML във ФАЙЛа и изход"
+
+#~ msgid "FILE"
+#~ msgstr "ФАЙЛ"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr ""
+#~ "Да не се включват функции за обработка на сигналите SIGUSR1 и SIGUSR2"
index bebce39..a776ebe 100644 (file)
--- a/po/ca.po
+++ b/po/ca.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-04 19:41+0100\n"
 "Last-Translator: Jordi Mallach <jordi@sindominio.net>\n"
 "Language-Team: Catalan <ca@dodds.net>\n"
@@ -556,9 +556,17 @@ msgstr "nivell de referència dels valors de guany de la pista i àlbum"
 msgid "language code"
 msgstr "codi de la llengua"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "codi de la llengua per a aquest flux, conformant amb ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "codi de la llengua"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "imatge"
 
@@ -1033,29 +1041,6 @@ msgstr "No s'ha pogut carregar el fitxer de connector: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "L'element o connector «%s» no existeix\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Forma d'ús: gst-xmllaunch <file.xml> [ element.propietat=valor … ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERROR: l'anàlisi del fitxer xml «%s» ha fallat.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ERROR: no hi ha cap conducte de nivell superior en el fitxer «%s».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "AVÍS: només es gestiona un element de primer nivell ara mateix.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ERROR: no s'ha pogut analitzar l'argument de la línia d'ordres %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "AVÍS: no s'ha trobat l'element anomenat «%s».\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1154,18 +1139,9 @@ msgstr "No mostres informació d'estat de TIPUS"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPUS1,TIPUS2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Desa la representació xml del conducte a FITXER i surt"
-
-msgid "FILE"
-msgstr "FITXER"
-
 msgid "Do not install a fault handler"
 msgstr "No instal·les un gestor de fallades"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "No instaŀles gestors de senyals per a SIGUSR1 i SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Imprimeix una traça d'alloc (si s'ha habilitat al compilar)"
 
@@ -1239,6 +1215,36 @@ msgstr "S'està establint el conducte a NUL…\n"
 msgid "Freeing pipeline ...\n"
 msgstr "S'està alliberant el conducte…\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Forma d'ús: gst-xmllaunch <file.xml> [ element.propietat=valor … ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERROR: l'anàlisi del fitxer xml «%s» ha fallat.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERROR: no hi ha cap conducte de nivell superior en el fitxer «%s».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "AVÍS: només es gestiona un element de primer nivell ara mateix.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERROR: no s'ha pogut analitzar l'argument de la línia d'ordres %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "AVÍS: no s'ha trobat l'element anomenat «%s».\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Desa la representació xml del conducte a FITXER i surt"
+
+#~ msgid "FILE"
+#~ msgstr "FITXER"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "No instaŀles gestors de senyals per a SIGUSR1 i SIGUSR2"
+
 #~ msgid "Internal GStreamer error: state change failed."
 #~ msgstr ""
 #~ "S'ha produït un error intern de GStreamer: ha fallat el canvi d'estat."
index 7a53c7d..9f023cb 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-12-01 08:17+0100\n"
 "Last-Translator: Marek Černocký <marek@manet.cz>\n"
 "Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
@@ -549,9 +549,17 @@ msgstr "Hodnota referenční úrovně zesílení stopy a alba"
 msgid "language code"
 msgstr "kód jazyka"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "Kód jazyka pro tento proud, ve shodě s ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "kód jazyka"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "obrázek"
 
@@ -1028,29 +1036,6 @@ msgstr "Nelze načíst soubor se zásuvným modulem: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Prvek nebo zásuvný modul „%s“ neexistuje\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Použití: gst-xmllaunch <soubor.xml> [prvek.vlastnost=hodnota…]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "CHYBA: zpracovávání souboru XML „%s“ selhalo.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "CHYBA: v souboru „%s“ není žádný prvek „pipeline“ nejvyšší úrovně.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"VAROVÁNÍ: v současné době je podporován jen jeden prvek nejvyšší úrovně.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "CHYBA: nelze zpracovat argument %d na příkazovém řádku: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "VAROVÁNÍ: prvek s názvem „%s“ nebyl nalezen.\n"
-
 msgid "Index statistics"
 msgstr "Přehledové statistiky"
 
@@ -1148,18 +1133,9 @@ msgstr "Pro TYP nevypisovat stavové informace"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYP1,TYP2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Uložit reprezentaci roury v xml do SOUBORu a skončit"
-
-msgid "FILE"
-msgstr "SOUBOR"
-
 msgid "Do not install a fault handler"
 msgstr "Neinstalovat obsluhu výjimek"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Neinstalovat obsluhu signálů SIGUSR1 a SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Vypisovat sledování přidělování paměti (je-li povoleno při překladu)"
 
@@ -1235,3 +1211,32 @@ msgstr "Nastavuje se roura na PRÁZDNÁ…\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Uvolňuje se roura…\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Použití: gst-xmllaunch <soubor.xml> [prvek.vlastnost=hodnota…]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "CHYBA: zpracovávání souboru XML „%s“ selhalo.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "CHYBA: v souboru „%s“ není žádný prvek „pipeline“ nejvyšší úrovně.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "VAROVÁNÍ: v současné době je podporován jen jeden prvek nejvyšší úrovně.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "CHYBA: nelze zpracovat argument %d na příkazovém řádku: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "VAROVÁNÍ: prvek s názvem „%s“ nebyl nalezen.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Uložit reprezentaci roury v xml do SOUBORu a skončit"
+
+#~ msgid "FILE"
+#~ msgstr "SOUBOR"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Neinstalovat obsluhu signálů SIGUSR1 a SIGUSR2"
index f9bdaf8..3e06425 100644 (file)
--- a/po/da.po
+++ b/po/da.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-06 22:52+0100\n"
 "Last-Translator: Mogens Jaeger <mogensjaeger@gmail.com>\n"
 "Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
@@ -555,9 +555,17 @@ msgstr "referenceniveau for spor og albums forstærkningsværdier"
 msgid "language code"
 msgstr "sprogkode"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "sprogkode for denne mediestrøm, i overensstemmelse med ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "sprogkode"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "billede"
 
@@ -1031,29 +1039,6 @@ msgstr "Kunne ikke indlæse pluginfilen: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Et sådant element eller plugin findes ikke '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Brug: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "FEJL: tolkning af XML fil '%s' mislykkedes.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "FEJL: intet topniveau rørledningselement i fil '%s'.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"ADVARSEL: der understøttes kun ét topniveauelement på nuværende tidspunkt.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "FEJL: kunne ikke tolke kommandolinieargumenetet %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ADVARSEL: elementet ved navn '%s' blev ikke fundet.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1149,18 +1134,9 @@ msgstr "Send ikke statusinformation af TYPE ud"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Gem XML-repræsentation af rørledning til FIL og afslut"
-
-msgid "FILE"
-msgstr "FIL"
-
 msgid "Do not install a fault handler"
 msgstr "Installér ikke en fejlhåndterer"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Undlad installering af signalhåndtering for SIGUSR1 og SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Udskriv allokeringsspor (hvis tilladt på oversættelsestidspunktet)"
 
@@ -1233,6 +1209,35 @@ msgstr "Rørledning sættes til NUL ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Rørledning frigøres ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Brug: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "FEJL: tolkning af XML fil '%s' mislykkedes.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "FEJL: intet topniveau rørledningselement i fil '%s'.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "ADVARSEL: der understøttes kun ét topniveauelement på nuværende "
+#~ "tidspunkt.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "FEJL: kunne ikke tolke kommandolinieargumenetet %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ADVARSEL: elementet ved navn '%s' blev ikke fundet.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Gem XML-repræsentation af rørledning til FIL og afslut"
+
+#~ msgid "FILE"
+#~ msgstr "FIL"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Undlad installering af signalhåndtering for SIGUSR1 og SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Kunne ikke skrive registraturcache til %s: %s"
 
index 36f8ae4..8eb8b15 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-27 23:44+0200\n"
 "Last-Translator: Christian Kirbach <christian.kirbach@googlemail.com>\n"
 "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@@ -569,9 +569,17 @@ msgstr "Referenzpegel für die Pegelanpassungen von Titel und Album"
 msgid "language code"
 msgstr "Sprachcode"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "Sprachcode für diesen Datenstrom nach ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "Sprachcode"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "Bild"
 
@@ -1051,29 +1059,6 @@ msgstr "Die Plugin-Datei konnte nicht geladen werden: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Kein solches Element oder Plugin »%s«\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Aufruf: gst-xmllaunch <file.xml> [ element.eigenschaft=wert ...]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "FEHLER: Auslesen der XML-Datei »%s« fehlgeschlagen.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "FEHLER: Kein Hauptleitungselement in Datei »%s«.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "WARNUNG: Zur Zeit wird nur ein Hauptelement unterstützt.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"FEHLER: Das Befehlszeilenargument »%d« konnte nicht ausgelesen werden: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "WARNUNG: Element namens »%s« nicht gefunden.\n"
-
 msgid "Index statistics"
 msgstr "Index-Statistiken"
 
@@ -1171,18 +1156,9 @@ msgstr "Zustandsinformation der Art ART nicht ausgeben"
 msgid "TYPE1,TYPE2,..."
 msgstr "ART1,ART2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "XML-Repräsentation der Leitung in DATEI speichern und beenden"
-
-msgid "FILE"
-msgstr "DATEI"
-
 msgid "Do not install a fault handler"
 msgstr "Keine Routine zum Abfangen von Fehlern installieren"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Keine Routinen für SIGUSR1 und SIGUSR2 installieren"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 "Speicherzuordnungsverfolgung ausgeben (falls zur Kompilierzeit aktiviert)"
@@ -1256,6 +1232,35 @@ msgstr "Leitung wird auf NULL gesetzt ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Leitung wird geleert ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Aufruf: gst-xmllaunch <file.xml> [ element.eigenschaft=wert ...]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "FEHLER: Auslesen der XML-Datei »%s« fehlgeschlagen.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "FEHLER: Kein Hauptleitungselement in Datei »%s«.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "WARNUNG: Zur Zeit wird nur ein Hauptelement unterstützt.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "FEHLER: Das Befehlszeilenargument »%d« konnte nicht ausgelesen werden: "
+#~ "%s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "WARNUNG: Element namens »%s« nicht gefunden.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "XML-Repräsentation der Leitung in DATEI speichern und beenden"
+
+#~ msgid "FILE"
+#~ msgstr "DATEI"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Keine Routinen für SIGUSR1 und SIGUSR2 installieren"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr ""
 #~ "Fehler beim Schreiben des Zwischenspeichers der Registry nach %s: %s"
index f2585be..0c2d67f 100644 (file)
--- a/po/el.po
+++ b/po/el.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-29 11:14+0200\n"
 "Last-Translator: Michael Kotsarinis <mk73628@gmail.com>\n"
 "Language-Team: Greek <team@lists.gnome.gr>\n"
@@ -563,9 +563,17 @@ msgstr "επίπεδο αναφοράς των τιμών κέρδους κομ
 msgid "language code"
 msgstr "κωδικός γλώσσας"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "κωδικός γλώσσας γι' αυτή τη ροή, συμμορφούμενος με το ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "κωδικός γλώσσας"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "εικόνα"
 
@@ -1045,31 +1053,6 @@ msgstr "Αδυναμία φόρτωσης αρχείου προσθέτου: %s\
 msgid "No such element or plugin '%s'\n"
 msgstr "Δεν υπάρχει τέτοιο στοιχείο ή πρόσθετο '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Χρήση: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERROR: αποτυχία ανάλυσης αρχείου xml '%s'.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERROR: δεν υπάρχει στοιχείο διασωλήνωσης στο ανώτερο επίπεδο στο αρχείο "
-"'%s'.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"WARNING: μόνο ένα στοιχείο σε ανώτερο επίπεδο υποστηρίζεται αυτή τη στιγμή.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ERROR: αδυναμία ανάλυσης ορίσματος γραμμής εντολής %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "WARNING: το στοιχείο με το όνομα '%s' δεν βρέθηκε.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1164,18 +1147,9 @@ msgstr "Να μην εξάγεται πληροφορία κατάστασης 
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Αποθήκευση xml αναπαράστασης της διασωλήνωσης στο FILE και έξοδος"
-
-msgid "FILE"
-msgstr "FILE"
-
 msgid "Do not install a fault handler"
 msgstr "Να μην εγκατασταθεί χειριστής σφαλμάτων"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Να μην εγκατασταθούν χειριστές σημάτων για SIGUSR1 και SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 "Εμφάνιση ίχνους αντιστοίχισης (αν είναι ενεργοποιημένο κατά τη μεταγλώττιση "
@@ -1249,3 +1223,34 @@ msgstr "Ορισμός διασωλήνωσης σε NULL …\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Αποδέσμευση της διασωλήνωσης …\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Χρήση: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERROR: αποτυχία ανάλυσης αρχείου xml '%s'.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERROR: δεν υπάρχει στοιχείο διασωλήνωσης στο ανώτερο επίπεδο στο αρχείο "
+#~ "'%s'.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "WARNING: μόνο ένα στοιχείο σε ανώτερο επίπεδο υποστηρίζεται αυτή τη "
+#~ "στιγμή.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "ERROR: αδυναμία ανάλυσης ορίσματος γραμμής εντολής %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "WARNING: το στοιχείο με το όνομα '%s' δεν βρέθηκε.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Αποθήκευση xml αναπαράστασης της διασωλήνωσης στο FILE και έξοδος"
+
+#~ msgid "FILE"
+#~ msgstr "FILE"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Να μην εγκατασταθούν χειριστές σημάτων για SIGUSR1 και SIGUSR2"
index fd70295..707e586 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.8.1\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2004-04-26 10:36-0400\n"
 "Last-Translator: Gareth Owen <gowen72@yahoo.com>\n"
 "Language-Team: English (British) <en_gb@li.org>\n"
@@ -569,7 +569,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1039,29 +1045,6 @@ msgstr "Could not open file \"%s\" for writing."
 msgid "No such element or plugin '%s'\n"
 msgstr "no source element for URI \"%s\""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERROR: parsing of xml file '%s' failed.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ERROR: no toplevel pipeline element in file '%s'.\n"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "WARNING: only one toplevel element is supported at this time."
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ERROR: could not parse command line argument %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "WARNING: element named '%s' not found.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1155,19 +1138,9 @@ msgstr "Do not output status information of TYPE"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Save xml representation of pipeline to FILE and exit"
-
-msgid "FILE"
-msgstr "FILE"
-
 msgid "Do not install a fault handler"
 msgstr "Do not install a fault handler"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Do not install a fault handler"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Print alloc trace (if enabled at compile time)"
 
@@ -1242,6 +1215,35 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr "RUNNING pipeline ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERROR: parsing of xml file '%s' failed.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ERROR: no toplevel pipeline element in file '%s'.\n"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "WARNING: only one toplevel element is supported at this time."
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "ERROR: could not parse command line argument %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "WARNING: element named '%s' not found.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Save xml representation of pipeline to FILE and exit"
+
+#~ msgid "FILE"
+#~ msgstr "FILE"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Do not install a fault handler"
+
 #~ msgid "Disable accelerated CPU instructions"
 #~ msgstr "Disable accelerated CPU instructions"
 
index 8cf2c4e..fe2dd8d 100644 (file)
--- a/po/eo.po
+++ b/po/eo.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-06-04 21:11+0100\n"
 "Last-Translator: Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>\n"
 "Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
@@ -528,7 +528,14 @@ msgstr ""
 msgid "language code"
 msgstr "Lingvokodo"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+#, fuzzy
+msgid "language name"
+msgstr "Lingvokodo"
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -971,28 +978,6 @@ msgstr ""
 msgid "No such element or plugin '%s'\n"
 msgstr ""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr ""
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1087,18 +1072,9 @@ msgstr ""
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPO1,TIPO2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-
-msgid "FILE"
-msgstr "DOSIERO"
-
 msgid "Do not install a fault handler"
 msgstr ""
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 
@@ -1169,3 +1145,6 @@ msgstr ""
 
 msgid "Freeing pipeline ...\n"
 msgstr ""
+
+#~ msgid "FILE"
+#~ msgstr "DOSIERO"
index b8b3b21..27828a2 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-10-02 15:45+0200\n"
 "Last-Translator: Jorge González González <aloriel@gmail.com>\n"
 "Language-Team: Spanish <es@li.org>\n"
@@ -557,9 +557,17 @@ msgstr "valor del nivel de referencia de ganancia de la pista y del álbum"
 msgid "language code"
 msgstr "código de idioma"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "código de idioma para este flujo, ajustándose a ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "código de idioma"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "imagen"
 
@@ -1037,32 +1045,6 @@ msgstr "No se pudo cargar el archivo de complemento: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "No existe el elemento o complemento «%s»\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Uso: gst-xmllaunch <archivo.xml> [ propiedad.del.elemento=valor … ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERROR: falló el análisis del archivo xml «%s».\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERROR: no existe el elemento de nivel superior de la segmentación en el "
-"archivo «%s».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"ADVERTENCIA: en este momento sólo se soporta un elemento de nivel superior.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ERROR: no se pudo analizar el argumento %d de la línea de comandos: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ADVERTENCIA: no se encontró el elemento llamado «%s».\n"
-
 msgid "Index statistics"
 msgstr "índice de las estadísticas"
 
@@ -1159,18 +1141,9 @@ msgstr "No sacar la salida de la información de estado del TIPO"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPO1,TIPO2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Guardar la representación xml del conducto a un ARCHIVO y salir"
-
-msgid "FILE"
-msgstr "ARCHIVO"
-
 msgid "Do not install a fault handler"
 msgstr "No instalar un manejador predeterminado"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "No instalar los manejadores de señales para SIGUSR1 y SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Imprimir la traza de asignaciones (si se activó al compilar)"
 
@@ -1242,6 +1215,39 @@ msgstr "Estableciendo el conducto a NULL …\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Liberando la tubería…\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Uso: gst-xmllaunch <archivo.xml> [ propiedad.del.elemento=valor … ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERROR: falló el análisis del archivo xml «%s».\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERROR: no existe el elemento de nivel superior de la segmentación en el "
+#~ "archivo «%s».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "ADVERTENCIA: en este momento sólo se soporta un elemento de nivel "
+#~ "superior.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERROR: no se pudo analizar el argumento %d de la línea de comandos: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ADVERTENCIA: no se encontró el elemento llamado «%s».\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Guardar la representación xml del conducto a un ARCHIVO y salir"
+
+#~ msgid "FILE"
+#~ msgstr "ARCHIVO"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "No instalar los manejadores de señales para SIGUSR1 y SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Error al escribir la caché de registro a %s: %s"
 
index ddd431a..c537365 100644 (file)
--- a/po/eu.po
+++ b/po/eu.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.26.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-03-25 13:10+0100\n"
 "Last-Translator: Mikel Olasagasti Uranga <hey_neken@mundurat.net>\n"
 "Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
@@ -561,9 +561,17 @@ msgstr "pistaren eta albumaren irabazi-balioen erreferentzia-maila"
 msgid "language code"
 msgstr "hizkuntza-kodea"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "korronte honen hizkuntza-kodea, ISO-639-1en arabera"
 
+#, fuzzy
+msgid "language name"
+msgstr "hizkuntza-kodea"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "irudia"
 
@@ -1036,31 +1044,6 @@ msgstr "Ezin izan da plugin fitxategia kargatu: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "'%s' elementua edo plugina ez da existitzen\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Erabilera: gst-xmllaunch <fitxategia.xml> [ elementua."
-"propietatea=balioa... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERROREA: huts egin du '%s' xml fitxategia analizatzean.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERROREA: ez dago goi-mailako kanalizazio-elementurik '%s' fitxategian.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "KONTUZ: goi-mailako elementu bat bakarra onartzen da oraingoan.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ERROREA: ezin izan da komando-lerroko %d. argumentua analizatu: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "KONTUZ: ez da aurkitu '%s' izeneko elementua.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1156,19 +1139,9 @@ msgstr "Ez erakutsi MOTA hauetako egoera-informazioa:"
 msgid "TYPE1,TYPE2,..."
 msgstr "1.MOTA, 2.MOTA..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Gorde kanalizazioen xml adierazpena FITXATEGIan eta irten"
-
-msgid "FILE"
-msgstr "FITXATEGIA"
-
 msgid "Do not install a fault handler"
 msgstr "Ez instalatu akats-maneiatzailerik"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Ez instalatu akats-maneiatzailerik"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Inprimatu esleipenen segimendua (konpilatzean gaitu bada)"
 
@@ -1239,3 +1212,35 @@ msgstr "Kanalizazioa NULUA gisa ezartzen... \n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Kanalizazioa askatzen...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Erabilera: gst-xmllaunch <fitxategia.xml> [ elementua."
+#~ "propietatea=balioa... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERROREA: huts egin du '%s' xml fitxategia analizatzean.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERROREA: ez dago goi-mailako kanalizazio-elementurik '%s' fitxategian.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "KONTUZ: goi-mailako elementu bat bakarra onartzen da oraingoan.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERROREA: ezin izan da komando-lerroko %d. argumentua analizatu: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "KONTUZ: ez da aurkitu '%s' izeneko elementua.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Gorde kanalizazioen xml adierazpena FITXATEGIan eta irten"
+
+#~ msgid "FILE"
+#~ msgstr "FITXATEGIA"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Ez instalatu akats-maneiatzailerik"
index 0f77f4d..ee24195 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -12,7 +12,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-17 23:10+0200\n"
 "Last-Translator: Tommi Vainikainen <Tommi.Vainikainen@iki.fi>\n"
 "Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
@@ -554,9 +554,17 @@ msgstr "viitetaso raidan ja albumin gain-arvoille"
 msgid "language code"
 msgstr "kielikoodi"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "tämän virran kielikoodi ISO-639-1-standardin mukaisesti"
 
+#, fuzzy
+msgid "language name"
+msgstr "kielikoodi"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "kuva"
 
@@ -1030,29 +1038,6 @@ msgstr "Ei voitu ladata liitännäistiedostoa: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Ei tällaista elementtiä tai liitännäistä ”%s”\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Käyttö: gst-xmllaunch <tiedosto.xml> [ elementti.ominaisuus=arvo ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "VIRHE: XML-tiedoston ”%s” jäsentäminen epäonnistui.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "VIRHE: päätason liukuhihnaelementtiä ei ole tiedostossa ”%s”.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "VAROITUS: vain yhtä päätason elementtiä tuetaan tällä kertaa.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "VIRHE: ei voitu jäsentää komentoriviargumenttia %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "VAROITUS: elementtiä nimeltä ”%s” ei löytynyt.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1147,18 +1132,9 @@ msgstr "Älä tulosta tilatietoa TYYPPI"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYYPPI1,TYYPPI2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Tallenna liukuhihnan XML-esitys TIEDOSTOon ja poistu"
-
-msgid "FILE"
-msgstr "TIEDOSTO"
-
 msgid "Do not install a fault handler"
 msgstr "Älä asenna virheenkäsittelintä"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Älä asenna SIGUSR1- ja SIGUSR2-signaalinkäsittelijöitä"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Tulosta varausjälki (jos valittu käännöksen yhteydessä)"
 
@@ -1232,6 +1208,34 @@ msgstr "Asetetaan liukuhihna tilaan TYHJÄ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Vapautetaan liukuhihna...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Käyttö: gst-xmllaunch <tiedosto.xml> [ elementti.ominaisuus=arvo ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "VIRHE: XML-tiedoston ”%s” jäsentäminen epäonnistui.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "VIRHE: päätason liukuhihnaelementtiä ei ole tiedostossa ”%s”.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "VAROITUS: vain yhtä päätason elementtiä tuetaan tällä kertaa.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "VIRHE: ei voitu jäsentää komentoriviargumenttia %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "VAROITUS: elementtiä nimeltä ”%s” ei löytynyt.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Tallenna liukuhihnan XML-esitys TIEDOSTOon ja poistu"
+
+#~ msgid "FILE"
+#~ msgstr "TIEDOSTO"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Älä asenna SIGUSR1- ja SIGUSR2-signaalinkäsittelijöitä"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Virhe kirjoitettaessa rekisterivälimuistia kohteeseen %s: %s"
 
index b4adae0..e69a2f7 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-28 09:34+0200\n"
 "Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
 "Language-Team: French <traduc@traduc.org>\n"
@@ -554,9 +554,17 @@ msgstr "niveau de référence des valeurs de gain de piste et d'album"
 msgid "language code"
 msgstr "code linguistique"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "code linguistique du flux, selon la norme ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "code linguistique"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "image"
 
@@ -1034,33 +1042,6 @@ msgstr "Impossible de charger le fichier de greffon : %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Aucun élément ou greffon « %s »\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Utilisation : gst-xmllaunch <fichier.xml> [ élément.propriété=valeur ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERREUR : l'analyse du fichier xml « %s » a échoué.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERREUR : pas d'élément pipeline de premier niveau dans le fichier « %s ».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"AVERTISSEMENT : actuellement, un seul élément de premier niveau est géré.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ERREUR : impossible d'analyser le paramètre numéro %d de la ligne de "
-"commande : %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "AVERTISSEMENT : l'élément nommé « %s » est introuvable.\n"
-
 msgid "Index statistics"
 msgstr "Statistiques d'index"
 
@@ -1155,18 +1136,9 @@ msgstr "N'affiche pas d'informations d'état de TYPE"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Enregistre une représentation xml du pipeline dans FICHIER et quitte"
-
-msgid "FILE"
-msgstr "FICHIER"
-
 msgid "Do not install a fault handler"
 msgstr "N'installe pas de gestionnaire de dysfonctionnement"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "N'installe pas de gestionnaire de signal pour SIGUSR1 et SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Affiche les traces d'allocations (si activées lors de la compilation)"
 
@@ -1237,3 +1209,39 @@ msgstr "Définition du pipeline à NULL...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Libération du pipeline...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Utilisation : gst-xmllaunch <fichier.xml> [ élément."
+#~ "propriété=valeur ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERREUR : l'analyse du fichier xml « %s » a échoué.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERREUR : pas d'élément pipeline de premier niveau dans le fichier "
+#~ "« %s ».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "AVERTISSEMENT : actuellement, un seul élément de premier niveau est "
+#~ "géré.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERREUR : impossible d'analyser le paramètre numéro %d de la ligne de "
+#~ "commande : %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "AVERTISSEMENT : l'élément nommé « %s » est introuvable.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr ""
+#~ "Enregistre une représentation xml du pipeline dans FICHIER et quitte"
+
+#~ msgid "FILE"
+#~ msgstr "FICHIER"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "N'installe pas de gestionnaire de signal pour SIGUSR1 et SIGUSR2"
index 021f6ee..5d254a1 100644 (file)
--- a/po/gl.po
+++ b/po/gl.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-09-05 12:49+0200\n"
 "Last-Translator: Fran Dieguez <frandieguez@ubuntu.com>\n"
 "Language-Team: Galician <proxecto@trasno.net>\n"
@@ -551,9 +551,17 @@ msgstr "valor do nivel de referencia da ganancia da pista e do álbum"
 msgid "language code"
 msgstr "código de idioma"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "código de idioma para este fluxo, axustándose a ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "código de idioma"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "imaxe"
 
@@ -1027,30 +1035,6 @@ msgstr "Non foi posíbel cargar o ficheiro do engadido: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Non existe o elemento ou engadido «%s»\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Uso: gst-xmllaunch <ficheiro.xml> [ propiedade.do.elemento=valor … ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERRO: non foi posíbel analizar o ficheiro xml «%s».\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERRO: non existe o elemento de nivel superior da canalización no ficheiro "
-"«%s».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "AVISO: neste momento só se admite un elemento de nivel superior.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ERRO: non foi posíbel analizar o argumento %d da liña de ordes: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "AVISO: non se atopou o elemento nomeado «%s».\n"
-
 msgid "Index statistics"
 msgstr "Estatísticas do índice"
 
@@ -1147,18 +1131,9 @@ msgstr "Non sacar a saída da información de estado do TIPO"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPO1,TIPO2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Gardar a representación xml da canalización a un FICHEIRO e saír"
-
-msgid "FILE"
-msgstr "FICHEIRO"
-
 msgid "Do not install a fault handler"
 msgstr "Non instalar un manexador predeterminado"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Non instalar os manexadores de sinais para SIGUSR1 e SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Imprimir a traza de asignacións (se foi activada ao compilar)"
 
@@ -1229,3 +1204,34 @@ msgstr "Estabelecendo a tubería a NULL...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Liberando a tubería...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Uso: gst-xmllaunch <ficheiro.xml> [ propiedade.do.elemento=valor … ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERRO: non foi posíbel analizar o ficheiro xml «%s».\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERRO: non existe o elemento de nivel superior da canalización no ficheiro "
+#~ "«%s».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "AVISO: neste momento só se admite un elemento de nivel superior.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERRO: non foi posíbel analizar o argumento %d da liña de ordes: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "AVISO: non se atopou o elemento nomeado «%s».\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Gardar a representación xml da canalización a un FICHEIRO e saír"
+
+#~ msgid "FILE"
+#~ msgstr "FICHEIRO"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Non instalar os manexadores de sinais para SIGUSR1 e SIGUSR2"
index ebe8521..198b92a 100644 (file)
--- a/po/hu.po
+++ b/po/hu.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-01 13:39+0100\n"
 "Last-Translator: Gabor Kelemen <kelemeng@gnome.hu>\n"
 "Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
@@ -550,9 +550,17 @@ msgstr "szám és album hangosításának referenciaszintje"
 msgid "language code"
 msgstr "nyelvi kód"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "az adatfolyam ISO-639-1 szabványnak megfelelő nyelvi kódja"
 
+#, fuzzy
+msgid "language name"
+msgstr "nyelvi kód"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "kép"
 
@@ -1022,29 +1030,6 @@ msgstr "Nem tölthető be a bővítményfájl: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Nincs ilyen elem vagy bővítmény: „%s”\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Használat: gst-xmllaunch <fájl.xml> [ elem.tulajdonság=érték … ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "HIBA: a(z) „%s” xml fájl feldolgozása meghiúsult.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"HIBA: nincs felső szintű adatcsatorna elem a következő fájlban: „%s”.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "FIGYELMEZTETÉS: egyszerre csak egy felső szintű elem támogatott.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "HIBA: nem elemezhető a(z) %d. parancssori argumentum: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "FIGYELMEZTETÉS: a(z) „%s” nevű elem nem található.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1139,18 +1124,9 @@ msgstr "Ne írjon ki a TÍPUS típus állapotinformációit"
 msgid "TYPE1,TYPE2,..."
 msgstr "TÍPUS1,TÍPUS2,…"
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Az adatcsatorna xml ábrázolásának mentése a FÁJLBA és kilépés"
-
-msgid "FILE"
-msgstr "FÁJL"
-
 msgid "Do not install a fault handler"
 msgstr "Ne telepítsen hibakezelőt"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Ne telepítsen szignálkezelőket a SIGUSR1 és SIGUSR2 szignálokhoz"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Foglalási nyomkövetés kiírása (ha fordításkor engedélyezték)"
 
@@ -1221,3 +1197,31 @@ msgstr "Az adatcsatorna beállítása NULL értékre…\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Adatcsatorna felszabadítása…\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Használat: gst-xmllaunch <fájl.xml> [ elem.tulajdonság=érték … ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "HIBA: a(z) „%s” xml fájl feldolgozása meghiúsult.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "HIBA: nincs felső szintű adatcsatorna elem a következő fájlban: „%s”.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "FIGYELMEZTETÉS: egyszerre csak egy felső szintű elem támogatott.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "HIBA: nem elemezhető a(z) %d. parancssori argumentum: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "FIGYELMEZTETÉS: a(z) „%s” nevű elem nem található.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Az adatcsatorna xml ábrázolásának mentése a FÁJLBA és kilépés"
+
+#~ msgid "FILE"
+#~ msgstr "FÁJL"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Ne telepítsen szignálkezelőket a SIGUSR1 és SIGUSR2 szignálokhoz"
index 9b88775..654d37c 100644 (file)
--- a/po/id.po
+++ b/po/id.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.29.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-06-29 21:55+0700\n"
 "Last-Translator: Andhika Padmawan <andhika.padmawan@gmail.com>\n"
 "Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
@@ -553,9 +553,17 @@ msgstr "level referensi nilai peraihan jalur dan album"
 msgid "language code"
 msgstr "kode bahasa"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "kode bahasa arus ini, mengubahnya ke ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "kode bahasa"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "gambar"
 
@@ -1029,29 +1037,6 @@ msgstr "Tak dapat membuat berkas plugin: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Tak ada elemen atau plugin '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Penggunaan: gst-xmllaunch <berkas.xml> [ elemen.properti=nilai ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "GALAT: penguraian berkas xml '%s' gagal.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "GALAT: tak ada elemen baris pipa level atas di berkas '%s'.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"PERINGATAN: hanya satu elemen level atas yang didukung pada saat ini.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "GALAT: tak dapat menguraikan argumen baris perintah %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "GALAT: elemen yang dinamakan '%s' tak ditemukan.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1146,18 +1131,9 @@ msgstr "Jangan keluarkan informasi status dari TIPE"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPE1, TIPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Simpan perwakilan xml baris pipa ke BERKAS lalu keluar"
-
-msgid "FILE"
-msgstr "BERKAS"
-
 msgid "Do not install a fault handler"
 msgstr "Jangan instal penanganan galat"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Jangan instal penanganan sinyal untuk SIGUSR1 dan SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Cetak jejak alokasi (jika diaktifkan sewaktu kompilasi)"
 
@@ -1229,6 +1205,35 @@ msgstr "Mengatur baris pipa ke KOSONG ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Membebaskan baris pipa ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Penggunaan: gst-xmllaunch <berkas.xml> [ elemen.properti=nilai ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "GALAT: penguraian berkas xml '%s' gagal.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "GALAT: tak ada elemen baris pipa level atas di berkas '%s'.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "PERINGATAN: hanya satu elemen level atas yang didukung pada saat ini.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "GALAT: tak dapat menguraikan argumen baris perintah %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "GALAT: elemen yang dinamakan '%s' tak ditemukan.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Simpan perwakilan xml baris pipa ke BERKAS lalu keluar"
+
+#~ msgid "FILE"
+#~ msgstr "BERKAS"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Jangan instal penanganan sinyal untuk SIGUSR1 dan SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Galat menulis tembolok registry ke %s: %s"
 
index f26d740..3b4b15d 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -106,7 +106,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-10-25 10:03+0200\n"
 "Last-Translator: Luca Ferretti <elle.uca@infinito.it>\n"
 "Language-Team: Italian <tp@lists.linux.it>\n"
@@ -681,9 +681,17 @@ msgstr ""
 msgid "language code"
 msgstr "codice lingua"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "il codice della lingua per questo stream, conforme a ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "codice lingua"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "immagine"
 
@@ -1198,29 +1206,6 @@ msgstr "Impossibile caricare il file di plugin: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Elemento o plugin «%s» inesistente\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Uso: gst-xmllaunch <FILE.XML> [ ELEMENTO.PROPRIETA=VALORE ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERRORE: analisi del file xml «%s» non riuscita.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ERRORE: nessun elemento pipeline toplevel nel file «%s».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "ATTENZIONE: al momento è supportato sono un elemento toplevel.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ERRORE: impossibile analizzare l'argomento %d della riga di comando: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ATTENZIONE: elemento con nome «%s» non trovato.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1321,20 +1306,10 @@ msgstr "Non stampa le informazioni di stato per TIPO"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPO1,TIPO2,..."
 
-# -o, --output=FILE
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Salva su FILE una rappresentazione xml della pipeline ed esce"
-
-msgid "FILE"
-msgstr "FILE"
-
 # -f, --no-fault
 msgid "Do not install a fault handler"
 msgstr "Non installa un gestore di fault"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Non installa i gestori di segnale per SIGUSR1 e SIGUSR2"
-
 # -T, --trace
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Stampa traccia di alloc (se abilitato in compilazione)"
@@ -1414,6 +1389,35 @@ msgstr "Impostazione della pipeline a NULL ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Esecuzione di free sulla pipeline...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Uso: gst-xmllaunch <FILE.XML> [ ELEMENTO.PROPRIETA=VALORE ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERRORE: analisi del file xml «%s» non riuscita.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ERRORE: nessun elemento pipeline toplevel nel file «%s».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "ATTENZIONE: al momento è supportato sono un elemento toplevel.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERRORE: impossibile analizzare l'argomento %d della riga di comando: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ATTENZIONE: elemento con nome «%s» non trovato.\n"
+
+# -o, --output=FILE
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Salva su FILE una rappresentazione xml della pipeline ed esce"
+
+#~ msgid "FILE"
+#~ msgstr "FILE"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Non installa i gestori di segnale per SIGUSR1 e SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Errore nello scrivere la cache di registro su %s: %s"
 
index 6cab73a..2c7037a 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.20.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2008-10-16 19:57+0900\n"
 "Last-Translator: Makoto Kato <makoto.kt@gmail.com>\n"
 "Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
@@ -543,7 +543,14 @@ msgstr ""
 msgid "language code"
 msgstr "言語コード"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+#, fuzzy
+msgid "language name"
+msgstr "言語コード"
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1003,30 +1010,6 @@ msgstr "プラグインファイルをロードできませんでした: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr ""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "使い方: gst-xmllaunch <file.xml> [ element.property=value ...]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "エラー: xml ファイル '%s' の解析に失敗しました\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"エラー: ファイル '%s' にトップレベルのパイプラインエレメントがありません\n"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "警告: トップレベルのエレメントは一つのみサポートしています"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "エラー: コマンドライン引数 %d を解析できません: %s\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "警告: エレメント名 '%s' が見つかりません\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1125,19 +1108,9 @@ msgstr "TYPE のステータス情報を出力しない"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-
-msgid "FILE"
-msgstr "FILE"
-
 msgid "Do not install a fault handler"
 msgstr "フォールトハンドラをインストールしない"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "フォールトハンドラをインストールしない"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "alloc トレースを表示する (コンパイル時に有効にする必要があります)"
 
@@ -1211,6 +1184,33 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr "パイプラインを解放 (FREEING) しています...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "使い方: gst-xmllaunch <file.xml> [ element.property=value ...]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "エラー: xml ファイル '%s' の解析に失敗しました\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "エラー: ファイル '%s' にトップレベルのパイプラインエレメントがありません\n"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "警告: トップレベルのエレメントは一つのみサポートしています"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "エラー: コマンドライン引数 %d を解析できません: %s\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "警告: エレメント名 '%s' が見つかりません\n"
+
+#~ msgid "FILE"
+#~ msgstr "FILE"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "フォールトハンドラをインストールしない"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "%s へのレジストリキャッシュの書き込み中にエラーが発生しました: %s"
 
index 0ea69f5..cd850de 100644 (file)
--- a/po/lt.po
+++ b/po/lt.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.29.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-07-16 00:50+0300\n"
 "Last-Translator: Žygimantas Beručka <uid0@akl.lt>\n"
 "Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
@@ -550,9 +550,17 @@ msgstr "takelio ir albumo stiprinimo reikšmių santykinis lygis"
 msgid "language code"
 msgstr "kalbos kodas"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "šio srauto kalbos kodas, atitinkantis ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "kalbos kodas"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "paveikslėlis"
 
@@ -1032,30 +1040,6 @@ msgstr "Nepavyko įkelti įskiepio failo: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Nėra tokio elemento arba įskiepio „%s“\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Naudojimas: gst-xmllaunch <failas.xml> [ elementas.savybė=reikšmė ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "KLAIDA: nepavyko perskaityti xml failo „%s“.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "KLAIDA: nėra aukščiausio lygmens konvejerio elemento faile „%s“.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"ĮSPĖJIMAS: šiuo metu palaikomas tik vienas aukščiausio lygmens elementas.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "KLAIDA: nepavyko apdoroti komandinės eilutės argumento %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ĮSPĖJIMAS: nerastas elementas „%s“.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1150,18 +1134,9 @@ msgstr "Neišvesti šio TIPO būsenos informacijos"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPAS1,TIPAS2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Įrašyti konvejerio xml atitikmenį į FAILĄ ir išeiti"
-
-msgid "FILE"
-msgstr "FAILAS"
-
 msgid "Do not install a fault handler"
 msgstr "Neįdiegti klaidų apdorojimo posistemės"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Neįdiegti signalų apdorojimo posistemės signalams SIGUSR1 ir SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Išvesti alloc sekimą (jei įjungta kompiliavimo metu)"
 
@@ -1232,3 +1207,34 @@ msgstr "Nustatomas konvejeris į NULL...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Atlaisvinamas konvejeris...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Naudojimas: gst-xmllaunch <failas.xml> [ elementas.savybė=reikšmė ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "KLAIDA: nepavyko perskaityti xml failo „%s“.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "KLAIDA: nėra aukščiausio lygmens konvejerio elemento faile „%s“.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "ĮSPĖJIMAS: šiuo metu palaikomas tik vienas aukščiausio lygmens "
+#~ "elementas.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "KLAIDA: nepavyko apdoroti komandinės eilutės argumento %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ĮSPĖJIMAS: nerastas elementas „%s“.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Įrašyti konvejerio xml atitikmenį į FAILĄ ir išeiti"
+
+#~ msgid "FILE"
+#~ msgstr "FAILAS"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr ""
+#~ "Neįdiegti signalų apdorojimo posistemės signalams SIGUSR1 ir SIGUSR2"
index c9d96c9..7596618 100644 (file)
--- a/po/nb.po
+++ b/po/nb.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-10-24 21:36+0200\n"
 "Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
 "Language-Team: Norwegian Bokmaal <i18n-nb@lister.ping.uio.no>\n"
@@ -536,7 +536,14 @@ msgstr ""
 msgid "language code"
 msgstr "språkkode"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+#, fuzzy
+msgid "language name"
+msgstr "språkkode"
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -993,28 +1000,6 @@ msgstr "Kunne ikke laste tilleggsfil: «%s»\n"
 msgid "No such element or plugin '%s'\n"
 msgstr ""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr ""
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1109,18 +1094,9 @@ msgstr ""
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-
-msgid "FILE"
-msgstr "FIL"
-
 msgid "Do not install a fault handler"
 msgstr ""
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 
@@ -1191,3 +1167,6 @@ msgstr ""
 
 msgid "Freeing pipeline ...\n"
 msgstr "Frigjør rør ...\n"
+
+#~ msgid "FILE"
+#~ msgstr "FIL"
index 0385221..2d332c7 100644 (file)
--- a/po/nl.po
+++ b/po/nl.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-26 23:10+0200\n"
 "Last-Translator: Freek de Kruijf <f.de.kruijf@gmail.com>\n"
 "Language-Team: Dutch <vertaling@vrijschrift.org>\n"
@@ -557,9 +557,17 @@ msgstr "referentieniveau van de waarde van tarck- en albumgeluidsterkte"
 msgid "language code"
 msgstr "taalcode"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "taalcode van deze stroom, conform ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "taalcode"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "afbeelding"
 
@@ -1037,31 +1045,6 @@ msgstr "Kan plugin-bestand \"%s\" niet laden\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Geen element of plugin '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Gebruik: gst-xmllaunch <bestand.xml> [ element.eigenschap=waarde ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "FOUT: verwerken van xml-bestand '%s' mislukt.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "FOUT: geen bovenste pijplijn-element gevonden in file '%s'.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"WAARSCHUWING: slechts één element op het hoogste niveau ondersteund op dit "
-"moment.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "FOUT: kon argument %d op opdrachtregel niet verwerken: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "WAARSCHUWING: element met naam '%s' niet gevonden.\n"
-
 msgid "Index statistics"
 msgstr "Indexstatistieken"
 
@@ -1156,18 +1139,9 @@ msgstr "Statusinformatie van soort SOORT niet weergeven"
 msgid "TYPE1,TYPE2,..."
 msgstr "SOORT1,SOORT2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "XML-representatie van pijplijn in BESTAND opslaan en afsluiten"
-
-msgid "FILE"
-msgstr "BESTAND"
-
 msgid "Do not install a fault handler"
 msgstr "Geen foutafhandelaar installeren"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Geen signaalafhandelaars installeren voor SIGUSR1 en SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Toewijzingsspoor weergeven (indien aangezet tijdens compileren)"
 
@@ -1238,3 +1212,33 @@ msgstr "Pijplijn gezet op NULL ...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Pijplijn wordt vrijgemaakt ...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Gebruik: gst-xmllaunch <bestand.xml> [ element.eigenschap=waarde ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "FOUT: verwerken van xml-bestand '%s' mislukt.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "FOUT: geen bovenste pijplijn-element gevonden in file '%s'.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "WAARSCHUWING: slechts één element op het hoogste niveau ondersteund op "
+#~ "dit moment.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "FOUT: kon argument %d op opdrachtregel niet verwerken: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "WAARSCHUWING: element met naam '%s' niet gevonden.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "XML-representatie van pijplijn in BESTAND opslaan en afsluiten"
+
+#~ msgid "FILE"
+#~ msgstr "BESTAND"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Geen signaalafhandelaars installeren voor SIGUSR1 en SIGUSR2"
index f49bb22..f1f9ad4 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-26 17:54+0200\n"
 "Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
 "Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
@@ -550,9 +550,17 @@ msgstr "poziom odniesienia wartości osiągów ścieżki i albumu"
 msgid "language code"
 msgstr "kod języka"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "kod języka dla tego strumienia, zgodny z ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "kod języka"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "obrazek"
 
@@ -1033,29 +1041,6 @@ msgstr "Nie udało się wczytać pliku wtyczki: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Nie ma takiego elementu lub wtyczki '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Składnia: gst-xmllaunch <plik.xml> [ element.właściwość=wartość ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "BŁĄD: analiza pliku xml '%s' nie powiodła się.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "BŁĄD: brak głównego elementu potoku w pliku '%s'.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "UWAGA: aktualnie obsługiwany jest tylko jeden element główny.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "BŁĄD: nie udało się przeanalizować argumentu %d linii poleceń: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "UWAGA: nie znaleziono elementu o nazwie '%s'.\n"
-
 msgid "Index statistics"
 msgstr "Statystyki indeksu"
 
@@ -1150,18 +1135,9 @@ msgstr "Nie wypisywanie informacji o stanie tego RODZAJU"
 msgid "TYPE1,TYPE2,..."
 msgstr "RODZAJ1,RODZAJ2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Zapisanie reprezentacji xml potoku do PLIKU i zakończenie"
-
-msgid "FILE"
-msgstr "PLIK"
-
 msgid "Do not install a fault handler"
 msgstr "Nie instalowanie obsługi błędów"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Nieinstalowanie obsługi sygnałów SIGUSR1 i SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Wypisanie śladu alokacji (jeśli został włączony w czasie kompilacji)"
 
@@ -1232,3 +1208,32 @@ msgstr "Ustawianie potoku na NULL...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Zwalnianie potoku...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Składnia: gst-xmllaunch <plik.xml> [ element.właściwość=wartość ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "BŁĄD: analiza pliku xml '%s' nie powiodła się.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "BŁĄD: brak głównego elementu potoku w pliku '%s'.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "UWAGA: aktualnie obsługiwany jest tylko jeden element główny.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "BŁĄD: nie udało się przeanalizować argumentu %d linii poleceń: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "UWAGA: nie znaleziono elementu o nazwie '%s'.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Zapisanie reprezentacji xml potoku do PLIKU i zakończenie"
+
+#~ msgid "FILE"
+#~ msgstr "PLIK"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Nieinstalowanie obsługi sygnałów SIGUSR1 i SIGUSR2"
index 4a59558..b28aabb 100644 (file)
@@ -17,7 +17,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.31.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-01-08 01:36-0300\n"
 "Last-Translator: Fabrício Godoy <skarllot@gmail.com>\n"
 "Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n"
@@ -566,9 +566,17 @@ msgstr "nível de referência dos valores de ganho da faixa e do álbum"
 msgid "language code"
 msgstr "código da língua"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "código da língua deste fluxo, conforme o ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "código da língua"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "imagem"
 
@@ -1044,31 +1052,6 @@ msgstr "Não foi possível carregar o arquivo do plug-in: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Nenhum elemento ou plug-in \"%s\"\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Uso: gst-xmllaunch <arquivo.xml> [ elemento.propriedade=valor ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ERRO: a validação do arquivo xml \"%s\" falhou.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"ERRO: nenhum elemento de nível superior na fila de processamento do arquivo "
-"\"%s\".\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "AVISO: atualmente há suporte apenas a um elemento de nível superior.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"ERRO: não foi possível validar o argumento %d da linha de comando: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "AVISO: o elemento com o nome \"%s\" não foi encontrado.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1166,19 +1149,9 @@ msgstr "Não é possível obter informações do estado de saída do TIPO"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIPO1,TIPO2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-"Salvar representação da fila de processamento como xml para o ARQUIVO e sair"
-
-msgid "FILE"
-msgstr "ARQUIVO"
-
 msgid "Do not install a fault handler"
 msgstr "Não instale um manipulador de falhas"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Não fixar manipuladores de sinal para SIGUSR1 e SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Exibir trilha de alocação (se habilitado na compilação)"
 
@@ -1254,3 +1227,37 @@ msgstr "Definindo a fila de processamento para NULO...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Liberando a fila de processamento...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Uso: gst-xmllaunch <arquivo.xml> [ elemento.propriedade=valor ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ERRO: a validação do arquivo xml \"%s\" falhou.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "ERRO: nenhum elemento de nível superior na fila de processamento do "
+#~ "arquivo \"%s\".\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "AVISO: atualmente há suporte apenas a um elemento de nível superior.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ERRO: não foi possível validar o argumento %d da linha de comando: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "AVISO: o elemento com o nome \"%s\" não foi encontrado.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr ""
+#~ "Salvar representação da fila de processamento como xml para o ARQUIVO e "
+#~ "sair"
+
+#~ msgid "FILE"
+#~ msgstr "ARQUIVO"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Não fixar manipuladores de sinal para SIGUSR1 e SIGUSR2"
index ab39aac..8787bc8 100644 (file)
--- a/po/ro.po
+++ b/po/ro.po
@@ -5,7 +5,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.29.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-08-16 01:10+0300\n"
 "Last-Translator: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>\n"
 "Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
@@ -558,9 +558,17 @@ msgstr "nivelul de referință al valorilor câștigului pentru pistă și album
 msgid "language code"
 msgstr "cod limbă"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "codul de limbă al acestui flux, conform ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "cod limbă"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "imagine"
 
@@ -1051,33 +1059,6 @@ msgstr "Nu se poate încărca fișierul modul: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Niciun astfel de element sau modul „%s”\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Utilizare: gst-xmllaunch <fișier.xml> [ element.property=valoare ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "EROARE: prelucrarea fișierului xml „%s” a eșuat.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-"EROARE: niciun element de prim nivel al liniei de asamblare în fișierul "
-"„%s”.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"AVERTISMENT: doar un element de nivel de vârf este suportat în acest "
-"moment.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "EROARE: nu se poate analiza argumetul %d al liniei de comandă: %s\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "AVERTISMENT: elementul cu numele „%s” nu a fost găsit.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1172,19 +1153,9 @@ msgstr "Nu scoate informații despre stările de TIPUL"
 msgid "TYPE1,TYPE2,..."
 msgstr "TIP1,TIP2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr ""
-"Salvarea unei reprezentări xml a liniei de asamblare în FIȘIER și ieșire"
-
-msgid "FILE"
-msgstr "FIȘIER"
-
 msgid "Do not install a fault handler"
 msgstr "Nu instala un gestionar de erori"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Nu instala rutine de tratare a semnalului pentru SIGUSR1 și SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Afișează căile de alocare (dacă s-a activat la momentul compilării)"
 
@@ -1255,3 +1226,36 @@ msgstr "Se setează linia de asamblare pe NULL ...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Se eliberează linia de asamblare...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Utilizare: gst-xmllaunch <fișier.xml> [ element.property=valoare ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "EROARE: prelucrarea fișierului xml „%s” a eșuat.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr ""
+#~ "EROARE: niciun element de prim nivel al liniei de asamblare în fișierul "
+#~ "„%s”.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "AVERTISMENT: doar un element de nivel de vârf este suportat în acest "
+#~ "moment.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "EROARE: nu se poate analiza argumetul %d al liniei de comandă: %s\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "AVERTISMENT: elementul cu numele „%s” nu a fost găsit.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr ""
+#~ "Salvarea unei reprezentări xml a liniei de asamblare în FIȘIER și ieșire"
+
+#~ msgid "FILE"
+#~ msgstr "FIȘIER"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Nu instala rutine de tratare a semnalului pentru SIGUSR1 și SIGUSR2"
index 0144f7c..2f4b750 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-26 20:25+0400\n"
 "Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
 "Language-Team: Russian <gnu@mx.ru>\n"
@@ -553,9 +553,17 @@ msgstr "эталонный уровень для корректировки гр
 msgid "language code"
 msgstr "код языка"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "код языка для этого потока согласно ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "код языка"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "изображение"
 
@@ -1032,30 +1040,6 @@ msgstr "Не удалось загрузить файл модуля: «%s»\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Модуль или элемент «%s» не найден\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Использование: gst-xmllaunch <файл.xml> [ элемент.свойство=значение...]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ОШИБКА: ошибка разбора xml-файла «%s».\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ОШИБКА: в файле «%s» отсутствует главный элемент конвейера.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"ПРЕДУПРЕЖДЕНИЕ: в данный момент поддерживается только один главный элемент.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ОШИБКА: ошибка обработки аргумента командной строки %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ПРЕДУПРЕЖДЕНИЕ: элемент с именем «%s» не найден.\n"
-
 msgid "Index statistics"
 msgstr "Индексная статистика"
 
@@ -1150,18 +1134,9 @@ msgstr "Не выводить информацию о состоянии ТИП
 msgid "TYPE1,TYPE2,..."
 msgstr "ТИП1, ТИП2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Сохранить конвейер в XML-файл и выйти"
-
-msgid "FILE"
-msgstr "ФАЙЛ"
-
 msgid "Do not install a fault handler"
 msgstr "Не устанавливать обработчик ошибок"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Не устанавливать обработчики сигналов SIGUSR1 и SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Вывести трассировку выделения памяти (если включено при сборке)"
 
@@ -1233,6 +1208,36 @@ msgstr "Установка конвейера в состояние NULL...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Освобождение конвейера...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Использование: gst-xmllaunch <файл.xml> [ элемент.свойство=значение...]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ОШИБКА: ошибка разбора xml-файла «%s».\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ОШИБКА: в файле «%s» отсутствует главный элемент конвейера.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "ПРЕДУПРЕЖДЕНИЕ: в данный момент поддерживается только один главный "
+#~ "элемент.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "ОШИБКА: ошибка обработки аргумента командной строки %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: элемент с именем «%s» не найден.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Сохранить конвейер в XML-файл и выйти"
+
+#~ msgid "FILE"
+#~ msgstr "ФАЙЛ"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Не устанавливать обработчики сигналов SIGUSR1 и SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Ошибка записи кэша реестра в %s: %s"
 
index 7178bad..69d45a6 100644 (file)
--- a/po/rw.po
+++ b/po/rw.po
@@ -15,7 +15,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.8.8\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2005-04-04 10:55-0700\n"
 "Last-Translator: Steven Michael Murphy <murf@e-tools.com>\n"
 "Language-Team: Kinyarwanda <translation-team-rw@lists.sourceforge.net>\n"
@@ -723,7 +723,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1209,30 +1215,6 @@ msgstr "OYA Gufungura IDOSIYE kugirango"
 msgid "No such element or plugin '%s'\n"
 msgstr "Oya Inkomoko Ikigize: kugirango"
 
-#, fuzzy
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "IDOSIYE xml Ikigize: indangakintu Agaciro"
-
-#, fuzzy, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "Bya xml IDOSIYE Byanze"
-
-#, fuzzy, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "Oya Ikigize: in IDOSIYE"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "Ikigize: ni ku iyi Igihe"
-
-#, fuzzy, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "OYA Komandi: Umurongo"
-
-#, fuzzy, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "Ikigize: OYA Byabonetse"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1330,21 +1312,10 @@ msgid "TYPE1,TYPE2,..."
 msgstr ""
 
 #, fuzzy
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Kubika xml Bya Kuri Na Gusohoka"
-
-msgid "FILE"
-msgstr "IDOSIYE"
-
-#, fuzzy
 msgid "Do not install a fault handler"
 msgstr "OYA Kwinjiza porogaramu a"
 
 #, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "OYA Kwinjiza porogaramu a"
-
-#, fuzzy
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "NIBA Bikora ku Gukusanya Igihe"
 
@@ -1422,6 +1393,41 @@ msgid "Freeing pipeline ...\n"
 msgstr ""
 
 #, fuzzy
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "IDOSIYE xml Ikigize: indangakintu Agaciro"
+
+#, fuzzy
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "Bya xml IDOSIYE Byanze"
+
+#, fuzzy
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "Oya Ikigize: in IDOSIYE"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "Ikigize: ni ku iyi Igihe"
+
+#, fuzzy
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "OYA Komandi: Umurongo"
+
+#, fuzzy
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "Ikigize: OYA Byabonetse"
+
+#, fuzzy
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Kubika xml Bya Kuri Na Gusohoka"
+
+#~ msgid "FILE"
+#~ msgstr "IDOSIYE"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "OYA Kwinjiza porogaramu a"
+
+#, fuzzy
 #~ msgid "Error while writing to file descriptor \"%d\"."
 #~ msgstr "Kuri IDOSIYE"
 
index f818a54..e117ebb 100644 (file)
--- a/po/sk.po
+++ b/po/sk.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.30.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-11-08 16:13+0100\n"
 "Last-Translator: Peter Tuhársky <tuharsky@misbb.sk>\n"
 "Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
@@ -568,9 +568,17 @@ msgstr "Referenčná úroveň zisku pre stopu a pre album"
 msgid "language code"
 msgstr "jazykový kód"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "jazykový kód pre tento prúd údajov, v súlade s ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "jazykový kód"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "obrázok"
 
@@ -1045,29 +1053,6 @@ msgstr "Nepodarilo sa načítať súbor zásuvného modulu: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Takýto prvok alebo zásuvný modul neexistuje '%s'\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Použitie: gst-xmllaunch <súbor.xml> [ prvk.vlastnosť=hodnota ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "CHYBA: zlyhala analýza xml súboru '%s'.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "CHYBA: v súbore '%s' chýba prvok rúry najvyššej úrovne.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"VAROVANIE: v súčasnosti je podporovaný iba jeden prvok najvyššej úrovne.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "CHYBA: nepodarilo sa analyzovať argument príkazového riadku %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "VAROVANIE: prvok s názvom '%s' sa nenašiel.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1162,18 +1147,9 @@ msgstr "Nevypisovať informácie o stave TYPU"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYP1,TYP2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Uložiť reprezentáciu rúry v xml do SÚBORU a skončiť"
-
-msgid "FILE"
-msgstr "SÚBOR"
-
 msgid "Do not install a fault handler"
 msgstr "Neinštalovať obsluhu výnimiek"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Neinštalovať obsluhu signálov SIGUSR1 a SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Vypisovať stopu alokácie (ak je to povolené pri kompilácii)"
 
@@ -1248,6 +1224,36 @@ msgstr "Nastavujem rúru na NULOVÚ ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Uvoľňujem rúru ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Použitie: gst-xmllaunch <súbor.xml> [ prvk.vlastnosť=hodnota ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "CHYBA: zlyhala analýza xml súboru '%s'.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "CHYBA: v súbore '%s' chýba prvok rúry najvyššej úrovne.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "VAROVANIE: v súčasnosti je podporovaný iba jeden prvok najvyššej úrovne.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "CHYBA: nepodarilo sa analyzovať argument príkazového riadku %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "VAROVANIE: prvok s názvom '%s' sa nenašiel.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Uložiť reprezentáciu rúry v xml do SÚBORU a skončiť"
+
+#~ msgid "FILE"
+#~ msgstr "SÚBOR"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Neinštalovať obsluhu signálov SIGUSR1 a SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Chyba pri zápise vyrovnávacej pamäte registrov do %s: %s"
 
index beefdf2..485191f 100644 (file)
--- a/po/sl.po
+++ b/po/sl.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-09-22 15:02+0100\n"
 "Last-Translator: Klemen Košir <klemen.kosir@gmx.com>\n"
 "Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
@@ -550,9 +550,17 @@ msgstr "sklicna raven vrednosti pridobitve sledi in albuma"
 msgid "language code"
 msgstr "jezikovna koda"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "koda jezika pretoka v skladu z ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "jezikovna koda"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "slika"
 
@@ -1032,29 +1040,6 @@ msgstr "Datoteke vstavka ni mogoče naložiti: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Predmet ali datoteka \"%s\" ne obstaja\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Uporaba: gst-xmllaunch <datoteka.xml> [ predmet.lastnost=vrednost ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "NAPAKA: razčlenjevanje datoteke XML \"%s\" je spodletelo.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "NAPAKA: v datoteki \"%s\" ni vrhnjega predmeta cevovoda.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "OPOZORILO: trenutno je podprt le en vrhnji predmet.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "Napaka: argumenta %d ukazne vrstice ni mogoče razčleniti: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "OPOZORILO: predmeta z imenom \"%s\" ni mogoče najti.\n"
-
 msgid "Index statistics"
 msgstr "Statistika kazala"
 
@@ -1150,18 +1135,9 @@ msgstr "Ne izpiši podrobnosti stanja VRSTE"
 msgid "TYPE1,TYPE2,..."
 msgstr "VRSTA1, VRSTA2 ..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Shrani XML-predstavitev cevovoda v DATOTEKO in končaj"
-
-msgid "FILE"
-msgstr "DATOTEKA"
-
 msgid "Do not install a fault handler"
 msgstr "Na namesti ročnika napak"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Ne namesti ročnikov signalov za SIGUSR1 in SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr ""
 "Izpiši zaznavanje dodeljevanja (če je možnost omogočena v trenutku kodnega "
@@ -1234,3 +1210,31 @@ msgstr "Nastavljanje cevovoda na NULL ...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Sproščanje cevovoda ...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Uporaba: gst-xmllaunch <datoteka.xml> [ predmet.lastnost=vrednost ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "NAPAKA: razčlenjevanje datoteke XML \"%s\" je spodletelo.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "NAPAKA: v datoteki \"%s\" ni vrhnjega predmeta cevovoda.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "OPOZORILO: trenutno je podprt le en vrhnji predmet.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "Napaka: argumenta %d ukazne vrstice ni mogoče razčleniti: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "OPOZORILO: predmeta z imenom \"%s\" ni mogoče najti.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Shrani XML-predstavitev cevovoda v DATOTEKO in končaj"
+
+#~ msgid "FILE"
+#~ msgstr "DATOTEKA"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Ne namesti ročnikov signalov za SIGUSR1 in SIGUSR2"
index dbc2ffa..ec0e2f4 100644 (file)
--- a/po/sq.po
+++ b/po/sq.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.8.4\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2004-08-07 23:46+0200\n"
 "Last-Translator: Laurent Dhima <laurenti@alblinux.net>\n"
 "Language-Team: Albanian <begraj@hotmail.com>\n"
@@ -575,7 +575,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1044,30 +1050,6 @@ msgstr "E pamundur hapja e file \"%s\" në shkrim."
 msgid "No such element or plugin '%s'\n"
 msgstr "asnjë element burues për URI \"%s\""
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Përdorimi: gst-xmllaunch <file.xml> [ element.property=vlera ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "GABIM: analizimi i file xml '%s' dështoi.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "GABIM: asnjë element i pipline të toplevel tek file '%s'.\n"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "KUJDES: vetëm një element toplevel suportohet aktualisht."
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr ""
-"GABIM: i pamundur analizimi i argumentit %d të rreshtit të komandës: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "KUJDES: elementi me emrin '%s' nuk u gjet.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1161,19 +1143,9 @@ msgstr "Mos jep informacionin e gjendjes së LLOJIT"
 msgid "TYPE1,TYPE2,..."
 msgstr "LLOJI1,LLOJI2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Ruaj prezantimin xml të pipeline tek FILE dhe dil"
-
-msgid "FILE"
-msgstr "FILE"
-
 msgid "Do not install a fault handler"
 msgstr "Mos instalo një ushqyes të dëmtuar"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Mos instalo një ushqyes të dëmtuar"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Printo shenjat e alloc (nëse aktivuar në kohën e kompilimit)"
 
@@ -1248,6 +1220,37 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr "DUKE ZBATUAR pipeline ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Përdorimi: gst-xmllaunch <file.xml> [ element.property=vlera ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "GABIM: analizimi i file xml '%s' dështoi.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "GABIM: asnjë element i pipline të toplevel tek file '%s'.\n"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "KUJDES: vetëm një element toplevel suportohet aktualisht."
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "GABIM: i pamundur analizimi i argumentit %d të rreshtit të komandës: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "KUJDES: elementi me emrin '%s' nuk u gjet.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Ruaj prezantimin xml të pipeline tek FILE dhe dil"
+
+#~ msgid "FILE"
+#~ msgstr "FILE"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Mos instalo një ushqyes të dëmtuar"
+
 #~ msgid "Disable accelerated CPU instructions"
 #~ msgstr "Ç'aktivo instruksionet e përshpejtimit të CPU"
 
index 12c45c9..b54f79c 100644 (file)
--- a/po/sr.po
+++ b/po/sr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-12-05 10:40+0200\n"
 "Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
 "Language-Team: Serbian <gnu@prevod.org>\n"
@@ -556,9 +556,17 @@ msgstr "подсетни ниво вредности појачања нумер
 msgid "language code"
 msgstr "шифра језика"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "шифра језика за овај ток, према стандарду ИСО-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "шифра језика"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "слика"
 
@@ -1034,29 +1042,6 @@ msgstr "Не могу да учитам датотеку прикључка: %s\
 msgid "No such element or plugin '%s'\n"
 msgstr "Нема таквог елемента или прикључка „%s“\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Употреба: gst-xmllaunch <датотека.xml> [ елемент.особина=вредност ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ГРЕШКА: није успело рашчлањивање хмл датотеке „%s“.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ГРЕШКА: нема елемента спојке низа највишег нивоа у датотеци „%s“.\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "УПОЗОРЕЊЕ: тренутно је подржан само један елемент највишег нивоа.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ГРЕШКА: не могу да обрадим аргумент линије наредби %d.: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "УПОЗОРЕЊЕ: елемент под називом „%s“ није нађен.\n"
-
 msgid "Index statistics"
 msgstr "Статистике пописа"
 
@@ -1152,18 +1137,9 @@ msgstr "Не исписује податке о стању за ВРСТУ"
 msgid "TYPE1,TYPE2,..."
 msgstr "ВРСТА1,ВРСТА2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Чува хмл облик спојке низа у ДАТОТЕКУ и излази"
-
-msgid "FILE"
-msgstr "ДАТОТЕКА"
-
 msgid "Do not install a fault handler"
 msgstr "Неће инсталирати руковаоца грешкама"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Неће инсталирати руковаоце сигнала за СИГУСР1 и СИГУСР2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Испиши траг доделе меморије (ако је укључено при превођењу)"
 
@@ -1235,6 +1211,34 @@ msgstr "Постављам спојку низа на НИШТА ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Ослобађам спојку низа...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Употреба: gst-xmllaunch <датотека.xml> [ елемент.особина=вредност ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ГРЕШКА: није успело рашчлањивање хмл датотеке „%s“.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ГРЕШКА: нема елемента спојке низа највишег нивоа у датотеци „%s“.\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "УПОЗОРЕЊЕ: тренутно је подржан само један елемент највишег нивоа.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "ГРЕШКА: не могу да обрадим аргумент линије наредби %d.: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "УПОЗОРЕЊЕ: елемент под називом „%s“ није нађен.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Чува хмл облик спојке низа у ДАТОТЕКУ и излази"
+
+#~ msgid "FILE"
+#~ msgstr "ДАТОТЕКА"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Неће инсталирати руковаоце сигнала за СИГУСР1 и СИГУСР2"
+
 #~ msgid "Disable accelerated CPU instructions"
 #~ msgstr "Искључи убрзане инструкције процесора"
 
index d27e686..9b9f3e6 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.31.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-01-09 19:46+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -559,9 +559,17 @@ msgstr "referensnivå för förstärkningsvärden för spår och album"
 msgid "language code"
 msgstr "språkkod"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "språkkod för detta ström, enligt ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "språkkod"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "bild"
 
@@ -1041,28 +1049,6 @@ msgstr "Kunde inte läsa in fil för insticksmodul: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Inget sådant element eller insticksmodul \"%s\"\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Användning: gst-xmllaunch <fil.xml> [ element.egenskap=värde ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "FEL: tolkning av xml-filen \"%s\" misslyckades.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "FEL: inget rörledningselement på översta nivån i filen \"%s\".\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "VARNING: endast ett element på översta nivån stöds just nu.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "FEL: kunde inte tolka kommandoradsargumentet %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "VARNING: elementet med namnet \"%s\" hittades inte.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1157,18 +1143,9 @@ msgstr "Skriv inte ut statusinformation av TYP"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYP1,TYP2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Spara xml-representation av rörledningen i FIL och avsluta"
-
-msgid "FILE"
-msgstr "FIL"
-
 msgid "Do not install a fault handler"
 msgstr "Installera inte en felhanterare"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Installera inte signalhanterare för SIGUSR1 och SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Skriv ut alloc-spår (om aktiverat vid kompileringen)"
 
@@ -1243,6 +1220,34 @@ msgstr "Ställer in rörledningen till NULL...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Frigör rörledning ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Användning: gst-xmllaunch <fil.xml> [ element.egenskap=värde ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "FEL: tolkning av xml-filen \"%s\" misslyckades.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "FEL: inget rörledningselement på översta nivån i filen \"%s\".\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "VARNING: endast ett element på översta nivån stöds just nu.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "FEL: kunde inte tolka kommandoradsargumentet %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "VARNING: elementet med namnet \"%s\" hittades inte.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Spara xml-representation av rörledningen i FIL och avsluta"
+
+#~ msgid "FILE"
+#~ msgstr "FIL"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Installera inte signalhanterare för SIGUSR1 och SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Fel vid skrivning av registercache till %s: %s"
 
index d973ac9..3ff0ca9 100644 (file)
--- a/po/tr.po
+++ b/po/tr.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.8.0\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2004-04-03 03:14+0300\n"
 "Last-Translator: Baris Cicek <baris@teamforce.name.tr>\n"
 "Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"
@@ -575,7 +575,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1045,29 +1051,6 @@ msgstr "\"%s\" dosyası yazım için açılamadı."
 msgid "No such element or plugin '%s'\n"
 msgstr "\"%s\" URI'si için kaynak öğesi yok"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "Kullanım: gst-xmllaunch <dosya.xml> [ öğe.özellik=değer ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "HATA: xml dosyası '%s' ayrıştırması başarısız.\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "HATA: '%s' dosyasında üst seviye öğesi bulunamadı.\n"
-
-#, fuzzy
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "UYARI: Şu anda sadece bir tane üst seviye öğesi destekleniyor."
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "HATA: komut satırı argümanı %d ayrıştırılamadı: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "UYARI: '%s' isimli öğe bulunamadı.\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1161,19 +1144,9 @@ msgstr "TÜRÜN durum bilgisini gösterme"
 msgid "TYPE1,TYPE2,..."
 msgstr "TÜR1,TÜR2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Boruhattının xml belirtimini DOSYA'ya kaydet ve çık"
-
-msgid "FILE"
-msgstr "DOSYA"
-
 msgid "Do not install a fault handler"
 msgstr "Hatalı işleticiyi kurma"
 
-#, fuzzy
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Hatalı işleticiyi kurma"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "'alloc' takibini yazdır (derleme sırasında etkinleştirilmişse)"
 
@@ -1248,6 +1221,35 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr "BORUHATTI çalıştırılıyor ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "Kullanım: gst-xmllaunch <dosya.xml> [ öğe.özellik=değer ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "HATA: xml dosyası '%s' ayrıştırması başarısız.\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "HATA: '%s' dosyasında üst seviye öğesi bulunamadı.\n"
+
+#, fuzzy
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "UYARI: Şu anda sadece bir tane üst seviye öğesi destekleniyor."
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "HATA: komut satırı argümanı %d ayrıştırılamadı: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "UYARI: '%s' isimli öğe bulunamadı.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Boruhattının xml belirtimini DOSYA'ya kaydet ve çık"
+
+#~ msgid "FILE"
+#~ msgstr "DOSYA"
+
+#, fuzzy
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Hatalı işleticiyi kurma"
+
 #~ msgid "Disable accelerated CPU instructions"
 #~ msgstr "Hızlandırılmış CPU işlemlerini kapat"
 
index 502b224..36016b0 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.32.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-12-10 00:53+0000\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2011-04-30 20:26+0300\n"
 "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
 "Language-Team: Ukrainian <translation-team-uk@lists.sourceforge.net>\n"
@@ -550,9 +550,17 @@ msgstr "опорні рівні гучності композиції чи ал
 msgid "language code"
 msgstr "код мови"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "код мови для потоку, код має відповідати ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "код мови"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "зображення"
 
@@ -1029,30 +1037,6 @@ msgstr "Не вдалося завантажити файл модулю %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Немає елемента елемента або модуля «%s»\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Використання: gst-xmllaunch <file.xml> [ елемент.властивість=значення ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "ПОМИЛКА: помилка при аналізі xml файлу «%s».\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "ПОМИЛКА: немає верхнього елемента каналу у файлі «%s».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-"ПОПЕРЕДЖЕННЯ: наразі підтримується лише один елемент найвищого рівня.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "ПОМИЛКА: не вдалося проаналізувати аргумент командного рядка %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "ПОПЕРЕДЖЕННЯ: елемент з назвою «%s» не існує.\n"
-
 msgid "Index statistics"
 msgstr "Статистичні дані покажчика"
 
@@ -1147,18 +1131,9 @@ msgstr "Не виводити інформацію про стан типу ТИ
 msgid "TYPE1,TYPE2,..."
 msgstr "ТИП1,ТИП2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Зберегти xml представлення каналу у файл ФАЙЛ та завершитись"
-
-msgid "FILE"
-msgstr "ФАЙЛ"
-
 msgid "Do not install a fault handler"
 msgstr "Не встановлювати обробник збоїв"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Не встановлювати обробники сигналів для SIGUSR1 і SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "Вивести трасування розподілу пам’яті (якщо ввімкнено при компіляції)"
 
@@ -1230,6 +1205,37 @@ msgstr "Канал переводиться у стан NULL ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "Спорожнення каналу...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Використання: gst-xmllaunch <file.xml> [ елемент."
+#~ "властивість=значення ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "ПОМИЛКА: помилка при аналізі xml файлу «%s».\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "ПОМИЛКА: немає верхнього елемента каналу у файлі «%s».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr ""
+#~ "ПОПЕРЕДЖЕННЯ: наразі підтримується лише один елемент найвищого рівня.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr ""
+#~ "ПОМИЛКА: не вдалося проаналізувати аргумент командного рядка %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "ПОПЕРЕДЖЕННЯ: елемент з назвою «%s» не існує.\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Зберегти xml представлення каналу у файл ФАЙЛ та завершитись"
+
+#~ msgid "FILE"
+#~ msgstr "ФАЙЛ"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Не встановлювати обробники сигналів для SIGUSR1 і SIGUSR2"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "Помилка при записі кешу реєстру у %s: %s"
 
index 6dafb70..7e5105f 100644 (file)
--- a/po/vi.po
+++ b/po/vi.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.29.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-10-03 19:09+1030\n"
 "Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
 "Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
@@ -550,9 +550,17 @@ msgstr "lớp chỉ dẫn các giá trị khuếch đại của rãnh và tập
 msgid "language code"
 msgstr "mã ngôn ngữ"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "mã ngôn ngữ cho luồng này, tùy theo tiêu chuẩn ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "mã ngôn ngữ"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "ảnh"
 
@@ -1030,29 +1038,6 @@ msgstr "Không thể nạp tập tin phần bổ sung: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "Không có yếu tố hay phần bổ sung như vậy « %s »\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr ""
-"Cách sử dụng: gst-xmllaunch <tập_tin.xml> [ yếu_tố.tài_sản=giá_trị ...]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "LỖI: lỗi phân tách tập tin xml « %s ».\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "LỖI: không có yếu tố đường ống cấp đầu trong tập tin « %s ».\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "CẢNH BÁO : hiện thời hỗ trợ chỉ một yếu tố cấp đầu.\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "LỖI: không thể phân tách đối số dòng lệnh %d: %s.\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "CẢNH BÁO : không tìm thấy yếu tố tên « %s ».\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1147,18 +1132,9 @@ msgstr "Không xuất thông tin trạng thái KIỂU"
 msgid "TYPE1,TYPE2,..."
 msgstr "KIỂU1,KIỂU2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "Lưu đường ống dạng XML vào TẬP_TIN rồi thoát"
-
-msgid "FILE"
-msgstr "TẬP_TIN"
-
 msgid "Do not install a fault handler"
 msgstr "Không cài đặt bộ quản lý lỗi"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr "Đừng cài đặt bộ quản lý tín hiệu cho SIGUSR1 và SIGUSR2"
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "In ra vết cấp phát (nếu được bật khi biên dich)"
 
@@ -1231,3 +1207,31 @@ msgstr "Đang lập đường ống thành VÔ GIÁ TRỊ ...\n"
 
 msgid "Freeing pipeline ...\n"
 msgstr "Đang giải phóng đường ống...\n"
+
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr ""
+#~ "Cách sử dụng: gst-xmllaunch <tập_tin.xml> [ yếu_tố.tài_sản=giá_trị ...]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "LỖI: lỗi phân tách tập tin xml « %s ».\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "LỖI: không có yếu tố đường ống cấp đầu trong tập tin « %s ».\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "CẢNH BÁO : hiện thời hỗ trợ chỉ một yếu tố cấp đầu.\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "LỖI: không thể phân tách đối số dòng lệnh %d: %s.\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "CẢNH BÁO : không tìm thấy yếu tố tên « %s ».\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "Lưu đường ống dạng XML vào TẬP_TIN rồi thoát"
+
+#~ msgid "FILE"
+#~ msgstr "TẬP_TIN"
+
+#~ msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
+#~ msgstr "Đừng cài đặt bộ quản lý tín hiệu cho SIGUSR1 và SIGUSR2"
index 92a1d9e..98b1393 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.25.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2010-02-02 18:58+0800\n"
 "Last-Translator: Ji ZhengYu <zhengyuji@gmail.com>\n"
 "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@@ -535,9 +535,17 @@ msgstr "音轨和专辑增益的参考级别值"
 msgid "language code"
 msgstr "语言代码"
 
-msgid "language code for this stream, conforming to ISO-639-1"
+#, fuzzy
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
 msgstr "此流的语言代码,遵从为 ISO-639-1"
 
+#, fuzzy
+msgid "language name"
+msgstr "语言代码"
+
+msgid "freeform name of the language this stream is in"
+msgstr ""
+
 msgid "image"
 msgstr "图像"
 
@@ -1002,28 +1010,6 @@ msgstr "无法载入插件文件: %s\n"
 msgid "No such element or plugin '%s'\n"
 msgstr "没有那样的组件或插件‘%s’\n"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "用法: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "错误: xml 文件‘%s’解析失败。\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr "错误: 文件‘%s’中没有顶级管道组件。\n"
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr "警告: 此时仅支持一个一级组件。\n"
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "错误: 无法解析命令行参数 %d: %s。\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr "警告: 组件名‘%s’未找到。\n"
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1118,18 +1104,9 @@ msgstr "不输出类型的状态信息"
 msgid "TYPE1,TYPE2,..."
 msgstr "类型1,类型2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "保存管道的 xml 描述符至文件并退出"
-
-msgid "FILE"
-msgstr "文件"
-
 msgid "Do not install a fault handler"
 msgstr "不安装错误的处理程序"
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "打印分配记录(如果在编译时开启的话)"
 
@@ -1202,6 +1179,30 @@ msgstr "设置 NULL 管道 ...\n"
 msgid "Freeing pipeline ...\n"
 msgstr "释放管道资源 ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "用法: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "错误: xml 文件‘%s’解析失败。\n"
+
+#~ msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
+#~ msgstr "错误: 文件‘%s’中没有顶级管道组件。\n"
+
+#~ msgid "WARNING: only one toplevel element is supported at this time.\n"
+#~ msgstr "警告: 此时仅支持一个一级组件。\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "错误: 无法解析命令行参数 %d: %s。\n"
+
+#~ msgid "WARNING: element named '%s' not found.\n"
+#~ msgstr "警告: 组件名‘%s’未找到。\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "保存管道的 xml 描述符至文件并退出"
+
+#~ msgid "FILE"
+#~ msgstr "文件"
+
 #~ msgid "Error writing registry cache to %s: %s"
 #~ msgstr "寄存器缓存写入 %s 时出错: %s"
 
index 7bb8fee..30a68e2 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.8.8\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-06-04 13:33+0100\n"
+"POT-Creation-Date: 2012-01-05 11:27+0000\n"
 "PO-Revision-Date: 2005-04-27 14:55+0800\n"
 "Last-Translator: Abel Cheung <abelcheung@gmail.com>\n"
 "Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n"
@@ -564,7 +564,13 @@ msgstr ""
 msgid "language code"
 msgstr ""
 
-msgid "language code for this stream, conforming to ISO-639-1"
+msgid "language code for this stream, conforming to ISO-639-1 or ISO-639-2"
+msgstr ""
+
+msgid "language name"
+msgstr ""
+
+msgid "freeform name of the language this stream is in"
 msgstr ""
 
 msgid "image"
@@ -1023,28 +1029,6 @@ msgstr "無法開啟 “%s” 檔案來寫入內容。"
 msgid "No such element or plugin '%s'\n"
 msgstr "URI “%s” 沒有來源元件"
 
-msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-msgstr "用法:gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
-
-#, c-format
-msgid "ERROR: parse of xml file '%s' failed.\n"
-msgstr "錯誤:無法解析 XML 檔案 ‘%s’ 的內容。\n"
-
-#, c-format
-msgid "ERROR: no toplevel pipeline element in file '%s'.\n"
-msgstr ""
-
-msgid "WARNING: only one toplevel element is supported at this time.\n"
-msgstr ""
-
-#, c-format
-msgid "ERROR: could not parse command line argument %d: %s.\n"
-msgstr "錯誤:無法解析指令的第 %d 個參數:%s。\n"
-
-#, c-format
-msgid "WARNING: element named '%s' not found.\n"
-msgstr ""
-
 msgid "Index statistics"
 msgstr ""
 
@@ -1138,18 +1122,9 @@ msgstr "不顯示和 TYPE 有關的狀態資訊"
 msgid "TYPE1,TYPE2,..."
 msgstr "TYPE1,TYPE2,..."
 
-msgid "Save xml representation of pipeline to FILE and exit"
-msgstr "將代表管線的架構儲存至<檔案>,然後結束"
-
-msgid "FILE"
-msgstr "檔案"
-
 msgid "Do not install a fault handler"
 msgstr ""
 
-msgid "Do not install signal handlers for SIGUSR1 and SIGUSR2"
-msgstr ""
-
 msgid "Print alloc trace (if enabled at compile time)"
 msgstr "印出 alloc 追蹤訊息 (如果編譯程式時有啟用這項功能)"
 
@@ -1224,6 +1199,21 @@ msgstr ""
 msgid "Freeing pipeline ...\n"
 msgstr "執行管線 ...\n"
 
+#~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+#~ msgstr "用法:gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
+
+#~ msgid "ERROR: parse of xml file '%s' failed.\n"
+#~ msgstr "錯誤:無法解析 XML 檔案 ‘%s’ 的內容。\n"
+
+#~ msgid "ERROR: could not parse command line argument %d: %s.\n"
+#~ msgstr "錯誤:無法解析指令的第 %d 個參數:%s。\n"
+
+#~ msgid "Save xml representation of pipeline to FILE and exit"
+#~ msgstr "將代表管線的架構儲存至<檔案>,然後結束"
+
+#~ msgid "FILE"
+#~ msgstr "檔案"
+
 #~ msgid "Disable accelerated CPU instructions"
 #~ msgstr "關閉 CPU 優化功能"
 
index 045c437..6cc1b37 100755 (executable)
@@ -82,7 +82,7 @@ do
 done
 
 # GStreamer core libraries
-for path in base net check controller dataprotocol
+for path in base net check controller
 do
   LD_LIBRARY_PATH=$GST/gstreamer/libs/gst/$path/.libs:$LD_LIBRARY_PATH
   DYLD_LIBRARY_PATH=$GST/gstreamer/libs/gst/$path/.libs:$DYLD_LIBRARY_PATH
index 32eaff2..dc7e5fa 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#include <stdio.h>
+
 #include <gst/gst.h>
-#include <gst/controller/gstcontroller.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
+#include <gst/controller/gstcontrolbindingdirect.h>
 
 /* a song in buzztard can easily reach 30000 here */
 #define NUM_CP 15000
@@ -81,15 +83,12 @@ main (gint argc, gchar * argv[])
   gint i, j;
   GstElement *src, *sink;
   GstElement *bin;
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
-  GValue freq = { 0, };
   GstClockTime bt, ct;
   GstClockTimeDiff elapsed;
   GstClockTime tick;
 
   gst_init (&argc, &argv);
-  gst_controller_init (&argc, &argv);
 
   /* build pipeline */
   bin = gst_pipeline_new ("pipeline");
@@ -111,19 +110,12 @@ main (gint argc, gchar * argv[])
 
   tick = BLOCK_SIZE * GST_SECOND / 44100;
 
-  /* add a controller to the source */
-  if (!(ctrl = gst_controller_new (G_OBJECT (src), "freq", NULL))) {
-    GST_WARNING ("can't control source element");
-    goto Error;
-  }
-
   /* create and configure control source */
   csource = gst_interpolation_control_source_new ();
-  gst_controller_set_control_source (ctrl, "freq",
-      GST_CONTROL_SOURCE (csource));
-  gst_interpolation_control_source_set_interpolation_mode (csource,
-      GST_INTERPOLATE_LINEAR);
-  g_value_init (&freq, G_TYPE_DOUBLE);
+  gst_object_add_control_binding (GST_OBJECT (src),
+      gst_control_binding_direct_new (GST_OBJECT (src), "freq",
+          GST_CONTROL_SOURCE (csource)));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
 
   /* set control values, we set them in a linear order as we would when loading
@@ -132,8 +124,8 @@ main (gint argc, gchar * argv[])
   bt = gst_util_get_timestamp ();
 
   for (i = 0; i < NUM_CP; i++) {
-    g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
-    gst_interpolation_control_source_set (csource, i * tick, &freq);
+    gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
+        i * tick, g_random_double_range (50.0, 3000.0));
   }
 
   ct = gst_util_get_timestamp ();
@@ -149,8 +141,8 @@ main (gint argc, gchar * argv[])
 
   for (i = 0; i < 100; i++) {
     j = g_random_int_range (0, NUM_CP - 1);
-    g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
-    gst_interpolation_control_source_set (csource, j * tick, &freq);
+    gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
+        j * tick, g_random_double_range (50.0, 3000.0));
   }
 
   ct = gst_util_get_timestamp ();
@@ -161,17 +153,11 @@ main (gint argc, gchar * argv[])
   {
     GstClockTime sample_duration =
         gst_util_uint64_scale_int (1, GST_SECOND, 44100);
-    GstValueArray va = { "freq",
-      BLOCK_SIZE * NUM_CP,
-      sample_duration,
-      NULL
-    };
-
     gdouble *values = g_new0 (gdouble, BLOCK_SIZE * NUM_CP);
-    va.values = (gpointer *) values;
 
     bt = gst_util_get_timestamp ();
-    gst_control_source_get_value_array (GST_CONTROL_SOURCE (csource), 0, &va);
+    gst_control_source_get_value_array (GST_CONTROL_SOURCE (csource), 0,
+        sample_duration, BLOCK_SIZE * NUM_CP, values);
     ct = gst_util_get_timestamp ();
     g_free (values);
     elapsed = GST_CLOCK_DIFF (bt, ct);
@@ -179,7 +165,7 @@ main (gint argc, gchar * argv[])
         GST_TIME_ARGS (elapsed));
   }
 
-  g_object_unref (csource);
+  gst_object_unref (csource);
 
   /* play, this test sequential reads */
   bt = gst_util_get_timestamp ();
@@ -196,7 +182,6 @@ main (gint argc, gchar * argv[])
       GST_TIME_ARGS (elapsed));
 
   /* cleanup */
-  g_object_unref (G_OBJECT (ctrl));
   gst_object_unref (G_OBJECT (bin));
   res = 0;
 Error:
index e7ec274..d17191d 100644 (file)
@@ -25,7 +25,7 @@
 #define MAX_THREADS  1000
 
 static guint64 nbbuffers;
-static GMutex *mutex;
+static GMutex mutex;
 
 
 static void *
@@ -36,8 +36,8 @@ run_test (void *user_data)
   GstBuffer *buf;
   GstClockTime start, end;
 
-  g_mutex_lock (mutex);
-  g_mutex_unlock (mutex);
+  g_mutex_lock (&mutex);
+  g_mutex_unlock (&mutex);
 
   start = gst_util_get_timestamp ();
 
@@ -68,7 +68,7 @@ main (gint argc, gchar * argv[])
   GstClockTime start, end;
 
   gst_init (&argc, &argv);
-  mutex = g_mutex_new ();
+  g_mutex_init (&mutex);
 
   if (argc != 3) {
     g_print ("usage: %s <num_threads> <nbbuffers>\n", argv[0]);
@@ -88,7 +88,7 @@ main (gint argc, gchar * argv[])
     exit (-3);
   }
 
-  g_mutex_lock (mutex);
+  g_mutex_lock (&mutex);
   /* Let's just make sure the GstBufferClass is loaded ... */
   tmp = gst_buffer_new ();
 
@@ -96,12 +96,9 @@ main (gint argc, gchar * argv[])
   for (t = 0; t < num_threads; t++) {
     GError *error = NULL;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    threads[t] = g_thread_create (run_test, GINT_TO_POINTER (t), TRUE, &error);
-#else
     threads[t] = g_thread_try_new ("bufferstresstest", run_test,
         GINT_TO_POINTER (t), &error);
-#endif
+
     if (error) {
       printf ("ERROR: g_thread_create() %s\n", error->message);
       exit (-1);
@@ -110,7 +107,7 @@ main (gint argc, gchar * argv[])
 
   /* Signal all threads to start */
   start = gst_util_get_timestamp ();
-  g_mutex_unlock (mutex);
+  g_mutex_unlock (&mutex);
 
   for (t = 0; t < num_threads; t++) {
     if (threads[t])
index ed89840..47aa5cc 100644 (file)
@@ -35,7 +35,7 @@ run_test (void *user_data)
 
   while (running) {
     gst_clock_get_time (sysclock);
-    prev = G_ATOMIC_INT_ADD (&count, 1);
+    prev = g_atomic_int_add (&count, 1);
     if (prev == G_MAXINT)
       g_warning ("overflow");
   }
@@ -70,12 +70,9 @@ main (gint argc, gchar * argv[])
   for (t = 0; t < num_threads; t++) {
     GError *error = NULL;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    threads[t] = g_thread_create (run_test, sysclock, TRUE, &error);
-#else
     threads[t] = g_thread_try_new ("clockstresstest", run_test,
         sysclock, &error);
-#endif
+
     if (error) {
       printf ("ERROR: g_thread_create() %s\n", error->message);
       exit (-1);
index b384f95..dfd9caf 100644 (file)
@@ -25,7 +25,7 @@
 
 static GstPoll *set;
 static GList *fds = NULL;
-static GMutex *fdlock;
+static GMutex fdlock;
 static GTimer *timer;
 
 #define MAX_THREADS  100
@@ -37,7 +37,7 @@ mess_some_more (void)
   gint random;
   gint removed = 0;
 
-  g_mutex_lock (fdlock);
+  g_mutex_lock (&fdlock);
 
   for (walk = fds; walk;) {
     GstPollFD *fd = (GstPollFD *) walk->data;
@@ -106,7 +106,7 @@ mess_some_more (void)
     }
   }
 
-  g_mutex_unlock (fdlock);
+  g_mutex_unlock (&fdlock);
 }
 
 static void *
@@ -124,10 +124,10 @@ run_test (void *threadid)
     } else {
       mess_some_more ();
       if (g_timer_elapsed (timer, NULL) > 0.5) {
-        g_mutex_lock (fdlock);
+        g_mutex_lock (&fdlock);
         g_print ("active fds :%d\n", g_list_length (fds));
         g_timer_start (timer);
-        g_mutex_unlock (fdlock);
+        g_mutex_unlock (&fdlock);
       }
       g_usleep (1);
     }
@@ -145,7 +145,7 @@ main (gint argc, gchar * argv[])
 
   gst_init (&argc, &argv);
 
-  fdlock = g_mutex_new ();
+  g_mutex_init (&fdlock);
   timer = g_timer_new ();
 
   if (argc != 2) {
@@ -160,12 +160,9 @@ main (gint argc, gchar * argv[])
   for (t = 0; t < num_threads; t++) {
     GError *error = NULL;
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-    threads[t] = g_thread_create (run_test, GINT_TO_POINTER (t), TRUE, &error);
-#else
     threads[t] = g_thread_try_new ("pollstresstest", run_test,
         GINT_TO_POINTER (t), &error);
-#endif
+
     if (error) {
       printf ("ERROR: g_thread_create() %s\n", error->message);
       exit (-1);
index bf56a90..f254fae 100644 (file)
@@ -27,6 +27,9 @@ SUPPRESSIONS = $(top_srcdir)/common/gst.supp
 
 clean-local: clean-local-check
 
+# These tests don't even build any longer:
+#   gst/gstindex.c
+
 if GST_DISABLE_PARSE
 PARSE_CHECKS = pipelines/parse-disabled
 else
@@ -35,7 +38,7 @@ endif
 
 # Do not run the abi test in case any option which causes the API to change has
 # been used
-if !GST_DISABLE_LOADSAVE
+if FALSE
 if !GST_DISABLE_REGISTRY
 if !GST_DISABLE_TRACE
 ABI_CHECKS = gst/gstabi
@@ -43,6 +46,10 @@ endif
 endif
 endif
 
+if FALSE
+LIBSABI_CHECKS = libs/libsabi
+endif
+
 if HAVE_CXX
 CXX_CHECKS = gst/gstcpp libs/gstlibscpp
 else
@@ -58,12 +65,11 @@ REGISTRY_CHECKS =                           \
        gst/gst                                 \
        gst/gstbin                              \
        gst/gstchildproxy                       \
+       gst/gstcontroller                               \
        gst/gstelement                          \
        gst/gstelementfactory                   \
        gst/gstevent                            \
        gst/gstghostpad                         \
-       gst/gstindex                            \
-       gst/gstinterface                                \
        gst/gstplugin                           \
        gst/gstpreset                           \
        gst/gstquery                            \
@@ -98,6 +104,8 @@ check_PROGRAMS =                             \
        gst/gstatomicqueue                      \
        gst/gstbuffer                           \
        gst/gstbufferlist                       \
+       gst/gstmeta                             \
+       gst/gstmemory                           \
        gst/gstbus                              \
        gst/gstcaps                             \
        $(CXX_CHECKS)                           \
@@ -121,8 +129,7 @@ check_PROGRAMS =                            \
        generic/states                          \
        $(PARSE_CHECKS)                         \
        $(REGISTRY_CHECKS)                      \
-       libs/libsabi                            \
-       libs/gdp                                \
+       $(LIBSABI_CHECKS)                       \
        libs/adapter                            \
        libs/bitreader                          \
        libs/bytereader                         \
@@ -173,12 +180,6 @@ libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc
 
 gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS)
 
-libs_gdp_SOURCES = \
-       libs/gdp.c
-libs_gdp_LDADD = \
-       $(top_builddir)/libs/gst/dataprotocol/libgstdataprotocol-@GST_MAJORMINOR@.la \
-       $(LDADD)
-
 elements_fdsrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \
        -DTESTFILE=\"$(top_srcdir)/configure.ac\"
 elements_filesrc_CFLAGS=$(GST_OBJ_CFLAGS) $(AM_CFLAGS) \
@@ -192,7 +193,7 @@ libs_gstnetclientclock_LDADD = \
        $(LDADD)
 libs_gstnettimeprovider_LDADD = \
        $(top_builddir)/libs/gst/net/libgstnet-@GST_MAJORMINOR@.la \
-       $(LDADD)
+       $(GIO_LIBS) $(LDADD)
 
 # valgrind testing
 # these just need valgrind fixing, period
@@ -220,7 +221,6 @@ COVERAGE_DIRS = \
        libs/gst/base \
        libs/gst/controller \
        libs/gst/check \
-       libs/gst/dataprotocol \
        libs/gst/net \
        plugins/elements
 COVERAGE_FILES = $(foreach dir,$(COVERAGE_DIRS),$(wildcard $(top_builddir)/$(dir)/*.gcov))
index 97a6f09..17df2ca 100644 (file)
@@ -50,7 +50,7 @@ GST_START_TEST (test_unfixed_downstream_caps)
   gst_bin_add_many (GST_BIN (pipe), src, filter, NULL);
   fail_unless (gst_element_link (src, filter));
 
-  mysinkpad = gst_check_setup_sink_pad (filter, &sinktemplate, NULL);
+  mysinkpad = gst_check_setup_sink_pad (filter, &sinktemplate);
   gst_pad_set_active (mysinkpad, TRUE);
 
   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
index dacf00e..a3ed673 100644 (file)
@@ -99,14 +99,19 @@ GST_START_TEST (test_clipping)
 
   /* send segment */
   {
-    GstEvent *segment;
+    GstEvent *event;
+    GstSegment segment;
     gboolean eret;
 
     GST_DEBUG ("sending segment");
-    segment = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 5 * GST_SECOND, 1 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 1 * GST_SECOND;
+    segment.stop = 5 * GST_SECOND;
+    segment.time = 1 * GST_SECOND;
+
+    event = gst_event_new_segment (&segment);
 
-    eret = gst_pad_send_event (sinkpad, segment);
+    eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
@@ -258,14 +263,18 @@ GST_START_TEST (test_preroll_sync)
 
   /* send segment */
   {
-    GstEvent *segment;
+    GstEvent *event;
+    GstSegment segment;
     gboolean eret;
 
     GST_DEBUG ("sending segment");
-    segment = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 102 * GST_SECOND, 0 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 0 * GST_SECOND;
+    segment.stop = 102 * GST_SECOND;
+    segment.time = 0 * GST_SECOND;
 
-    eret = gst_pad_send_event (sinkpad, segment);
+    event = gst_event_new_segment (&segment);
+    eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
@@ -418,14 +427,18 @@ GST_START_TEST (test_eos)
 
   /* send segment, this should fail */
   {
-    GstEvent *segment;
+    GstEvent *event;
+    GstSegment segment;
     gboolean eret;
 
     GST_DEBUG ("sending segment");
-    segment = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 0 * GST_SECOND;
+    segment.stop = 2 * GST_SECOND;
+    segment.time = 0 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
-    eret = gst_pad_send_event (sinkpad, segment);
+    eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == TRUE);
   }
 
@@ -440,9 +453,9 @@ GST_START_TEST (test_eos)
 
     GST_DEBUG ("sending buffer");
 
-    /* buffer after EOS is not UNEXPECTED */
+    /* buffer after EOS is not EOS */
     fret = gst_pad_chain (sinkpad, buffer);
-    fail_unless (fret == GST_FLOW_UNEXPECTED);
+    fail_unless (fret == GST_FLOW_EOS);
   }
 
   /* flush, EOS state is flushed again. */
@@ -456,21 +469,25 @@ GST_START_TEST (test_eos)
     fail_unless (eret == TRUE);
 
     GST_DEBUG ("sending FLUSH_STOP");
-    event = gst_event_new_flush_stop ();
+    event = gst_event_new_flush_stop (TRUE);
     eret = gst_pad_send_event (sinkpad, event);
     fail_unless (eret == TRUE);
   }
 
   /* send segment, this should now work again */
   {
-    GstEvent *segment;
+    GstEvent *event;
+    GstSegment segment;
     gboolean eret;
 
     GST_DEBUG ("sending segment");
-    segment = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 0 * GST_SECOND;
+    segment.stop = 2 * GST_SECOND;
+    segment.time = 0 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
-    eret = gst_pad_send_event (sinkpad, segment);
+    eret = gst_pad_send_event (sinkpad, event);
     fail_unless (eret == TRUE);
   }
 
@@ -524,18 +541,22 @@ GST_START_TEST (test_eos2)
 
   /* send segment, this should work */
   {
-    GstEvent *segment;
+    GstEvent *event;
+    GstSegment segment;
     gboolean eret;
 
     GST_DEBUG ("sending segment");
-    segment = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 0 * GST_SECOND;
+    segment.stop = 2 * GST_SECOND;
+    segment.time = 0 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
-    eret = gst_pad_send_event (sinkpad, segment);
+    eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
-  /* send buffer that should return UNEXPECTED */
+  /* send buffer that should return EOS */
   {
     GstBuffer *buffer;
     GstFlowReturn fret;
@@ -546,12 +567,12 @@ GST_START_TEST (test_eos2)
 
     GST_DEBUG ("sending buffer");
 
-    /* this buffer will generate UNEXPECTED */
+    /* this buffer will generate EOS */
     fret = gst_pad_chain (sinkpad, buffer);
-    fail_unless (fret == GST_FLOW_UNEXPECTED);
+    fail_unless (fret == GST_FLOW_EOS);
   }
 
-  /* send buffer that should return UNEXPECTED */
+  /* send buffer that should return EOS */
   {
     GstBuffer *buffer;
     GstFlowReturn fret;
@@ -563,7 +584,7 @@ GST_START_TEST (test_eos2)
     GST_DEBUG ("sending buffer");
 
     fret = gst_pad_chain (sinkpad, buffer);
-    fail_unless (fret == GST_FLOW_UNEXPECTED);
+    fail_unless (fret == GST_FLOW_EOS);
   }
 
   gst_element_set_state (pipeline, GST_STATE_NULL);
@@ -582,7 +603,6 @@ GST_START_TEST (test_position)
   GstPad *sinkpad;
   GstStateChangeReturn ret;
   gboolean qret;
-  GstFormat qformat;
   gint64 qcur;
   GstBuffer *buffer;
   GstFlowReturn fret;
@@ -606,16 +626,14 @@ GST_START_TEST (test_position)
   fail_if (sinkpad == NULL);
 
   /* do position query, this should fail, we have nothing received yet */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   ret = gst_element_set_state (pipeline, GST_STATE_READY);
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
 
   /* do position query, this should fail, we have nothing received yet */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   /* make pipeline and element ready to accept data */
@@ -623,15 +641,19 @@ GST_START_TEST (test_position)
   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
 
   /* do position query, this should fail, we have nothing received yet */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   /* send segment, this should work */
   {
+    GstSegment segment;
+
     GST_DEBUG ("sending segment");
-    event = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 1 * GST_SECOND, 3 * GST_SECOND, 1 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 1 * GST_SECOND;
+    segment.stop = 3 * GST_SECOND;
+    segment.time = 1 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
     eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
@@ -639,8 +661,7 @@ GST_START_TEST (test_position)
 
   /* FIXME, do position query, this should succeed with the time value from the
    * segment. */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 1 * GST_SECOND);
 
@@ -660,8 +681,7 @@ GST_START_TEST (test_position)
 
   /* do position query, this should succeed with the time value from the
    * segment. */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 1 * GST_SECOND);
 
@@ -680,30 +700,33 @@ GST_START_TEST (test_position)
 
   /* do position query, this should succeed with the time value from the
    * segment before the flush. */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 1 * GST_SECOND);
 
   /* stop flushing, timing is affected now */
   {
     GST_DEBUG ("sending flush_stop");
-    event = gst_event_new_flush_stop ();
+    event = gst_event_new_flush_stop (TRUE);
 
     eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
   /* do position query, this should fail, the segment is flushed */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   /* send segment, this should work */
   {
+    GstSegment segment;
+
     GST_DEBUG ("sending segment");
-    event = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 2 * GST_SECOND, 4 * GST_SECOND, 1 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 2 * GST_SECOND;
+    segment.stop = 4 * GST_SECOND;
+    segment.time = 1 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
     eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
@@ -725,8 +748,7 @@ GST_START_TEST (test_position)
 
   /* do position query, this should succeed with the time value from the
    * segment. */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 1 * GST_SECOND);
 
@@ -735,8 +757,7 @@ GST_START_TEST (test_position)
 
   /* position now is increasing but never exceeds the boundaries of the segment */
   for (i = 0; i < 5; i++) {
-    qformat = GST_FORMAT_TIME;
-    qret = gst_element_query_position (sink, &qformat, &qcur);
+    qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
     GST_DEBUG ("position %" GST_TIME_FORMAT, GST_TIME_ARGS (qcur));
     fail_unless (qret == TRUE);
     fail_unless (qcur >= 1 * GST_SECOND && qcur <= 3 * GST_SECOND);
@@ -749,8 +770,7 @@ GST_START_TEST (test_position)
 
   /* after rendering the position must be bigger then the stream_time of the
    * buffer */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
 
@@ -764,35 +784,38 @@ GST_START_TEST (test_position)
   }
 
   /* this should now just report the stream time of the last buffer */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 2 * GST_SECOND);
 
   {
     GST_DEBUG ("sending flush_stop");
-    event = gst_event_new_flush_stop ();
+    event = gst_event_new_flush_stop (TRUE);
 
     eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
   /* do position query, this should fail, the segment is flushed */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   /* send segment, this should work */
   {
+    GstSegment segment;
+
     GST_DEBUG ("sending segment");
-    event = gst_event_new_new_segment (FALSE,
-        1.0, GST_FORMAT_TIME, 2 * GST_SECOND, 4 * GST_SECOND, 1 * GST_SECOND);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = 2 * GST_SECOND;
+    segment.stop = 4 * GST_SECOND;
+    segment.time = 1 * GST_SECOND;
+    event = gst_event_new_segment (&segment);
 
     eret = gst_pad_send_event (sinkpad, event);
     fail_if (eret == FALSE);
   }
 
-  /* send buffer that should return UNEXPECTED */
+  /* send buffer that should return EOS */
   buffer = gst_buffer_new ();
   GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
@@ -808,13 +831,12 @@ GST_START_TEST (test_position)
 
   /* preroll buffer is rendered, we expect no more buffer after this one */
   fret = chain_async_return (data);
-  fail_unless (fret == GST_FLOW_UNEXPECTED);
+  fail_unless (fret == GST_FLOW_EOS);
 
   /* do position query, this should succeed with the stream time of the buffer
    * against the clock. Since the buffer is synced against the clock, the time
    * should be at least the stream time of the buffer. */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur >= 2 * GST_SECOND && qcur <= 3 * GST_SECOND);
 
@@ -822,8 +844,7 @@ GST_START_TEST (test_position)
    * against the segment */
   g_usleep (2 * G_USEC_PER_SEC);
 
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur == 3 * GST_SECOND);
 
@@ -835,8 +856,7 @@ GST_START_TEST (test_position)
   /* we report the time of the last start of the buffer. This is slightly
    * incorrect, we should report the exact time when we paused but there is no
    * record of that anywhere */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == TRUE);
   fail_unless (qcur >= 4 * GST_SECOND);
 
@@ -844,14 +864,12 @@ GST_START_TEST (test_position)
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
 
   /* fails again because we are in the wrong state */
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   gst_element_set_state (pipeline, GST_STATE_NULL);
 
-  qformat = GST_FORMAT_TIME;
-  qret = gst_element_query_position (sink, &qformat, &qcur);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &qcur);
   fail_unless (qret == FALSE);
 
   gst_object_unref (sinkpad);
@@ -865,17 +883,7 @@ typedef GstPushSrc OOBSource;
 typedef GstPushSrcClass OOBSourceClass;
 
 GType oob_source_get_type (void);
-GST_BOILERPLATE (OOBSource, oob_source, GstPushSrc, GST_TYPE_PUSH_SRC);
-
-static void
-oob_source_base_init (gpointer g_class)
-{
-  static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
-      GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
-
-  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (g_class),
-      gst_static_pad_template_get (&sinktemplate));
-}
+G_DEFINE_TYPE (OOBSource, oob_source, GST_TYPE_PUSH_SRC);
 
 static GstFlowReturn
 oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
@@ -891,13 +899,19 @@ oob_source_create (GstPushSrc * src, GstBuffer ** p_buf)
 static void
 oob_source_class_init (OOBSourceClass * klass)
 {
+  static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
+      GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
 
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sinktemplate));
+
   pushsrc_class->create = GST_DEBUG_FUNCPTR (oob_source_create);
 }
 
 static void
-oob_source_init (OOBSource * src, OOBSourceClass * g_class)
+oob_source_init (OOBSource * src)
 {
   /* nothing to do */
 }
index 3573be6..2988676 100644 (file)
@@ -34,16 +34,13 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS_ANY);
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
     have_eos = TRUE;
-    gst_event_unref (event);
-    return TRUE;
   }
-
   gst_event_unref (event);
-  return FALSE;
+  return TRUE;
 }
 
 static GstElement *
@@ -53,7 +50,7 @@ setup_fakesrc (void)
 
   GST_DEBUG ("setup_fakesrc");
   fakesrc = gst_check_setup_element ("fakesrc");
-  mysinkpad = gst_check_setup_sink_pad (fakesrc, &sinktemplate, NULL);
+  mysinkpad = gst_check_setup_sink_pad (fakesrc, &sinktemplate);
   gst_pad_set_event_function (mysinkpad, event_func);
   gst_pad_set_active (mysinkpad, TRUE);
   have_eos = FALSE;
@@ -117,7 +114,7 @@ GST_START_TEST (test_sizetype_empty)
   while (l) {
     GstBuffer *buf = l->data;
 
-    fail_unless (GST_BUFFER_SIZE (buf) == 0);
+    fail_unless (gst_buffer_get_size (buf) == 0);
     l = l->next;
   }
   gst_check_drop_buffers ();
@@ -155,7 +152,7 @@ GST_START_TEST (test_sizetype_fixed)
   while (l) {
     GstBuffer *buf = l->data;
 
-    fail_unless (GST_BUFFER_SIZE (buf) == 8192);
+    fail_unless (gst_buffer_get_size (buf) == 8192);
     l = l->next;
   }
   gst_check_drop_buffers ();
@@ -194,8 +191,8 @@ GST_START_TEST (test_sizetype_random)
   while (l) {
     GstBuffer *buf = l->data;
 
-    fail_if (GST_BUFFER_SIZE (buf) > 8192);
-    fail_if (GST_BUFFER_SIZE (buf) < 4096);
+    fail_if (gst_buffer_get_size (buf) > 8192);
+    fail_if (gst_buffer_get_size (buf) < 4096);
     l = l->next;
   }
   gst_check_drop_buffers ();
index 6c92f6d..06ba059 100644 (file)
@@ -37,16 +37,14 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS_ANY);
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
     have_eos = TRUE;
-    gst_event_unref (event);
-    return TRUE;
   }
 
   gst_event_unref (event);
-  return FALSE;
+  return TRUE;
 }
 
 static GstElement *
@@ -56,7 +54,7 @@ setup_fdsrc (void)
 
   GST_DEBUG ("setup_fdsrc");
   fdsrc = gst_check_setup_element ("fdsrc");
-  mysinkpad = gst_check_setup_sink_pad (fdsrc, &sinktemplate, NULL);
+  mysinkpad = gst_check_setup_sink_pad (fdsrc, &sinktemplate);
   gst_pad_set_event_function (mysinkpad, event_func);
   gst_pad_set_active (mysinkpad, TRUE);
   return fdsrc;
index 2e37ad7..eb173e7 100644 (file)
@@ -48,7 +48,7 @@ setup_filesink (void)
 
   GST_DEBUG ("setup_filesink");
   filesink = gst_check_setup_element ("filesink");
-  mysrcpad = gst_check_setup_src_pad (filesink, &srctemplate, NULL);
+  mysrcpad = gst_check_setup_src_pad (filesink, &srctemplate);
   gst_pad_set_active (mysrcpad, TRUE);
   return filesink;
 }
@@ -65,19 +65,17 @@ cleanup_filesink (GstElement * filesink)
 /* this queries via the element vfunc, which is currently not implemented */
 #define CHECK_QUERY_POSITION(filesink,format,position)                  \
     G_STMT_START {                                                       \
-      GstFormat fmt = format;                                            \
       gint64 pos;                                                        \
-      fail_unless (gst_element_query_position (filesink, &fmt, &pos));   \
+      fail_unless (gst_element_query_position (filesink, format, &pos)); \
       fail_unless_equals_int (pos, position);                            \
     } G_STMT_END
 #else
 #define CHECK_QUERY_POSITION(filesink,format,position)                   \
     G_STMT_START {                                                       \
-      GstFormat fmt = format;                                            \
       GstPad *pad;                                                       \
       gint64 pos;                                                        \
       pad = gst_element_get_static_pad (filesink, "sink");               \
-      fail_unless (gst_pad_query_position (pad, &fmt, &pos));            \
+      fail_unless (gst_pad_query_position (pad, format, &pos));          \
       fail_unless_equals_int (pos, position);                            \
       gst_object_unref (pad);                                            \
     } G_STMT_END
@@ -87,9 +85,12 @@ cleanup_filesink (GstElement * filesink)
     G_STMT_START {                                                        \
       GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes);               \
       GRand *rand = g_rand_new_with_seed (num_bytes);                     \
+      guint8 *data;                                                       \
       guint i;                                                            \
+      data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);             \
       for (i = 0; i < num_bytes; ++i)                                     \
-        GST_BUFFER_DATA(buf)[i] = (g_rand_int (rand) >> 24) & 0xff;       \
+        data[i] = (g_rand_int (rand) >> 24) & 0xff;                       \
+      gst_buffer_unmap (buf, data, num_bytes);                            \
       fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \
       g_rand_free (rand);                                                 \
     } G_STMT_END
@@ -102,6 +103,7 @@ GST_START_TEST (test_seeking)
   GstElement *filesink;
   gchar *tmp_fn;
   gint fd;
+  GstSegment segment;
 
   tmpdir = g_get_tmp_dir ();
   if (tmpdir == NULL)
@@ -141,8 +143,8 @@ GST_START_TEST (test_seeking)
   gst_query_unref (seeking_query);
 #endif
 
-  fail_unless (gst_pad_push_event (mysrcpad,
-          gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0)));
+  gst_segment_init (&segment, GST_FORMAT_BYTES);
+  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
 
   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
 
@@ -159,9 +161,8 @@ GST_START_TEST (test_seeking)
   PUSH_BYTES (8800);
   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8900);
 
-  if (gst_pad_push_event (mysrcpad,
-          gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 8800, -1,
-              0))) {
+  segment.start = 8800;
+  if (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))) {
     GST_LOG ("seek ok");
     /* make sure that new position is reported immediately */
     CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8800);
@@ -264,23 +265,26 @@ GST_START_TEST (test_uri_interface)
   fail_unless_equals_string (location, "/i/do/not/exist");
   g_free (location);
 
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
   fail_unless_equals_string (location, "file:///i/do/not/exist");
+  g_free (location);
 
   /* should accept file:///foo/bar URIs */
   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
-          "file:///foo/bar"));
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
+          "file:///foo/bar", NULL));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
   fail_unless_equals_string (location, "file:///foo/bar");
+  g_free (location);
   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/bar");
   g_free (location);
 
   /* should accept file://localhost/foo/bar URIs */
   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
-          "file://localhost/foo/baz"));
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
+          "file://localhost/foo/baz", NULL));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
   fail_unless_equals_string (location, "file:///foo/baz");
+  g_free (location);
   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/baz");
   g_free (location);
@@ -290,12 +294,13 @@ GST_START_TEST (test_uri_interface)
   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/b?r");
   g_free (location);
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
   fail_unless_equals_string (location, "file:///foo/b%3Fr");
+  g_free (location);
 
   /* should fail with other hostnames */
   fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
-          "file://hostname/foo/foo"));
+          "file://hostname/foo/foo", NULL));
 
   /* cleanup */
   gst_element_set_bus (filesink, NULL);
index 340d5a5..8a86b67 100644 (file)
@@ -37,7 +37,7 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS_ANY);
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
 
@@ -73,7 +73,7 @@ setup_filesrc (void)
 
   GST_DEBUG ("setup_filesrc");
   filesrc = gst_check_setup_element ("filesrc");
-  mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate, NULL);
+  mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate);
   gst_pad_set_event_function (mysinkpad, event_func);
   gst_pad_set_active (mysinkpad, TRUE);
 
@@ -171,6 +171,8 @@ GST_START_TEST (test_pull)
   GstPad *pad;
   GstFlowReturn ret;
   GstBuffer *buffer1, *buffer2;
+  guint8 *data1, *data2;
+  gsize size1, size2;
 
   src = setup_filesrc ();
 
@@ -184,7 +186,7 @@ GST_START_TEST (test_pull)
   fail_unless (pad != NULL);
 
   /* activate the pad in pull mode */
-  res = gst_pad_activate_pull (pad, TRUE);
+  res = gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE);
   fail_unless (res == TRUE);
 
   /* not start playing */
@@ -208,16 +210,18 @@ GST_START_TEST (test_pull)
   ret = gst_pad_get_range (pad, 0, 100, &buffer1);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer1 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer1) == 100);
+  fail_unless (gst_buffer_get_size (buffer1) == 100);
 
   ret = gst_pad_get_range (pad, 0, 50, &buffer2);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer2 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer2) == 50);
+  fail_unless (gst_buffer_get_size (buffer2) == 50);
 
   /* this should be the same */
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer1), GST_BUFFER_DATA (buffer2),
-          50) == 0);
+  data1 = gst_buffer_map (buffer1, &size1, NULL, GST_MAP_READ);
+  data2 = gst_buffer_map (buffer2, &size2, NULL, GST_MAP_READ);
+  fail_unless (memcmp (data1, data2, 50) == 0);
+  gst_buffer_unmap (buffer2, data2, size2);
 
   gst_buffer_unref (buffer2);
 
@@ -225,12 +229,14 @@ GST_START_TEST (test_pull)
   ret = gst_pad_get_range (pad, 50, 50, &buffer2);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer2 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer2) == 50);
+  fail_unless (gst_buffer_get_size (buffer2) == 50);
 
   /* compare with previously read data */
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer1) + 50,
-          GST_BUFFER_DATA (buffer2), 50) == 0);
+  data2 = gst_buffer_map (buffer2, &size2, NULL, GST_MAP_READ);
+  fail_unless (memcmp (data1 + 50, data2, 50) == 0);
+  gst_buffer_unmap (buffer2, data2, size2);
 
+  gst_buffer_unmap (buffer1, data1, size1);
   gst_buffer_unref (buffer1);
   gst_buffer_unref (buffer2);
 
@@ -238,45 +244,45 @@ GST_START_TEST (test_pull)
   ret = gst_pad_get_range (pad, stop - 10, 10, &buffer1);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer1 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer1) == 10);
+  fail_unless (gst_buffer_get_size (buffer1) == 10);
   gst_buffer_unref (buffer1);
 
   /* read 20 bytes at end-10 should give exactly 10 bytes */
   ret = gst_pad_get_range (pad, stop - 10, 20, &buffer1);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer1 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer1) == 10);
+  fail_unless (gst_buffer_get_size (buffer1) == 10);
   gst_buffer_unref (buffer1);
 
   /* read 0 bytes at end-1 should return 0 bytes */
   ret = gst_pad_get_range (pad, stop - 1, 0, &buffer1);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer1 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer1) == 0);
+  fail_unless (gst_buffer_get_size (buffer1) == 0);
   gst_buffer_unref (buffer1);
 
   /* read 10 bytes at end-1 should return 1 byte */
   ret = gst_pad_get_range (pad, stop - 1, 10, &buffer1);
   fail_unless (ret == GST_FLOW_OK);
   fail_unless (buffer1 != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer1) == 1);
+  fail_unless (gst_buffer_get_size (buffer1) == 1);
   gst_buffer_unref (buffer1);
 
   /* read 0 bytes at end should EOS */
   ret = gst_pad_get_range (pad, stop, 0, &buffer1);
-  fail_unless (ret == GST_FLOW_UNEXPECTED);
+  fail_unless (ret == GST_FLOW_EOS);
 
   /* read 10 bytes before end should EOS */
   ret = gst_pad_get_range (pad, stop, 10, &buffer1);
-  fail_unless (ret == GST_FLOW_UNEXPECTED);
+  fail_unless (ret == GST_FLOW_EOS);
 
   /* read 0 bytes after end should EOS */
   ret = gst_pad_get_range (pad, stop + 10, 0, &buffer1);
-  fail_unless (ret == GST_FLOW_UNEXPECTED);
+  fail_unless (ret == GST_FLOW_EOS);
 
   /* read 10 bytes after end should EOS too */
   ret = gst_pad_get_range (pad, stop + 10, 10, &buffer1);
-  fail_unless (ret == GST_FLOW_UNEXPECTED);
+  fail_unless (ret == GST_FLOW_EOS);
 
   fail_unless (gst_element_set_state (src,
           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
@@ -343,23 +349,26 @@ GST_START_TEST (test_uri_interface)
   fail_unless_equals_string (location, "/i/do/not/exist");
   g_free (location);
 
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
   fail_unless_equals_string (location, "file:///i/do/not/exist");
+  g_free (location);
 
   /* should accept file:///foo/bar URIs */
   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
-          "file:///foo/bar"));
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
+          "file:///foo/bar", NULL));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
   fail_unless_equals_string (location, "file:///foo/bar");
+  g_free (location);
   g_object_get (G_OBJECT (src), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/bar");
   g_free (location);
 
   /* should accept file://localhost/foo/bar URIs */
   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
-          "file://localhost/foo/baz"));
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
+          "file://localhost/foo/baz", NULL));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
   fail_unless_equals_string (location, "file:///foo/baz");
+  g_free (location);
   g_object_get (G_OBJECT (src), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/baz");
   g_free (location);
@@ -369,12 +378,13 @@ GST_START_TEST (test_uri_interface)
   g_object_get (G_OBJECT (src), "location", &location, NULL);
   fail_unless_equals_string (location, "/foo/b?r");
   g_free (location);
-  location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
+  location = gst_uri_handler_get_uri (GST_URI_HANDLER (src));
   fail_unless_equals_string (location, "file:///foo/b%3Fr");
+  g_free (location);
 
   /* should fail with other hostnames */
   fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
-          "file://hostname/foo/foo"));
+          "file://hostname/foo/foo", NULL));
 
   /* cleanup */
   gst_element_set_bus (src, NULL);
@@ -390,7 +400,7 @@ check_uri_for_uri (GstElement * e, const gchar * in_uri, const gchar * uri)
   GstQuery *query;
   gchar *query_uri = NULL;
 
-  gst_uri_handler_set_uri (GST_URI_HANDLER (e), in_uri);
+  gst_uri_handler_set_uri (GST_URI_HANDLER (e), in_uri, NULL);
 
   query = gst_query_new_uri ();
   fail_unless (gst_element_query (e, query));
index 3e0c589..3a4ed01 100644 (file)
@@ -34,30 +34,28 @@ struct TestData
 };
 
 static void
-setup_test_objects (struct TestData *td, GstPadChainFunction chain_func,
-    GstPadBufferAllocFunction alloc_func)
+setup_test_objects (struct TestData *td, GstPadChainFunction chain_func)
 {
-  td->mycaps = gst_caps_new_simple ("test/test", NULL);
+  td->mycaps = gst_caps_new_empty_simple ("test/test");
 
   td->funnel = gst_element_factory_make ("funnel", NULL);
 
   td->funnelsrc = gst_element_get_static_pad (td->funnel, "src");
   fail_unless (td->funnelsrc != NULL);
 
-  td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink11");
+  td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink_11");
   fail_unless (td->funnelsink11 != NULL);
-  fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink11"));
+  fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink_11"));
 
-  td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink22");
+  td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink_22");
   fail_unless (td->funnelsink22 != NULL);
-  fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink22"));
+  fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink_22"));
 
   fail_unless (gst_element_set_state (td->funnel, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS);
 
   td->mysink = gst_pad_new ("sink", GST_PAD_SINK);
   gst_pad_set_chain_function (td->mysink, chain_func);
-  gst_pad_set_bufferalloc_function (td->mysink, alloc_func);
   gst_pad_set_active (td->mysink, TRUE);
   gst_pad_set_caps (td->mysink, td->mycaps);
 
@@ -108,7 +106,7 @@ static gint bufcount = 0;
 static gint alloccount = 0;
 
 static GstFlowReturn
-chain_ok (GstPad * pad, GstBuffer * buffer)
+chain_ok (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   bufcount++;
 
@@ -117,29 +115,15 @@ chain_ok (GstPad * pad, GstBuffer * buffer)
   return GST_FLOW_OK;
 }
 
-static GstFlowReturn
-alloc_ok (GstPad * pad,
-    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buffer)
-{
-  alloccount++;
-
-  fail_unless (buffer != NULL);
-  fail_unless (*buffer == NULL);
-
-  *buffer = gst_buffer_new_and_alloc (size);
-  gst_buffer_set_caps (*buffer, caps);
-  GST_BUFFER_OFFSET (*buffer) = offset;
-
-  return GST_FLOW_OK;
-}
-
 GST_START_TEST (test_funnel_simple)
 {
   struct TestData td;
+#if 0
   GstBuffer *buf1 = NULL;
   GstBuffer *buf2 = NULL;
+#endif
 
-  setup_test_objects (&td, chain_ok, alloc_ok);
+  setup_test_objects (&td, chain_ok);
 
   bufcount = 0;
   alloccount = 0;
@@ -149,6 +133,7 @@ GST_START_TEST (test_funnel_simple)
 
   fail_unless (bufcount == 2);
 
+#if 0
   fail_unless (gst_pad_alloc_buffer (td.mysrc1, 0, 1024, td.mycaps,
           &buf1) == GST_FLOW_OK);
   fail_unless (gst_pad_alloc_buffer (td.mysrc2, 1024, 1024, td.mycaps,
@@ -158,6 +143,7 @@ GST_START_TEST (test_funnel_simple)
 
   gst_buffer_unref (buf1);
   gst_buffer_unref (buf2);
+#endif
 
   release_test_objects (&td);
 }
index b845466..57677d8 100644 (file)
@@ -42,7 +42,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS_ANY);
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
     have_eos = TRUE;
@@ -62,8 +62,8 @@ setup_identity (void)
   GST_DEBUG ("setup_identity");
 
   identity = gst_check_setup_element ("identity");
-  mysrcpad = gst_check_setup_src_pad (identity, &srctemplate, NULL);
-  mysinkpad = gst_check_setup_sink_pad (identity, &sinktemplate, NULL);
+  mysrcpad = gst_check_setup_src_pad (identity, &srctemplate);
+  mysinkpad = gst_check_setup_sink_pad (identity, &sinktemplate);
   gst_pad_set_event_function (mysinkpad, event_func);
   gst_pad_set_active (mysrcpad, TRUE);
   gst_pad_set_active (mysinkpad, TRUE);
@@ -87,6 +87,7 @@ GST_START_TEST (test_one_buffer)
 {
   GstElement *identity;
   GstBuffer *buffer;
+  gpointer data;
 
   identity = setup_identity ();
   fail_unless (gst_element_set_state (identity,
@@ -95,7 +96,10 @@ GST_START_TEST (test_one_buffer)
 
   buffer = gst_buffer_new_and_alloc (4);
   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
-  memcpy (GST_BUFFER_DATA (buffer), "data", 4);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
+  memcpy (data, "data", 4);
+  gst_buffer_unmap (buffer, data, 4);
 
   /* pushing gives away my reference ... */
   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK,
index a3d2782..acb0c7e 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <gst/check/gstcheck.h>
 
-static GStaticMutex _check_lock = G_STATIC_MUTEX_INIT;
+static GMutex _check_lock;
 
 static GstElement *
 setup_multiqueue (GstElement * pipe, GstElement * inputs[],
@@ -41,7 +41,7 @@ setup_multiqueue (GstElement * pipe, GstElement * inputs[],
     GstPad *srcpad = NULL;
 
     /* create multiqueue sink (and source) pad */
-    sinkpad = gst_element_get_request_pad (mq, "sink%d");
+    sinkpad = gst_element_get_request_pad (mq, "sink_%u");
     fail_unless (sinkpad != NULL,
         "failed to create multiqueue request pad #%u", i);
 
@@ -66,10 +66,10 @@ setup_multiqueue (GstElement * pipe, GstElement * inputs[],
 
       /* only the sink pads are by request, the source pads are sometimes pads,
        * so this should return NULL */
-      srcpad = gst_element_get_request_pad (mq, "src%d");
+      srcpad = gst_element_get_request_pad (mq, "src_%u");
       fail_unless (srcpad == NULL);
 
-      g_snprintf (padname, sizeof (padname), "src%d", i);
+      g_snprintf (padname, sizeof (padname), "src_%u", i);
       srcpad = gst_element_get_static_pad (mq, padname);
       fail_unless (srcpad != NULL, "failed to get multiqueue src pad #%u", i);
       fail_unless (GST_PAD_IS_SRC (srcpad),
@@ -193,21 +193,21 @@ GST_START_TEST (test_request_pads)
 
   mq = gst_element_factory_make ("multiqueue", NULL);
 
-  sink1 = gst_element_get_request_pad (mq, "foo%d");
+  sink1 = gst_element_get_request_pad (mq, "foo_%u");
   fail_unless (sink1 == NULL,
-      "Expected NULL pad, as there is no request pad template for 'foo%%d'");
+      "Expected NULL pad, as there is no request pad template for 'foo_%%u'");
 
-  sink1 = gst_element_get_request_pad (mq, "src%d");
+  sink1 = gst_element_get_request_pad (mq, "src_%u");
   fail_unless (sink1 == NULL,
-      "Expected NULL pad, as there is no request pad template for 'src%%d'");
+      "Expected NULL pad, as there is no request pad template for 'src_%%u'");
 
-  sink1 = gst_element_get_request_pad (mq, "sink%d");
+  sink1 = gst_element_get_request_pad (mq, "sink_%u");
   fail_unless (sink1 != NULL);
   fail_unless (GST_IS_PAD (sink1));
   fail_unless (GST_PAD_IS_SINK (sink1));
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1));
 
-  sink2 = gst_element_get_request_pad (mq, "sink%d");
+  sink2 = gst_element_get_request_pad (mq, "sink_%u");
   fail_unless (sink2 != NULL);
   fail_unless (GST_IS_PAD (sink2));
   fail_unless (GST_PAD_IS_SINK (sink2));
@@ -233,7 +233,7 @@ mq_sinkpad_to_srcpad (GstElement * mq, GstPad * sink)
 
   mq_sinkpad_name = gst_pad_get_name (sink);
   fail_unless (g_str_has_prefix (mq_sinkpad_name, "sink"));
-  mq_srcpad_name = g_strdup_printf ("src%s", mq_sinkpad_name + 4);
+  mq_srcpad_name = g_strdup_printf ("src_%s", mq_sinkpad_name + 5);
   srcpad = gst_element_get_static_pad (mq, mq_srcpad_name);
   fail_unless (srcpad != NULL);
 
@@ -250,33 +250,33 @@ GST_START_TEST (test_request_pads_named)
 
   mq = gst_element_factory_make ("multiqueue", NULL);
 
-  sink1 = gst_element_get_request_pad (mq, "sink1");
+  sink1 = gst_element_get_request_pad (mq, "sink_1");
   fail_unless (sink1 != NULL);
   fail_unless (GST_IS_PAD (sink1));
   fail_unless (GST_PAD_IS_SINK (sink1));
-  fail_unless_equals_string (GST_PAD_NAME (sink1), "sink1");
+  fail_unless_equals_string (GST_PAD_NAME (sink1), "sink_1");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1));
 
-  sink3 = gst_element_get_request_pad (mq, "sink3");
+  sink3 = gst_element_get_request_pad (mq, "sink_3");
   fail_unless (sink3 != NULL);
   fail_unless (GST_IS_PAD (sink3));
   fail_unless (GST_PAD_IS_SINK (sink3));
-  fail_unless_equals_string (GST_PAD_NAME (sink3), "sink3");
+  fail_unless_equals_string (GST_PAD_NAME (sink3), "sink_3");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink3));
 
-  sink2 = gst_element_get_request_pad (mq, "sink2");
+  sink2 = gst_element_get_request_pad (mq, "sink_2");
   fail_unless (sink2 != NULL);
   fail_unless (GST_IS_PAD (sink2));
   fail_unless (GST_PAD_IS_SINK (sink2));
-  fail_unless_equals_string (GST_PAD_NAME (sink2), "sink2");
+  fail_unless_equals_string (GST_PAD_NAME (sink2), "sink_2");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink2));
 
   /* This gets us the first unused id, sink0 */
-  sink4 = gst_element_get_request_pad (mq, "sink%d");
+  sink4 = gst_element_get_request_pad (mq, "sink_%u");
   fail_unless (sink4 != NULL);
   fail_unless (GST_IS_PAD (sink4));
   fail_unless (GST_PAD_IS_SINK (sink4));
-  fail_unless_equals_string (GST_PAD_NAME (sink4), "sink0");
+  fail_unless_equals_string (GST_PAD_NAME (sink4), "sink_0");
   GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink4));
 
   GST_LOG ("Cleaning up");
@@ -289,10 +289,27 @@ GST_START_TEST (test_request_pads_named)
 
 GST_END_TEST;
 
-static GstCaps *
-mq_dummypad_getcaps (GstPad * sinkpad)
+static gboolean
+mq_dummypad_query (GstPad * sinkpad, GstObject * parent, GstQuery * query)
 {
-  return gst_caps_new_any ();
+  gboolean res = TRUE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter, *caps;
+
+      gst_query_parse_caps (query, &filter);
+      caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      break;
+    }
+    default:
+      res = gst_pad_query_default (sinkpad, parent, query);
+      break;
+  }
+  return res;
 }
 
 struct PadData
@@ -309,20 +326,24 @@ struct PadData
 };
 
 static GstFlowReturn
-mq_dummypad_chain (GstPad * sinkpad, GstBuffer * buf)
+mq_dummypad_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
 {
   guint32 cur_id;
   struct PadData *pad_data;
+  guint8 *data;
+  gsize size;
 
   pad_data = gst_pad_get_element_private (sinkpad);
 
-  g_static_mutex_lock (&_check_lock);
+  g_mutex_lock (&_check_lock);
   fail_if (pad_data == NULL);
   /* Read an ID from the first 4 bytes of the buffer data and check it's
    * what we expect */
-  fail_unless (GST_BUFFER_SIZE (buf) >= 4);
-  g_static_mutex_unlock (&_check_lock);
-  cur_id = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf));
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  fail_unless (size >= 4);
+  g_mutex_unlock (&_check_lock);
+  cur_id = GST_READ_UINT32_BE (data);
+  gst_buffer_unmap (buf, data, size);
 
   g_mutex_lock (pad_data->mutex);
 
@@ -332,12 +353,12 @@ mq_dummypad_chain (GstPad * sinkpad, GstBuffer * buf)
   if (!pad_data->is_linked) {
     /* If there are no linked pads, we can't track a max_id for them :) */
     if (pad_data->n_linked > 0 && !pad_data->first_buf) {
-      g_static_mutex_lock (&_check_lock);
+      g_mutex_lock (&_check_lock);
       fail_unless (cur_id <= *(pad_data->max_linked_id_ptr) + 1,
           "Got buffer %u on pad %u before buffer %u was seen on a "
           "linked pad (max: %u)", cur_id, pad_data->pad_num, cur_id - 1,
           *(pad_data->max_linked_id_ptr));
-      g_static_mutex_unlock (&_check_lock);
+      g_mutex_unlock (&_check_lock);
     }
   } else {
     /* Update the max_id value */
@@ -356,14 +377,14 @@ mq_dummypad_chain (GstPad * sinkpad, GstBuffer * buf)
 }
 
 static gboolean
-mq_dummypad_event (GstPad * sinkpad, GstEvent * event)
+mq_dummypad_event (GstPad * sinkpad, GstObject * parent, GstEvent * event)
 {
   struct PadData *pad_data;
 
   pad_data = gst_pad_get_element_private (sinkpad);
-  g_static_mutex_lock (&_check_lock);
+  g_mutex_lock (&_check_lock);
   fail_if (pad_data == NULL);
-  g_static_mutex_unlock (&_check_lock);
+  g_mutex_unlock (&_check_lock);
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
     g_mutex_lock (pad_data->mutex);
@@ -428,11 +449,11 @@ run_output_order_test (gint n_linked)
     name = g_strdup_printf ("dummysrc%d", i);
     inputpads[i] = gst_pad_new (name, GST_PAD_SRC);
     g_free (name);
-    gst_pad_set_getcaps_function (inputpads[i], mq_dummypad_getcaps);
+    gst_pad_set_query_function (inputpads[i], mq_dummypad_query);
 
-    mq_sinkpad = gst_element_get_request_pad (mq, "sink%d");
+    mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
     fail_unless (mq_sinkpad != NULL);
-    gst_pad_link (inputpads[i], mq_sinkpad);
+    fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK);
 
     gst_pad_set_active (inputpads[i], TRUE);
 
@@ -443,7 +464,7 @@ run_output_order_test (gint n_linked)
     g_free (name);
     gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain);
     gst_pad_set_event_function (sinkpads[i], mq_dummypad_event);
-    gst_pad_set_getcaps_function (sinkpads[i], mq_dummypad_getcaps);
+    gst_pad_set_query_function (sinkpads[i], mq_dummypad_query);
 
     pad_data[i].pad_num = i;
     pad_data[i].max_linked_id_ptr = &max_linked_id;
@@ -455,7 +476,7 @@ run_output_order_test (gint n_linked)
     pad_data[i].first_buf = TRUE;
     gst_pad_set_element_private (sinkpads[i], pad_data + i);
 
-    gst_pad_link (mq_srcpad, sinkpads[i]);
+    fail_unless (gst_pad_link (mq_srcpad, sinkpads[i]) == GST_PAD_LINK_OK);
     gst_pad_set_active (sinkpads[i], TRUE);
 
     gst_object_unref (mq_sinkpad);
@@ -475,18 +496,22 @@ run_output_order_test (gint n_linked)
     guint8 cur_pad;
     GstBuffer *buf;
     GstFlowReturn ret;
+    gpointer data;
 
     cur_pad = pad_pattern[i % n];
 
     buf = gst_buffer_new_and_alloc (4);
-    g_static_mutex_lock (&_check_lock);
+    g_mutex_lock (&_check_lock);
     fail_if (buf == NULL);
-    g_static_mutex_unlock (&_check_lock);
-    GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), i + 1);
+    g_mutex_unlock (&_check_lock);
+
+    data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+    GST_WRITE_UINT32_BE (data, i + 1);
+    gst_buffer_unmap (buf, data, 4);
     GST_BUFFER_TIMESTAMP (buf) = (i + 1) * GST_SECOND;
 
     ret = gst_pad_push (inputpads[cur_pad], buf);
-    g_static_mutex_lock (&_check_lock);
+    g_mutex_lock (&_check_lock);
     if (pad_data[cur_pad].is_linked) {
       fail_unless (ret == GST_FLOW_OK,
           "Push on pad %d returned %d when FLOW_OK was expected", cur_pad, ret);
@@ -496,7 +521,7 @@ run_output_order_test (gint n_linked)
           "Push on pad %d returned %d when FLOW_OK or NOT_LINKED  was expected",
           cur_pad, ret);
     }
-    g_static_mutex_unlock (&_check_lock);
+    g_mutex_unlock (&_check_lock);
   }
   for (i = 0; i < NPADS; i++) {
     gst_pad_push_event (inputpads[i], gst_event_new_eos ());
@@ -554,6 +579,7 @@ GST_START_TEST (test_sparse_stream)
   GCond *cond;
   gint i;
   const gint NBUFFERS = 100;
+  GstSegment segment;
 
   mutex = g_mutex_new ();
   cond = g_cond_new ();
@@ -579,11 +605,11 @@ GST_START_TEST (test_sparse_stream)
     name = g_strdup_printf ("dummysrc%d", i);
     inputpads[i] = gst_pad_new (name, GST_PAD_SRC);
     g_free (name);
-    gst_pad_set_getcaps_function (inputpads[i], mq_dummypad_getcaps);
+    gst_pad_set_query_function (inputpads[i], mq_dummypad_query);
 
-    mq_sinkpad = gst_element_get_request_pad (mq, "sink%d");
+    mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
     fail_unless (mq_sinkpad != NULL);
-    gst_pad_link (inputpads[i], mq_sinkpad);
+    fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK);
 
     gst_pad_set_active (inputpads[i], TRUE);
 
@@ -594,7 +620,7 @@ GST_START_TEST (test_sparse_stream)
     g_free (name);
     gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain);
     gst_pad_set_event_function (sinkpads[i], mq_dummypad_event);
-    gst_pad_set_getcaps_function (sinkpads[i], mq_dummypad_getcaps);
+    gst_pad_set_query_function (sinkpads[i], mq_dummypad_query);
 
     pad_data[i].pad_num = i;
     pad_data[i].max_linked_id_ptr = &max_linked_id;
@@ -606,7 +632,7 @@ GST_START_TEST (test_sparse_stream)
     pad_data[i].first_buf = TRUE;
     gst_pad_set_element_private (sinkpads[i], pad_data + i);
 
-    gst_pad_link (mq_srcpad, sinkpads[i]);
+    fail_unless (gst_pad_link (mq_srcpad, sinkpads[i]) == GST_PAD_LINK_OK);
     gst_pad_set_active (sinkpads[i], TRUE);
 
     gst_object_unref (mq_sinkpad);
@@ -620,7 +646,8 @@ GST_START_TEST (test_sparse_stream)
   gst_element_set_state (pipe, GST_STATE_PLAYING);
 
   /* Push 2 new segment events */
-  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+  gst_segment_init (&segment, GST_FORMAT_TIME);
+  event = gst_event_new_segment (&segment);
   gst_pad_push_event (inputpads[0], gst_event_ref (event));
   gst_pad_push_event (inputpads[1], event);
 
@@ -628,14 +655,19 @@ GST_START_TEST (test_sparse_stream)
     GstBuffer *buf;
     GstFlowReturn ret;
     GstClockTime ts;
+    gpointer data;
 
     ts = gst_util_uint64_scale_int (GST_SECOND, i, 10);
 
     buf = gst_buffer_new_and_alloc (4);
-    g_static_mutex_lock (&_check_lock);
+    g_mutex_lock (&_check_lock);
     fail_if (buf == NULL);
-    g_static_mutex_unlock (&_check_lock);
-    GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), i + 1);
+    g_mutex_unlock (&_check_lock);
+
+    data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+    GST_WRITE_UINT32_BE (data, i + 1);
+    gst_buffer_unmap (buf, data, 4);
+
     GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (GST_SECOND, i, 10);
 
     /* If i == 0, also push the buffer to the 2nd pad */
@@ -643,13 +675,16 @@ GST_START_TEST (test_sparse_stream)
       ret = gst_pad_push (inputpads[1], gst_buffer_ref (buf));
 
     ret = gst_pad_push (inputpads[0], buf);
-    g_static_mutex_lock (&_check_lock);
+    g_mutex_lock (&_check_lock);
     fail_unless (ret == GST_FLOW_OK,
         "Push on pad %d returned %d when FLOW_OK was expected", 0, ret);
-    g_static_mutex_unlock (&_check_lock);
+    g_mutex_unlock (&_check_lock);
 
     /* Push a new segment update on the 2nd pad */
-    event = gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, ts, -1, ts);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.start = ts;
+    segment.time = ts;
+    event = gst_event_new_segment (&segment);
     gst_pad_push_event (inputpads[1], event);
   }
 
index 3a6e4e4..140a3ce 100644 (file)
@@ -72,7 +72,7 @@ queue_underrun (GstElement * queue, gpointer user_data)
 }
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GST_DEBUG ("%s event", gst_event_type_get_name (GST_EVENT_TYPE (event)));
   events = g_list_append (events, event);
@@ -97,7 +97,7 @@ setup (void)
   queue = gst_check_setup_element ("queue");
   g_signal_connect (queue, "underrun", G_CALLBACK (queue_underrun), NULL);
 
-  mysrcpad = gst_check_setup_src_pad (queue, &srctemplate, NULL);
+  mysrcpad = gst_check_setup_src_pad (queue, &srctemplate);
   gst_pad_set_active (mysrcpad, TRUE);
 
   mysinkpad = NULL;
@@ -167,7 +167,7 @@ GST_START_TEST (test_non_leaky_underrun)
 {
   g_signal_connect (queue, "overrun", G_CALLBACK (queue_overrun), NULL);
   g_object_set (G_OBJECT (queue), "max-size-buffers", 2, NULL);
-  mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate, NULL);
+  mysinkpad = gst_check_setup_sink_pad (queue, &sinktemplate);
   gst_pad_set_active (mysinkpad, TRUE);
 
   GST_DEBUG ("starting");
@@ -541,6 +541,7 @@ GST_START_TEST (test_time_level_task_not_started)
 {
   GstEvent *event;
   GstClockTime time;
+  GstSegment segment;
 
   GST_DEBUG ("starting");
 
@@ -548,18 +549,24 @@ GST_START_TEST (test_time_level_task_not_started)
           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
       "could not set to playing");
 
-  event = gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME,
-      1 * GST_SECOND, 5 * GST_SECOND, 0);
+  gst_segment_init (&segment, GST_FORMAT_TIME);
+  segment.start = 1 * GST_SECOND;
+  segment.stop = 5 * GST_SECOND;
+  segment.time = 0;
+  segment.position = 1 * GST_SECOND;
+
+  event = gst_event_new_segment (&segment);
   gst_pad_push_event (mysrcpad, event);
 
   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
   fail_if (time != 0 * GST_SECOND);
 
-  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
-      1 * GST_SECOND, 5 * GST_SECOND, 0);
+  segment.base = 4 * GST_SECOND;
+  event = gst_event_new_segment (&segment);
   gst_pad_push_event (mysrcpad, event);
 
   g_object_get (G_OBJECT (queue), "current-level-time", &time, NULL);
+  GST_DEBUG ("time now %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
   fail_if (time != 4 * GST_SECOND);
 
   GST_DEBUG ("stopping");
@@ -569,23 +576,24 @@ GST_START_TEST (test_time_level_task_not_started)
 
 GST_END_TEST;
 
+#if 0
 static gboolean
 event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate,
     GstFormat format, gint64 start, gint64 stop, gint64 position)
 {
   gboolean ns_update;
-  gdouble ns_rate;
+  gdouble ns_rate, ns_arate;
   GstFormat ns_format;
   gint64 ns_start;
   gint64 ns_stop;
   gint64 ns_position;
 
-  if (GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT) {
+  if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT) {
     return FALSE;
   }
 
-  gst_event_parse_new_segment (event, &ns_update, &ns_rate, &ns_format,
-      &ns_start, &ns_stop, &ns_position);
+  gst_event_parse_new_segment (event, &ns_update, &ns_rate, &ns_arate,
+      &ns_format, &ns_start, &ns_stop, &ns_position);
 
   GST_DEBUG ("update %d, rate %lf, format %s, start %" GST_TIME_FORMAT
       ", stop %" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT, ns_update,
@@ -615,7 +623,7 @@ GST_START_TEST (test_newsegment)
   fail_unless (overrun_count == 0);
   fail_unless (underrun_count == 0);
 
-  event = gst_event_new_new_segment (FALSE, 2.0, GST_FORMAT_TIME, 0,
+  event = gst_event_new_new_segment (FALSE, 2.0, 1.0, GST_FORMAT_TIME, 0,
       2 * GST_SECOND, 0);
   gst_pad_push_event (mysrcpad, event);
 
@@ -623,7 +631,7 @@ GST_START_TEST (test_newsegment)
   fail_unless (overrun_count == 0);
   fail_unless (underrun_count == 0);
 
-  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
+  event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0,
       3 * GST_SECOND, 0);
   gst_pad_push_event (mysrcpad, event);
 
@@ -631,7 +639,7 @@ GST_START_TEST (test_newsegment)
   fail_unless (overrun_count == 0);
   fail_unless (underrun_count == 0);
 
-  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+  event = gst_event_new_new_segment (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
       4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND);
   gst_pad_push_event (mysrcpad, event);
 
@@ -692,6 +700,7 @@ GST_START_TEST (test_newsegment)
 }
 
 GST_END_TEST;
+#endif
 
 static Suite *
 queue_suite (void)
@@ -707,7 +716,9 @@ queue_suite (void)
   tcase_add_test (tc_chain, test_leaky_downstream);
   tcase_add_test (tc_chain, test_time_level);
   tcase_add_test (tc_chain, test_time_level_task_not_started);
+#if 0
   tcase_add_test (tc_chain, test_newsegment);
+#endif
 
   return s;
 }
index 9b7e186..09c54b4 100644 (file)
@@ -34,11 +34,12 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS_ANY);
 
 /* Data probe cb to drop everything but count buffers and events */
-static gboolean
-probe_cb (GstPad * pad, GstMiniObject * obj, gpointer user_data)
+static GstPadProbeReturn
+probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
   gint count = 0;
   const gchar *count_type = NULL;
+  GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
 
   GST_LOG_OBJECT (pad, "got data");
 
@@ -56,7 +57,7 @@ probe_cb (GstPad * pad, GstMiniObject * obj, gpointer user_data)
   g_object_set_data (G_OBJECT (pad), count_type, GINT_TO_POINTER (count));
 
   /* drop everything */
-  return FALSE;
+  return GST_PAD_PROBE_DROP;
 }
 
 /* Create and link output pad: selector:src%d ! output_pad */
@@ -74,12 +75,14 @@ setup_output_pad (GstElement * element, GstStaticPadTemplate * tmpl)
   fail_if (output_pad == NULL, "Could not create a output_pad");
 
   /* add probe */
-  probe_id = gst_pad_add_data_probe (output_pad, G_CALLBACK (probe_cb), NULL);
+  probe_id =
+      gst_pad_add_probe (output_pad, GST_PAD_PROBE_TYPE_DATA_BOTH,
+      (GstPadProbeCallback) probe_cb, NULL, NULL);
   g_object_set_data (G_OBJECT (output_pad), "probe_id",
       GINT_TO_POINTER (probe_id));
 
   /* request src pad */
-  srcpad = gst_element_get_request_pad (element, "src%d");
+  srcpad = gst_element_get_request_pad (element, "src_%u");
   fail_if (srcpad == NULL, "Could not get source pad from %s",
       GST_ELEMENT_NAME (element));
 
@@ -110,7 +113,7 @@ cleanup_pad (GstPad * pad, GstElement * element)
   /* remove probe if necessary */
   probe_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "probe_id"));
   if (probe_id)
-    gst_pad_remove_data_probe (pad, probe_id);
+    gst_pad_remove_probe (pad, probe_id);
 
   /* unlink */
   selpad = gst_pad_get_peer (pad);
@@ -120,9 +123,6 @@ cleanup_pad (GstPad * pad, GstElement * element)
     gst_pad_unlink (pad, selpad);
   }
 
-  /* caps could have been set, make sure they get unset */
-  gst_pad_set_caps (pad, NULL);
-
   GST_DEBUG_OBJECT (pad, "clean up %" GST_PTR_FORMAT " and  %" GST_PTR_FORMAT,
       selpad, pad);
 
@@ -201,13 +201,23 @@ selector_set_active_pad (GstElement * elem, GstPad * selpad)
 static void
 push_newsegment_events (GList * input_pads)
 {
+  GstSegment seg;
   GList *l;
 
+  seg.flags = GST_SEGMENT_FLAG_NONE;
+  seg.rate = seg.applied_rate = 1.0;
+  seg.format = GST_FORMAT_BYTES;
+  seg.base = 0;
+  seg.start = 0;
+  seg.stop = -1;
+  seg.time = 0;
+  seg.position = 0;
+  seg.duration = -1;
+
   for (l = input_pads; l; l = l->next) {
     GstPad *pad = l->data;
 
-    gst_pad_push_event (pad, gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
-            GST_FORMAT_BYTES, 0, -1, 0));
+    gst_pad_push_event (pad, gst_event_new_segment (&seg));
   }
 }
 
@@ -224,8 +234,6 @@ push_switched_buffers (GList * input_pads,
   /* setup dummy buffer */
   caps = gst_caps_from_string ("application/x-unknown");
   buf = gst_buffer_new_and_alloc (1);
-  gst_buffer_set_caps (buf, caps);
-  gst_caps_unref (caps);
 
   while (l != NULL) {
     /* set selector pad */
@@ -242,6 +250,7 @@ push_switched_buffers (GList * input_pads,
 
   /* cleanup buffer */
   gst_buffer_unref (buf);
+  gst_caps_unref (caps);
 }
 
 /* Create output-selector with given number of src pads and switch
@@ -255,7 +264,7 @@ run_output_selector_buffer_count (gint num_output_pads,
   gint i = 0;
   GList *output_pads = NULL, *input_pads = NULL;
   GstElement *sel = gst_check_setup_element ("output-selector");
-  GstPad *input_pad = gst_check_setup_src_pad (sel, &srctemplate, NULL);
+  GstPad *input_pad = gst_check_setup_src_pad (sel, &srctemplate);
 
   input_pads = g_list_append (input_pads, input_pad);
   gst_pad_set_active (input_pad, TRUE);
@@ -293,7 +302,7 @@ setup_input_pad (GstElement * element)
   fail_if (input_pad == NULL, "Could not create a input_pad");
 
   /* request sink pad */
-  sinkpad = gst_element_get_request_pad (element, "sink%d");
+  sinkpad = gst_element_get_request_pad (element, "sink_%u");
   fail_if (sinkpad == NULL, "Could not get sink pad from %s",
       GST_ELEMENT_NAME (element));
 
@@ -323,7 +332,7 @@ run_input_selector_buffer_count (gint num_input_pads,
   gint i = 0, probe_id = 0;
   GList *input_pads = NULL, *output_pads = NULL;
   GstElement *sel = gst_check_setup_element ("input-selector");
-  GstPad *output_pad = gst_check_setup_sink_pad (sel, &sinktemplate, NULL);
+  GstPad *output_pad = gst_check_setup_sink_pad (sel, &sinktemplate);
 
   output_pads = g_list_append (output_pads, output_pad);
   gst_pad_set_active (output_pad, TRUE);
@@ -331,7 +340,9 @@ run_input_selector_buffer_count (gint num_input_pads,
     input_pads = g_list_append (input_pads, setup_input_pad (sel));
   }
   /* add probe */
-  probe_id = gst_pad_add_data_probe (output_pad, G_CALLBACK (probe_cb), NULL);
+  probe_id =
+      gst_pad_add_probe (output_pad, GST_PAD_PROBE_TYPE_DATA_BOTH,
+      (GstPadProbeCallback) probe_cb, NULL, NULL);
   g_object_set_data (G_OBJECT (output_pad), "probe_id",
       GINT_TO_POINTER (probe_id));
 
@@ -346,7 +357,7 @@ run_input_selector_buffer_count (gint num_input_pads,
           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
 
   /* clean up */
-  gst_pad_remove_data_probe (output_pad, probe_id);
+  gst_pad_remove_probe (output_pad, probe_id);
   gst_pad_set_active (output_pad, FALSE);
   gst_check_teardown_sink_pad (sel);
   GST_DEBUG ("setting selector pad to NULL");
@@ -411,12 +422,12 @@ GST_START_TEST (test_output_selector_no_srcpad_negotiation);
      * setcaps should accept any caps when there are no srcpads */
     g_object_set (sel, "pad-negotiation-mode", i, NULL);
 
-    caps = gst_pad_get_caps (pad);
+    caps = gst_pad_query_caps (pad, NULL);
     fail_unless (gst_caps_is_any (caps));
 
     gst_caps_unref (caps);
 
-    caps = gst_caps_new_simple ("mymedia/mycaps", NULL);
+    caps = gst_caps_new_empty_simple ("mymedia/mycaps");
     fail_unless (gst_pad_set_caps (pad, caps));
     gst_caps_unref (caps);
   }
@@ -448,7 +459,7 @@ static void
 setup_output_selector (void)
 {
   sel = gst_check_setup_element ("output-selector");
-  input_pad = gst_check_setup_src_pad (sel, &srctemplate, NULL);
+  input_pad = gst_check_setup_src_pad (sel, &srctemplate);
   gst_pad_set_active (input_pad, TRUE);
 
   output_pads = g_list_append (output_pads, setup_output_pad (sel,
@@ -488,7 +499,7 @@ GST_START_TEST (test_output_selector_getcaps_none);
 
     g_object_set (sel, "active-pad", pad, NULL);
 
-    caps = gst_pad_peer_get_caps (input_pad);
+    caps = gst_pad_peer_query_caps (input_pad, NULL);
 
     /* in 'none' mode, the getcaps returns the template, which is ANY */
     g_assert (gst_caps_is_any (caps));
@@ -518,7 +529,7 @@ GST_START_TEST (test_output_selector_getcaps_all);
 
   /* in 'all' mode, the intersection of the srcpad caps should be returned on
    * the sinkpad's getcaps */
-  expected = gst_caps_new_simple ("format/abc", NULL);
+  expected = gst_caps_new_empty_simple ("format/abc");
 
   for (walker = output_pads; walker; walker = g_list_next (walker)) {
     GstCaps *caps;
@@ -528,7 +539,7 @@ GST_START_TEST (test_output_selector_getcaps_all);
 
     g_object_set (sel, "active-pad", pad, NULL);
 
-    caps = gst_pad_peer_get_caps (input_pad);
+    caps = gst_pad_peer_query_caps (input_pad, NULL);
 
     g_assert (gst_caps_is_equal (caps, expected));
     gst_caps_unref (caps);
@@ -559,6 +570,7 @@ GST_START_TEST (test_output_selector_getcaps_active);
   for (walker = output_pads; walker; walker = g_list_next (walker)) {
     GstCaps *caps;
     GstPad *pad;
+    GstPadTemplate *templ;
 
     pad = gst_pad_get_peer ((GstPad *) walker->data);
 
@@ -567,12 +579,14 @@ GST_START_TEST (test_output_selector_getcaps_active);
     /* in 'active' mode, the active srcpad peer's caps should be returned on
      * the sinkpad's getcaps */
 
-    expected = gst_pad_template_get_caps (gst_pad_get_pad_template ((GstPad *)
-            walker->data));
-    caps = gst_pad_peer_get_caps (input_pad);
+    templ = gst_pad_get_pad_template ((GstPad *) walker->data);
+    expected = gst_pad_template_get_caps (templ);
+    caps = gst_pad_peer_query_caps (input_pad, NULL);
 
     g_assert (gst_caps_is_equal (caps, expected));
     gst_caps_unref (caps);
+    gst_caps_unref (expected);
+    gst_object_unref (templ);
     gst_object_unref (pad);
   }
 
index e0fed0f..c2c22fb 100644 (file)
@@ -78,7 +78,7 @@ GST_START_TEST (test_num_buffers)
     g_object_set (sinks[i], "signal-handoffs", TRUE, NULL);
     g_signal_connect (sinks[i], "handoff", (GCallback) handoff, &counts[i]);
 
-    req_pads[i] = gst_element_get_request_pad (tee, "src%d");
+    req_pads[i] = gst_element_get_request_pad (tee, "src_%u");
     fail_unless (req_pads[i] != NULL);
 
     qpad = gst_element_get_static_pad (queues[i], "sink");
@@ -144,7 +144,7 @@ GST_START_TEST (test_stress)
   for (i = 0; i < 50000; i++) {
     GstPad *pad;
 
-    pad = gst_element_get_request_pad (tee, "src%d");
+    pad = gst_element_get_request_pad (tee, "src_%u");
     gst_element_release_request_pad (tee, pad);
     gst_object_unref (pad);
 
@@ -166,10 +166,6 @@ GST_START_TEST (test_stress)
 
 GST_END_TEST;
 
-static GstFlowReturn
-final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf);
-
 typedef struct
 {
   GstElement *tee;
@@ -187,6 +183,8 @@ typedef struct
 static void
 buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
 {
+  h->app_thread = NULL;
+
   h->tee = gst_check_setup_element ("tee");
   fail_if (h->tee == NULL);
 
@@ -195,25 +193,23 @@ buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
   fail_unless_equals_int (gst_element_set_state (h->tee, GST_STATE_PLAYING),
       TRUE);
 
-  h->caps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
+  h->caps = gst_caps_new_empty_simple ("video/x-raw-yuv");
 
   h->start_srcpad = gst_pad_new ("src", GST_PAD_SRC);
   fail_if (h->start_srcpad == NULL);
-  fail_unless (gst_pad_set_caps (h->start_srcpad, h->caps) == TRUE);
   fail_unless (gst_pad_set_active (h->start_srcpad, TRUE) == TRUE);
+  fail_unless (gst_pad_set_caps (h->start_srcpad, h->caps) == TRUE);
 
   h->tee_sinkpad = gst_element_get_static_pad (h->tee, "sink");
   fail_if (h->tee_sinkpad == NULL);
 
-  h->tee_srcpad = gst_element_get_request_pad (h->tee, "src%d");
+  h->tee_srcpad = gst_element_get_request_pad (h->tee, "src_%u");
   fail_if (h->tee_srcpad == NULL);
 
   h->final_sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
   fail_if (h->final_sinkpad == NULL);
-  gst_pad_set_bufferalloc_function (h->final_sinkpad,
-      final_sinkpad_bufferalloc);
-  fail_unless (gst_pad_set_caps (h->final_sinkpad, h->caps) == TRUE);
   fail_unless (gst_pad_set_active (h->final_sinkpad, TRUE) == TRUE);
+  fail_unless (gst_pad_set_caps (h->final_sinkpad, h->caps) == TRUE);
   g_object_set_qdata (G_OBJECT (h->final_sinkpad),
       g_quark_from_static_string ("buffer-alloc-harness"), h);
 
@@ -226,7 +222,8 @@ buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
 static void
 buffer_alloc_harness_teardown (BufferAllocHarness * h)
 {
-  g_thread_join (h->app_thread);
+  if (h->app_thread)
+    g_thread_join (h->app_thread);
 
   gst_pad_set_active (h->final_sinkpad, FALSE);
   gst_object_unref (h->final_sinkpad);
@@ -238,6 +235,7 @@ buffer_alloc_harness_teardown (BufferAllocHarness * h)
   gst_check_teardown_element (h->tee);
 }
 
+#if 0
 static gpointer
 app_thread_func (gpointer data)
 {
@@ -261,7 +259,9 @@ app_thread_func (gpointer data)
 
   return NULL;
 }
+#endif
 
+#if 0
 static GstFlowReturn
 final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
@@ -304,20 +304,16 @@ final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
 
   return GST_FLOW_OK;
 }
+#endif
 
 /* Simulate an app releasing the pad while the first alloc_buffer() is in
  * progress. */
 GST_START_TEST (test_release_while_buffer_alloc)
 {
   BufferAllocHarness h;
-  GstBuffer *buf;
 
   buffer_alloc_harness_setup (&h, 1);
 
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
-
   buffer_alloc_harness_teardown (&h);
 }
 
@@ -328,18 +324,9 @@ GST_END_TEST;
 GST_START_TEST (test_release_while_second_buffer_alloc)
 {
   BufferAllocHarness h;
-  GstBuffer *buf;
 
   buffer_alloc_harness_setup (&h, 2);
 
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
-
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
-
   buffer_alloc_harness_teardown (&h);
 }
 
@@ -352,7 +339,9 @@ GST_START_TEST (test_internal_links)
   GstPad *sinkpad, *srcpad1, *srcpad2;
   GstIterator *it;
   GstIteratorResult res;
-  gpointer val1, val2;
+  GValue val1 = { 0, }
+  , val2 = {
+  0,};
 
   tee = gst_check_setup_element ("tee");
 
@@ -362,60 +351,57 @@ GST_START_TEST (test_internal_links)
   fail_unless (it != NULL);
 
   /* iterator should not return anything */
-  val1 = NULL;
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_DONE);
-  fail_unless (val1 == NULL);
+  fail_unless (g_value_get_object (&val1) == NULL);
 
-  srcpad1 = gst_element_get_request_pad (tee, "src%d");
+  srcpad1 = gst_element_get_request_pad (tee, "src_%u");
   fail_unless (srcpad1 != NULL);
 
   /* iterator should resync */
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_RESYNC);
-  fail_unless (val1 == NULL);
+  fail_unless (g_value_get_object (&val1) == NULL);
   gst_iterator_resync (it);
 
   /* we should get something now */
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_OK);
-  fail_unless (GST_PAD_CAST (val1) == srcpad1);
+  fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == srcpad1);
 
-  gst_object_unref (val1);
+  g_value_reset (&val1);
 
-  val1 = NULL;
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_DONE);
-  fail_unless (val1 == NULL);
+  fail_unless (g_value_get_object (&val1) == NULL);
 
-  srcpad2 = gst_element_get_request_pad (tee, "src%d");
+  srcpad2 = gst_element_get_request_pad (tee, "src_%u");
   fail_unless (srcpad2 != NULL);
 
   /* iterator should resync */
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_RESYNC);
-  fail_unless (val1 == NULL);
+  fail_unless (g_value_get_object (&val1) == NULL);
   gst_iterator_resync (it);
 
   /* we should get one of the 2 pads now */
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_OK);
-  fail_unless (GST_PAD_CAST (val1) == srcpad1
-      || GST_PAD_CAST (val1) == srcpad2);
+  fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == srcpad1
+      || GST_PAD_CAST (g_value_get_object (&val1)) == srcpad2);
 
   /* and the other */
   res = gst_iterator_next (it, &val2);
   fail_unless (res == GST_ITERATOR_OK);
-  fail_unless (GST_PAD_CAST (val2) == srcpad1
-      || GST_PAD_CAST (val2) == srcpad2);
-  fail_unless (val1 != val2);
-  gst_object_unref (val1);
-  gst_object_unref (val2);
+  fail_unless (GST_PAD_CAST (g_value_get_object (&val2)) == srcpad1
+      || GST_PAD_CAST (g_value_get_object (&val2)) == srcpad2);
+  fail_unless (g_value_get_object (&val1) != g_value_get_object (&val2));
+  g_value_reset (&val1);
+  g_value_reset (&val2);
 
-  val1 = NULL;
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_DONE);
-  fail_unless (val1 == NULL);
+  fail_unless (g_value_get_object (&val1) == NULL);
 
   gst_iterator_free (it);
 
@@ -425,8 +411,8 @@ GST_START_TEST (test_internal_links)
 
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_OK);
-  fail_unless (GST_PAD_CAST (val1) == sinkpad);
-  gst_object_unref (val1);
+  fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == sinkpad);
+  g_value_reset (&val1);
 
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_DONE);
@@ -437,12 +423,14 @@ GST_START_TEST (test_internal_links)
 
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_OK);
-  fail_unless (GST_PAD_CAST (val1) == sinkpad);
-  gst_object_unref (val1);
+  fail_unless (GST_PAD_CAST (g_value_get_object (&val1)) == sinkpad);
+  g_value_reset (&val1);
 
   res = gst_iterator_next (it, &val1);
   fail_unless (res == GST_ITERATOR_DONE);
 
+  g_value_unset (&val1);
+  g_value_unset (&val2);
   gst_iterator_free (it);
   gst_object_unref (srcpad1);
   gst_object_unref (srcpad2);
@@ -453,14 +441,14 @@ GST_START_TEST (test_internal_links)
 GST_END_TEST;
 
 static GstFlowReturn
-_fake_chain (GstPad * pad, GstBuffer * buffer)
+_fake_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   gst_buffer_unref (buffer);
   return GST_FLOW_OK;
 }
 
 static GstFlowReturn
-_fake_chain_error (GstPad * pad, GstBuffer * buffer)
+_fake_chain_error (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   gst_buffer_unref (buffer);
   return GST_FLOW_ERROR;
@@ -474,28 +462,34 @@ GST_START_TEST (test_flow_aggregation)
   GstBuffer *buffer;
   GstCaps *caps;
 
-  caps = gst_caps_new_simple ("test/test", NULL);
+  caps = gst_caps_new_empty_simple ("test/test");
 
   tee = gst_element_factory_make ("tee", NULL);
   fail_unless (tee != NULL);
   teesink = gst_element_get_static_pad (tee, "sink");
   fail_unless (teesink != NULL);
-  teesrc1 = gst_element_get_request_pad (tee, "src%d");
+  teesrc1 = gst_element_get_request_pad (tee, "src_%u");
   fail_unless (teesrc1 != NULL);
-  teesrc2 = gst_element_get_request_pad (tee, "src%d");
+  teesrc2 = gst_element_get_request_pad (tee, "src_%u");
   fail_unless (teesrc2 != NULL);
 
+  GST_DEBUG ("Creating mysink1");
   mysink1 = gst_pad_new ("mysink1", GST_PAD_SINK);
+  gst_pad_set_chain_function (mysink1, _fake_chain);
+  gst_pad_set_active (mysink1, TRUE);
   gst_pad_set_caps (mysink1, caps);
+
+  GST_DEBUG ("Creating mysink2");
   mysink2 = gst_pad_new ("mysink2", GST_PAD_SINK);
+  gst_pad_set_chain_function (mysink2, _fake_chain);
+  gst_pad_set_active (mysink2, TRUE);
   gst_pad_set_caps (mysink2, caps);
+
+  GST_DEBUG ("Creating mysrc");
   mysrc = gst_pad_new ("mysrc", GST_PAD_SRC);
+  gst_pad_set_active (mysrc, TRUE);
   gst_pad_set_caps (mysrc, caps);
 
-  gst_pad_set_chain_function (mysink1, _fake_chain);
-  gst_pad_set_active (mysink1, TRUE);
-  gst_pad_set_chain_function (mysink2, _fake_chain);
-  gst_pad_set_active (mysink2, TRUE);
 
   fail_unless (gst_pad_link (mysrc, teesink) == GST_PAD_LINK_OK);
   fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
@@ -505,59 +499,77 @@ GST_START_TEST (test_flow_aggregation)
           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
 
   buffer = gst_buffer_new ();
+#if 0
   gst_buffer_set_caps (buffer, caps);
+#endif
 
+  GST_DEBUG ("Try to push a buffer");
   /* First check if everything works in normal state */
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
   /* One pad being in wrong state must result in wrong state */
+  GST_DEBUG ("Trying to push with mysink2 disabled");
   gst_pad_set_active (mysink2, FALSE);
   fail_unless (gst_pad_push (mysrc,
           gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
 
+  GST_DEBUG ("Trying to push with mysink2 disabled");
   gst_pad_set_active (mysink1, FALSE);
   gst_pad_set_active (mysink2, TRUE);
+  gst_pad_set_caps (mysink2, caps);
   fail_unless (gst_pad_push (mysrc,
           gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
 
+  GST_DEBUG ("Trying to push with mysink2 and mysink1 disabled");
   gst_pad_set_active (mysink2, FALSE);
   fail_unless (gst_pad_push (mysrc,
           gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
 
   /* Test if everything still works in normal state */
+  GST_DEBUG ("Reactivate both pads and try pushing");
   gst_pad_set_active (mysink1, TRUE);
+  gst_pad_set_caps (mysink1, caps);
   gst_pad_set_active (mysink2, TRUE);
+  gst_pad_set_caps (mysink2, caps);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
   /* One unlinked pad must return OK, two unlinked pads must return NOT_LINKED */
+  GST_DEBUG ("Pushing with mysink1 unlinked");
   fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
+  GST_DEBUG ("Pushing with mysink2 unlinked");
   fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
   fail_unless (gst_pad_unlink (teesrc2, mysink2) == TRUE);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
+  GST_DEBUG ("Pushing with mysink1 AND mysink2 unlinked");
   fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE);
   fail_unless (gst_pad_push (mysrc,
           gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
 
   /* Test if everything still works in normal state */
+  GST_DEBUG ("Relink both pads and try pushing");
   fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
   fail_unless (gst_pad_link (teesrc2, mysink2) == GST_PAD_LINK_OK);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
 
   /* One pad returning ERROR should result in ERROR */
+  GST_DEBUG ("Pushing with mysink1 returning GST_FLOW_ERROR");
   gst_pad_set_chain_function (mysink1, _fake_chain_error);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
 
+  GST_DEBUG ("Pushing with mysink2 returning GST_FLOW_ERROR");
   gst_pad_set_chain_function (mysink1, _fake_chain);
   gst_pad_set_chain_function (mysink2, _fake_chain_error);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
 
+  GST_DEBUG ("Pushing with mysink1 AND mysink2 returning GST_FLOW_ERROR");
   gst_pad_set_chain_function (mysink1, _fake_chain_error);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
 
   /* And now everything still needs to work */
+  GST_DEBUG ("Try pushing with everything ok");
   gst_pad_set_chain_function (mysink1, _fake_chain);
   gst_pad_set_chain_function (mysink2, _fake_chain);
   fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
index 8823b04..2d7ef33 100644 (file)
@@ -40,39 +40,25 @@ gboolean event_received = FALSE;
 gboolean buffer_allocated = FALSE;
 
 static gboolean
-event_func (GstPad * pad, GstEvent * event)
+event_func (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   event_received = TRUE;
   gst_event_unref (event);
   return TRUE;
 }
 
-static GstFlowReturn
-bufferalloc_func (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
-    GstBuffer ** buf)
-{
-  buffer_allocated = TRUE;
-  *buf = gst_buffer_new_and_alloc (size);
-  GST_BUFFER_OFFSET (*buf) = offset;
-  gst_buffer_set_caps (*buf, caps);
-
-  return GST_FLOW_OK;
-}
-
 GST_START_TEST (test_valve_basic)
 {
   GstElement *valve;
   GstPad *sink;
   GstPad *src;
-  GstBuffer *buf;
-  GstCaps *caps;
+  GstCaps *caps, *templ_caps;
 
   valve = gst_check_setup_element ("valve");
 
   sink = gst_check_setup_sink_pad_by_name (valve, &sinktemplate, "src");
   src = gst_check_setup_src_pad_by_name (valve, &srctemplate, "sink");
   gst_pad_set_event_function (sink, event_func);
-  gst_pad_set_bufferalloc_function (sink, bufferalloc_func);
   gst_pad_set_active (src, TRUE);
   gst_pad_set_active (sink, TRUE);
   gst_element_set_state (valve, GST_STATE_PLAYING);
@@ -81,15 +67,13 @@ GST_START_TEST (test_valve_basic)
 
   fail_unless (gst_pad_push_event (src, gst_event_new_eos ()) == TRUE);
   fail_unless (event_received == TRUE);
-  fail_unless (gst_pad_alloc_buffer (src, 0, 10, NULL, &buf) == GST_FLOW_OK);
-  fail_unless (buffer_allocated == TRUE);
-  gst_buffer_unref (buf);
   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (g_list_length (buffers) == 2);
-  caps = gst_pad_get_caps (src);
-  fail_unless (caps && gst_caps_is_equal (caps,
-          gst_pad_get_pad_template_caps (src)));
+  caps = gst_pad_query_caps (src, NULL);
+  templ_caps = gst_pad_get_pad_template_caps (src);
+  fail_unless (caps && gst_caps_is_equal (caps, templ_caps));
+  gst_caps_unref (templ_caps);
   gst_caps_unref (caps);
 
   gst_check_drop_buffers ();
@@ -98,15 +82,13 @@ GST_START_TEST (test_valve_basic)
   g_object_set (valve, "drop", TRUE, NULL);
   fail_unless (gst_pad_push_event (src, gst_event_new_eos ()) == TRUE);
   fail_unless (event_received == FALSE);
-  fail_unless (gst_pad_alloc_buffer (src, 0, 10, NULL, &buf) == GST_FLOW_OK);
-  fail_unless (buffer_allocated == FALSE);
-  gst_buffer_unref (buf);
   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
   fail_unless (buffers == NULL);
-  caps = gst_pad_get_caps (src);
-  fail_unless (caps && gst_caps_is_equal (caps,
-          gst_pad_get_pad_template_caps (src)));
+  caps = gst_pad_query_caps (src, NULL);
+  templ_caps = gst_pad_get_pad_template_caps (src);
+  fail_unless (caps && gst_caps_is_equal (caps, templ_caps));
+  gst_caps_unref (templ_caps);
   gst_caps_unref (caps);
 
   gst_pad_set_active (src, FALSE);
index fd5d62b..84aafac 100644 (file)
@@ -763,13 +763,15 @@ GST_END_TEST;
 static GMutex *blocked_lock;
 static GCond *blocked_cond;
 
-static void
-pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
   g_mutex_lock (blocked_lock);
-  GST_DEBUG ("srcpad blocked: %d, sending signal", blocked);
+  GST_DEBUG ("srcpad blocked: %d, sending signal", info->type);
   g_cond_signal (blocked_cond);
   g_mutex_unlock (blocked_lock);
+
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_add_live2)
@@ -778,6 +780,7 @@ GST_START_TEST (test_add_live2)
   GstStateChangeReturn ret;
   GstState current, pending;
   GstPad *srcpad, *sinkpad;
+  gulong id;
 
   blocked_lock = g_mutex_new ();
   blocked_cond = g_cond_new ();
@@ -799,7 +802,8 @@ GST_START_TEST (test_add_live2)
   GST_DEBUG ("blocking srcpad");
   /* block source pad */
   srcpad = gst_element_get_static_pad (src, "src");
-  gst_pad_set_blocked_async (srcpad, TRUE, pad_blocked_cb, NULL);
+  id = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+      pad_blocked_cb, NULL, NULL);
 
   /* set source to PAUSED without adding it to the pipeline */
   ret = gst_element_set_state (src, GST_STATE_PAUSED);
@@ -827,7 +831,7 @@ GST_START_TEST (test_add_live2)
   GST_DEBUG ("unblocking srcpad");
 
   /* and unblock */
-  gst_pad_set_blocked_async (srcpad, FALSE, pad_blocked_cb, NULL);
+  gst_pad_remove_probe (srcpad, id);
 
   GST_DEBUG ("getting state");
 
@@ -898,10 +902,14 @@ GST_START_TEST (test_bin_live)
   gst_object_unref (pipeline);
 }
 
-GST_END_TEST static void
+GST_END_TEST static gpointer
 send_eos (GstPad * sinkpad)
 {
-  gst_pad_send_event (sinkpad, gst_event_new_eos ());
+  gboolean ret;
+
+  ret = gst_pad_send_event (sinkpad, gst_event_new_eos ());
+
+  return GINT_TO_POINTER (ret);
 }
 
 /* push a buffer with a very long duration in a fakesink, then push an EOS
@@ -972,6 +980,9 @@ GST_START_TEST (test_fake_eos)
   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
 
+  /* we can join now */
+  g_thread_join (thread);
+
   gst_object_unref (pipeline);
 }
 
@@ -995,15 +1006,13 @@ static GstBusSyncReply
 async_done_func (GstBus * bus, GstMessage * msg, GstElement * sink)
 {
   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
-    GstFormat format;
     gint64 position;
 
     GST_DEBUG ("we have ASYNC_DONE now");
     fail_unless (have_preroll == TRUE, "no preroll buffer received");
 
     /* get the position now */
-    format = GST_FORMAT_TIME;
-    gst_element_query_position (sink, &format, &position);
+    gst_element_query_position (sink, GST_FORMAT_TIME, &position);
 
     GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
 
@@ -1040,20 +1049,18 @@ send_buffer (GstPad * sinkpad)
 GST_START_TEST (test_async_done)
 {
   GstElement *sink;
-  GstBuffer *buffer;
   GstEvent *event;
   GstStateChangeReturn ret;
   GstPad *sinkpad;
-  GstFlowReturn res;
+  gboolean res;
   GstBus *bus;
   GThread *thread;
-  GstFormat format;
   gint64 position;
   gboolean qret;
+  GstSegment segment;
 
   sink = gst_element_factory_make ("fakesink", "sink");
   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
-  g_object_set (G_OBJECT (sink), "preroll-queue-len", 2, NULL);
   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
 
   g_signal_connect (sink, "preroll-handoff", (GCallback) async_done_handoff,
@@ -1071,45 +1078,20 @@ GST_START_TEST (test_async_done)
 
   /* make newsegment, this sets the position to 10sec when the buffer prerolls */
   GST_DEBUG ("sending segment");
-  event =
-      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1,
-      10 * GST_SECOND);
+  gst_segment_init (&segment, GST_FORMAT_TIME);
+  segment.time = 10 * GST_SECOND;
+
+  event = gst_event_new_segment (&segment);
   res = gst_pad_send_event (sinkpad, event);
+  fail_unless (res == TRUE);
 
   /* We have not yet received any buffers so we are still in the READY state,
    * the position is therefore still not queryable. */
-  format = GST_FORMAT_TIME;
   position = -1;
-  qret = gst_element_query_position (sink, &format, &position);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position);
   fail_unless (qret == TRUE, "position wrong");
   fail_unless (position == 10 * GST_SECOND, "position is wrong");
 
-  /* Since we are paused and the preroll queue has a length of 2, this function
-   * will return immediately, the preroll handoff will be called and the stream
-   * position should now be 10 seconds. */
-  GST_DEBUG ("pushing first buffer");
-  buffer = gst_buffer_new_and_alloc (10);
-  GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
-  GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
-  res = gst_pad_chain (sinkpad, buffer);
-  fail_unless (res == GST_FLOW_OK, "no OK flow return");
-
-  /* scond buffer, will not block either but position should still be 10
-   * seconds */
-  GST_DEBUG ("pushing second buffer");
-  buffer = gst_buffer_new_and_alloc (10);
-  GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
-  GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
-  res = gst_pad_chain (sinkpad, buffer);
-  fail_unless (res == GST_FLOW_OK, "no OK flow return");
-
-  /* check if position is still 10 seconds */
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (sink, &format, &position);
-  GST_DEBUG ("first buffer position %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (position));
-  fail_unless (position == 10 * GST_SECOND, "position is wrong");
-
   /* last buffer, blocks because preroll queue is filled. Start the push in a
    * new thread so that we can check the position */
   GST_DEBUG ("starting thread");
@@ -1123,8 +1105,7 @@ GST_START_TEST (test_async_done)
   /* check if position is still 10 seconds. This is racy because  the above
    * thread might not yet have started the push, because of the above sleep,
    * this is very unlikely, though. */
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (sink, &format, &position);
+  gst_element_query_position (sink, GST_FORMAT_TIME, &position);
   GST_DEBUG ("second buffer position %" GST_TIME_FORMAT,
       GST_TIME_ARGS (position));
   fail_unless (position == 10 * GST_SECOND, "position is wrong");
@@ -1139,8 +1120,7 @@ GST_START_TEST (test_async_done)
   GST_DEBUG ("joining thread");
   g_thread_join (thread);
 
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (sink, &format, &position);
+  gst_element_query_position (sink, GST_FORMAT_TIME, &position);
   GST_DEBUG ("last buffer position %" GST_TIME_FORMAT,
       GST_TIME_ARGS (position));
   fail_unless (position == 310 * GST_SECOND, "position is wrong");
@@ -1159,14 +1139,12 @@ static GstBusSyncReply
 async_done_eos_func (GstBus * bus, GstMessage * msg, GstElement * sink)
 {
   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
-    GstFormat format;
     gint64 position;
 
     GST_DEBUG ("we have ASYNC_DONE now");
 
     /* get the position now */
-    format = GST_FORMAT_TIME;
-    gst_element_query_position (sink, &format, &position);
+    gst_element_query_position (sink, GST_FORMAT_TIME, &position);
 
     GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
 
@@ -1189,13 +1167,13 @@ GST_START_TEST (test_async_done_eos)
   GstPad *sinkpad;
   gboolean res;
   GstBus *bus;
-  GstFormat format;
-  gint64 position;
   gboolean qret;
+  GstSegment segment;
+  gint64 position;
+  GThread *thread;
 
   sink = gst_element_factory_make ("fakesink", "sink");
   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
-  g_object_set (G_OBJECT (sink), "preroll-queue-len", 1, NULL);
 
   sinkpad = gst_element_get_static_pad (sink, "sink");
 
@@ -1209,16 +1187,16 @@ GST_START_TEST (test_async_done_eos)
 
   /* make newsegment, this sets the position to 10sec when the buffer prerolls */
   GST_DEBUG ("sending segment");
-  event =
-      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1,
-      10 * GST_SECOND);
+  gst_segment_init (&segment, GST_FORMAT_TIME);
+  segment.time = 10 * GST_SECOND;
+  event = gst_event_new_segment (&segment);
   res = gst_pad_send_event (sinkpad, event);
+  fail_unless (res == TRUE);
 
   /* We have not yet received any buffers so we are still in the READY state,
    * the position is therefore still not queryable. */
-  format = GST_FORMAT_TIME;
   position = -1;
-  qret = gst_element_query_position (sink, &format, &position);
+  qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position);
   fail_unless (qret == TRUE, "position wrong");
   fail_unless (position == 10 * GST_SECOND, "position is wrong");
 
@@ -1226,19 +1204,22 @@ GST_START_TEST (test_async_done_eos)
    * will return immediately. The EOS will complete the preroll and the
    * position should now be 10 seconds. */
   GST_DEBUG ("pushing EOS");
-  event = gst_event_new_eos ();
-  res = gst_pad_send_event (sinkpad, event);
-  fail_unless (res == TRUE, "no TRUE return");
+  GST_DEBUG ("starting thread");
+  thread = g_thread_create ((GThreadFunc) send_eos, sinkpad, TRUE, NULL);
+  fail_if (thread == NULL, "no thread");
+
+  /* wait for preroll */
+  gst_element_get_state (sink, NULL, NULL, -1);
 
   /* check if position is still 10 seconds */
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (sink, &format, &position);
+  gst_element_query_position (sink, GST_FORMAT_TIME, &position);
   GST_DEBUG ("EOS position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
   fail_unless (position == 10 * GST_SECOND, "position is wrong");
 
-  gst_object_unref (sinkpad);
-
   gst_element_set_state (sink, GST_STATE_NULL);
+  g_thread_join (thread);
+
+  gst_object_unref (sinkpad);
   gst_object_unref (sink);
   gst_object_unref (bus);
 }
index 4db8a1b..3c2ad7f 100644 (file)
@@ -45,7 +45,7 @@ setup (void)
     ignorelist = g_strsplit (STATE_IGNORE_ELEMENTS, " ", 0);
   }
 
-  plugins = gst_registry_get_plugin_list (gst_registry_get_default ());
+  plugins = gst_registry_get_plugin_list (gst_registry_get ());
 
   for (p = plugins; p; p = p->next) {
     GstPlugin *plugin = p->data;
@@ -54,17 +54,19 @@ setup (void)
       continue;
 
     features =
-        gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
+        gst_registry_get_feature_list_by_plugin (gst_registry_get (),
         gst_plugin_get_name (plugin));
 
     for (f = features; f; f = f->next) {
       GstPluginFeature *feature = f->data;
-      const gchar *name = gst_plugin_feature_get_name (feature);
+      const gchar *name;
       gboolean ignore = FALSE;
 
       if (!GST_IS_ELEMENT_FACTORY (feature))
         continue;
 
+      name = GST_OBJECT_NAME (feature);
+
       if (ignorelist) {
         gchar **s;
 
@@ -79,7 +81,7 @@ setup (void)
       }
 
       GST_DEBUG ("adding element %s", name);
-      elements = g_list_prepend (elements, (gpointer) g_strdup (name));
+      elements = g_list_prepend (elements, g_strdup (name));
     }
     gst_plugin_feature_list_free (features);
   }
index cfe2588..bd4f8a0 100644 (file)
@@ -9,6 +9,7 @@ gstbus
 gstcaps
 gstchildproxy
 gstclock
+gstcontroller
 gstcpp
 gstdata
 gstdatetime
@@ -18,8 +19,9 @@ gstevent
 gstghostpad
 gstiterator
 gstindex
-gstinterface
 gstmessage
+gstmeta
+gstmemory
 gstminiobject
 gstobject
 gstpad
@@ -41,4 +43,3 @@ gstquery
 gsttask
 *.check.xml
 gstinfo
-gstxml
index dd09334..ea468b3 100644 (file)
@@ -6,12 +6,12 @@
 
 static const gchar *caps_list[] = {
   "audio/x-adpcm, layout=(string)quicktime; audio/x-adpcm, layout=(string)quicktime; audio/x-adpcm, layout=(string)wav; audio/x-adpcm, layout=(string)wav; audio/x-adpcm, layout=(string)dk3; audio/x-adpcm, layout=(string)dk3; audio/x-adpcm, layout=(string)dk4; audio/x-adpcm, layout=(string)dk4; audio/x-adpcm, layout=(string)westwood; audio/x-adpcm, layout=(string)westwood; audio/x-adpcm, layout=(string)smjpeg; audio/x-adpcm, layout=(string)smjpeg; audio/x-adpcm, layout=(string)microsoft; audio/x-adpcm, layout=(string)microsoft; audio/x-adpcm, layout=(string)4xm; audio/x-adpcm, layout=(string)4xm; audio/x-adpcm, layout=(string)xa; audio/x-adpcm, layout=(string)xa; audio/x-adpcm, layout=(string)adx; audio/x-adpcm, layout=(string)adx; audio/x-adpcm, layout=(string)ea; audio/x-adpcm, layout=(string)ea; audio/x-adpcm, layout=(string)g726; audio/x-adpcm, layout=(string)g726",
-  "video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)I420; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUY2; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y42B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)32, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUV9; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y41B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234",
-  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-jpeg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)[ 3, 5 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-3ivx, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)[ 41, 43 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)1, systemstream=(boolean)false, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int){ 576, 480 }; video/x-huffyuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]",
-  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], divxversion=(int)[ 3, 5 ]; video/x-xvid, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-3ivx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], msmpegversion=(int)[ 41, 43 ]; video/mpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], mpegversion=(int)1, systemstream=(boolean)false; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, width=(int)720, height=(int){ 576, 480 }, systemstream=(boolean)false; video/x-huffyuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
+  "video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)I420; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)YUY2; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)Y42B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)32, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, endianness=(int)4321; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)YUV9; video/x-raw, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(string)Y41B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234",
+  "video/x-raw, format=(string){ YUY2, I420 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-jpeg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)[ 3, 5 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-3ivx, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)[ 41, 43 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)1, systemstream=(boolean)false, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int){ 576, 480 }; video/x-huffyuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]",
+  "video/x-raw, format=(string){ YUY2, I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], divxversion=(int)[ 3, 5 ]; video/x-xvid, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-3ivx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], msmpegversion=(int)[ 41, 43 ]; video/mpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], mpegversion=(int)1, systemstream=(boolean)false; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, width=(int)720, height=(int){ 576, 480 }, systemstream=(boolean)false; video/x-huffyuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
   "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
   "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
-  "video/x-raw-yuv, format=(fourcc){ I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
+  "video/x-raw, format=(string){ I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
   "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0x000000FF, framerate = (double) [ 0, max ]",
   "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0xFF000000, framerate = (double) [ 0, max ]",
   "video/x-raw-rgb,\\ bpp=(int)32",
@@ -28,7 +28,7 @@ static const gchar *caps_list[] = {
   "test/gst-fraction-range, fraction = (fraction) { [ 1/4, 1/3 ], [ 1/8, 2/8 ] }",
 
   /* Some random checks */
-  "video/x-raw-yuv, format = (fourcc) { I420, Y42B, Y444 }, framerate = (fraction) [1/MAX, MAX], width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]",
+  "video/x-raw, format = (string) { I420, Y42B, Y444 }, framerate = (fraction) [1/MAX, MAX], width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]",
 
   "ANY",
   "EMPTY"
index c81fdeb..b028958 100644 (file)
@@ -61,7 +61,7 @@ GST_START_TEST (test_interface)
   GstBin *bin, *bin2;
   GstElement *filesrc;
   GstIterator *it;
-  gpointer item;
+  GValue item = { 0, };
 
   bin = GST_BIN (gst_bin_new (NULL));
   fail_unless (bin != NULL, "Could not create bin");
@@ -77,8 +77,8 @@ GST_START_TEST (test_interface)
   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
   fail_unless (it != NULL);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  fail_unless (item == (gpointer) filesrc);
-  gst_object_unref (GST_OBJECT (item));
+  fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
   gst_iterator_free (it);
 
@@ -89,8 +89,8 @@ GST_START_TEST (test_interface)
   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
   fail_unless (it != NULL);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  fail_unless (item == (gpointer) filesrc);
-  gst_object_unref (GST_OBJECT (item));
+  fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
   gst_iterator_free (it);
 
@@ -103,8 +103,8 @@ GST_START_TEST (test_interface)
       GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  fail_unless (item == (gpointer) filesrc);
-  gst_object_unref (GST_OBJECT (item));
+  fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
   gst_iterator_free (it);
 
@@ -112,12 +112,13 @@ GST_START_TEST (test_interface)
   gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  gst_object_unref (GST_OBJECT (item));
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  gst_object_unref (GST_OBJECT (item));
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
-  gst_object_unref (GST_OBJECT (item));
+  g_value_reset (&item);
   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
+  g_value_unset (&item);
   gst_iterator_free (it);
 
   gst_object_unref (bin);
@@ -710,7 +711,7 @@ GST_START_TEST (test_children_state_change_order_semi_sink)
   fail_unless (gst_element_link (identity, sink) == TRUE);
 
   /* this is not very nice but should work just fine in this case. */
-  GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK);    /* <======== */
+  GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_FLAG_SINK);  /* <======== */
 
   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
   fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
@@ -887,7 +888,7 @@ GST_START_TEST (test_iterate_sorted)
 {
   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline, *bin;
   GstIterator *it;
-  gpointer elem;
+  GValue elem = { 0, };
 
   pipeline = gst_pipeline_new (NULL);
   fail_unless (pipeline != NULL, "Could not create pipeline");
@@ -922,19 +923,21 @@ GST_START_TEST (test_iterate_sorted)
 
   it = gst_bin_iterate_sorted (GST_BIN (pipeline));
   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
-  fail_unless (elem == sink2);
-  gst_object_unref (elem);
+  fail_unless (g_value_get_object (&elem) == (gpointer) sink2);
+  g_value_reset (&elem);
 
   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
-  fail_unless (elem == identity);
-  gst_object_unref (elem);
+  fail_unless (g_value_get_object (&elem) == (gpointer) identity);
+  g_value_reset (&elem);
 
   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
-  fail_unless (elem == bin);
-  gst_object_unref (elem);
+  fail_unless (g_value_get_object (&elem) == (gpointer) bin);
+  g_value_reset (&elem);
 
+  g_value_unset (&elem);
   gst_iterator_free (it);
 
+  ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
   gst_object_unref (pipeline);
 }
 
index be608ec..1ac9688 100644 (file)
 
 #include <gst/check/gstcheck.h>
 
-GST_START_TEST (test_caps)
-{
-  GstBuffer *buffer;
-  GstCaps *caps, *caps2;
-
-  buffer = gst_buffer_new_and_alloc (4);
-  caps = gst_caps_from_string ("audio/x-raw-int");
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
-
-  fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
-
-  gst_buffer_set_caps (buffer, caps);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
-
-  fail_unless (GST_BUFFER_CAPS (buffer) == caps);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
-
-  fail_unless (gst_buffer_get_caps (buffer) == caps);
-  gst_caps_unref (caps);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
-
-  caps2 = gst_caps_from_string ("audio/x-raw-float");
-  ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
-
-  gst_buffer_set_caps (buffer, caps2);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
-  ASSERT_CAPS_REFCOUNT (caps2, "caps2", 2);
-
-  gst_buffer_set_caps (buffer, NULL);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
-  ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
-
-  /* clean up, with caps2 still set as caps */
-  gst_buffer_set_caps (buffer, caps2);
-  ASSERT_CAPS_REFCOUNT (caps2, "caps2", 2);
-  gst_buffer_unref (buffer);
-  ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
-  gst_caps_unref (caps);
-  gst_caps_unref (caps2);
-}
-
-GST_END_TEST;
-
-
 GST_START_TEST (test_subbuffer)
 {
   GstBuffer *buffer, *sub;
+  gsize size, maxsize, ssize;
+  guint8 *data, *sdata;
 
   buffer = gst_buffer_new_and_alloc (4);
-  memset (GST_BUFFER_DATA (buffer), 0, 4);
+
+  /* check sizes, buffer starts out empty */
+  data = gst_buffer_map (buffer, &size, &maxsize, GST_MAP_WRITE);
+  fail_unless (size == 4, "buffer has wrong size");
+  fail_unless (maxsize >= 4, "buffer has wrong size");
+  memset (data, 0, 4);
+  gst_buffer_unmap (buffer, data, 4);
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
   /* set some metadata */
   GST_BUFFER_TIMESTAMP (buffer) = 1;
   GST_BUFFER_DURATION (buffer) = 2;
   GST_BUFFER_OFFSET (buffer) = 3;
   GST_BUFFER_OFFSET_END (buffer) = 4;
 
-  sub = gst_buffer_create_sub (buffer, 1, 2);
-  fail_if (sub == NULL, "create_sub of buffer returned NULL");
-  fail_unless (GST_BUFFER_SIZE (sub) == 2, "subbuffer has wrong size");
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer) + 1, GST_BUFFER_DATA (sub),
-          2) == 0, "subbuffer contains the wrong data");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 2);
+  sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 2);
+  fail_if (sub == NULL, "copy region of buffer returned NULL");
+
+  sdata = gst_buffer_map (sub, &ssize, NULL, GST_MAP_READ);
+  fail_unless (ssize == 2, "subbuffer has wrong size");
+  fail_unless (memcmp (data + 1, sdata, 2) == 0,
+      "subbuffer contains the wrong data");
   ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1);
   fail_unless (GST_BUFFER_TIMESTAMP (sub) == -1,
       "subbuffer has wrong timestamp");
@@ -101,23 +68,25 @@ GST_START_TEST (test_subbuffer)
   fail_unless (GST_BUFFER_OFFSET (sub) == -1, "subbuffer has wrong offset");
   fail_unless (GST_BUFFER_OFFSET_END (sub) == -1,
       "subbuffer has wrong offset end");
+  gst_buffer_unmap (sub, sdata, ssize);
   gst_buffer_unref (sub);
 
   /* create a subbuffer of size 0 */
-  sub = gst_buffer_create_sub (buffer, 1, 0);
-  fail_if (sub == NULL, "create_sub of buffer returned NULL");
-  fail_unless (GST_BUFFER_SIZE (sub) == 0, "subbuffer has wrong size");
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer) + 1, GST_BUFFER_DATA (sub),
-          0) == 0, "subbuffer contains the wrong data");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 2);
+  sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 0);
+  fail_if (sub == NULL, "copy_region of buffer returned NULL");
+  sdata = gst_buffer_map (sub, &ssize, NULL, GST_MAP_READ);
+  fail_unless (ssize == 0, "subbuffer has wrong size");
+  fail_unless (memcmp (data + 1, sdata, 0) == 0,
+      "subbuffer contains the wrong data");
   ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1);
+  gst_buffer_unmap (sub, sdata, ssize);
   gst_buffer_unref (sub);
 
   /* test if metadata is coppied, not a complete buffer copy so only the
    * timestamp and offset fields are copied. */
-  sub = gst_buffer_create_sub (buffer, 0, 1);
-  fail_if (sub == NULL, "create_sub of buffer returned NULL");
-  fail_unless (GST_BUFFER_SIZE (sub) == 1, "subbuffer has wrong size");
+  sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 1);
+  fail_if (sub == NULL, "copy_region of buffer returned NULL");
+  fail_unless (gst_buffer_get_size (sub) == 1, "subbuffer has wrong size");
   fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1,
       "subbuffer has wrong timestamp");
   fail_unless (GST_BUFFER_OFFSET (sub) == 3, "subbuffer has wrong offset");
@@ -128,9 +97,9 @@ GST_START_TEST (test_subbuffer)
 
   /* test if metadata is coppied, a complete buffer is copied so all the timing
    * fields should be copied. */
-  sub = gst_buffer_create_sub (buffer, 0, 4);
-  fail_if (sub == NULL, "create_sub of buffer returned NULL");
-  fail_unless (GST_BUFFER_SIZE (sub) == 4, "subbuffer has wrong size");
+  sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 4);
+  fail_if (sub == NULL, "copy_region of buffer returned NULL");
+  fail_unless (gst_buffer_get_size (sub) == 4, "subbuffer has wrong size");
   fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1,
       "subbuffer has wrong timestamp");
   fail_unless (GST_BUFFER_DURATION (sub) == 2, "subbuffer has wrong duration");
@@ -140,6 +109,8 @@ GST_START_TEST (test_subbuffer)
 
   /* clean up */
   gst_buffer_unref (sub);
+
+  gst_buffer_unmap (buffer, data, size);
   gst_buffer_unref (buffer);
 }
 
@@ -151,11 +122,11 @@ GST_START_TEST (test_is_span_fast)
 
   buffer = gst_buffer_new_and_alloc (4);
 
-  sub1 = gst_buffer_create_sub (buffer, 0, 2);
-  fail_if (sub1 == NULL, "create_sub of buffer returned NULL");
+  sub1 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 2);
+  fail_if (sub1 == NULL, "copy_region of buffer returned NULL");
 
-  sub2 = gst_buffer_create_sub (buffer, 2, 2);
-  fail_if (sub2 == NULL, "create_sub of buffer returned NULL");
+  sub2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 2, 2);
+  fail_if (sub2 == NULL, "copy_region of buffer returned NULL");
 
   fail_if (gst_buffer_is_span_fast (buffer, sub2) == TRUE,
       "a parent buffer can't be span_fasted");
@@ -177,71 +148,84 @@ GST_END_TEST;
 GST_START_TEST (test_span)
 {
   GstBuffer *buffer, *sub1, *sub2, *span;
+  guint8 *data;
+  gsize size;
 
   buffer = gst_buffer_new_and_alloc (4);
-  memcpy (GST_BUFFER_DATA (buffer), "data", 4);
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_WRITE);
+  memcpy (data, "data", 4);
+  gst_buffer_unmap (buffer, data, 4);
 
   ASSERT_CRITICAL (gst_buffer_span (NULL, 1, NULL, 2));
   ASSERT_CRITICAL (gst_buffer_span (buffer, 1, NULL, 2));
   ASSERT_CRITICAL (gst_buffer_span (NULL, 1, buffer, 2));
   ASSERT_CRITICAL (gst_buffer_span (buffer, 0, buffer, 10));
 
-  sub1 = gst_buffer_create_sub (buffer, 0, 2);
-  fail_if (sub1 == NULL, "create_sub of buffer returned NULL");
+  sub1 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 2);
+  fail_if (sub1 == NULL, "copy_region of buffer returned NULL");
 
-  sub2 = gst_buffer_create_sub (buffer, 2, 2);
-  fail_if (sub2 == NULL, "create_sub of buffer returned NULL");
+  sub2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 2, 2);
+  fail_if (sub2 == NULL, "copy_region of buffer returned NULL");
 
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1);
 
   /* span will create a new subbuffer from the parent */
   span = gst_buffer_span (sub1, 0, sub2, 4);
-  fail_unless (GST_BUFFER_SIZE (span) == 4, "spanned buffer is wrong size");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 4);
+  data = gst_buffer_map (span, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 4, "spanned buffer is wrong size");
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1);
   ASSERT_BUFFER_REFCOUNT (span, "span", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (span), "data", 4) == 0,
+  fail_unless (memcmp (data, "data", 4) == 0,
       "spanned buffer contains the wrong data");
+  gst_buffer_unmap (span, data, size);
   gst_buffer_unref (span);
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
 
   /* span from non-contiguous buffers will create new buffers */
   span = gst_buffer_span (sub2, 0, sub1, 4);
-  fail_unless (GST_BUFFER_SIZE (span) == 4, "spanned buffer is wrong size");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  data = gst_buffer_map (span, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 4, "spanned buffer is wrong size");
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1);
   ASSERT_BUFFER_REFCOUNT (span, "span", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (span), "tada", 4) == 0,
+  fail_unless (memcmp (data, "tada", 4) == 0,
       "spanned buffer contains the wrong data");
+  gst_buffer_unmap (span, data, size);
   gst_buffer_unref (span);
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
 
   /* span with different sizes */
   span = gst_buffer_span (sub1, 1, sub2, 3);
-  fail_unless (GST_BUFFER_SIZE (span) == 3, "spanned buffer is wrong size");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 4);
+  data = gst_buffer_map (span, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 3, "spanned buffer is wrong size");
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1);
   ASSERT_BUFFER_REFCOUNT (span, "span", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (span), "ata", 3) == 0,
+  fail_unless (memcmp (data, "ata", 3) == 0,
       "spanned buffer contains the wrong data");
+  gst_buffer_unmap (span, data, size);
   gst_buffer_unref (span);
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
 
   span = gst_buffer_span (sub2, 0, sub1, 3);
-  fail_unless (GST_BUFFER_SIZE (span) == 3, "spanned buffer is wrong size");
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  data = gst_buffer_map (span, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 3, "spanned buffer is wrong size");
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   ASSERT_BUFFER_REFCOUNT (sub2, "sub2", 1);
   ASSERT_BUFFER_REFCOUNT (span, "span", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (span), "tad", 3) == 0,
+  fail_unless (memcmp (data, "tad", 3) == 0,
       "spanned buffer contains the wrong data");
+  gst_buffer_unmap (span, data, size);
   gst_buffer_unref (span);
-  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 3);
+  ASSERT_BUFFER_REFCOUNT (buffer, "parent", 1);
 
   /* clean up */
   gst_buffer_unref (sub1);
@@ -259,13 +243,13 @@ create_read_only_buffer (void)
 {
   GstBuffer *buf;
 
-  buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_BUFFER);
+  buf = gst_buffer_new ();
 
   /* assign some read-only data to the new buffer */
-  GST_BUFFER_DATA (buf) = (guint8 *) ro_memory;
-  GST_BUFFER_SIZE (buf) = sizeof (ro_memory);
-
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
+  gst_buffer_take_memory (buf, -1,
+      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+          (gpointer) ro_memory, NULL,
+          sizeof (ro_memory), 0, sizeof (ro_memory)));
 
   return buf;
 }
@@ -273,21 +257,19 @@ create_read_only_buffer (void)
 GST_START_TEST (test_make_writable)
 {
   GstBuffer *buf, *buf2;
+  guint8 *data;
+  gsize size;
 
   /* create read-only buffer and make it writable */
   buf = create_read_only_buffer ();
-  fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY),
-      "read-only buffer should have read-only flag set");
-  buf = gst_buffer_make_writable (buf);
-  fail_unless (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY),
-      "writable buffer must not have read-only flag set");
-  GST_BUFFER_DATA (buf)[4] = 'a';
+
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
+  data[4] = 'a';
+  gst_buffer_unmap (buf, data, size);
   gst_buffer_unref (buf);
 
   /* alloc'ed buffer with refcount 1 should be writable */
   buf = gst_buffer_new_and_alloc (32);
-  fail_unless (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY),
-      "_new_and_alloc'ed buffer must not have read-only flag set");
   buf2 = gst_buffer_make_writable (buf);
   fail_unless (buf == buf2,
       "_make_writable() should have returned same buffer");
@@ -295,8 +277,6 @@ GST_START_TEST (test_make_writable)
 
   /* alloc'ed buffer with refcount >1 should be copied */
   buf = gst_buffer_new_and_alloc (32);
-  fail_unless (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY),
-      "_new_and_alloc'ed buffer must not have read-only flag set");
   gst_buffer_ref (buf);
   buf2 = gst_buffer_make_writable (buf);
   fail_unless (buf != buf2, "_make_writable() should have returned a copy!");
@@ -309,20 +289,18 @@ GST_END_TEST;
 GST_START_TEST (test_subbuffer_make_writable)
 {
   GstBuffer *buf, *sub_buf;
+  guint8 *data;
+  gsize size;
 
   /* create sub-buffer of read-only buffer and make it writable */
   buf = create_read_only_buffer ();
-  fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY),
-      "read-only buffer should have read-only flag set");
 
-  sub_buf = gst_buffer_create_sub (buf, 0, 8);
-  fail_unless (GST_BUFFER_FLAG_IS_SET (sub_buf, GST_BUFFER_FLAG_READONLY),
-      "sub-buffer of read-only buffer should have read-only flag set");
+  sub_buf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, 0, 8);
 
-  sub_buf = gst_buffer_make_writable (sub_buf);
-  fail_unless (!GST_BUFFER_FLAG_IS_SET (sub_buf, GST_BUFFER_FLAG_READONLY),
-      "writable buffer must not have read-only flag set");
-  GST_BUFFER_DATA (sub_buf)[4] = 'a';
+  data = gst_buffer_map (sub_buf, &size, NULL, GST_MAP_WRITE);
+  fail_if (data == NULL);
+  data[4] = 'a';
+  gst_buffer_unmap (sub_buf, data, size);
   gst_buffer_unref (sub_buf);
   gst_buffer_unref (buf);
 }
@@ -338,23 +316,18 @@ GST_START_TEST (test_metadata_writable)
   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
   /* Buffer with refcount 1 should have writable metadata */
-  fail_unless (gst_buffer_is_metadata_writable (buffer) == TRUE);
+  fail_unless (gst_buffer_is_writable (buffer) == TRUE);
 
   /* Check that a buffer with refcount 2 does not have writable metadata */
   gst_buffer_ref (buffer);
   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 2);
-  fail_unless (gst_buffer_is_metadata_writable (buffer) == FALSE);
+  fail_unless (gst_buffer_is_writable (buffer) == FALSE);
 
   /* Check that make_metadata_writable produces a new sub-buffer with 
    * writable metadata. */
-  sub1 = gst_buffer_make_metadata_writable (buffer);
+  sub1 = gst_buffer_make_writable (buffer);
   fail_if (sub1 == buffer);
-  fail_unless (gst_buffer_is_metadata_writable (sub1) == TRUE);
-
-  /* Check that the original metadata is still not writable 
-   * (subbuffer should be holding a reference, and so should we) */
-  ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 2);
-  fail_unless (gst_buffer_is_metadata_writable (buffer) == FALSE);
+  fail_unless (gst_buffer_is_writable (sub1) == TRUE);
 
   /* Check that make_metadata_writable() maintains the buffer flags */
   fail_unless (GST_BUFFER_FLAG_IS_SET (sub1, GST_BUFFER_FLAG_DISCONT));
@@ -370,7 +343,7 @@ GST_START_TEST (test_metadata_writable)
   /* Drop the subbuffer and check that the metadata is now writable again */
   ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
   gst_buffer_unref (sub1);
-  fail_unless (gst_buffer_is_metadata_writable (buffer) == TRUE);
+  fail_unless (gst_buffer_is_writable (buffer) == TRUE);
 
   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
   gst_buffer_unref (buffer);
@@ -381,6 +354,8 @@ GST_END_TEST;
 GST_START_TEST (test_copy)
 {
   GstBuffer *buffer, *copy;
+  gsize size, ssize;
+  guint8 *data, *sdata;
 
   buffer = gst_buffer_new_and_alloc (4);
   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
@@ -388,22 +363,33 @@ GST_START_TEST (test_copy)
   copy = gst_buffer_copy (buffer);
   ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
   ASSERT_BUFFER_REFCOUNT (copy, "copy", 1);
-  /* data must be copied and thus point to different memory */
-  fail_if (GST_BUFFER_DATA (buffer) == GST_BUFFER_DATA (copy));
+  /* buffers are copied and must point to different memory */
+  fail_if (buffer == copy);
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  sdata = gst_buffer_map (copy, &ssize, NULL, GST_MAP_READ);
+
+  /* NOTE that data is refcounted */
+  fail_unless (size == ssize);
+
+  gst_buffer_unmap (copy, sdata, ssize);
+  gst_buffer_unmap (buffer, data, size);
 
   gst_buffer_unref (copy);
   gst_buffer_unref (buffer);
 
   /* a 0-sized buffer has NULL data as per docs */
   buffer = gst_buffer_new_and_alloc (0);
-  fail_unless (GST_BUFFER_DATA (buffer) == NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 0);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  fail_unless (data == NULL);
+  gst_buffer_unmap (buffer, data, size);
 
   /* copying a 0-sized buffer should not crash and also set
    * the data member NULL. */
   copy = gst_buffer_copy (buffer);
-  fail_unless (GST_BUFFER_DATA (copy) == NULL);
-  fail_unless (GST_BUFFER_SIZE (copy) == 0);
+  data = gst_buffer_map (copy, &size, NULL, GST_MAP_READ);
+  fail_unless (data == NULL);
+  gst_buffer_unmap (copy, data, size);
 
   gst_buffer_unref (copy);
   gst_buffer_unref (buffer);
@@ -414,24 +400,28 @@ GST_END_TEST;
 GST_START_TEST (test_try_new_and_alloc)
 {
   GstBuffer *buf;
+  gsize size;
+  guint8 *data;
 
   /* special case: alloc of 0 bytes results in new buffer with NULL data */
-  buf = gst_buffer_try_new_and_alloc (0);
+  buf = gst_buffer_new_and_alloc (0);
   fail_unless (buf != NULL);
   fail_unless (GST_IS_BUFFER (buf));
-  fail_unless (GST_BUFFER_SIZE (buf) == 0);
-  fail_unless (GST_BUFFER_DATA (buf) == NULL);
-  fail_unless (GST_BUFFER_MALLOCDATA (buf) == NULL);
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  fail_unless (data == NULL);
+  gst_buffer_unmap (buf, data, size);
   gst_buffer_unref (buf);
 
   /* normal alloc should still work */
-  buf = gst_buffer_try_new_and_alloc (640 * 480 * 4);
+  buf = gst_buffer_new_and_alloc (640 * 480 * 4);
   fail_unless (buf != NULL);
   fail_unless (GST_IS_BUFFER (buf));
-  fail_unless (GST_BUFFER_SIZE (buf) == (640 * 480 * 4));
-  fail_unless (GST_BUFFER_DATA (buf) != NULL);
-  fail_unless (GST_BUFFER_MALLOCDATA (buf) != NULL);
-  GST_BUFFER_DATA (buf)[640 * 479 * 4 + 479] = 0xff;
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
+  fail_unless (data != NULL);
+  fail_unless (size == (640 * 480 * 4));
+  data[640 * 479 * 4 + 479] = 0xff;
+  gst_buffer_unmap (buf, data, size);
+
   gst_buffer_unref (buf);
 
 #if 0
@@ -443,7 +433,7 @@ GST_START_TEST (test_try_new_and_alloc)
   /* now this better fail (don't run in valgrind, it will abort
    * or warn when passing silly arguments to malloc) */
   if (!RUNNING_ON_VALGRIND) {
-    buf = gst_buffer_try_new_and_alloc ((guint) - 1);
+    buf = gst_buffer_new_and_alloc ((guint) - 1);
     fail_unless (buf == NULL);
   }
 #endif
@@ -451,55 +441,177 @@ GST_START_TEST (test_try_new_and_alloc)
 
 GST_END_TEST;
 
-GST_START_TEST (test_qdata)
+GST_START_TEST (test_size)
 {
-  GstStructure *s;
-  GstBuffer *buf, *buf2, *buf3;
-  GQuark q1, q2, q3;
-
-  q1 = g_quark_from_static_string ("GstFooBar");
-  q2 = g_quark_from_static_string ("MyBorkData");
-  q3 = g_quark_from_static_string ("DoNotExist");
-
-  buf = gst_buffer_new ();
-  ASSERT_CRITICAL (gst_buffer_set_qdata (buf, q1, (s =
-              gst_structure_id_empty_new (q2))));
-  gst_structure_free (s);
-
-  gst_buffer_set_qdata (buf, q1, gst_structure_id_empty_new (q1));
-  gst_buffer_set_qdata (buf, q2, gst_structure_id_empty_new (q2));
-  fail_unless (gst_buffer_get_qdata (buf, q3) == NULL);
-  fail_unless (gst_buffer_get_qdata (buf, q1) != NULL);
-  fail_unless (gst_buffer_get_qdata (buf, q2) != NULL);
-
-  /* full copy */
-  buf2 = gst_buffer_copy (buf);
-
-  /* now back to the original buffer... */
-  gst_buffer_set_qdata (buf, q1, NULL);
-  fail_unless (gst_buffer_get_qdata (buf, q1) == NULL);
-
-  /* force creation of sub-buffer with writable metadata */
-  gst_buffer_ref (buf);
-  buf3 = gst_buffer_make_metadata_writable (buf);
+  GstBuffer *buf;
+  GstMemory *mem;
+  gsize maxalloc, maxalloc2, maxalloc3, maxalloc4;
+  gsize size, maxsize, offset;
+
+  /* one memory block */
+  buf = gst_buffer_new_allocate (NULL, 100, 0);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc >= 100);
+
+  mem = gst_buffer_peek_memory (buf, 0, GST_MAP_WRITE);
+  gst_memory_resize (mem, 10, 70);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 70);
+  fail_unless (offset == 10);
+  fail_unless (maxsize == maxalloc);
+
+  /* new memory */
+  mem = gst_allocator_alloc (NULL, 100, 0);
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc2);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc2 >= 100);
+
+  gst_memory_resize (mem, 20, 60);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 60);
+  fail_unless (offset == 20);
+  fail_unless (maxsize == maxalloc2);
+
+  /* append */
+  gst_buffer_take_memory (buf, -1, mem);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
+  fail_unless (size == 130);
+  fail_unless (offset == 10);
+  /* the maxsize is the size of the first buffer plus the remaining size in the
+   * second buffer */
+  fail_unless (maxalloc == 80 + (maxalloc2 - 20));
+
+  /* appending an empty block */
+  mem = gst_allocator_alloc (NULL, 100, 0);
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc3);
+  gst_memory_resize (mem, 0, 0);
+  gst_buffer_take_memory (buf, -1, mem);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
+  fail_unless (size == 130);
+  fail_unless (offset == 10);
+  /* the maxsize is the size of the first buffer plus the remaining size in the
+   * second buffer and the last empty buffer*/
+  fail_unless (maxalloc == 80 + (maxalloc2 - 20) + maxalloc3);
+
+  /* prepending an empty block */
+  mem = gst_allocator_alloc (NULL, 100, 0);
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc4);
+  gst_memory_resize (mem, 0, 0);
+  gst_buffer_take_memory (buf, 0, mem);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
+  fail_unless (size == 130);
+  /* empty buffer maxsize can be used as offset */
+  fail_unless (offset == 10 + maxalloc4);
+  /* the maxsize is the size of the first buffer plus the remaining size in the
+   * second buffer and the last empty buffer*/
+  fail_unless (maxalloc == 80 + (maxalloc2 - 20) + maxalloc3 + maxalloc4);
 
-  /* and check the copies/subbuffers.. */
-  fail_unless (gst_buffer_get_qdata (buf2, q3) == NULL);
-  fail_unless (gst_buffer_get_qdata (buf2, q1) != NULL);
-  fail_unless (gst_buffer_get_qdata (buf2, q2) != NULL);
+  gst_buffer_unref (buf);
+}
 
-  fail_unless (gst_buffer_get_qdata (buf3, q3) == NULL);
-  fail_unless (gst_buffer_get_qdata (buf3, q1) == NULL);
-  fail_unless (gst_buffer_get_qdata (buf3, q2) != NULL);
-  gst_buffer_set_qdata (buf3, q1, gst_structure_id_empty_new (q1));
-  fail_unless (gst_buffer_get_qdata (buf3, q1) != NULL);
+GST_END_TEST;
 
-  /* original buffer shouldn't have changed */
-  fail_unless (gst_buffer_get_qdata (buf, q1) == NULL);
+GST_START_TEST (test_resize)
+{
+  GstBuffer *buf;
+  gsize maxalloc;
+  gsize size, maxsize, offset;
+
+  /* one memory block */
+  buf = gst_buffer_new_allocate (NULL, 100, 0);
+
+  size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc >= 100);
+
+  ASSERT_CRITICAL (gst_buffer_resize (buf, 200, 50));
+  ASSERT_CRITICAL (gst_buffer_resize (buf, 0, 150));
+  ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc));
+  ASSERT_CRITICAL (gst_buffer_resize (buf, maxalloc, 1));
+
+  /* this does nothing */
+  gst_buffer_resize (buf, 0, 100);
+
+  /* nothing should have changed */
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 0, 50);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 50);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 0, 100);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 1, 99);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxsize == maxalloc);
+
+  ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc - 1));
+
+  gst_buffer_resize (buf, 0, 99);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, -1, 100);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  ASSERT_CRITICAL (gst_buffer_resize (buf, -1, 100));
+
+  gst_buffer_resize (buf, 50, 40);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 40);
+  fail_unless (offset == 50);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, -50, 100);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 0, 0);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 0);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 0, 100);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_buffer_resize (buf, 0, 100);
+  size = gst_buffer_get_sizes (buf, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
 
   gst_buffer_unref (buf);
-  gst_buffer_unref (buf2);
-  gst_buffer_unref (buf3);
 }
 
 GST_END_TEST;
@@ -511,7 +623,6 @@ gst_buffer_suite (void)
   TCase *tc_chain = tcase_create ("general");
 
   suite_add_tcase (s, tc_chain);
-  tcase_add_test (tc_chain, test_caps);
   tcase_add_test (tc_chain, test_subbuffer);
   tcase_add_test (tc_chain, test_subbuffer_make_writable);
   tcase_add_test (tc_chain, test_make_writable);
@@ -520,7 +631,8 @@ gst_buffer_suite (void)
   tcase_add_test (tc_chain, test_metadata_writable);
   tcase_add_test (tc_chain, test_copy);
   tcase_add_test (tc_chain, test_try_new_and_alloc);
-  tcase_add_test (tc_chain, test_qdata);
+  tcase_add_test (tc_chain, test_size);
+  tcase_add_test (tc_chain, test_resize);
 
   return s;
 }
index 0885644..55ca748 100644 (file)
@@ -34,7 +34,7 @@ static void
 setup (void)
 {
   list = gst_buffer_list_new ();
-  caps = gst_caps_new_simple ("text/plain", NULL);
+  caps = gst_caps_new_empty_simple ("text/plain");
 }
 
 static void
@@ -44,107 +44,70 @@ cleanup (void)
   gst_buffer_list_unref (list);
 }
 
+#if 0
 static GstBuffer *
 buffer_from_string (const gchar * str)
 {
-  guint size;
+  gsize size;
   GstBuffer *buf;
+  gpointer data;
 
   size = strlen (str);
   buf = gst_buffer_new_and_alloc (size);
   gst_buffer_set_caps (buf, caps);
   GST_BUFFER_TIMESTAMP (buf) = TIMESTAMP;
-  memcpy (GST_BUFFER_DATA (buf), str, size);
-  GST_BUFFER_SIZE (buf) = size;
+
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+  memcpy (data, str, size);
+  gst_buffer_unmap (buf, data, size);
 
   return buf;
 }
 
+static void
+check_buffer (GstBuffer * buf, gsize size, const gchar * data)
+{
+  gchar *bdata;
+  gsize bsize, csize, msize;
+
+  bdata = gst_buffer_map (buf, &bsize, &msize, GST_MAP_READ);
+  csize = size ? size : bsize;
+  GST_DEBUG ("%lu %lu %lu", bsize, csize, msize);
+  fail_unless (bsize == csize);
+  fail_unless (memcmp (bdata, data, csize) == 0);
+  gst_buffer_unmap (buf, bdata, bsize);
+}
+#endif
+
 GST_START_TEST (test_add_and_iterate)
 {
-  GstBufferListIterator *it;
   GstBuffer *buf1;
   GstBuffer *buf2;
-  GstBuffer *buf3;
-  GstBuffer *buf4;
-  GstBuffer *buf;
 
   /* buffer list is initially empty */
-  fail_unless (gst_buffer_list_n_groups (list) == 0);
-
-  it = gst_buffer_list_iterate (list);
+  fail_unless (gst_buffer_list_length (list) == 0);
 
-  ASSERT_CRITICAL (gst_buffer_list_iterator_add (it, NULL));
-  ASSERT_CRITICAL (gst_buffer_list_iterator_add (NULL, NULL));
+  ASSERT_CRITICAL (gst_buffer_list_insert (list, 0, NULL));
+  ASSERT_CRITICAL (gst_buffer_list_insert (NULL, 0, NULL));
 
-  /* cannot add buffer without adding a group first */
   buf1 = gst_buffer_new ();
-  ASSERT_CRITICAL (gst_buffer_list_iterator_add (it, buf1));
 
   /* add a group of 2 buffers */
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-  gst_buffer_list_iterator_add_group (it);
-  fail_unless (gst_buffer_list_n_groups (list) == 1);
-  ASSERT_CRITICAL (gst_buffer_list_iterator_add (it, NULL));
+  fail_unless (gst_buffer_list_length (list) == 0);
+  ASSERT_CRITICAL (gst_buffer_list_insert (list, -1, NULL));
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);
-  gst_buffer_list_iterator_add (it, buf1);
+  gst_buffer_list_add (list, buf1);
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);     /* list takes ownership */
-  fail_unless (gst_buffer_list_n_groups (list) == 1);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
+  fail_unless (gst_buffer_list_length (list) == 1);
   buf2 = gst_buffer_new ();
-  gst_buffer_list_iterator_add (it, buf2);
+  gst_buffer_list_add (list, buf2);
   ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1);
-  fail_unless (gst_buffer_list_n_groups (list) == 1);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-
-  /* add another group of 2 buffers */
-  gst_buffer_list_iterator_add_group (it);
-  fail_unless (gst_buffer_list_n_groups (list) == 2);
-  buf3 = gst_buffer_new ();
-  gst_buffer_list_iterator_add (it, buf3);
-  ASSERT_BUFFER_REFCOUNT (buf3, "buf3", 1);
-  fail_unless (gst_buffer_list_n_groups (list) == 2);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-  buf4 = gst_buffer_new ();
-  gst_buffer_list_iterator_add (it, buf4);
-  ASSERT_BUFFER_REFCOUNT (buf4, "buf4", 1);
-  fail_unless (gst_buffer_list_n_groups (list) == 2);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-
-  /* freeing iterator does not affect list */
-  gst_buffer_list_iterator_free (it);
-  fail_unless (gst_buffer_list_n_groups (list) == 2);
-
-  /* create a new iterator */
-  it = gst_buffer_list_iterate (list);
-
-  /* iterate list */
-  fail_unless (gst_buffer_list_iterator_next (it) == NULL);
-  fail_unless (gst_buffer_list_iterator_next_group (it));
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 2);
-  buf = gst_buffer_list_iterator_next (it);
-  fail_unless (buf == buf1);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 1);
-  buf = gst_buffer_list_iterator_next (it);
-  fail_unless (buf == buf2);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-  fail_unless (gst_buffer_list_iterator_next (it) == NULL);
-  fail_unless (gst_buffer_list_iterator_next_group (it));
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 2);
-  buf = gst_buffer_list_iterator_next (it);
-  fail_unless (buf == buf3);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 1);
-  buf = gst_buffer_list_iterator_next (it);
-  fail_unless (buf == buf4);
-  fail_unless (gst_buffer_list_iterator_n_buffers (it) == 0);
-  fail_unless (gst_buffer_list_iterator_next (it) == NULL);
-  fail_if (gst_buffer_list_iterator_next_group (it));
-
-  gst_buffer_list_iterator_free (it);
+  fail_unless (gst_buffer_list_length (list) == 2);
 }
 
 GST_END_TEST;
 
+#if 0
 GST_START_TEST (test_make_writable)
 {
   GstBufferListIterator *it;
@@ -546,9 +509,7 @@ GST_START_TEST (test_merge)
   gst_buffer_unref (buf);
   fail_unless (GST_BUFFER_CAPS (merged_buf) == caps);
   fail_unless (GST_BUFFER_TIMESTAMP (merged_buf) == TIMESTAMP);
-  fail_unless (GST_BUFFER_SIZE (merged_buf) == 3);
-  fail_unless (memcmp (GST_BUFFER_DATA (merged_buf), "One",
-          GST_BUFFER_SIZE (merged_buf)) == 0);
+  check_buffer (merged_buf, 3, "One");
   gst_buffer_unref (merged_buf);
 
   /* add another buffer to the same group */
@@ -559,17 +520,13 @@ GST_START_TEST (test_merge)
   ASSERT_BUFFER_REFCOUNT (merged_buf, "merged_buf", 1);
   fail_unless (GST_BUFFER_CAPS (merged_buf) == caps);
   fail_unless (GST_BUFFER_TIMESTAMP (merged_buf) == TIMESTAMP);
-  fail_unless (GST_BUFFER_SIZE (merged_buf) == 8);
-  fail_unless (memcmp (GST_BUFFER_DATA (merged_buf), "OneGroup",
-          GST_BUFFER_SIZE (merged_buf)) == 0);
+  check_buffer (merged_buf, 8, "OneGroup");
 
   /* merging the same group again should return a new buffer with merged data */
   buf = gst_buffer_list_iterator_merge_group (merge_it);
   ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
   fail_unless (buf != merged_buf);
-  fail_unless (GST_BUFFER_SIZE (buf) == 8);
-  fail_unless (memcmp (GST_BUFFER_DATA (buf), "OneGroup",
-          GST_BUFFER_SIZE (buf)) == 0);
+  check_buffer (buf, 8, "OneGroup");
   gst_buffer_unref (buf);
   gst_buffer_unref (merged_buf);
 
@@ -583,9 +540,7 @@ GST_START_TEST (test_merge)
   ASSERT_BUFFER_REFCOUNT (merged_buf, "merged_buf", 1);
   fail_unless (GST_BUFFER_CAPS (merged_buf) == caps);
   fail_unless (GST_BUFFER_TIMESTAMP (merged_buf) == TIMESTAMP);
-  fail_unless (GST_BUFFER_SIZE (merged_buf) == 8);
-  fail_unless (memcmp (GST_BUFFER_DATA (merged_buf), "OneGroup",
-          GST_BUFFER_SIZE (merged_buf)) == 0);
+  check_buffer (merged_buf, 8, "OneGroup");
   gst_buffer_unref (merged_buf);
 
   /* merge the second group */
@@ -594,9 +549,7 @@ GST_START_TEST (test_merge)
   ASSERT_BUFFER_REFCOUNT (merged_buf, "merged_buf", 1);
   fail_unless (GST_BUFFER_CAPS (merged_buf) == caps);
   fail_unless (GST_BUFFER_TIMESTAMP (merged_buf) == TIMESTAMP);
-  fail_unless (GST_BUFFER_SIZE (merged_buf) == 12);
-  fail_unless (memcmp (GST_BUFFER_DATA (merged_buf), "AnotherGroup",
-          GST_BUFFER_SIZE (merged_buf)) == 0);
+  check_buffer (merged_buf, 12, "AnotherGroup");
   gst_buffer_unref (merged_buf);
 
   gst_buffer_list_iterator_free (merge_it);
@@ -609,8 +562,7 @@ GST_START_TEST (test_merge)
   buf = gst_buffer_list_iterator_steal (it);
   gst_buffer_list_iterator_free (it);
   fail_unless (buf != NULL);
-  fail_unless (memcmp (GST_BUFFER_DATA (buf), "Group",
-          GST_BUFFER_SIZE (buf)) == 0);
+  check_buffer (buf, 0, "Group");
   gst_buffer_unref (buf);
   merge_it = gst_buffer_list_iterate (list);
   fail_unless (gst_buffer_list_iterator_next_group (merge_it));
@@ -618,9 +570,7 @@ GST_START_TEST (test_merge)
   ASSERT_BUFFER_REFCOUNT (merged_buf, "merged_buf", 1);
   fail_unless (GST_BUFFER_CAPS (merged_buf) == caps);
   fail_unless (GST_BUFFER_TIMESTAMP (merged_buf) == TIMESTAMP);
-  fail_unless (GST_BUFFER_SIZE (merged_buf) == 3);
-  fail_unless (memcmp (GST_BUFFER_DATA (merged_buf), "One",
-          GST_BUFFER_SIZE (merged_buf)) == 0);
+  check_buffer (merged_buf, 3, "One");
   gst_buffer_unref (merged_buf);
 
   /* steal the first buffer too and merge the first group again */
@@ -629,8 +579,7 @@ GST_START_TEST (test_merge)
   fail_unless (gst_buffer_list_iterator_next (it) != NULL);
   buf = gst_buffer_list_iterator_steal (it);
   fail_unless (buf != NULL);
-  fail_unless (memcmp (GST_BUFFER_DATA (buf), "One",
-          GST_BUFFER_SIZE (buf)) == 0);
+  check_buffer (buf, 3, "One");
   gst_buffer_unref (buf);
   gst_buffer_list_iterator_free (it);
   fail_unless (gst_buffer_list_iterator_merge_group (merge_it) == NULL);
@@ -796,13 +745,13 @@ GST_START_TEST (test_list)
 
     buf = gst_buffer_list_get (list, 0, i);
     g_snprintf (name, 10, "%d", i);
-    fail_unless (memcmp (name, (gchar *) GST_BUFFER_DATA (buf),
-            GST_BUFFER_SIZE (buf)) == 0);
+    check_buffer (buf, 0, name);
   }
   gst_buffer_list_iterator_free (it);
 }
 
 GST_END_TEST;
+#endif
 
 static Suite *
 gst_buffer_list_suite (void)
@@ -813,6 +762,7 @@ gst_buffer_list_suite (void)
   suite_add_tcase (s, tc_chain);
   tcase_add_checked_fixture (tc_chain, setup, cleanup);
   tcase_add_test (tc_chain, test_add_and_iterate);
+#if 0
   tcase_add_test (tc_chain, test_make_writable);
   tcase_add_test (tc_chain, test_copy);
   tcase_add_test (tc_chain, test_steal);
@@ -821,6 +771,7 @@ gst_buffer_list_suite (void)
   tcase_add_test (tc_chain, test_merge);
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_list);
+#endif
 
   return s;
 }
index cd8b9d0..e5af97e 100644 (file)
@@ -53,34 +53,13 @@ GST_START_TEST (test_from_string)
 
 GST_END_TEST;
 
-GST_START_TEST (test_buffer)
-{
-  GstCaps *c1;
-  GstBuffer *buffer;
-
-  buffer = gst_buffer_new_and_alloc (1000);
-  c1 = gst_caps_new_simple ("audio/x-raw-int",
-      "buffer", GST_TYPE_BUFFER, buffer, NULL);
-
-  GST_DEBUG ("caps: %" GST_PTR_FORMAT, c1);
-  gst_buffer_unref (buffer);
-
-  buffer = gst_buffer_new_and_alloc (1000);
-  gst_buffer_set_caps (buffer, c1);     /* doesn't give away our c1 ref */
-
-  gst_caps_unref (c1);
-  gst_buffer_unref (buffer);    /* Should now drop both references */
-}
-
-GST_END_TEST;
-
 GST_START_TEST (test_double_append)
 {
   GstStructure *s1;
   GstCaps *c1;
 
   c1 = gst_caps_new_any ();
-  s1 = gst_structure_from_string ("audio/x-raw-int,rate=44100", NULL);
+  s1 = gst_structure_from_string ("audio/x-raw,rate=44100", NULL);
   gst_caps_append_structure (c1, s1);
   ASSERT_CRITICAL (gst_caps_append_structure (c1, s1));
 
@@ -96,7 +75,7 @@ GST_START_TEST (test_mutability)
   gint ret;
 
   c1 = gst_caps_new_any ();
-  s1 = gst_structure_from_string ("audio/x-raw-int,rate=44100", NULL);
+  s1 = gst_structure_from_string ("audio/x-raw,rate=44100", NULL);
   gst_structure_set (s1, "rate", G_TYPE_INT, 48000, NULL);
   gst_caps_append_structure (c1, s1);
   gst_structure_set (s1, "rate", G_TYPE_INT, 22500, NULL);
@@ -121,7 +100,7 @@ GST_END_TEST;
 
 GST_START_TEST (test_static_caps)
 {
-  static GstStaticCaps scaps = GST_STATIC_CAPS ("audio/x-raw-int,rate=44100");
+  static GstStaticCaps scaps = GST_STATIC_CAPS ("audio/x-raw,rate=44100");
   GstCaps *caps1;
   GstCaps *caps2;
 
@@ -146,57 +125,71 @@ GST_START_TEST (test_static_caps)
 GST_END_TEST;
 
 static const gchar non_simple_caps_string[] =
-    "video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 1/100, 100 ], "
-    "width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, "
-    "format=(fourcc)YUY2, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], "
-    "height=(int)[ 16, 4096 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, "
-    "endianness=(int)1234, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], "
-    "height=(int)[ 16, 4096 ]; video/x-raw-yuv, "
-    "format=(fourcc){ I420, YUY2, YV12 }, width=(int)[ 16, 4096 ], "
+    "video/x-raw, format=(string)I420, framerate=(fraction)[ 1/100, 100 ], "
+    "width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw, "
+    "format=(string)YUY2, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], "
+    "height=(int)[ 16, 4096 ]; video/x-raw, format=(string)RGB8_PALETTED, "
+    "framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], "
+    "height=(int)[ 16, 4096 ]; video/x-raw, "
+    "format=(string){ I420, YUY2, YV12 }, width=(int)[ 16, 4096 ], "
     "height=(int)[ 16, 4096 ], framerate=(fraction)[ 1/100, 100 ]";
 
 static gboolean
-check_fourcc_list (const GValue * format_value)
+check_string_list (const GValue * format_value)
 {
-  const GValue *fourcc_value;
+  const GValue *string_value;
+  gboolean got_rgb8 = FALSE;
   gboolean got_yv12 = FALSE;
   gboolean got_i420 = FALSE;
   gboolean got_yuy2 = FALSE;
-  guint32 fourcc;
-
-  fourcc_value = gst_value_list_get_value (format_value, 0);
-  fail_unless (fourcc_value != NULL);
-  fail_unless (GST_VALUE_HOLDS_FOURCC (fourcc_value));
-  fourcc = gst_value_get_fourcc (fourcc_value);
-  fail_unless (fourcc != 0);
-  got_i420 = got_i420 || (fourcc == GST_STR_FOURCC ("I420"));
-  got_yuy2 = got_yuy2 || (fourcc == GST_STR_FOURCC ("YUY2"));
-  got_yv12 = got_yv12 || (fourcc == GST_STR_FOURCC ("YV12"));
-
-  fourcc_value = gst_value_list_get_value (format_value, 1);
-  fail_unless (fourcc_value != NULL);
-  fail_unless (GST_VALUE_HOLDS_FOURCC (fourcc_value));
-  fourcc = gst_value_get_fourcc (fourcc_value);
-  fail_unless (fourcc != 0);
-  got_i420 = got_i420 || (fourcc == GST_STR_FOURCC ("I420"));
-  got_yuy2 = got_yuy2 || (fourcc == GST_STR_FOURCC ("YUY2"));
-  got_yv12 = got_yv12 || (fourcc == GST_STR_FOURCC ("YV12"));
-
-  fourcc_value = gst_value_list_get_value (format_value, 2);
-  fail_unless (fourcc_value != NULL);
-  fail_unless (GST_VALUE_HOLDS_FOURCC (fourcc_value));
-  fourcc = gst_value_get_fourcc (fourcc_value);
-  fail_unless (fourcc != 0);
-  got_i420 = got_i420 || (fourcc == GST_STR_FOURCC ("I420"));
-  got_yuy2 = got_yuy2 || (fourcc == GST_STR_FOURCC ("YUY2"));
-  got_yv12 = got_yv12 || (fourcc == GST_STR_FOURCC ("YV12"));
-
-  return (got_i420 && got_yuy2 && got_yv12);
+  const gchar *string;
+
+  string_value = gst_value_list_get_value (format_value, 0);
+  fail_unless (string_value != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (string_value));
+  string = g_value_get_string (string_value);
+  fail_unless (string != NULL);
+  got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED"));
+  got_i420 = got_i420 || (g_str_equal (string, "I420"));
+  got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2"));
+  got_yv12 = got_yv12 || (g_str_equal (string, "YV12"));
+
+  string_value = gst_value_list_get_value (format_value, 1);
+  fail_unless (string_value != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (string_value));
+  string = g_value_get_string (string_value);
+  fail_unless (string != NULL);
+  got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED"));
+  got_i420 = got_i420 || (g_str_equal (string, "I420"));
+  got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2"));
+  got_yv12 = got_yv12 || (g_str_equal (string, "YV12"));
+
+  string_value = gst_value_list_get_value (format_value, 2);
+  fail_unless (string_value != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (string_value));
+  string = g_value_get_string (string_value);
+  fail_unless (string != NULL);
+  got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED"));
+  got_i420 = got_i420 || (g_str_equal (string, "I420"));
+  got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2"));
+  got_yv12 = got_yv12 || (g_str_equal (string, "YV12"));
+
+  string_value = gst_value_list_get_value (format_value, 3);
+  fail_unless (string_value != NULL);
+  fail_unless (G_VALUE_HOLDS_STRING (string_value));
+  string = g_value_get_string (string_value);
+  fail_unless (string != NULL);
+  got_rgb8 = got_rgb8 || (g_str_equal (string, "RGB8_PALETTED"));
+  got_i420 = got_i420 || (g_str_equal (string, "I420"));
+  got_yuy2 = got_yuy2 || (g_str_equal (string, "YUY2"));
+  got_yv12 = got_yv12 || (g_str_equal (string, "YV12"));
+
+  return (got_rgb8 && got_i420 && got_yuy2 && got_yv12);
 }
 
 GST_START_TEST (test_simplify)
 {
-  GstStructure *s1, *s2;
+  GstStructure *s1;
   gboolean did_simplify;
   GstCaps *caps;
 
@@ -210,78 +203,16 @@ GST_START_TEST (test_simplify)
 
   /* check simplified caps, should be:
    *
-   * video/x-raw-rgb, bpp=(int)8, depth=(int)8, endianness=(int)1234,
-   *     framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ],
-   *     height=(int)[ 16, 4096 ];
-   * video/x-raw-yuv, format=(fourcc){ YV12, YUY2, I420 },
+   * video/x-raw, format=(string){ RGB8_PALETTED, YV12, YUY2, I420 },
    *     width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ],
    *     framerate=(fraction)[ 1/100, 100 ]
    */
-  fail_unless (gst_caps_get_size (caps) == 2);
+  GST_DEBUG ("simplyfied %" GST_PTR_FORMAT, caps);
+  fail_unless (gst_caps_get_size (caps) == 1);
   s1 = gst_caps_get_structure (caps, 0);
-  s2 = gst_caps_get_structure (caps, 1);
   fail_unless (s1 != NULL);
-  fail_unless (s2 != NULL);
 
-  if (!gst_structure_has_name (s1, "video/x-raw-rgb")) {
-    GstStructure *tmp;
-
-    tmp = s1;
-    s1 = s2;
-    s2 = tmp;
-  }
-
-  fail_unless (gst_structure_has_name (s1, "video/x-raw-rgb"));
-  {
-    const GValue *framerate_value;
-    const GValue *width_value;
-    const GValue *height_value;
-    const GValue *val_fps;
-    GValue test_fps = { 0, };
-    gint bpp, depth, endianness;
-    gint min_width, max_width;
-    gint min_height, max_height;
-
-    fail_unless (gst_structure_get_int (s1, "bpp", &bpp));
-    fail_unless (bpp == 8);
-
-    fail_unless (gst_structure_get_int (s1, "depth", &depth));
-    fail_unless (depth == 8);
-
-    fail_unless (gst_structure_get_int (s1, "endianness", &endianness));
-    fail_unless (endianness == G_LITTLE_ENDIAN);
-
-    g_value_init (&test_fps, GST_TYPE_FRACTION);
-    framerate_value = gst_structure_get_value (s1, "framerate");
-    fail_unless (framerate_value != NULL);
-    fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value));
-
-    val_fps = gst_value_get_fraction_range_min (framerate_value);
-    gst_value_set_fraction (&test_fps, 1, 100);
-    fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL);
-
-    val_fps = gst_value_get_fraction_range_max (framerate_value);
-    gst_value_set_fraction (&test_fps, 100, 1);
-    fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL);
-
-    g_value_unset (&test_fps);
-
-    width_value = gst_structure_get_value (s1, "width");
-    fail_unless (width_value != NULL);
-    fail_unless (GST_VALUE_HOLDS_INT_RANGE (width_value));
-    min_width = gst_value_get_int_range_min (width_value);
-    max_width = gst_value_get_int_range_max (width_value);
-    fail_unless (min_width == 16 && max_width == 4096);
-
-    height_value = gst_structure_get_value (s1, "height");
-    fail_unless (height_value != NULL);
-    fail_unless (GST_VALUE_HOLDS_INT_RANGE (height_value));
-    min_height = gst_value_get_int_range_min (height_value);
-    max_height = gst_value_get_int_range_max (height_value);
-    fail_unless (min_height == 16 && max_height == 4096);
-  }
-
-  fail_unless (gst_structure_has_name (s2, "video/x-raw-yuv"));
+  fail_unless (gst_structure_has_name (s1, "video/x-raw"));
   {
     const GValue *framerate_value;
     const GValue *format_value;
@@ -292,14 +223,14 @@ GST_START_TEST (test_simplify)
     gint min_width, max_width;
     gint min_height, max_height;
 
-    format_value = gst_structure_get_value (s2, "format");
+    format_value = gst_structure_get_value (s1, "format");
     fail_unless (format_value != NULL);
     fail_unless (GST_VALUE_HOLDS_LIST (format_value));
-    fail_unless (gst_value_list_get_size (format_value) == 3);
-    fail_unless (check_fourcc_list (format_value) == TRUE);
+    fail_unless (gst_value_list_get_size (format_value) == 4);
+    fail_unless (check_string_list (format_value) == TRUE);
 
     g_value_init (&test_fps, GST_TYPE_FRACTION);
-    framerate_value = gst_structure_get_value (s2, "framerate");
+    framerate_value = gst_structure_get_value (s1, "framerate");
     fail_unless (framerate_value != NULL);
     fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value));
 
@@ -313,14 +244,14 @@ GST_START_TEST (test_simplify)
 
     g_value_unset (&test_fps);
 
-    width_value = gst_structure_get_value (s2, "width");
+    width_value = gst_structure_get_value (s1, "width");
     fail_unless (width_value != NULL);
     fail_unless (GST_VALUE_HOLDS_INT_RANGE (width_value));
     min_width = gst_value_get_int_range_min (width_value);
     max_width = gst_value_get_int_range_max (width_value);
     fail_unless (min_width == 16 && max_width == 4096);
 
-    height_value = gst_structure_get_value (s2, "height");
+    height_value = gst_structure_get_value (s1, "height");
     fail_unless (height_value != NULL);
     fail_unless (GST_VALUE_HOLDS_INT_RANGE (height_value));
     min_height = gst_value_get_int_range_min (height_value);
@@ -352,24 +283,23 @@ GST_START_TEST (test_subset)
 {
   GstCaps *c1, *c2;
 
-  c1 = gst_caps_from_string ("video/x-raw-yuv; video/x-raw-rgb");
-  c2 = gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)YUY2");
+  c1 = gst_caps_from_string ("video/x-raw; video/x-raw");
+  c2 = gst_caps_from_string ("video/x-raw, format=(string)YUY2");
   fail_unless (gst_caps_is_subset (c2, c1));
   fail_if (gst_caps_is_subset (c1, c2));
   gst_caps_unref (c1);
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string
-      ("audio/x-raw-int, channels=(int)[ 1, 2 ], rate=(int)44100");
-  c2 = gst_caps_from_string
-      ("audio/x-raw-int, channels=(int)1, rate=(int)44100");
+      ("audio/x-raw, channels=(int)[ 1, 2 ], rate=(int)44100");
+  c2 = gst_caps_from_string ("audio/x-raw, channels=(int)1, rate=(int)44100");
   fail_unless (gst_caps_is_subset (c2, c1));
   fail_if (gst_caps_is_subset (c1, c2));
   gst_caps_unref (c1);
   gst_caps_unref (c2);
 
-  c1 = gst_caps_from_string ("audio/x-raw-int, channels=(int) {1}");
-  c2 = gst_caps_from_string ("audio/x-raw-int, channels=(int)1");
+  c1 = gst_caps_from_string ("audio/x-raw, channels=(int) {1}");
+  c2 = gst_caps_from_string ("audio/x-raw, channels=(int)1");
   fail_unless (gst_caps_is_subset (c2, c1));
   fail_unless (gst_caps_is_subset (c1, c2));
   fail_unless (gst_caps_is_equal (c1, c2));
@@ -377,9 +307,9 @@ GST_START_TEST (test_subset)
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string
-      ("audio/x-raw-int, rate=(int)44100, channels=(int)3, endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)false");
+      ("audio/x-raw, rate=(int)44100, channels=(int)3, format=(string)U16_LE");
   c2 = gst_caps_from_string
-      ("audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)16, depth=(int)[ 1, 16 ], signed=(boolean){ true, false }");
+      ("audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], format=(string){ S16_LE, U16_LE }");
   fail_unless (gst_caps_is_subset (c1, c2));
   fail_if (gst_caps_is_subset (c2, c1));
   gst_caps_unref (c1);
@@ -393,7 +323,7 @@ GST_START_TEST (test_merge_fundamental)
   GstCaps *c1, *c2;
 
   /* ANY + specific = ANY */
-  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c1 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c2 = gst_caps_new_any ();
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
@@ -402,7 +332,7 @@ GST_START_TEST (test_merge_fundamental)
   gst_caps_unref (c2);
 
   /* specific + ANY = ANY */
-  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c2 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c1 = gst_caps_new_any ();
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
@@ -411,7 +341,7 @@ GST_START_TEST (test_merge_fundamental)
   gst_caps_unref (c2);
 
   /* EMPTY + specific = specific */
-  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c1 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c2 = gst_caps_new_empty ();
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
@@ -420,7 +350,7 @@ GST_START_TEST (test_merge_fundamental)
   gst_caps_unref (c2);
 
   /* specific + EMPTY = specific */
-  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c2 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c1 = gst_caps_new_empty ();
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
@@ -436,19 +366,19 @@ GST_START_TEST (test_merge_same)
   GstCaps *c1, *c2, *test;
 
   /* this is the same */
-  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
-  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
+  c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
+  test = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (test);
   gst_caps_unref (c2);
 
   /* and so is this */
-  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
+  c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
@@ -490,123 +420,121 @@ GST_START_TEST (test_merge_subset)
   GstCaps *c1, *c2, *test;
 
   /* the 2nd is already covered */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=1");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* here it is not */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2],rate=44100");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,2],rate=44100");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* second one was already contained in the first one */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,3]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,3]");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* second one was already contained in the first one */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* second one was already contained in the first one */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[2,4]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[2,4]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* second one was already contained in the first one */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[2,3]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[2,3]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
+  test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* these caps cannot be merged */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[2,3]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,4]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[2,3]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test =
       gst_caps_from_string
-      ("audio/x-raw-int,channels=[2,3];audio/x-raw-int,channels=[1,4]");
+      ("audio/x-raw,channels=[2,3];audio/x-raw,channels=[1,4]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
   /* these caps cannot be merged */
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,3]");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test =
       gst_caps_from_string
-      ("audio/x-raw-int,channels=[1,2];audio/x-raw-int,channels=[1,3]");
+      ("audio/x-raw,channels=[1,2];audio/x-raw,channels=[1,3]");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels={1,2}");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels={1,2,3,4}");
+  c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}");
+  c1 = gst_caps_from_string ("audio/x-raw,channels={1,2,3,4}");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels={1,2};"
-      "audio/x-raw-int,channels={1,2,3,4}");
+  test = gst_caps_from_string ("audio/x-raw,channels={1,2};"
+      "audio/x-raw,channels={1,2,3,4}");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels={1,2}");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels={1,3}");
+  c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}");
+  c1 = gst_caps_from_string ("audio/x-raw,channels={1,3}");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels={1,2};"
-      "audio/x-raw-int,channels={1,3}");
+  test = gst_caps_from_string ("audio/x-raw,channels={1,2};"
+      "audio/x-raw,channels={1,3}");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
-  c2 = gst_caps_from_string
-      ("video/x-raw-yuv, framerate=(fraction){ 15/2, 5/1 }");
-  c1 = gst_caps_from_string
-      ("video/x-raw-yuv, framerate=(fraction){ 15/1, 5/1 }");
+  c2 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/2, 5/1 }");
+  c1 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/1, 5/1 }");
   test = gst_caps_copy (c1);
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
@@ -614,22 +542,22 @@ GST_START_TEST (test_merge_subset)
   gst_caps_unref (test);
   gst_caps_unref (c2);
 
-  c2 = gst_caps_from_string ("audio/x-raw-int");
-  c1 = gst_caps_from_string ("audio/x-raw-int,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw");
+  c1 = gst_caps_from_string ("audio/x-raw,channels=1");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int");
+  test = gst_caps_from_string ("audio/x-raw");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
 
-  c2 = gst_caps_from_string ("audio/x-raw-int,channels=1");
-  c1 = gst_caps_from_string ("audio/x-raw-int");
+  c2 = gst_caps_from_string ("audio/x-raw,channels=1");
+  c1 = gst_caps_from_string ("audio/x-raw");
   gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
-  test = gst_caps_from_string ("audio/x-raw-int,channels=1; audio/x-raw-int");
+  test = gst_caps_from_string ("audio/x-raw,channels=1; audio/x-raw");
   fail_unless (gst_caps_is_equal (c2, test));
   gst_caps_unref (c2);
   gst_caps_unref (test);
@@ -644,14 +572,14 @@ GST_START_TEST (test_intersect)
 
   /* field not specified = any value possible, so the intersection
    * should keep fields which are only part of one set of caps */
-  c2 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,width=20");
-  c1 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420");
+  c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c1 = gst_caps_from_string ("video/x-raw,format=(string)I420");
 
   ci1 = gst_caps_intersect (c2, c1);
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
   fail_unless (gst_caps_get_size (ci1) == 1, NULL);
   s = gst_caps_get_structure (ci1, 0);
-  fail_unless (gst_structure_has_name (s, "video/x-raw-yuv"));
+  fail_unless (gst_structure_has_name (s, "video/x-raw"));
   fail_unless (gst_structure_get_value (s, "format") != NULL);
   fail_unless (gst_structure_get_value (s, "width") != NULL);
 
@@ -660,7 +588,7 @@ GST_START_TEST (test_intersect)
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2);
   fail_unless (gst_caps_get_size (ci2) == 1, NULL);
   s = gst_caps_get_structure (ci2, 0);
-  fail_unless (gst_structure_has_name (s, "video/x-raw-yuv"));
+  fail_unless (gst_structure_has_name (s, "video/x-raw"));
   fail_unless (gst_structure_get_value (s, "format") != NULL);
   fail_unless (gst_structure_get_value (s, "width") != NULL);
 
@@ -674,8 +602,8 @@ GST_START_TEST (test_intersect)
 
   /* ========== */
 
-  c2 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,width=20");
-  c1 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,width=30");
+  c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=30");
 
   ci1 = gst_caps_intersect (c2, c1);
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
@@ -696,8 +624,8 @@ GST_START_TEST (test_intersect)
 
   /* ========== */
 
-  c2 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,width=20");
-  c1 = gst_caps_from_string ("video/x-raw-rgb,format=(fourcc)I420,width=20");
+  c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c1 = gst_caps_from_string ("video/x-raw2,format=(string)I420,width=20");
 
   ci1 = gst_caps_intersect (c2, c1);
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
@@ -718,14 +646,14 @@ GST_START_TEST (test_intersect)
 
   /* ========== */
 
-  c2 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,width=20");
-  c1 = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420,height=30");
+  c2 = gst_caps_from_string ("video/x-raw,format=(string)I420,width=20");
+  c1 = gst_caps_from_string ("video/x-raw,format=(string)I420,height=30");
 
   ci1 = gst_caps_intersect (c2, c1);
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci1);
   fail_unless (gst_caps_get_size (ci1) == 1, NULL);
   s = gst_caps_get_structure (ci1, 0);
-  fail_unless (gst_structure_has_name (s, "video/x-raw-yuv"));
+  fail_unless (gst_structure_has_name (s, "video/x-raw"));
   fail_unless (gst_structure_get_value (s, "format") != NULL);
   fail_unless (gst_structure_get_value (s, "width") != NULL);
   fail_unless (gst_structure_get_value (s, "height") != NULL);
@@ -735,7 +663,7 @@ GST_START_TEST (test_intersect)
   GST_DEBUG ("intersected: %" GST_PTR_FORMAT, ci2);
   fail_unless (gst_caps_get_size (ci2) == 1, NULL);
   s = gst_caps_get_structure (ci2, 0);
-  fail_unless (gst_structure_has_name (s, "video/x-raw-yuv"));
+  fail_unless (gst_structure_has_name (s, "video/x-raw"));
   fail_unless (gst_structure_get_value (s, "format") != NULL);
   fail_unless (gst_structure_get_value (s, "height") != NULL);
   fail_unless (gst_structure_get_value (s, "width") != NULL);
@@ -756,14 +684,14 @@ GST_START_TEST (test_intersect2)
   GstCaps *caps1, *caps2, *icaps;
 
   /* tests array subtraction */
-  caps1 = gst_caps_from_string ("audio/x-raw-float, "
+  caps1 = gst_caps_from_string ("audio/x-raw, "
       "channel-positions=(int)<                      "
       "{ 1, 2, 3, 4, 5, 6 },                         "
       "{ 1, 2, 3, 4, 5, 6 },                         "
       "{ 1, 2, 3, 4, 5, 6 },                         "
       "{ 1, 2, 3, 4, 5, 6 },                         "
       "{ 1, 2, 3, 4, 5, 6 },                         " "{ 1, 2, 3, 4, 5, 6 }>");
-  caps2 = gst_caps_from_string ("audio/x-raw-float, "
+  caps2 = gst_caps_from_string ("audio/x-raw, "
       "channel-positions=(int)< 1, 2, 3, 4, 5, 6 >");
   icaps = gst_caps_intersect (caps1, caps2);
   GST_LOG ("intersected caps: %" GST_PTR_FORMAT, icaps);
@@ -876,9 +804,9 @@ GST_START_TEST (test_intersect_duplication)
   GstCaps *c1, *c2, *test;
 
   c1 = gst_caps_from_string
-      ("audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]");
+      ("audio/x-raw, format=(string)S16_LE, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]");
   c2 = gst_caps_from_string
-      ("audio/x-raw-int, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)[ 1, 16 ], rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }");
+      ("audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]; audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ]; audio/x-raw, format=(string) { S16_LE, S16_BE, U16_LE, U16_BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ]");
 
   test = gst_caps_intersect_full (c1, c2, GST_CAPS_INTERSECT_FIRST);
   fail_unless_equals_int (gst_caps_get_size (test), 1);
@@ -987,7 +915,6 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_from_string);
   tcase_add_test (tc_chain, test_double_append);
   tcase_add_test (tc_chain, test_mutability);
-  tcase_add_test (tc_chain, test_buffer);
   tcase_add_test (tc_chain, test_static_caps);
   tcase_add_test (tc_chain, test_simplify);
   tcase_add_test (tc_chain, test_truncate);
diff --git a/tests/check/gst/gstcontroller.c b/tests/check/gst/gstcontroller.c
new file mode 100644 (file)
index 0000000..c25c92b
--- /dev/null
@@ -0,0 +1,674 @@
+/* GStreamer
+ *
+ * unit test for the controller library
+ *
+ * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
+ * Copyright (C) <2006-2007> Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+
+/* local test element */
+
+enum
+{
+  PROP_INT = 1,
+  PROP_FLOAT,
+  PROP_DOUBLE,
+  PROP_BOOLEAN,
+  PROP_READONLY,
+  PROP_STATIC,
+  PROP_CONSTRUCTONLY,
+  PROP_COUNT
+};
+
+#define GST_TYPE_TEST_OBJ            (gst_test_obj_get_type ())
+#define GST_TEST_OBJ(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj))
+#define GST_TEST_OBJ_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass))
+#define GST_IS_TEST_OBJ(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ))
+#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ))
+#define GST_TEST_OBJ_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass))
+
+typedef struct _GstTestObj GstTestObj;
+typedef struct _GstTestObjClass GstTestObjClass;
+
+struct _GstTestObj
+{
+  GstElement parent;
+  gint val_int;
+  gfloat val_float;
+  gdouble val_double;
+  gboolean val_boolean;
+};
+struct _GstTestObjClass
+{
+  GstElementClass parent_class;
+};
+
+static GType gst_test_obj_get_type (void);
+
+static void
+gst_test_obj_get_property (GObject * object,
+    guint property_id, GValue * value, GParamSpec * pspec)
+{
+  GstTestObj *self = GST_TEST_OBJ (object);
+
+  switch (property_id) {
+    case PROP_INT:
+      g_value_set_int (value, self->val_int);
+      break;
+    case PROP_FLOAT:
+      g_value_set_float (value, self->val_float);
+      break;
+    case PROP_DOUBLE:
+      g_value_set_double (value, self->val_double);
+      break;
+    case PROP_BOOLEAN:
+      g_value_set_boolean (value, self->val_boolean);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_test_obj_set_property (GObject * object,
+    guint property_id, const GValue * value, GParamSpec * pspec)
+{
+  GstTestObj *self = GST_TEST_OBJ (object);
+
+  switch (property_id) {
+    case PROP_INT:
+      self->val_int = g_value_get_int (value);
+      GST_DEBUG ("test value int=%d", self->val_int);
+      break;
+    case PROP_FLOAT:
+      self->val_float = g_value_get_float (value);
+      GST_DEBUG ("test value float=%f", self->val_float);
+      break;
+    case PROP_DOUBLE:
+      self->val_double = g_value_get_double (value);
+      GST_DEBUG ("test value double=%lf", self->val_double);
+      break;
+    case PROP_BOOLEAN:
+      self->val_boolean = g_value_get_boolean (value);
+      GST_DEBUG ("test value boolean=%d", self->val_boolean);
+      break;
+    case PROP_CONSTRUCTONLY:
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_test_obj_class_init (GstTestObjClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_test_obj_set_property;
+  gobject_class->get_property = gst_test_obj_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_INT,
+      g_param_spec_int ("int",
+          "int prop",
+          "int number parameter",
+          0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FLOAT,
+      g_param_spec_float ("float",
+          "float prop",
+          "float number parameter",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_DOUBLE,
+      g_param_spec_double ("double",
+          "double prop",
+          "double number parameter",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_BOOLEAN,
+      g_param_spec_boolean ("boolean",
+          "boolean prop",
+          "boolean parameter",
+          FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_READONLY,
+      g_param_spec_int ("readonly",
+          "readonly prop",
+          "readonly parameter",
+          0, G_MAXINT, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_STATIC,
+      g_param_spec_int ("static",
+          "static prop",
+          "static parameter", 0, G_MAXINT, 0, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_CONSTRUCTONLY,
+      g_param_spec_int ("construct-only",
+          "construct-only prop",
+          "construct-only parameter",
+          0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_test_obj_base_init (GstTestObjClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details_simple (element_class,
+      "test object for unit tests",
+      "Test", "Use in unit tests", "Stefan Sauer <ensonic@users.sf.net>");
+}
+
+static GType
+gst_test_obj_get_type (void)
+{
+  static volatile gsize test_obj_type = 0;
+
+  if (g_once_init_enter (&test_obj_type)) {
+    GType type;
+    static const GTypeInfo info = {
+      (guint16) sizeof (GstTestObjClass),
+      (GBaseInitFunc) gst_test_obj_base_init,   // base_init
+      NULL,                     // base_finalize
+      (GClassInitFunc) gst_test_obj_class_init, // class_init
+      NULL,                     // class_finalize
+      NULL,                     // class_data
+      (guint16) sizeof (GstTestObj),
+      0,                        // n_preallocs
+      NULL,                     // instance_init
+      NULL                      // value_table
+    };
+    type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0);
+    g_once_init_leave (&test_obj_type, type);
+  }
+  return test_obj_type;
+}
+
+/* test control source */
+
+#define GST_TYPE_TEST_CONTROL_SOURCE            (gst_test_control_source_get_type ())
+#define GST_TEST_CONTROL_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSource))
+#define GST_TEST_CONTROL_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass))
+#define GST_IS_TEST_CONTROL_SOURCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_SOURCE))
+#define GST_IS_TEST_CONTROL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_SOURCE))
+#define GST_TEST_CONTROL_SOURCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_SOURCE, GstTestControlSourceClass))
+
+typedef struct _GstTestControlSource GstTestControlSource;
+typedef struct _GstTestControlSourceClass GstTestControlSourceClass;
+
+struct _GstTestControlSource
+{
+  GstControlSource parent;
+
+  gdouble value;
+};
+struct _GstTestControlSourceClass
+{
+  GstControlSourceClass parent_class;
+};
+
+static GType gst_test_control_source_get_type (void);
+
+static GstTestControlSource *
+gst_test_control_source_new (void)
+{
+  return g_object_newv (GST_TYPE_TEST_CONTROL_SOURCE, 0, NULL);
+}
+
+static gboolean
+gst_test_control_source_get (GstTestControlSource * self,
+    GstClockTime timestamp, gdouble * value)
+{
+  *value = self->value;
+  return TRUE;
+}
+
+static gboolean
+gst_test_control_source_get_value_array (GstTestControlSource * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gdouble * values)
+{
+  guint i;
+
+  for (i = 0; i < n_values; i++) {
+    *values = self->value;
+    values++;
+  }
+  return TRUE;
+}
+
+static void
+gst_test_control_source_init (GstTestControlSource * self)
+{
+  GstControlSource *cs = (GstControlSource *) self;
+
+  cs->get_value = (GstControlSourceGetValue) gst_test_control_source_get;
+  cs->get_value_array = (GstControlSourceGetValueArray)
+      gst_test_control_source_get_value_array;
+  self->value = 0.0;
+}
+
+static GType
+gst_test_control_source_get_type (void)
+{
+  static volatile gsize test_countrol_source_type = 0;
+
+  if (g_once_init_enter (&test_countrol_source_type)) {
+    GType type;
+    static const GTypeInfo info = {
+      (guint16) sizeof (GstTestControlSourceClass),
+      NULL,                     // base_init
+      NULL,                     // base_finalize
+      NULL,                     // class_init
+      NULL,                     // class_finalize
+      NULL,                     // class_data
+      (guint16) sizeof (GstTestControlSource),
+      0,                        // n_preallocs
+      (GInstanceInitFunc) gst_test_control_source_init, // instance_init
+      NULL                      // value_table
+    };
+    type =
+        g_type_register_static (GST_TYPE_CONTROL_SOURCE, "GstTestControlSource",
+        &info, 0);
+    g_once_init_leave (&test_countrol_source_type, type);
+  }
+  return test_countrol_source_type;
+}
+
+/* test control binding */
+
+#define GST_TYPE_TEST_CONTROL_BINDING            (gst_test_control_binding_get_type ())
+#define GST_TEST_CONTROL_BINDING(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBinding))
+#define GST_TEST_CONTROL_BINDING_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass))
+#define GST_IS_TEST_CONTROL_BINDING(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_CONTROL_BINDING))
+#define GST_IS_TEST_CONTROL_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_CONTROL_BINDING))
+#define GST_TEST_CONTROL_BINDING_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_CONTROL_BINDING, GstTestControlBindingClass))
+
+typedef struct _GstTestControlBinding GstTestControlBinding;
+typedef struct _GstTestControlBindingClass GstTestControlBindingClass;
+
+struct _GstTestControlBinding
+{
+  GstControlBinding parent;
+
+  GstControlSource *cs;
+};
+struct _GstTestControlBindingClass
+{
+  GstControlBindingClass parent_class;
+};
+
+static GType gst_test_control_binding_get_type (void);
+
+static GstControlBinding *
+gst_test_control_binding_new (GstObject * object, const gchar * property_name,
+    GstControlSource * cs)
+{
+  GstTestControlBinding *self;
+  self = (GstTestControlBinding *) g_object_new (GST_TYPE_TEST_CONTROL_BINDING,
+      "object", object, "name", property_name, NULL);
+
+  self->cs = gst_object_ref (cs);
+
+  return (GstControlBinding *) self;
+}
+
+static GstControlSource *
+gst_test_control_binding_get_control_source (GstTestControlBinding * self)
+{
+  g_return_val_if_fail (GST_IS_TEST_CONTROL_BINDING (self), NULL);
+
+  return self->cs ? gst_object_ref (self->cs) : NULL;
+}
+
+static GType
+gst_test_control_binding_get_type (void)
+{
+  static volatile gsize test_countrol_source_type = 0;
+
+  if (g_once_init_enter (&test_countrol_source_type)) {
+    GType type;
+    static const GTypeInfo info = {
+      (guint16) sizeof (GstTestControlBindingClass),
+      NULL,                     // base_init
+      NULL,                     // base_finalize
+      NULL,                     // class_init
+      NULL,                     // class_finalize
+      NULL,                     // class_data
+      (guint16) sizeof (GstTestControlBinding),
+      0,                        // n_preallocs
+      NULL,                     // instance_init
+      NULL                      // value_table
+    };
+    type =
+        g_type_register_static (GST_TYPE_CONTROL_BINDING,
+        "GstTestControlBinding", &info, 0);
+    g_once_init_leave (&test_countrol_source_type, type);
+  }
+  return test_countrol_source_type;
+}
+
+
+static void
+setup (void)
+{
+  gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ);
+}
+
+static void
+teardown (void)
+{
+}
+
+
+/* TESTS */
+
+/* tests for an element with no controlled params */
+GST_START_TEST (controller_new_fail1)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should not exist */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "_schrompf_",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for readonly params */
+GST_START_TEST (controller_new_fail2)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should exist and but is readonly */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "readonly",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for static params */
+GST_START_TEST (controller_new_fail3)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should exist and but is not controlable */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "static",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for construct-only params */
+GST_START_TEST (controller_new_fail4)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should exist and but is construct-only */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "construct-only",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) == NULL, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+
+/* tests for an element with controlled params */
+GST_START_TEST (controller_new_okay1)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should exist and should be controllable */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "int",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests for an element with several controlled params */
+GST_START_TEST (controller_new_okay2)
+{
+  GstElement *elem;
+  GstTestControlSource *cs1, *cs2;
+  GstControlBinding *cb1, *cb2;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs1 = gst_test_control_source_new ();
+  cs2 = gst_test_control_source_new ();
+
+  /* these properties should exist and should be controllable */
+  cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int",
+      GST_CONTROL_SOURCE (cs1));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL);
+
+  cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "boolean",
+      GST_CONTROL_SOURCE (cs2));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL);
+
+  gst_object_unref (cb1);
+  gst_object_unref (cb2);
+  gst_object_unref (cs1);
+  gst_object_unref (cs2);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* controlling a param twice should be handled */
+GST_START_TEST (controller_param_twice)
+{
+  GstElement *elem;
+  GstTestControlSource *cs;
+  GstControlBinding *cb;
+  gboolean res;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+  cs = gst_test_control_source_new ();
+
+  /* that property should exist and should be controllable */
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "int",
+      GST_CONTROL_SOURCE (cs));
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
+  cb = gst_object_ref (cb);
+
+  res = gst_object_add_control_binding (GST_OBJECT (elem), cb);
+  fail_unless (res, NULL);
+
+  /* setting it again will just unset the old and set it again
+   * this might cause some trouble with binding the control source again
+   */
+  res = gst_object_add_control_binding (GST_OBJECT (elem), cb);
+  fail_unless (res, NULL);
+
+  /* it should have been added now, let remove it */
+  res = gst_object_remove_control_binding (GST_OBJECT (elem), cb);
+  fail_unless (res, NULL);
+
+  /* removing it again should not work */
+  res = gst_object_remove_control_binding (GST_OBJECT (elem), cb);
+  fail_unless (!res, NULL);
+
+  gst_object_unref (cb);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests if we can run controller methods against any GObject */
+GST_START_TEST (controller_any_gobject)
+{
+  GstElement *elem;
+  gboolean res;
+
+  elem = gst_element_factory_make ("bin", "test_elem");
+
+  /* that element is not controllable */
+  res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
+  /* Syncing should still succeed as there's nothing to sync */
+  fail_unless (res == TRUE, NULL);
+
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests if we cleanup properly */
+GST_START_TEST (controller_controlsource_refcounts)
+{
+  GstElement *elem;
+  GstControlBinding *cb, *test_cb;
+  GstControlSource *cs, *test_cs;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  cs = (GstControlSource *) gst_test_control_source_new ();
+  fail_unless (cs != NULL, NULL);
+
+  fail_unless_equals_int (G_OBJECT (cs)->ref_count, 1);
+
+  cb = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs);
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb) != NULL, NULL);
+  fail_unless_equals_int (G_OBJECT (cs)->ref_count, 2);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem), cb));
+
+  test_cb = gst_object_get_control_binding (GST_OBJECT (elem), "int");
+  fail_unless (test_cb != NULL, NULL);
+
+  test_cs =
+      gst_test_control_binding_get_control_source (GST_TEST_CONTROL_BINDING
+      (test_cb));
+  fail_unless (test_cs != NULL, NULL);
+  fail_unless (test_cs == cs);
+  fail_unless_equals_int (G_OBJECT (cs)->ref_count, 3);
+  gst_object_unref (test_cs);
+  gst_object_unref (test_cb);
+  gst_object_unref (cs);
+
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* tests if we can bind a control source twice */
+GST_START_TEST (controller_bind_twice)
+{
+  GstElement *elem;
+  GstControlSource *cs;
+  GstControlBinding *cb1, *cb2;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  cs = (GstControlSource *) gst_test_control_source_new ();
+  fail_unless (cs != NULL, NULL);
+
+  cb1 = gst_test_control_binding_new (GST_OBJECT (elem), "int", cs);
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb1) != NULL, NULL);
+  cb2 = gst_test_control_binding_new (GST_OBJECT (elem), "double", cs);
+  fail_unless (GST_CONTROL_BINDING_PSPEC (cb2) != NULL, NULL);
+
+  gst_object_unref (cb1);
+  gst_object_unref (cb2);
+  gst_object_unref (cs);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+gst_controller_suite (void)
+{
+  Suite *s = suite_create ("Controller");
+  TCase *tc = tcase_create ("general");
+
+  suite_add_tcase (s, tc);
+  tcase_add_checked_fixture (tc, setup, teardown);
+  tcase_add_test (tc, controller_new_fail1);
+  tcase_add_test (tc, controller_new_fail2);
+  tcase_add_test (tc, controller_new_fail3);
+  tcase_add_test (tc, controller_new_fail4);
+  tcase_add_test (tc, controller_new_okay1);
+  tcase_add_test (tc, controller_new_okay2);
+  tcase_add_test (tc, controller_param_twice);
+  tcase_add_test (tc, controller_any_gobject);
+  tcase_add_test (tc, controller_controlsource_refcounts);
+  tcase_add_test (tc, controller_bind_twice);
+
+  return s;
+}
+
+GST_CHECK_MAIN (gst_controller);
index 57f3357..5bb45da 100644 (file)
@@ -164,6 +164,188 @@ GST_START_TEST (test_link_no_pads)
 
 GST_END_TEST;
 
+typedef struct _GstTestElement
+{
+  GstElement parent;
+
+} GstTestElement;
+
+typedef struct _GstTestElementClass
+{
+  GstElementClass parent;
+
+} GstTestElementClass;
+
+static void
+gst_test_element_class_init (GstTestElementClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstPadTemplate *templ;
+
+  gst_element_class_set_metadata (element_class, "Test element",
+      "Element", "Does nothing", "Foo Bar <foo@bar.com>");
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 0);
+
+  fail_unless (gst_element_class_get_pad_template (element_class,
+          "test") == NULL);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 1);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test")) != NULL);
+  fail_unless (gst_caps_is_any (templ->caps));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("test2", GST_PAD_SRC, GST_PAD_ALWAYS,
+          GST_CAPS_ANY));
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 2);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test2")) != NULL);
+  fail_unless (gst_caps_is_any (templ->caps));
+
+  /* Add "test" again, with NONE caps this time */
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS,
+          GST_CAPS_NONE));
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 2);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test")) != NULL);
+  fail_unless (gst_caps_is_empty (templ->caps));
+}
+
+static GType
+gst_test_element_get_type (void)
+{
+  static GType gst_test_element_type = G_TYPE_NONE;
+
+  if (gst_test_element_type == G_TYPE_NONE) {
+    static const GTypeInfo gst_test_element_info = {
+      sizeof (GstTestElementClass),
+      NULL,                     /* base_init */
+      NULL,                     /* base_finalize */
+      (GClassInitFunc) gst_test_element_class_init,
+      NULL,
+      NULL,
+      sizeof (GstTestElement),
+      0,
+      NULL,                     /* instance_init */
+      NULL
+    };
+
+    gst_test_element_type = g_type_register_static (GST_TYPE_ELEMENT,
+        "GstTestElement", &gst_test_element_info, 0);
+  }
+  return gst_test_element_type;
+}
+
+typedef struct _GstTestElement2
+{
+  GstTestElement parent;
+
+} GstTestElement2;
+
+typedef struct _GstTestElement2Class
+{
+  GstTestElementClass parent;
+
+} GstTestElement2Class;
+
+static void
+gst_test_element2_class_init (GstTestElement2Class * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstPadTemplate *templ;
+
+  gst_element_class_set_metadata (element_class, "Test element 2",
+      "Element", "Does nothing", "Foo Bar <foo@bar.com>");
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 2);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test")) != NULL);
+  fail_unless (gst_caps_is_empty (templ->caps));
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test2")) != NULL);
+  fail_unless (gst_caps_is_any (templ->caps));
+
+  /* Add "test" pad with ANY caps, should have "test" pad with EMPTY caps before */
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 2);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test")) != NULL);
+  fail_unless (gst_caps_is_any (templ->caps));
+
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("test4", GST_PAD_SRC, GST_PAD_ALWAYS,
+          GST_CAPS_ANY));
+
+  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
+          (element_class)), 3);
+
+  fail_unless ((templ =
+          gst_element_class_get_pad_template (element_class, "test4")) != NULL);
+  fail_unless (gst_caps_is_any (templ->caps));
+}
+
+static GType
+gst_test_element2_get_type (void)
+{
+  static GType gst_test_element2_type = G_TYPE_NONE;
+
+  if (gst_test_element2_type == G_TYPE_NONE) {
+    static const GTypeInfo gst_test_element2_info = {
+      sizeof (GstTestElement2Class),
+      NULL,                     /* base_init */
+      NULL,                     /* base_finalize */
+      (GClassInitFunc) gst_test_element2_class_init,
+      NULL,
+      NULL,
+      sizeof (GstTestElement2),
+      0,
+      NULL,                     /* instance_init */
+      NULL
+    };
+
+    gst_test_element2_type =
+        g_type_register_static (gst_test_element_get_type (), "GstTestElement2",
+        &gst_test_element2_info, 0);
+  }
+  return gst_test_element2_type;
+}
+
+
+GST_START_TEST (test_pad_templates)
+{
+  GstTestElement *test;
+  GstTestElement2 *test2;
+
+  test = g_object_new (gst_test_element_get_type (), NULL);
+  test2 = g_object_new (gst_test_element2_get_type (), NULL);
+
+  g_object_unref (test);
+  g_object_unref (test2);
+}
+
+GST_END_TEST;
 
 static Suite *
 gst_element_suite (void)
@@ -177,6 +359,7 @@ gst_element_suite (void)
   tcase_add_test (tc_chain, test_error_no_bus);
   tcase_add_test (tc_chain, test_link);
   tcase_add_test (tc_chain, test_link_no_pads);
+  tcase_add_test (tc_chain, test_pad_templates);
 
   return s;
 }
index 52add0a..2efb704 100644 (file)
@@ -53,10 +53,9 @@ setup_factory (void)
   gst_plugin_feature_set_name (feature, "test");
 
   factory = GST_ELEMENT_FACTORY_CAST (feature);
-  factory->details.longname = g_strdup ("test");
-  factory->details.klass = g_strdup ("test");
-  factory->details.description = g_strdup ("test");
-  factory->details.author = g_strdup ("test");
+#if 0
+  gst_element_class_set_metadata (factory, "test", "test", "test", "test");
+#endif
 
   setup_pad_template (factory, &sink_template);
   setup_pad_template (factory, &src_template);
@@ -87,7 +86,7 @@ GST_START_TEST (test_can_sink_any_caps)
   factory = setup_factory ();
   fail_if (factory == NULL);
 
-  caps = gst_caps_new_simple ("audio/x-raw-int", NULL);
+  caps = gst_caps_new_empty_simple ("audio/x-raw-int");
   fail_if (caps == NULL);
   res = gst_element_factory_can_sink_any_caps (factory, caps);
   fail_if (!res);
@@ -108,7 +107,7 @@ GST_START_TEST (test_can_sink_all_caps)
   factory = setup_factory ();
   fail_if (factory == NULL);
 
-  caps = gst_caps_new_simple ("audio/x-raw-int", NULL);
+  caps = gst_caps_new_empty_simple ("audio/x-raw-int");
   fail_if (caps == NULL);
   res = gst_element_factory_can_sink_all_caps (factory, caps);
   fail_if (res);
index 18b8f70..7bb9303 100644 (file)
@@ -39,12 +39,17 @@ GST_START_TEST (create_events)
   }
   /* FLUSH_STOP */
   {
-    event = gst_event_new_flush_stop ();
+    gboolean reset_time;
+
+    event = gst_event_new_flush_stop (TRUE);
     fail_if (event == NULL);
     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP);
     fail_unless (GST_EVENT_IS_UPSTREAM (event));
     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
     fail_unless (GST_EVENT_IS_SERIALIZED (event));
+
+    gst_event_parse_flush_stop (event, &reset_time);
+    fail_unless (reset_time == TRUE);
     gst_event_unref (event);
   }
   /* EOS */
@@ -57,70 +62,38 @@ GST_START_TEST (create_events)
     fail_unless (GST_EVENT_IS_SERIALIZED (event));
     gst_event_unref (event);
   }
-  /* NEWSEGMENT */
+  /* SEGMENT */
   {
-    gdouble rate, applied_rate;
-    GstFormat format;
-    gint64 start, end, base;
-    gboolean update;
-
-    event =
-        gst_event_new_new_segment (FALSE, 0.5, GST_FORMAT_TIME, 1, G_MAXINT64,
-        0xdeadbeef);
-    fail_if (event == NULL);
-    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
-    fail_if (GST_EVENT_IS_UPSTREAM (event));
-    fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
-    fail_unless (GST_EVENT_IS_SERIALIZED (event));
-
-    gst_event_parse_new_segment (event, &update, &rate, &format, &start, &end,
-        &base);
-    fail_unless (update == FALSE);
-    fail_unless (rate == 0.5);
-    fail_unless (format == GST_FORMAT_TIME);
-    fail_unless (start == 1);
-    fail_unless (end == G_MAXINT64);
-    fail_unless (base == 0xdeadbeef);
-
-    /* Check that the new segment was created with applied_rate of 1.0 */
-    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-        &format, &start, &end, &base);
+    GstSegment segment, parsed;
 
-    fail_unless (update == FALSE);
-    fail_unless (rate == 0.5);
-    fail_unless (applied_rate == 1.0);
-    fail_unless (format == GST_FORMAT_TIME);
-    fail_unless (start == 1);
-    fail_unless (end == G_MAXINT64);
-
-    gst_event_unref (event);
-
-    event =
-        gst_event_new_new_segment_full (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
-        G_MAXINT64 - 1, 0xdeadbeef);
+    gst_segment_init (&segment, GST_FORMAT_TIME);
+    segment.rate = 0.5;
+    segment.applied_rate = 1.0;
+    segment.start = 1;
+    segment.stop = G_MAXINT64;
+    segment.time = 0xdeadbeef;
 
+    event = gst_event_new_segment (&segment);
     fail_if (event == NULL);
-    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
+    fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
     fail_if (GST_EVENT_IS_UPSTREAM (event));
     fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
     fail_unless (GST_EVENT_IS_SERIALIZED (event));
 
-    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-        &format, &start, &end, &base);
-
-    fail_unless (update == TRUE);
-    fail_unless (rate == 0.75);
-    fail_unless (applied_rate == 0.5);
-    fail_unless (format == GST_FORMAT_BYTES);
-    fail_unless (start == 0);
-    fail_unless (end == (G_MAXINT64 - 1));
+    gst_event_copy_segment (event, &parsed);
+    fail_unless (parsed.rate == 0.5);
+    fail_unless (parsed.applied_rate == 1.0);
+    fail_unless (parsed.format == GST_FORMAT_TIME);
+    fail_unless (parsed.start == 1);
+    fail_unless (parsed.stop == G_MAXINT64);
+    fail_unless (parsed.time == 0xdeadbeef);
 
     gst_event_unref (event);
   }
 
   /* TAGS */
   {
-    GstTagList *taglist = gst_tag_list_new ();
+    GstTagList *taglist = gst_tag_list_new_empty ();
     GstTagList *tl2 = NULL;
 
     event = gst_event_new_tag (taglist);
@@ -143,32 +116,32 @@ GST_START_TEST (create_events)
     GstClockTimeDiff ctd1 = G_GINT64_CONSTANT (10), ctd2;
     GstClockTime ct1 = G_GUINT64_CONSTANT (20), ct2;
 
-    event = gst_event_new_qos (p1, ctd1, ct1);
+    event = gst_event_new_qos (t1, p1, ctd1, ct1);
     fail_if (event == NULL);
     fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
     fail_unless (GST_EVENT_IS_UPSTREAM (event));
     fail_if (GST_EVENT_IS_DOWNSTREAM (event));
     fail_if (GST_EVENT_IS_SERIALIZED (event));
 
-    gst_event_parse_qos (event, &p2, &ctd2, &ct2);
+    gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
     fail_unless (p1 == p2);
     fail_unless (ctd1 == ctd2);
     fail_unless (ct1 == ct2);
-    gst_event_parse_qos_full (event, &t2, &p2, &ctd2, &ct2);
-    fail_unless (t2 == GST_QOS_TYPE_UNDERFLOW);
+    gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
+    fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
     fail_unless (p1 == p2);
     fail_unless (ctd1 == ctd2);
     fail_unless (ct1 == ct2);
     gst_event_unref (event);
 
     ctd1 = G_GINT64_CONSTANT (-10);
-    event = gst_event_new_qos (p1, ctd1, ct1);
-    gst_event_parse_qos_full (event, &t2, &p2, &ctd2, &ct2);
-    fail_unless (t2 == GST_QOS_TYPE_OVERFLOW);
+    event = gst_event_new_qos (t1, p1, ctd1, ct1);
+    gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
+    fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
     gst_event_unref (event);
 
-    event = gst_event_new_qos_full (t1, p1, ctd1, ct1);
-    gst_event_parse_qos_full (event, &t2, &p2, &ctd2, &ct2);
+    event = gst_event_new_qos (t1, p1, ctd1, ct1);
+    gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
     fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
     fail_unless (p1 == p2);
     fail_unless (ctd1 == ctd2);
@@ -225,7 +198,7 @@ GST_START_TEST (create_events)
 
   /* Custom event types */
   {
-    structure = gst_structure_empty_new ("application/x-custom");
+    structure = gst_structure_new_empty ("application/x-custom");
     fail_if (structure == NULL);
     event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
     fail_if (event == NULL);
@@ -244,7 +217,7 @@ GST_START_TEST (create_events)
 
   /* Event copying */
   {
-    structure = gst_structure_empty_new ("application/x-custom");
+    structure = gst_structure_new_empty ("application/x-custom");
     fail_if (structure == NULL);
     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
 
@@ -264,7 +237,7 @@ GST_START_TEST (create_events)
 
   /* Make events writable */
   {
-    structure = gst_structure_empty_new ("application/x-custom");
+    structure = gst_structure_new_empty ("application/x-custom");
     fail_if (structure == NULL);
     event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
     /* ref the event so that it becomes non-writable */
@@ -296,14 +269,15 @@ static GTimeVal sent_event_time;
 static GstEvent *got_event_before_q, *got_event_after_q;
 static GTimeVal got_event_time;
 
-static gboolean
-event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
+static GstPadProbeReturn
+event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
+  GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info);
   gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
 
-  fail_unless (GST_IS_EVENT (data));
+  GST_DEBUG ("event probe called %p", data);
 
-  GST_DEBUG ("event probe called");
+  fail_unless (GST_IS_EVENT (data));
 
   if (before_q) {
     switch (GST_EVENT_TYPE (GST_EVENT (data))) {
@@ -336,7 +310,65 @@ event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
     }
   }
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
+}
+
+
+typedef struct
+{
+  GMutex *lock;
+  GCond *cond;
+  gboolean signaled;
+} SignalData;
+
+static void
+signal_data_init (SignalData * data)
+{
+  GST_DEBUG ("init %p", data);
+  data->lock = g_mutex_new ();
+  data->cond = g_cond_new ();
+  data->signaled = FALSE;
+}
+
+static void
+signal_data_cleanup (SignalData * data)
+{
+  GST_DEBUG ("free %p", data);
+  g_mutex_free (data->lock);
+  g_cond_free (data->cond);
+}
+
+static void
+signal_data_signal (SignalData * data)
+{
+  g_mutex_lock (data->lock);
+  data->signaled = TRUE;
+  g_cond_broadcast (data->cond);
+  GST_DEBUG ("signaling %p", data);
+  g_mutex_unlock (data->lock);
+}
+
+static void
+signal_data_wait (SignalData * data)
+{
+  g_mutex_lock (data->lock);
+  GST_DEBUG ("signal wait %p", data);
+  while (!data->signaled)
+    g_cond_wait (data->cond, data->lock);
+  GST_DEBUG ("signal wait done %p", data);
+  g_mutex_unlock (data->lock);
+}
+
+static GstPadProbeReturn
+signal_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+  SignalData *data = (SignalData *) user_data;
+
+  GST_DEBUG ("signal called %p", data);
+  signal_data_signal (data);
+  GST_DEBUG ("signal done %p", data);
+
+  return GST_PAD_PROBE_OK;
 }
 
 static void test_event
@@ -346,6 +378,8 @@ static void test_event
   GstEvent *event;
   GstPad *peer;
   gint i;
+  SignalData data;
+  gulong id;
 
   got_event_before_q = got_event_after_q = NULL;
 
@@ -356,20 +390,27 @@ static void test_event
   GST_DEBUG ("test event called");
 
   event = gst_event_new_custom (type,
-      gst_structure_empty_new ("application/x-custom"));
+      gst_structure_new_empty ("application/x-custom"));
   g_get_current_time (&sent_event_time);
   got_event_time.tv_sec = 0;
   got_event_time.tv_usec = 0;
 
+  signal_data_init (&data);
+
   /* We block the pad so the stream lock is released and we can send the event */
-  fail_unless (gst_pad_set_blocked (fake_srcpad, TRUE) == TRUE);
+  id = gst_pad_add_probe (fake_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+      signal_blocked, &data, NULL);
+  fail_unless (id != 0);
+
+  signal_data_wait (&data);
 
   /* We send on the peer pad, since the pad is blocked */
+  GST_DEBUG ("sending event %p", event);
   fail_unless ((peer = gst_pad_get_peer (pad)) != NULL);
   gst_pad_send_event (peer, event);
   gst_object_unref (peer);
 
-  fail_unless (gst_pad_set_blocked (fake_srcpad, FALSE) == TRUE);
+  gst_pad_remove_probe (fake_srcpad, id);
 
   if (expect_before_q) {
     /* Wait up to 5 seconds for the event to appear */
@@ -404,6 +445,8 @@ static void test_event
     gst_event_unref (got_event_after_q);
 
   got_event_before_q = got_event_after_q = NULL;
+
+  signal_data_cleanup (&data);
 }
 
 static gint64
@@ -440,12 +483,12 @@ GST_START_TEST (send_custom_events)
 
   /* add pad-probes to faksrc.src and fakesink.sink */
   fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL);
-  gst_pad_add_event_probe (srcpad, (GCallback) event_probe,
-      GINT_TO_POINTER (TRUE));
+  gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      event_probe, GINT_TO_POINTER (TRUE), NULL);
 
   fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL);
-  gst_pad_add_event_probe (sinkpad, (GCallback) event_probe,
-      GINT_TO_POINTER (FALSE));
+  gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      event_probe, GINT_TO_POINTER (FALSE), NULL);
 
   /* Upstream events */
   test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
@@ -497,6 +540,8 @@ GST_START_TEST (send_custom_events)
   gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
       GST_CLOCK_TIME_NONE);
 
+  gst_object_unref (sinkpad);
+  gst_object_unref (srcpad);
   gst_object_unref (pipeline);
 }
 
index 8ba15d6..01fcb84 100644 (file)
@@ -190,7 +190,7 @@ GST_START_TEST (test_ghost_pads_notarget)
 
   /* check caps, untargetted pad should return ANY or the padtemplate caps 
    * when it was created from a template */
-  caps = gst_pad_get_caps (srcpad);
+  caps = gst_pad_query_caps (srcpad, NULL);
   fail_unless (gst_caps_is_any (caps));
   gst_caps_unref (caps);
 
@@ -240,6 +240,7 @@ GST_START_TEST (test_remove_target)
   fail_unless (target == NULL);
 
   gst_object_unref (b1);
+  gst_object_unref (ghost);
 }
 
 GST_END_TEST;
@@ -477,8 +478,8 @@ typedef struct
   GCond *cond;
 } BlockData;
 
-static void
-block_callback (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+block_callback (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
   BlockData *block_data = (BlockData *) user_data;
 
@@ -486,6 +487,8 @@ block_callback (GstPad * pad, gboolean blocked, gpointer user_data)
   GST_DEBUG ("blocked\n");
   g_cond_signal (block_data->cond);
   g_mutex_unlock (block_data->mutex);
+
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_ghost_pads_block)
@@ -513,7 +516,8 @@ GST_START_TEST (test_ghost_pads_block)
   block_data.cond = g_cond_new ();
 
   g_mutex_lock (block_data.mutex);
-  gst_pad_set_blocked_async (srcghost, TRUE, block_callback, &block_data);
+  gst_pad_add_probe (srcghost, GST_PAD_PROBE_TYPE_BLOCK, block_callback,
+      &block_data, NULL);
   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
   /* and wait now */
   g_cond_wait (block_data.cond, block_data.mutex);
@@ -554,7 +558,8 @@ GST_START_TEST (test_ghost_pads_probes)
   block_data.cond = g_cond_new ();
 
   g_mutex_lock (block_data.mutex);
-  gst_pad_set_blocked_async (srcghost, TRUE, block_callback, &block_data);
+  gst_pad_add_probe (srcghost, GST_PAD_PROBE_TYPE_BLOCK, block_callback,
+      &block_data, NULL);
   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
   /* and wait now */
   g_cond_wait (block_data.cond, block_data.mutex);
@@ -575,16 +580,14 @@ GST_START_TEST (test_ghost_pads_new_from_template)
   GstPad *sinkpad, *ghostpad;
   GstPadTemplate *padtempl, *ghosttempl;
   GstCaps *padcaps, *ghostcaps, *newcaps;
-  GstCaps *copypadcaps;
 
   padcaps = gst_caps_from_string ("some/caps");
   fail_unless (padcaps != NULL);
   ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
   fail_unless (ghostcaps != NULL);
 
-  copypadcaps = gst_caps_copy (padcaps);
   padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, copypadcaps);
+      GST_PAD_ALWAYS, padcaps);
   fail_unless (padtempl != NULL);
   ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
       GST_PAD_ALWAYS, ghostcaps);
@@ -599,11 +602,12 @@ GST_START_TEST (test_ghost_pads_new_from_template)
   fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
 
   /* check ghostpad caps are from the sinkpad */
-  newcaps = gst_pad_get_caps (ghostpad);
+  newcaps = gst_pad_query_caps (ghostpad, NULL);
   fail_unless (newcaps != NULL);
   fail_unless (gst_caps_is_equal (newcaps, padcaps));
   gst_caps_unref (newcaps);
   gst_caps_unref (padcaps);
+  gst_caps_unref (ghostcaps);
 
   gst_object_unref (sinkpad);
   gst_object_unref (ghostpad);
@@ -619,21 +623,17 @@ GST_START_TEST (test_ghost_pads_new_no_target_from_template)
   GstPad *sinkpad, *ghostpad;
   GstPadTemplate *padtempl, *ghosttempl;
   GstCaps *padcaps, *ghostcaps, *newcaps;
-  GstCaps *copypadcaps, *copyghostcaps;
 
   padcaps = gst_caps_from_string ("some/caps");
   fail_unless (padcaps != NULL);
   ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
   fail_unless (ghostcaps != NULL);
 
-  copypadcaps = gst_caps_copy (padcaps);
-  copyghostcaps = gst_caps_copy (ghostcaps);
-
   padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, copypadcaps);
+      GST_PAD_ALWAYS, padcaps);
   fail_unless (padtempl != NULL);
   ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
-      GST_PAD_ALWAYS, copyghostcaps);
+      GST_PAD_ALWAYS, ghostcaps);
 
   sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
   fail_unless (sinkpad != NULL);
@@ -645,7 +645,7 @@ GST_START_TEST (test_ghost_pads_new_no_target_from_template)
   fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
 
   /* check ghostpad caps are from the ghostpad template */
-  newcaps = gst_pad_get_caps (ghostpad);
+  newcaps = gst_pad_query_caps (ghostpad, NULL);
   fail_unless (newcaps != NULL);
   fail_unless (gst_caps_is_equal (newcaps, ghostcaps));
   gst_caps_unref (newcaps);
@@ -653,7 +653,7 @@ GST_START_TEST (test_ghost_pads_new_no_target_from_template)
   fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
 
   /* check ghostpad caps are now from the target pad */
-  newcaps = gst_pad_get_caps (ghostpad);
+  newcaps = gst_pad_query_caps (ghostpad, NULL);
   fail_unless (newcaps != NULL);
   fail_unless (gst_caps_is_equal (newcaps, padcaps));
   gst_caps_unref (newcaps);
@@ -687,10 +687,12 @@ GST_START_TEST (test_ghost_pads_forward_setcaps)
   templ_caps = gst_caps_from_string ("meh; muh");
   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
       GST_PAD_ALWAYS, templ_caps);
+  gst_caps_unref (templ_caps);
 
   templ_caps = gst_caps_from_string ("muh; meh");
   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
       GST_PAD_ALWAYS, templ_caps);
+  gst_caps_unref (templ_caps);
 
   src = gst_pad_new_from_template (src_template, "src");
   sink = gst_pad_new_from_template (sink_template, "sink");
@@ -702,16 +704,19 @@ GST_START_TEST (test_ghost_pads_forward_setcaps)
       G_CALLBACK (ghost_notify_caps), &notify_counter);
   fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
 
+  /* Activate pads for caps forwarding/setting to work */
+  gst_pad_set_active (src, TRUE);
+  gst_pad_set_active (ghost, TRUE);
+
   caps1 = gst_caps_from_string ("meh");
   fail_unless (gst_pad_set_caps (src, caps1));
-  caps2 = GST_PAD_CAPS (ghost);
+  caps2 = gst_pad_get_current_caps (ghost);
   fail_unless (gst_caps_is_equal (caps1, caps2));
   fail_unless_equals_int (notify_counter, 1);
 
   gst_object_unref (ghost);
   gst_caps_unref (caps1);
-
-  fail_unless (gst_pad_set_caps (src, NULL));
+  gst_caps_unref (caps2);
 
   /* source 2, setting the caps on the ghostpad does not influence the caps of
    * the target */
@@ -721,10 +726,15 @@ GST_START_TEST (test_ghost_pads_forward_setcaps)
       G_CALLBACK (ghost_notify_caps), &notify_counter);
   fail_unless (gst_pad_link (ghost, sink) == GST_PAD_LINK_OK);
 
+  gst_pad_set_active (ghost, TRUE);
+  gst_pad_set_active (sink, TRUE);
+
   caps1 = gst_caps_from_string ("meh");
   fail_unless (gst_pad_set_caps (ghost, caps1));
-  caps2 = GST_PAD_CAPS (src);
+#if 0
+  caps2 = gst_pad_get_current_caps (src);
   fail_unless (caps2 == NULL);
+#endif
   fail_unless_equals_int (notify_counter, 1);
 
   gst_object_unref (ghost);
@@ -739,26 +749,39 @@ GST_START_TEST (test_ghost_pads_forward_setcaps)
       G_CALLBACK (ghost_notify_caps), &notify_counter);
   fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
 
+  gst_pad_set_active (src, TRUE);
+  gst_pad_set_active (ghost, TRUE);
+
   caps1 = gst_caps_from_string ("muh");
   fail_unless (gst_pad_set_caps (ghost, caps1));
-  caps2 = GST_PAD_CAPS (sink);
+  caps2 = gst_pad_get_current_caps (sink);
   fail_unless (gst_caps_is_equal (caps1, caps2));
   fail_unless_equals_int (notify_counter, 1);
 
   gst_object_unref (ghost);
   gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+
+  /* clear caps on pads */
+  gst_pad_set_active (src, FALSE);
+  gst_pad_set_active (src, TRUE);
+  gst_pad_set_active (sink, FALSE);
+  gst_pad_set_active (sink, TRUE);
 
   /* sink pad 2, setting caps just on the target pad should not influence the caps
    * on the ghostpad. */
   notify_counter = 0;
   ghost = gst_ghost_pad_new ("ghostsink", sink);
+  fail_unless (gst_pad_get_current_caps (ghost) == NULL);
   g_signal_connect (ghost, "notify::caps",
       G_CALLBACK (ghost_notify_caps), &notify_counter);
   fail_unless (gst_pad_link (src, ghost) == GST_PAD_LINK_OK);
 
+  gst_pad_set_active (ghost, TRUE);
+
   caps1 = gst_caps_from_string ("muh");
   fail_unless (gst_pad_set_caps (sink, caps1));
-  caps2 = GST_PAD_CAPS (ghost);
+  caps2 = gst_pad_get_current_caps (ghost);
   fail_unless (caps2 == NULL);
   fail_unless_equals_int (notify_counter, 0);
 
@@ -818,11 +841,13 @@ GST_START_TEST (test_ghost_pads_sink_link_unlink)
   fail_unless (padcaps != NULL);
   srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
       GST_PAD_ALWAYS, padcaps);
+  gst_caps_unref (padcaps);
 
   padcaps = gst_caps_from_string ("some/caps");
   fail_unless (padcaps != NULL);
   sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
       GST_PAD_ALWAYS, padcaps);
+  gst_caps_unref (padcaps);
 
   srcpad = gst_pad_new_from_template (srctempl, "src");
   fail_unless (srcpad != NULL);
@@ -890,11 +915,13 @@ GST_START_TEST (test_ghost_pads_src_link_unlink)
   fail_unless (padcaps != NULL);
   srctempl = gst_pad_template_new ("srctempl", GST_PAD_SRC,
       GST_PAD_ALWAYS, padcaps);
+  gst_caps_unref (padcaps);
 
   padcaps = gst_caps_from_string ("some/caps");
   fail_unless (padcaps != NULL);
   sinktempl = gst_pad_template_new ("sinktempl", GST_PAD_SINK,
       GST_PAD_ALWAYS, padcaps);
+  gst_caps_unref (padcaps);
 
   srcpad = gst_pad_new_from_template (srctempl, "src");
   fail_unless (srcpad != NULL);
index a29a433..e7757d8 100644 (file)
@@ -127,10 +127,13 @@ GST_START_TEST (info_segment_format_printf_extension)
 
     gst_segment_init (&segment, GST_FORMAT_TIME);
 
-    gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
-        GST_FORMAT_TIME, 0, 5 * 60 * GST_SECOND, 0);
+    segment.rate = 1.0;
+    segment.applied_rate = 2.0;
+    segment.start = 0;
+    segment.stop = 5 * 60 * GST_SECOND;
+    segment.time = 0;
 
-    segment.last_stop = 2 * GST_SECOND;
+    segment.position = 2 * GST_SECOND;
     segment.duration = 90 * 60 * GST_SECOND;
 
     GST_LOG ("TIME: %" GST_SEGMENT_FORMAT, &segment);
@@ -142,8 +145,11 @@ GST_START_TEST (info_segment_format_printf_extension)
 
     gst_segment_init (&segment, GST_FORMAT_BYTES);
 
-    gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
-        GST_FORMAT_BYTES, 0, 9999999, 0);
+    segment.rate = 1.0;
+    segment.applied_rate = 1.0;
+    segment.start = 0;
+    segment.stop = 9999999;
+    segment.time = 0;
 
     GST_LOG ("BYTE: %" GST_SEGMENT_FORMAT, &segment);
   }
@@ -154,8 +160,11 @@ GST_START_TEST (info_segment_format_printf_extension)
 
     gst_segment_init (&segment, 98765432);
 
-    gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
-        GST_FORMAT_BYTES, 0, 987654321, 0);
+    segment.rate = 1.0;
+    segment.applied_rate = 1.0;
+    segment.start = 0;
+    segment.stop = 987654321;
+    segment.time = 0;
 
     GST_LOG ("UNKNOWN: %" GST_SEGMENT_FORMAT, &segment);
   }
diff --git a/tests/check/gst/gstinterface.c b/tests/check/gst/gstinterface.c
deleted file mode 100644 (file)
index 4697a1f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* GStreamer GstImplementsInterface check
- * Copyright (C) 2008 Tim-Philipp Müller <tim centricular net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#include <gst/check/gstcheck.h>
-
-GST_START_TEST (test_without_implements_interface)
-{
-  GstElement *element;
-
-  /* we shouldn't crash if someone tries to use
-   * gst_element_implements_interface() on an element which doesn't implement
-   * the GstImplementsInterface (neither if the element does implement the
-   * requested interface, nor if it doesn't) */
-  element = gst_element_factory_make ("filesrc", "filesrc");
-  fail_unless (element != NULL, "Could not create filesrc element");
-
-  /* does not implement GstImplementsInterface, but does implement the
-   * GstUriHandler interface, so should just return TRUE */
-  fail_if (!gst_element_implements_interface (element, GST_TYPE_URI_HANDLER));
-  fail_if (gst_element_implements_interface (element,
-          GST_TYPE_IMPLEMENTS_INTERFACE));
-  gst_object_unref (element);
-
-  element = gst_element_factory_make ("identity", "identity");
-  fail_unless (element != NULL, "Could not create identity element");
-  fail_if (gst_element_implements_interface (element, GST_TYPE_URI_HANDLER));
-  fail_if (gst_element_implements_interface (element,
-          GST_TYPE_IMPLEMENTS_INTERFACE));
-  gst_object_unref (element);
-}
-
-GST_END_TEST;
-
-static Suite *
-gst_interface_suite (void)
-{
-  Suite *s = suite_create ("GstImplementsInterface");
-  TCase *tc_chain = tcase_create ("correctness");
-
-  suite_add_tcase (s, tc_chain);
-  tcase_add_test (tc_chain, test_without_implements_interface);
-  return s;
-}
-
-GST_CHECK_MAIN (gst_interface);
index 8a2b464..3263d89 100644 (file)
@@ -44,13 +44,13 @@ GST_START_TEST (test_manual_iteration)
   GMutex *m;
   GstIterator *iter;
   GstIteratorResult res;
-  gpointer item;
+  GValue item = { 0, };
   gint i = 0;
 
   l = make_list_of_ints (NUM_ELEMENTS);
   m = g_mutex_new ();
 
-  iter = gst_iterator_new_list (G_TYPE_INT, m, &cookie, &l, NULL, NULL, NULL);
+  iter = gst_iterator_new_list (G_TYPE_POINTER, m, &cookie, &l, NULL, NULL);
 
   fail_unless (iter != NULL);
 
@@ -58,7 +58,8 @@ GST_START_TEST (test_manual_iteration)
     res = gst_iterator_next (iter, &item);
     if (i < NUM_ELEMENTS) {
       fail_unless (res == GST_ITERATOR_OK);
-      fail_unless (GPOINTER_TO_INT (item) == i);
+      fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == i);
+      g_value_reset (&item);
       i++;
       continue;
     } else {
@@ -66,8 +67,8 @@ GST_START_TEST (test_manual_iteration)
       break;
     }
   }
-
   /* clean up */
+  g_value_unset (&item);
   gst_iterator_free (iter);
   g_mutex_free (m);
   g_list_free (l);
@@ -82,14 +83,14 @@ GST_START_TEST (test_resync)
   GMutex *m;
   GstIterator *iter;
   GstIteratorResult res;
-  gpointer item;
+  GValue item = { 0, };
   gint i = 0;
   gboolean hacked_list = FALSE;
 
   l = make_list_of_ints (NUM_ELEMENTS);
   m = g_mutex_new ();
 
-  iter = gst_iterator_new_list (G_TYPE_INT, m, &cookie, &l, NULL, NULL, NULL);
+  iter = gst_iterator_new_list (G_TYPE_POINTER, m, &cookie, &l, NULL, NULL);
 
   fail_unless (iter != NULL);
 
@@ -97,12 +98,14 @@ GST_START_TEST (test_resync)
     res = gst_iterator_next (iter, &item);
     if (i < NUM_ELEMENTS / 2) {
       fail_unless (res == GST_ITERATOR_OK);
-      fail_unless (GPOINTER_TO_INT (item) == i);
+      fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == i);
+      g_value_reset (&item);
       i++;
       continue;
     } else if (!hacked_list) {
       /* here's where we test resync */
       fail_unless (res == GST_ITERATOR_OK);
+      g_value_reset (&item);
       l = g_list_prepend (l, GINT_TO_POINTER (-1));
       cookie++;
       hacked_list = TRUE;
@@ -112,12 +115,14 @@ GST_START_TEST (test_resync)
       gst_iterator_resync (iter);
       res = gst_iterator_next (iter, &item);
       fail_unless (res == GST_ITERATOR_OK);
-      fail_unless (GPOINTER_TO_INT (item) == -1);
+      fail_unless (GPOINTER_TO_INT (g_value_get_pointer (&item)) == -1);
+      g_value_reset (&item);
       break;
     }
   }
 
   /* clean up */
+  g_value_unset (&item);
   gst_iterator_free (iter);
   g_mutex_free (m);
   g_list_free (l);
@@ -126,9 +131,10 @@ GST_START_TEST (test_resync)
 GST_END_TEST;
 
 static gboolean
-add_fold_func (gpointer item, GValue * ret, gpointer user_data)
+add_fold_func (const GValue * item, GValue * ret, gpointer user_data)
 {
-  g_value_set_int (ret, g_value_get_int (ret) + GPOINTER_TO_INT (item));
+  g_value_set_int (ret,
+      g_value_get_int (ret) + GPOINTER_TO_INT (g_value_get_pointer (item)));
   return TRUE;
 }
 
@@ -144,7 +150,7 @@ GST_START_TEST (test_fold)
 
   l = make_list_of_ints (NUM_ELEMENTS);
   m = g_mutex_new ();
-  iter = gst_iterator_new_list (G_TYPE_INT, m, &cookie, &l, NULL, NULL, NULL);
+  iter = gst_iterator_new_list (G_TYPE_POINTER, m, &cookie, &l, NULL, NULL);
   fail_unless (iter != NULL);
 
   expected = 0;
@@ -170,28 +176,34 @@ GST_END_TEST;
 GST_START_TEST (test_single)
 {
   GstIterator *it;
-  GstStructure *s = gst_structure_new ("test", NULL);
+  GstStructure *s = gst_structure_new_empty ("test");
+  GValue v = { 0, };
   GstStructure *i;
 
-  it = gst_iterator_new_single (GST_TYPE_STRUCTURE, s,
-      (GstCopyFunction) gst_structure_copy, (GFreeFunc) gst_structure_free);
+  g_value_init (&v, GST_TYPE_STRUCTURE);
+  g_value_set_boxed (&v, s);
+  it = gst_iterator_new_single (GST_TYPE_STRUCTURE, &v);
+  g_value_reset (&v);
 
-  fail_unless (gst_iterator_next (it, (gpointer) & i) == GST_ITERATOR_OK);
+  fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_OK);
+  i = g_value_get_boxed (&v);
   fail_unless (strcmp (gst_structure_get_name (s),
           gst_structure_get_name (i)) == 0);
-  gst_structure_free (i);
   i = NULL;
-  fail_unless (gst_iterator_next (it, (gpointer) & i) == GST_ITERATOR_DONE);
-  fail_unless (i == NULL);
+  g_value_reset (&v);
+
+  fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_DONE);
+  fail_unless (g_value_get_boxed (&v) == NULL);
 
   gst_iterator_free (it);
   gst_structure_free (s);
 
-  it = gst_iterator_new_single (GST_TYPE_STRUCTURE, NULL,
-      (GstCopyFunction) gst_structure_copy, (GFreeFunc) gst_structure_free);
+  it = gst_iterator_new_single (GST_TYPE_STRUCTURE, NULL);
+
+  fail_unless (gst_iterator_next (it, &v) == GST_ITERATOR_DONE);
+  fail_unless (g_value_get_boxed (&v) == NULL);
 
-  fail_unless (gst_iterator_next (it, (gpointer) & i) == GST_ITERATOR_DONE);
-  fail_unless (i == NULL);
+  g_value_reset (&v);
 
   gst_iterator_free (it);
 }
diff --git a/tests/check/gst/gstmemory.c b/tests/check/gst/gstmemory.c
new file mode 100644 (file)
index 0000000..5439c89
--- /dev/null
@@ -0,0 +1,531 @@
+/* GStreamer
+ *
+ * unit test for GstMemory
+ *
+ * Copyright (C) <2012> Wim Taymans <wim.taymans at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_VALGRIND_H
+# include <valgrind/valgrind.h>
+#else
+# define RUNNING_ON_VALGRIND FALSE
+#endif
+
+#include <gst/check/gstcheck.h>
+
+GST_START_TEST (test_submemory)
+{
+  GstMemory *memory, *sub;
+  gsize size, maxsize, ssize;
+  guint8 *data, *sdata;
+
+  memory = gst_allocator_alloc (NULL, 4, 0);
+
+  /* check sizes, memory starts out empty */
+  data = gst_memory_map (memory, &size, &maxsize, GST_MAP_WRITE);
+  fail_unless (size == 4, "memory has wrong size");
+  fail_unless (maxsize >= 4, "memory has wrong size");
+  memset (data, 0, 4);
+  gst_memory_unmap (memory);
+
+  data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
+
+  sub = gst_memory_share (memory, 1, 2);
+  fail_if (sub == NULL, "share of memory returned NULL");
+
+  sdata = gst_memory_map (sub, &ssize, NULL, GST_MAP_READ);
+  fail_unless (ssize == 2, "submemory has wrong size");
+  fail_unless (memcmp (data + 1, sdata, 2) == 0,
+      "submemory contains the wrong data");
+  ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
+  gst_memory_unmap (sub);
+  gst_memory_unref (sub);
+
+  /* create a submemory of size 0 */
+  sub = gst_memory_share (memory, 1, 0);
+  fail_if (sub == NULL, "share memory returned NULL");
+  sdata = gst_memory_map (sub, &ssize, NULL, GST_MAP_READ);
+  fail_unless (ssize == 0, "submemory has wrong size");
+  fail_unless (memcmp (data + 1, sdata, 0) == 0,
+      "submemory contains the wrong data");
+  ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
+  gst_memory_unmap (sub);
+  gst_memory_unref (sub);
+
+  /* test if metadata is coppied, not a complete memory copy so only the
+   * timestamp and offset fields are copied. */
+  sub = gst_memory_share (memory, 0, 1);
+  fail_if (sub == NULL, "share of memory returned NULL");
+  fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 1,
+      "submemory has wrong size");
+  gst_memory_unref (sub);
+
+  /* test if metadata is coppied, a complete memory is copied so all the timing
+   * fields should be copied. */
+  sub = gst_memory_share (memory, 0, 4);
+  fail_if (sub == NULL, "share of memory returned NULL");
+  fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 4,
+      "submemory has wrong size");
+
+  /* clean up */
+  gst_memory_unref (sub);
+
+  gst_memory_unmap (memory);
+  gst_memory_unref (memory);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_is_span)
+{
+  GstMemory *memory, *sub1, *sub2;
+
+  memory = gst_allocator_alloc (NULL, 4, 0);
+
+  sub1 = gst_memory_share (memory, 0, 2);
+  fail_if (sub1 == NULL, "share of memory returned NULL");
+
+  sub2 = gst_memory_share (memory, 2, 2);
+  fail_if (sub2 == NULL, "share of memory returned NULL");
+
+  fail_if (gst_memory_is_span (memory, sub2, NULL) == TRUE,
+      "a parent memory can't be span");
+
+  fail_if (gst_memory_is_span (sub1, memory, NULL) == TRUE,
+      "a parent memory can't be span");
+
+  fail_if (gst_memory_is_span (sub1, sub2, NULL) == FALSE,
+      "two submemorys next to each other should be span");
+
+  /* clean up */
+  gst_memory_unref (sub1);
+  gst_memory_unref (sub2);
+  gst_memory_unref (memory);
+}
+
+GST_END_TEST;
+
+static const char ro_memory[] = "abcdefghijklmnopqrstuvwxyz";
+
+static GstMemory *
+create_read_only_memory (void)
+{
+  GstMemory *mem;
+
+  /* assign some read-only data to the new memory */
+  mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+      (gpointer) ro_memory, NULL, sizeof (ro_memory), 0, sizeof (ro_memory));
+  fail_if (gst_memory_is_writable (mem));
+
+  return mem;
+}
+
+GST_START_TEST (test_writable)
+{
+  GstMemory *mem, *mem2;
+  guint8 *data;
+  gsize size;
+
+  /* create read-only memory and try to write */
+  mem = create_read_only_memory ();
+
+  ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
+  fail_if (gst_memory_is_writable (mem));
+
+  mem2 = gst_memory_copy (mem, 0, -1);
+  fail_if (gst_memory_is_writable (mem));
+  fail_unless (gst_memory_is_writable (mem2));
+
+  data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
+  data[4] = 'a';
+  gst_memory_unmap (mem2);
+
+  gst_memory_ref (mem2);
+  ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
+  gst_memory_unref (mem2);
+
+  data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
+  data[4] = 'a';
+  gst_memory_unmap (mem2);
+  gst_memory_unref (mem2);
+
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_submemory_writable)
+{
+  GstMemory *mem, *sub_mem;
+  gsize size;
+
+  /* create sub-memory of read-only memory and try to write */
+  mem = create_read_only_memory ();
+
+  sub_mem = gst_memory_share (mem, 0, 8);
+  fail_if (gst_memory_is_writable (sub_mem));
+
+  ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
+  ASSERT_CRITICAL (gst_memory_map (sub_mem, &size, NULL, GST_MAP_WRITE));
+
+  gst_memory_unref (sub_mem);
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_copy)
+{
+  GstMemory *memory, *copy;
+  gsize size, ssize;
+
+  memory = gst_allocator_alloc (NULL, 4, 0);
+  ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
+
+  copy = gst_memory_copy (memory, 0, -1);
+  ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
+  ASSERT_MEMORY_REFCOUNT (copy, "copy", 1);
+  /* memorys are copied and must point to different memory */
+  fail_if (memory == copy);
+
+  gst_memory_map (memory, &size, NULL, GST_MAP_READ);
+  gst_memory_map (copy, &ssize, NULL, GST_MAP_READ);
+
+  /* NOTE that data is refcounted */
+  fail_unless (size == ssize);
+
+  gst_memory_unmap (copy);
+  gst_memory_unmap (memory);
+
+  gst_memory_unref (copy);
+  gst_memory_unref (memory);
+
+  memory = gst_allocator_alloc (NULL, 0, 0);
+  gst_memory_map (memory, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 0);
+  gst_memory_unmap (memory);
+
+  /* copying a 0-sized memory should not crash */
+  copy = gst_memory_copy (memory, 0, -1);
+  gst_memory_map (copy, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 0);
+  gst_memory_unmap (copy);
+
+  gst_memory_unref (copy);
+  gst_memory_unref (memory);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_try_new_and_alloc)
+{
+  GstMemory *mem;
+  gsize size;
+  guint8 *data;
+
+  mem = gst_allocator_alloc (NULL, 0, 0);
+  fail_unless (mem != NULL);
+  data = gst_memory_map (mem, &size, NULL, GST_MAP_READ);
+  fail_unless (size == 0);
+  gst_memory_unmap (mem);
+  gst_memory_unref (mem);
+
+  /* normal alloc should still work */
+  mem = gst_allocator_alloc (NULL, 640 * 480 * 4, 0);
+  fail_unless (mem != NULL);
+  data = gst_memory_map (mem, &size, NULL, GST_MAP_WRITE);
+  fail_unless (data != NULL);
+  fail_unless (size == (640 * 480 * 4));
+  data[640 * 479 * 4 + 479] = 0xff;
+  gst_memory_unmap (mem);
+
+  gst_memory_unref (mem);
+
+#if 0
+  /* Disabled this part of the test, because it happily succeeds on 64-bit
+   * machines that have enough memory+swap, because the address space is large
+   * enough. There's not really any way to test the failure case except by
+   * allocating chunks of memory until it fails, which would suck. */
+
+  /* now this better fail (don't run in valgrind, it will abort
+   * or warn when passing silly arguments to malloc) */
+  if (!RUNNING_ON_VALGRIND) {
+    mem = gst_allocator_alloc (NULL, (guint) - 1, 0);
+    fail_unless (mem == NULL);
+  }
+#endif
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_resize)
+{
+  GstMemory *mem;
+  gsize maxalloc;
+  gsize size, maxsize, offset;
+
+  /* one memory block */
+  mem = gst_allocator_alloc (NULL, 100, 0);
+
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc >= 100);
+
+  ASSERT_CRITICAL (gst_memory_resize (mem, 200, 50));
+  ASSERT_CRITICAL (gst_memory_resize (mem, 0, 150));
+  ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc));
+  ASSERT_CRITICAL (gst_memory_resize (mem, maxalloc, 1));
+
+  /* this does nothing */
+  gst_memory_resize (mem, 0, 100);
+
+  /* nothing should have changed */
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 0, 50);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 50);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 0, 100);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 1, 99);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxsize == maxalloc);
+
+  ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc - 1));
+
+  gst_memory_resize (mem, 0, 99);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, -1, 100);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  /* can't set offset below 0 */
+  ASSERT_CRITICAL (gst_memory_resize (mem, -1, 100));
+
+  gst_memory_resize (mem, 50, 40);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 40);
+  fail_unless (offset == 50);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, -50, 100);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 0, 0);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 0);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 0, 100);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_resize (mem, 0, 100);
+  size = gst_memory_get_sizes (mem, &offset, &maxsize);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_map)
+{
+  GstMemory *mem;
+  gsize maxalloc;
+  gsize size, maxsize, offset;
+  gpointer data;
+
+  /* one memory block */
+  mem = gst_allocator_alloc (NULL, 100, 0);
+
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc >= 100);
+
+  /* see if simply mapping works */
+  data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
+  fail_unless (data != NULL);
+  fail_unless (size == 100);
+  fail_unless (maxsize == maxalloc);
+
+  gst_memory_unmap (mem);
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_map_nested)
+{
+  GstMemory *mem;
+  gsize size1, maxsize1, size2, maxsize2;
+  gpointer data1, data2;
+
+  mem = gst_allocator_alloc (NULL, 100, 0);
+
+  /* nested mapping */
+  data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
+  fail_unless (data1 != NULL);
+  fail_unless (size1 == 100);
+
+  data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
+  fail_unless (data2 == data1);
+  fail_unless (size2 == 100);
+
+  /* unmap */
+  gst_memory_unmap (mem);
+  gst_memory_unmap (mem);
+
+  data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
+  /* not allowed */
+  ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE));
+  ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
+  data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
+  gst_memory_unmap (mem);
+  gst_memory_unmap (mem);
+  fail_unless (mem->state == 0);
+
+  data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_WRITE);
+  /* not allowed */
+  ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ));
+  ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
+  data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
+  gst_memory_unmap (mem);
+  gst_memory_unmap (mem);
+  /* nothing was mapped */
+  ASSERT_CRITICAL (gst_memory_unmap (mem));
+
+  data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READWRITE);
+  data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
+  gst_memory_unmap (mem);
+  data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
+  gst_memory_unmap (mem);
+  gst_memory_unmap (mem);
+  /* nothing was mapped */
+  ASSERT_CRITICAL (gst_memory_unmap (mem));
+
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_map_resize)
+{
+  GstMemory *mem;
+  gsize size, maxsize, maxalloc, offset;
+  gpointer data;
+
+  mem = gst_allocator_alloc (NULL, 100, 0);
+
+  /* do mapping */
+  data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
+  fail_unless (data != NULL);
+  fail_unless (size == 100);
+
+  /* resize the buffer */
+  gst_memory_resize (mem, 1, size - 1);
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxalloc >= 100);
+  gst_memory_unmap (mem);
+
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxalloc >= 100);
+
+  data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
+  fail_unless (data != NULL);
+  fail_unless (size == 99);
+  fail_unless (offset == 1);
+  fail_unless (maxsize >= 100);
+  gst_memory_unmap (mem);
+
+  /* and larger */
+  data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
+  gst_memory_resize (mem, -1, 100);
+  gst_memory_unmap (mem);
+
+  size = gst_memory_get_sizes (mem, &offset, &maxalloc);
+  fail_unless (size == 100);
+  fail_unless (offset == 0);
+  fail_unless (maxalloc >= 100);
+
+  data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
+  gst_memory_unmap (mem);
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+gst_memory_suite (void)
+{
+  Suite *s = suite_create ("GstMemory");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+  tcase_add_test (tc_chain, test_submemory);
+  tcase_add_test (tc_chain, test_submemory_writable);
+  tcase_add_test (tc_chain, test_writable);
+  tcase_add_test (tc_chain, test_is_span);
+  tcase_add_test (tc_chain, test_copy);
+  tcase_add_test (tc_chain, test_try_new_and_alloc);
+  tcase_add_test (tc_chain, test_resize);
+  tcase_add_test (tc_chain, test_map);
+  tcase_add_test (tc_chain, test_map_nested);
+  tcase_add_test (tc_chain, test_map_resize);
+
+  return s;
+}
+
+GST_CHECK_MAIN (gst_memory);
index 423226a..91f4e38 100644 (file)
@@ -102,7 +102,7 @@ GST_START_TEST (test_parsing)
     GstTagList *tag;
 
     /* FIXME, do some more tag adding */
-    tag = gst_tag_list_new ();
+    tag = gst_tag_list_new_empty ();
     fail_if (tag == NULL);
     message = gst_message_new_tag (NULL, tag);
     fail_if (message == NULL);
@@ -208,7 +208,7 @@ GST_START_TEST (test_parsing)
 
     /* create a task with some dummy function, we're not actually going to run
      * the task here */
-    task = gst_task_create ((GstTaskFunction) gst_object_unref, NULL);
+    task = gst_task_new ((GstTaskFunction) gst_object_unref, NULL);
 
     ASSERT_OBJECT_REFCOUNT (task, "task", 1);
 
diff --git a/tests/check/gst/gstmeta.c b/tests/check/gst/gstmeta.c
new file mode 100644 (file)
index 0000000..69eb370
--- /dev/null
@@ -0,0 +1,200 @@
+/* GStreamer
+ *
+ * unit test for GstMeta
+ *
+ * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_VALGRIND_H
+# include <valgrind/valgrind.h>
+#else
+# define RUNNING_ON_VALGRIND FALSE
+#endif
+
+#include <gst/check/gstcheck.h>
+
+/* test metadata for PTS/DTS and duration */
+typedef struct
+{
+  GstMeta meta;
+
+  GstClockTime pts;
+  GstClockTime dts;
+  GstClockTime duration;
+  GstClockTime clock_rate;
+} GstMetaTest;
+
+static const GstMetaInfo *gst_meta_test_get_info (void);
+#define GST_META_TEST_INFO (gst_meta_test_get_info())
+
+#define GST_META_TEST_GET(buf) ((GstMetaTest *)gst_buffer_get_meta(buf,GST_META_TEST_INFO))
+#define GST_META_TEST_ADD(buf) ((GstMetaTest *)gst_buffer_add_meta(buf,GST_META_TEST_INFO,NULL))
+
+#if 0
+/* unused currently. This is a user function to fill the metadata with default
+ * values. We don't call this from the init function because the user is mostly
+ * likely going to override the values immediately after */
+static void
+gst_meta_test_init (GstMetaTest * meta)
+{
+  meta->pts = GST_CLOCK_TIME_NONE;
+  meta->dts = GST_CLOCK_TIME_NONE;
+  meta->duration = GST_CLOCK_TIME_NONE;
+  meta->clock_rate = GST_SECOND;
+}
+#endif
+
+static void
+test_init_func (GstMetaTest * meta, GstBuffer * buffer)
+{
+  GST_DEBUG ("init called on buffer %p, meta %p", buffer, meta);
+  /* nothing to init really, the init function is mostly for allocating
+   * additional memory or doing special setup as part of adding the metadata to
+   * the buffer*/
+}
+
+static void
+test_free_func (GstMetaTest * meta, GstBuffer * buffer)
+{
+  GST_DEBUG ("free called on buffer %p, meta %p", buffer, meta);
+  /* nothing to free really */
+}
+
+static void
+test_copy_func (GstBuffer * copybuf, GstMetaTest * meta,
+    GstBuffer * buffer, gsize offset, gsize size)
+{
+  GstMetaTest *test;
+
+  GST_DEBUG ("copy called from buffer %p to %p, meta %p, %u-%u", buffer,
+      copybuf, meta, offset, size);
+
+  test = GST_META_TEST_ADD (copybuf);
+  if (offset == 0) {
+    /* same offset, copy timestamps */
+    test->pts = meta->pts;
+    test->dts = meta->dts;
+    if (size == gst_buffer_get_size (buffer)) {
+      /* same size, copy duration */
+      test->duration = meta->duration;
+    } else {
+      /* else clear */
+      test->duration = GST_CLOCK_TIME_NONE;
+    }
+  } else {
+    test->pts = -1;
+    test->dts = -1;
+    test->duration = -1;
+  }
+  test->clock_rate = meta->clock_rate;
+}
+
+static const GstMetaInfo *
+gst_meta_test_get_info (void)
+{
+  static const GstMetaInfo *meta_test_info = NULL;
+
+  if (meta_test_info == NULL) {
+    meta_test_info = gst_meta_register ("GstMetaTest", "GstMetaTest",
+        sizeof (GstMetaTest),
+        (GstMetaInitFunction) test_init_func,
+        (GstMetaFreeFunction) test_free_func,
+        (GstMetaCopyFunction) test_copy_func, (GstMetaTransformFunction) NULL);
+  }
+  return meta_test_info;
+}
+
+GST_START_TEST (test_meta_test)
+{
+  GstBuffer *buffer, *copy, *subbuf;
+  GstMetaTest *meta;
+  gpointer data;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
+  fail_if (data == NULL);
+  memset (data, 0, 4);
+  gst_buffer_unmap (buffer, data, 4);
+
+  /* add some metadata */
+  meta = GST_META_TEST_ADD (buffer);
+  fail_if (meta == NULL);
+  /* fill some values */
+  meta->pts = 1000;
+  meta->dts = 2000;
+  meta->duration = 1000;
+  meta->clock_rate = 1000;
+
+  /* copy of the buffer */
+  copy = gst_buffer_copy (buffer);
+  /* get metadata of the buffer */
+  meta = GST_META_TEST_GET (copy);
+  fail_if (meta == NULL);
+  fail_if (meta->pts != 1000);
+  fail_if (meta->dts != 2000);
+  fail_if (meta->duration != 1000);
+  fail_if (meta->clock_rate != 1000);
+  gst_buffer_unref (copy);
+
+  /* make subbuffer */
+  subbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 1);
+  /* get metadata of the buffer */
+  meta = GST_META_TEST_GET (subbuf);
+  fail_if (meta == NULL);
+  fail_if (meta->pts != 1000);
+  fail_if (meta->dts != 2000);
+  fail_if (meta->duration != -1);
+  fail_if (meta->clock_rate != 1000);
+  gst_buffer_unref (subbuf);
+
+  /* make another subbuffer */
+  subbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 3);
+  /* get metadata of the buffer */
+  meta = GST_META_TEST_GET (subbuf);
+  fail_if (meta == NULL);
+  fail_if (meta->pts != -1);
+  fail_if (meta->dts != -1);
+  fail_if (meta->duration != -1);
+  fail_if (meta->clock_rate != 1000);
+  gst_buffer_unref (subbuf);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+static Suite *
+gst_buffermeta_suite (void)
+{
+  Suite *s = suite_create ("GstMeta");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+  tcase_add_test (tc_chain, test_meta_test);
+
+  return s;
+}
+
+GST_CHECK_MAIN (gst_buffermeta);
index 0a7a731..237f7e4 100644 (file)
@@ -29,10 +29,10 @@ GST_START_TEST (test_copy)
 
   buffer = gst_buffer_new_and_alloc (4);
 
-  copy = GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT (buffer)));
+  copy = GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CAST (buffer)));
 
   fail_if (copy == NULL, "Copy of buffer returned NULL");
-  fail_unless (GST_BUFFER_SIZE (copy) == 4,
+  fail_unless (gst_buffer_get_size (copy) == 4,
       "Copy of buffer has different size");
 }
 
@@ -44,18 +44,11 @@ GST_START_TEST (test_is_writable)
   GstMiniObject *mobj;
 
   buffer = gst_buffer_new_and_alloc (4);
-  mobj = GST_MINI_OBJECT (buffer);
+  mobj = GST_MINI_OBJECT_CAST (buffer);
 
   fail_unless (gst_mini_object_is_writable (mobj),
       "A buffer with one ref should be writable");
 
-  GST_MINI_OBJECT_FLAG_SET (mobj, GST_MINI_OBJECT_FLAG_READONLY);
-  fail_if (gst_mini_object_is_writable (mobj),
-      "A buffer with READONLY set should not be writable");
-  GST_MINI_OBJECT_FLAG_UNSET (mobj, GST_MINI_OBJECT_FLAG_READONLY);
-  fail_unless (gst_mini_object_is_writable (mobj),
-      "A buffer with one ref and READONLY not set should be writable");
-
   fail_if (gst_mini_object_ref (mobj) == NULL, "Could not ref the mobj");
 
   fail_if (gst_mini_object_is_writable (mobj),
@@ -70,7 +63,7 @@ GST_START_TEST (test_make_writable)
   GstMiniObject *mobj, *mobj2, *mobj3;
 
   buffer = gst_buffer_new_and_alloc (4);
-  mobj = GST_MINI_OBJECT (buffer);
+  mobj = GST_MINI_OBJECT_CAST (buffer);
 
   mobj2 = gst_mini_object_make_writable (mobj);
   fail_unless (GST_IS_BUFFER (mobj2), "make_writable did not return a buffer");
@@ -123,7 +116,7 @@ GST_START_TEST (test_ref_threaded)
 
   buffer = gst_buffer_new_and_alloc (4);
 
-  mobj = GST_MINI_OBJECT (buffer);
+  mobj = GST_MINI_OBJECT_CAST (buffer);
 
   MAIN_START_THREADS (num_threads, thread_ref, mobj);
 
@@ -202,21 +195,12 @@ GST_START_TEST (test_weak_ref)
 
 GST_END_TEST;
 
+#if 0
 /* ======== recycle test ======== */
 
 static gint recycle_buffer_count = 10;
 
-#define MY_TYPE_RECYCLE_BUFFER (my_recycle_buffer_get_type ())
-
-#define MY_IS_RECYCLE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-    MY_TYPE_RECYCLE_BUFFER))
-#define MY_RECYCLE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-    MY_TYPE_RECYCLE_BUFFER, MyRecycleBuffer))
-#define MY_RECYCLE_BUFFER_CAST(obj) ((MyRecycleBuffer *) (obj))
-
 typedef struct _MyBufferPool MyBufferPool;
-typedef struct _MyRecycleBuffer MyRecycleBuffer;
-typedef struct _MyRecycleBufferClass MyRecycleBufferClass;
 
 struct _MyBufferPool
 {
@@ -225,18 +209,6 @@ struct _MyBufferPool
   volatile gboolean is_closed;
 };
 
-struct _MyRecycleBuffer
-{
-  GstBuffer buffer;
-
-  MyBufferPool *pool;
-};
-
-struct _MyRecycleBufferClass
-{
-  GstBufferClass parent_class;
-};
-
 static void my_recycle_buffer_destroy (MyRecycleBuffer * buf);
 
 static MyBufferPool *
@@ -279,28 +251,10 @@ my_buffer_pool_drain_one (MyBufferPool * self)
   return buf;
 }
 
-GType my_recycle_buffer_get_type (void);
-G_DEFINE_TYPE (MyRecycleBuffer, my_recycle_buffer, GST_TYPE_BUFFER);
-
-static void my_recycle_buffer_finalize (GstMiniObject * mini_object);
-
-static void
-my_recycle_buffer_class_init (MyRecycleBufferClass * klass)
-{
-  GstMiniObjectClass *miniobject_class = GST_MINI_OBJECT_CLASS (klass);
-
-  miniobject_class->finalize = my_recycle_buffer_finalize;
-}
-
-static void
-my_recycle_buffer_init (MyRecycleBuffer * self)
-{
-}
-
 static void
 my_recycle_buffer_finalize (GstMiniObject * mini_object)
 {
-  MyRecycleBuffer *self = MY_RECYCLE_BUFFER_CAST (mini_object);
+  GstBuffer *self = GST_BUFFER_CAST (mini_object);
 
   if (self->pool != NULL) {
     my_buffer_pool_add (self->pool, GST_BUFFER_CAST (self));
@@ -314,10 +268,11 @@ my_recycle_buffer_finalize (GstMiniObject * mini_object)
 static GstBuffer *
 my_recycle_buffer_new (MyBufferPool * pool)
 {
-  MyRecycleBuffer *buf;
+  GstBuffer *buf;
 
-  buf = MY_RECYCLE_BUFFER (gst_mini_object_new (MY_TYPE_RECYCLE_BUFFER));
-  buf->pool = pool;
+  buf = gst_buffer_new ();
+
+  //buf->pool = pool;
 
   return GST_BUFFER_CAST (buf);
 }
@@ -376,6 +331,7 @@ GST_START_TEST (test_recycle_threaded)
 }
 
 GST_END_TEST;
+#endif
 
 /* ======== value collection test ======== */
 typedef struct _MyFoo
@@ -410,7 +366,7 @@ my_foo_get_property (GObject * object, guint prop_id, GValue * value,
   g_assert (prop_id == PROP_BUFFER);
 
   new_buf = gst_buffer_new_and_alloc (1024);
-  gst_value_set_mini_object (value, GST_MINI_OBJECT (new_buf));
+  g_value_set_boxed (value, GST_MINI_OBJECT (new_buf));
   gst_buffer_unref (new_buf);
 }
 
@@ -422,8 +378,7 @@ my_foo_set_property (GObject * object, guint prop_id, const GValue * value,
 
   g_assert (prop_id == PROP_BUFFER);
 
-  mini_obj = gst_value_get_mini_object (value);
-  g_assert (GST_IS_MINI_OBJECT (mini_obj));
+  mini_obj = g_value_get_boxed (value);
   g_assert (GST_IS_BUFFER (mini_obj));
 
 #if 0
@@ -445,7 +400,7 @@ my_foo_class_init (MyFooClass * klass)
   gobject_klass->set_property = my_foo_set_property;
 
   g_object_class_install_property (gobject_klass, PROP_BUFFER,
-      gst_param_spec_mini_object ("buffer", "Buffer",
+      g_param_spec_boxed ("buffer", "Buffer",
           "a newly created GstBuffer", GST_TYPE_BUFFER, G_PARAM_READWRITE));
 }
 
@@ -481,9 +436,9 @@ GST_START_TEST (test_dup_null_mini_object)
 
   g_value_init (&value, GST_TYPE_BUFFER);
 
-  gst_value_set_mini_object (&value, NULL);
+  g_value_set_boxed (&value, NULL);
 
-  mo = gst_value_dup_mini_object (&value);
+  mo = GST_MINI_OBJECT_CAST (g_value_dup_boxed (&value));
   g_assert (mo == NULL);
 
   g_value_unset (&value);
@@ -507,7 +462,7 @@ gst_mini_object_suite (void)
   tcase_add_test (tc_chain, test_ref_threaded);
   tcase_add_test (tc_chain, test_unref_threaded);
   tcase_add_test (tc_chain, test_weak_ref);
-  tcase_add_test (tc_chain, test_recycle_threaded);
+  //tcase_add_test (tc_chain, test_recycle_threaded);
   tcase_add_test (tc_chain, test_value_collection);
   tcase_add_test (tc_chain, test_dup_null_mini_object);
   return s;
index d5956db..6f7ccb8 100644 (file)
@@ -360,7 +360,7 @@ GST_START_TEST (test_fake_object_parentage)
   fail_if (object1 == NULL, "Failed to create instance of GstFakeObject");
   fail_unless (GST_IS_OBJECT (object1),
       "GstFakeObject instance is not a GstObject");
-  fail_unless (GST_OBJECT_IS_FLOATING (object1),
+  fail_unless (g_object_is_floating (object1),
       "GstFakeObject instance is not floating");
 
   /* check the parent */
@@ -374,7 +374,7 @@ GST_START_TEST (test_fake_object_parentage)
   fail_if (result == TRUE, "GstFakeObject accepted itself as parent");
 
   /* should still be floating */
-  fail_unless (GST_OBJECT_IS_FLOATING (object1),
+  fail_unless (g_object_is_floating (object1),
       "GstFakeObject instance is not floating");
 
   /* create another object */
@@ -383,7 +383,7 @@ GST_START_TEST (test_fake_object_parentage)
       "Failed to create another instance of GstFakeObject");
   fail_unless (GST_IS_OBJECT (object2),
       "second GstFakeObject instance is not a GstObject");
-  fail_unless (GST_OBJECT_IS_FLOATING (object1),
+  fail_unless (g_object_is_floating (object1),
       "GstFakeObject instance is not floating");
 
   /* try to set other object as parent */
@@ -392,10 +392,10 @@ GST_START_TEST (test_fake_object_parentage)
       "GstFakeObject could not accept other object as parent");
 
   /* should not be floating anymore */
-  fail_if (GST_OBJECT_IS_FLOATING (object1),
+  fail_if (g_object_is_floating (object1),
       "GstFakeObject instance is still floating");
   /* parent should still be floating */
-  fail_unless (GST_OBJECT_IS_FLOATING (object2),
+  fail_unless (g_object_is_floating (object2),
       "GstFakeObject instance is not floating");
 
   /* check the parent */
@@ -416,7 +416,7 @@ GST_START_TEST (test_fake_object_parentage)
   fail_if (parent != NULL, "GstFakeObject has parent");
 
   /* object should not be floating */
-  fail_if (GST_OBJECT_IS_FLOATING (object1),
+  fail_if (g_object_is_floating (object1),
       "GstFakeObject instance is floating again");
 
   gst_object_unref (object1);
index bf930e6..f0953a8 100644 (file)
@@ -88,7 +88,9 @@ GST_START_TEST (test_link_unlink_threaded)
   fail_if (sink == NULL);
 
   caps = gst_caps_from_string ("foo/bar");
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
@@ -126,13 +128,23 @@ GST_START_TEST (test_refcount)
   /* one for me */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
 
-  gst_pad_set_caps (src, caps);
-  gst_pad_set_caps (sink, caps);
+  /* can't set caps on flushing sinkpad */
+  fail_if (gst_pad_set_caps (src, caps) == TRUE);
+  fail_if (gst_pad_set_caps (sink, caps) == TRUE);
   /* one for me and one for each set_caps */
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+
+  gst_pad_set_active (src, TRUE);
+  fail_unless (gst_pad_set_caps (src, caps) == TRUE);
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
+
+  gst_pad_set_active (sink, TRUE);
+  fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
   plr = gst_pad_link (src, sink);
   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
+  /* src caps added to pending caps on sink */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
   gst_pad_unlink (src, sink);
@@ -169,8 +181,16 @@ GST_START_TEST (test_get_allowed_caps)
   caps = gst_caps_from_string ("foo/bar");
 
   sink = gst_pad_new ("sink", GST_PAD_SINK);
-  gst_pad_set_caps (src, caps);
-  gst_pad_set_caps (sink, caps);
+  gst_pad_set_active (src, TRUE);
+  /* source pad is active and will accept the caps event */
+  fail_unless (gst_pad_set_caps (src, caps) == TRUE);
+  /* sink pad is not active and will refuse the caps event */
+  fail_if (gst_pad_set_caps (sink, caps) == TRUE);
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
+
+  gst_pad_set_active (sink, TRUE);
+  /* sink pad is now active and will accept the caps event */
+  fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
   plr = gst_pad_link (src, sink);
@@ -199,13 +219,218 @@ GST_START_TEST (test_get_allowed_caps)
 
 GST_END_TEST;
 
+static GstCaps *event_caps = NULL;
+
+static gboolean
+sticky_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+  GstCaps *caps;
+
+  fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
+
+  /* Ensure we get here just once: */
+  fail_unless (event_caps == NULL);
+
+  /* The event must arrive before any buffer: */
+  fail_unless_equals_int (g_list_length (buffers), 0);
+
+  gst_event_parse_caps (event, &caps);
+  event_caps = gst_caps_ref (caps);
+
+  gst_event_unref (event);
+
+  return TRUE;
+}
+
+/* Tests whether caps get properly forwarded when pads
+   are initially unlinked */
+GST_START_TEST (test_sticky_caps_unlinked)
+{
+  GstCaps *caps;
+  GstPadTemplate *src_template, *sink_template;
+  GstPad *src, *sink;
+  GstEvent *event;
+
+  caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
+  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
+      GST_PAD_ALWAYS, caps);
+  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
+      GST_PAD_ALWAYS, caps);
+  gst_caps_unref (caps);
+
+  src = gst_pad_new_from_template (src_template, "src");
+  fail_if (src == NULL);
+  sink = gst_pad_new_from_template (sink_template, "sink");
+  fail_if (sink == NULL);
+  gst_pad_set_event_function (sink, sticky_event);
+  gst_pad_set_chain_function (sink, gst_check_chain_func);
+
+  gst_object_unref (src_template);
+  gst_object_unref (sink_template);
+
+  caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+
+  event = gst_event_new_caps (caps);
+  gst_pad_set_active (src, TRUE);
+  fail_unless (gst_pad_push_event (src, event) == TRUE);
+  fail_unless (event_caps == NULL);
+
+  /* Linking and activating will not forward the sticky event yet... */
+  fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
+  gst_pad_set_active (sink, TRUE);
+  fail_unless (event_caps == NULL);
+
+  /* ...but the first buffer will: */
+  fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
+  fail_unless (event_caps == caps);
+  fail_unless_equals_int (g_list_length (buffers), 1);
+
+  gst_caps_replace (&caps, NULL);
+  gst_caps_replace (&event_caps, NULL);
+
+  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
+  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
+  gst_object_unref (src);
+  gst_object_unref (sink);
+}
+
+GST_END_TEST;
+
+/* Same as test_sticky_caps_unlinked except that the source pad
+ * has a template of ANY and we will attempt to push
+ * incompatible caps */
+GST_START_TEST (test_sticky_caps_unlinked_incompatible)
+{
+  GstCaps *caps, *failcaps;
+  GstPadTemplate *src_template, *sink_template;
+  GstPad *src, *sink;
+  GstEvent *event;
+
+  /* Source pad has ANY caps
+   * Sink pad has foobar caps
+   * We will push the pony express caps (which should fail)
+   */
+  caps = gst_caps_new_any ();
+  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
+      GST_PAD_ALWAYS, caps);
+  gst_caps_unref (caps);
+  caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
+  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
+      GST_PAD_ALWAYS, caps);
+  gst_caps_unref (caps);
+
+  src = gst_pad_new_from_template (src_template, "src");
+  fail_if (src == NULL);
+  sink = gst_pad_new_from_template (sink_template, "sink");
+  fail_if (sink == NULL);
+  gst_pad_set_event_function (sink, sticky_event);
+  gst_pad_set_chain_function (sink, gst_check_chain_func);
+
+  gst_object_unref (src_template);
+  gst_object_unref (sink_template);
+
+  failcaps = gst_caps_from_string ("pony/express, failure=(boolean)true");
+  ASSERT_CAPS_REFCOUNT (failcaps, "caps", 1);
+
+  event = gst_event_new_caps (failcaps);
+  gst_caps_unref (failcaps);
+  gst_pad_set_active (src, TRUE);
+  /* The pad isn't linked yet, and anything matches the source pad template
+   * (which is ANY) */
+  fail_unless (gst_pad_push_event (src, event) == TRUE);
+  fail_unless (event_caps == NULL);
+
+  /* Linking and activating will not forward the sticky event yet... */
+  fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
+  gst_pad_set_active (sink, TRUE);
+  fail_unless (event_caps == NULL);
+
+  /* ...but the first buffer will and should FAIL since the caps 
+   * are not compatible */
+  fail_unless (gst_pad_push (src,
+          gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED);
+  /* We shouldn't have received the caps event since it's incompatible */
+  fail_unless (event_caps == NULL);
+  /* We shouldn't have received any buffers since caps are incompatible */
+  fail_unless_equals_int (g_list_length (buffers), 0);
+
+  gst_caps_replace (&event_caps, NULL);
+
+  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
+  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
+  gst_object_unref (src);
+  gst_object_unref (sink);
+}
+
+GST_END_TEST;
+
+/* Like test_sticky_caps_unlinked, but link before caps: */
+
+GST_START_TEST (test_sticky_caps_flushing)
+{
+  GstCaps *caps;
+  GstPadTemplate *src_template, *sink_template;
+  GstPad *src, *sink;
+  GstEvent *event;
+
+  caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
+  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
+      GST_PAD_ALWAYS, caps);
+  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
+      GST_PAD_ALWAYS, caps);
+  gst_caps_unref (caps);
+
+  src = gst_pad_new_from_template (src_template, "src");
+  fail_if (src == NULL);
+  sink = gst_pad_new_from_template (sink_template, "sink");
+  fail_if (sink == NULL);
+  gst_pad_set_event_function (sink, sticky_event);
+  gst_pad_set_chain_function (sink, gst_check_chain_func);
+
+  gst_object_unref (src_template);
+  gst_object_unref (sink_template);
+
+  fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
+
+  caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+
+  event = gst_event_new_caps (caps);
+  gst_pad_set_active (src, TRUE);
+  /* The caps event gets accepted by the source pad (and stored) */
+  fail_unless (gst_pad_push_event (src, event) == TRUE);
+  /* But wasn't forwarded since the sink pad is flushing (not activated) */
+  fail_unless (event_caps == NULL);
+
+  /* Activating will not forward the sticky event yet... */
+  gst_pad_set_active (sink, TRUE);
+  fail_unless (event_caps == NULL);
+
+  /* ...but the first buffer will: */
+  fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
+  fail_unless (event_caps == caps);
+  fail_unless_equals_int (g_list_length (buffers), 1);
+
+  gst_caps_replace (&caps, NULL);
+  gst_caps_replace (&event_caps, NULL);
+
+  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
+  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
+  gst_object_unref (src);
+  gst_object_unref (sink);
+}
+
+GST_END_TEST;
+
 static gboolean
 name_is_valid (const gchar * name, GstPadPresence presence)
 {
   GstPadTemplate *new;
-  GstCaps *any = GST_CAPS_ANY;
+  GstCaps *any = gst_caps_new_any ();
 
   new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
+  gst_caps_unref (any);
   if (new) {
     gst_object_unref (GST_OBJECT (new));
     return TRUE;
@@ -234,14 +459,15 @@ GST_START_TEST (test_name_is_valid)
 
 GST_END_TEST;
 
-static gboolean
-_probe_handler (GstPad * pad, GstBuffer * buffer, gpointer userdata)
+static GstPadProbeReturn
+_probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata)
 {
   gint ret = GPOINTER_TO_INT (userdata);
 
   if (ret == 1)
-    return TRUE;
-  return FALSE;
+    return GST_PAD_PROBE_OK;
+
+  return GST_PAD_PROBE_DROP;
 }
 
 GST_START_TEST (test_push_unlinked)
@@ -258,37 +484,50 @@ GST_START_TEST (test_push_unlinked)
 
   caps = gst_caps_from_string ("foo/bar");
 
+  /* pushing on an inactive pad will return wrong state */
+  GST_DEBUG ("push buffer inactive");
+  buffer = gst_buffer_new ();
+  gst_buffer_ref (buffer);
+  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
+  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
+  gst_buffer_unref (buffer);
+
+  gst_pad_set_active (src, TRUE);
+  GST_DEBUG ("push caps event inactive");
   gst_pad_set_caps (src, caps);
   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
 
   /* pushing on an unlinked pad will drop the buffer */
+  GST_DEBUG ("push buffer unlinked");
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   gst_buffer_unref (buffer);
 
-  /* adding a probe that returns FALSE will drop the buffer without trying
+  /* adding a probe that returns _DROP will drop the buffer without trying
    * to chain */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (0));
+  GST_DEBUG ("push buffer drop");
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
+      _probe_handler, GINT_TO_POINTER (0), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   gst_buffer_unref (buffer);
-  gst_pad_remove_buffer_probe (src, id);
+  gst_pad_remove_probe (src, id);
 
-  /* adding a probe that returns TRUE will still chain the buffer,
+  /* adding a probe that returns _OK will still chain the buffer,
    * and hence drop because pad is unlinked */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (1));
+  GST_DEBUG ("push buffer ok");
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
+      _probe_handler, GINT_TO_POINTER (1), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   gst_buffer_unref (buffer);
-  gst_pad_remove_buffer_probe (src, id);
+  gst_pad_remove_probe (src, id);
 
 
   /* cleanup */
@@ -323,7 +562,9 @@ GST_START_TEST (test_push_linked)
   /* one for me */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
 
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
   /* one for me and one for each set_caps */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
@@ -333,17 +574,6 @@ GST_START_TEST (test_push_linked)
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
   buffer = gst_buffer_new ();
-#if 0
-  /* FIXME, new pad should be flushing */
-  gst_buffer_ref (buffer);
-  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
-  gst_buffer_ref (buffer);
-  fail_unless (gst_pad_chain (sink, buffer) == GST_FLOW_WRONG_STATE);
-#endif
-
-  /* activate pads */
-  gst_pad_set_active (src, TRUE);
-  gst_pad_set_active (sink, TRUE);
 
   /* test */
   /* pushing on a linked pad will drop the ref to the buffer */
@@ -360,23 +590,23 @@ GST_START_TEST (test_push_linked)
 
   /* adding a probe that returns FALSE will drop the buffer without trying
    * to chain */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (0));
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
+      _probe_handler, GINT_TO_POINTER (0), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   gst_buffer_unref (buffer);
-  gst_pad_remove_buffer_probe (src, id);
+  gst_pad_remove_probe (src, id);
   fail_unless_equals_int (g_list_length (buffers), 0);
 
   /* adding a probe that returns TRUE will still chain the buffer */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (1));
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
+      _probe_handler, GINT_TO_POINTER (1), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
-  gst_pad_remove_buffer_probe (src, id);
+  gst_pad_remove_probe (src, id);
 
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
   gst_buffer_unref (buffer);
@@ -389,7 +619,7 @@ GST_START_TEST (test_push_linked)
 
   /* teardown */
   gst_pad_unlink (src, sink);
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
   gst_object_unref (src);
   gst_object_unref (sink);
   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
@@ -423,7 +653,10 @@ GST_START_TEST (test_push_linked_flushing)
   /* one for me */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
 
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  /* need to activate to make it accept the caps */
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
   /* one for me and one for each set_caps */
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
@@ -433,6 +666,8 @@ GST_START_TEST (test_push_linked_flushing)
   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
 
   /* not activating the pads here, which keeps them flushing */
+  gst_pad_set_active (src, FALSE);
+  gst_pad_set_active (sink, FALSE);
 
   /* pushing on a flushing pad will drop the buffer */
   buffer = gst_buffer_new ();
@@ -442,33 +677,35 @@ GST_START_TEST (test_push_linked_flushing)
   fail_unless_equals_int (g_list_length (buffers), 0);
   gst_buffer_unref (buffer);
 
+  gst_pad_set_active (src, TRUE);
+  gst_pad_set_active (sink, FALSE);
+
   /* adding a probe that returns FALSE will drop the buffer without trying
    * to chain */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (0));
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
+      GINT_TO_POINTER (0), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   fail_unless_equals_int (g_list_length (buffers), 0);
   gst_buffer_unref (buffer);
-  gst_pad_remove_buffer_probe (src, id);
+  gst_pad_remove_probe (src, id);
 
   /* adding a probe that returns TRUE will still chain the buffer,
    * and hence drop because pad is flushing */
-  id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
-      GINT_TO_POINTER (1));
+  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
+      GINT_TO_POINTER (1), NULL);
   buffer = gst_buffer_new ();
   gst_buffer_ref (buffer);
   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
   fail_unless_equals_int (g_list_length (buffers), 0);
   gst_buffer_unref (buffer);
-  gst_pad_remove_buffer_probe (src, id);
-
+  gst_pad_remove_probe (src, id);
 
   /* cleanup */
-  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
+  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
   gst_pad_link (src, sink);
   gst_object_unref (src);
@@ -484,22 +721,38 @@ buffer_from_string (const gchar * str)
 {
   guint size;
   GstBuffer *buf;
+  gpointer data;
 
   size = strlen (str);
   buf = gst_buffer_new_and_alloc (size);
-  memcpy (GST_BUFFER_DATA (buf), str, size);
-  GST_BUFFER_SIZE (buf) = size;
+
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+  memcpy (data, str, size);
+  gst_buffer_unmap (buf, data, size);
 
   return buf;
 }
 
+static gboolean
+buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
+{
+  gboolean res;
+  gpointer data;
+
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
+  res = memcmp (data, str, size) == 0;
+  GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
+  gst_buffer_unmap (buf, data, size);
+
+  return res;
+}
+
 GST_START_TEST (test_push_buffer_list_compat)
 {
   GstPad *src, *sink;
   GstPadLinkReturn plr;
   GstCaps *caps;
   GstBufferList *list;
-  GstBufferListIterator *it;
   GstBuffer *buffer;
 
   /* setup */
@@ -513,7 +766,9 @@ GST_START_TEST (test_push_buffer_list_compat)
 
   caps = gst_caps_from_string ("foo/bar");
 
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
 
   plr = gst_pad_link (src, sink);
@@ -521,31 +776,21 @@ GST_START_TEST (test_push_buffer_list_compat)
 
   list = gst_buffer_list_new ();
 
-  /* activate pads */
-  gst_pad_set_active (src, TRUE);
-  gst_pad_set_active (sink, TRUE);
-
   /* test */
   /* adding to a buffer list will drop the ref to the buffer */
-  it = gst_buffer_list_iterate (list);
-  gst_buffer_list_iterator_add_group (it);
-  gst_buffer_list_iterator_add (it, buffer_from_string ("List"));
-  gst_buffer_list_iterator_add (it, buffer_from_string ("Group"));
-  gst_buffer_list_iterator_add_group (it);
-  gst_buffer_list_iterator_add (it, buffer_from_string ("Another"));
-  gst_buffer_list_iterator_add (it, buffer_from_string ("List"));
-  gst_buffer_list_iterator_add (it, buffer_from_string ("Group"));
-  gst_buffer_list_iterator_free (it);
+  gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
+  gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));
+
   fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
   fail_unless_equals_int (g_list_length (buffers), 2);
   buffer = GST_BUFFER (buffers->data);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer), "ListGroup", 9) == 0);
+  fail_unless (buffer_compare (buffer, "ListGroup", 9));
   gst_buffer_unref (buffer);
   buffers = g_list_delete_link (buffers, buffers);
   buffer = GST_BUFFER (buffers->data);
   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
-  fail_unless (memcmp (GST_BUFFER_DATA (buffer), "AnotherListGroup", 16) == 0);
+  fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
   gst_buffer_unref (buffer);
   buffers = g_list_delete_link (buffers, buffers);
   fail_unless (buffers == NULL);
@@ -566,15 +811,10 @@ GST_START_TEST (test_flowreturn)
   GQuark quark;
 
   /* test some of the macros */
-  ret = GST_FLOW_UNEXPECTED;
-  fail_if (strcmp (gst_flow_get_name (ret), "unexpected"));
+  ret = GST_FLOW_EOS;
+  fail_if (strcmp (gst_flow_get_name (ret), "eos"));
   quark = gst_flow_to_quark (ret);
-  fail_if (strcmp (g_quark_to_string (quark), "unexpected"));
-
-  ret = GST_FLOW_RESEND;
-  fail_if (strcmp (gst_flow_get_name (ret), "resend"));
-  quark = gst_flow_to_quark (ret);
-  fail_if (strcmp (g_quark_to_string (quark), "resend"));
+  fail_if (strcmp (g_quark_to_string (quark), "eos"));
 
   /* custom returns */
   ret = GST_FLOW_CUSTOM_SUCCESS;
@@ -618,13 +858,14 @@ GST_START_TEST (test_push_negotiation)
   GstPadTemplate *src_template;
   GstPadTemplate *sink_template;
   GstCaps *caps;
-  GstBuffer *buffer;
 
   /* setup */
   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
       GST_PAD_ALWAYS, srccaps);
   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
       GST_PAD_ALWAYS, sinkcaps);
+  gst_caps_unref (srccaps);
+  gst_caps_unref (sinkcaps);
 
   sink = gst_pad_new_from_template (sink_template, "sink");
   fail_if (sink == NULL);
@@ -636,8 +877,6 @@ GST_START_TEST (test_push_negotiation)
   plr = gst_pad_link (src, sink);
   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
 
-  buffer = gst_buffer_new ();
-
   /* activate pads */
   gst_pad_set_active (src, TRUE);
   gst_pad_set_active (sink, TRUE);
@@ -646,11 +885,7 @@ GST_START_TEST (test_push_negotiation)
 
   /* Should fail if src pad caps are incompatible with sink pad caps */
   gst_pad_set_caps (src, caps);
-  gst_buffer_set_caps (buffer, caps);
-  gst_buffer_ref (buffer);
-  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_NEGOTIATED);
-  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
-  gst_buffer_unref (buffer);
+  fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
 
   /* teardown */
   gst_pad_unlink (src, sink);
@@ -678,7 +913,9 @@ GST_START_TEST (test_src_unref_unlink)
 
   caps = gst_caps_from_string ("foo/bar");
 
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
 
   plr = gst_pad_link (src, sink);
@@ -712,7 +949,9 @@ GST_START_TEST (test_sink_unref_unlink)
 
   caps = gst_caps_from_string ("foo/bar");
 
+  gst_pad_set_active (src, TRUE);
   gst_pad_set_caps (src, caps);
+  gst_pad_set_active (sink, TRUE);
   gst_pad_set_caps (sink, caps);
 
   plr = gst_pad_link (src, sink);
@@ -731,57 +970,25 @@ GST_START_TEST (test_sink_unref_unlink)
 
 GST_END_TEST;
 
-/* gst_pad_get_caps should return a copy of the caps */
-GST_START_TEST (test_get_caps_must_be_copy)
-{
-  GstPad *pad;
-  GstCaps *caps;
-  GstPadTemplate *templ;
+static gulong id;
 
-  caps = gst_caps_new_any ();
-  templ =
-      gst_pad_template_new ("test_templ", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
-
-  pad = gst_pad_new_from_template (templ, NULL);
-  fail_unless (GST_PAD_CAPS (pad) == NULL, "caps present on pad");
-  /* This is a writable copy ! */
-  caps = gst_pad_get_caps (pad);
-
-  /* we must own the caps */
-  ASSERT_OBJECT_REFCOUNT (caps, "caps", 1);
-
-  /* cleanup */
-  gst_object_unref (templ);
-  gst_caps_unref (caps);
-  gst_object_unref (pad);
-}
-
-GST_END_TEST;
-
-static void
-unblock_async_cb (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+block_async_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
   gboolean *bool_user_data = (gboolean *) user_data;
 
-  /* here we should have blocked == 1 unblocked == 0 */
-  fail_unless (bool_user_data[0] == TRUE);
-  fail_unless (bool_user_data[1] == FALSE);
-
-  bool_user_data[1] = TRUE;
-}
-
-static void
-block_async_cb (GstPad * pad, gboolean blocked, gpointer user_data)
-{
-  gboolean *bool_user_data = (gboolean *) user_data;
+  fail_unless ((info->type & GST_PAD_PROBE_TYPE_BLOCK) != 0);
 
   /* here we should have blocked == 0 unblocked == 0 */
   fail_unless (bool_user_data[0] == FALSE);
   fail_unless (bool_user_data[1] == FALSE);
 
-  bool_user_data[0] = blocked;
+  bool_user_data[0] = TRUE;
 
-  gst_pad_set_blocked_async (pad, FALSE, unblock_async_cb, user_data);
+  gst_pad_remove_probe (pad, id);
+  bool_user_data[1] = TRUE;
+
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_block_async)
@@ -795,7 +1002,8 @@ GST_START_TEST (test_block_async)
   fail_unless (pad != NULL);
 
   gst_pad_set_active (pad, TRUE);
-  gst_pad_set_blocked_async (pad, TRUE, block_async_cb, &data);
+  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_cb, &data,
+      NULL);
 
   fail_unless (data[0] == FALSE);
   fail_unless (data[1] == FALSE);
@@ -806,11 +1014,72 @@ GST_START_TEST (test_block_async)
 
 GST_END_TEST;
 
+static GstPadProbeReturn
+block_async_cb_return_ok (GstPad * pad, GstPadProbeInfo * info,
+    gpointer user_data)
+{
+  return GST_PAD_PROBE_OK;
+}
+
+static gpointer
+push_buffer_async (GstPad * pad)
+{
+  return GINT_TO_POINTER (gst_pad_push (pad, gst_buffer_new ()));
+}
+
+static void
+test_pad_blocking_with_type (GstPadProbeType type)
+{
+  GstPad *pad;
+  GThread *thread;
+  GstFlowReturn ret;
+
+  pad = gst_pad_new ("src", GST_PAD_SRC);
+  fail_unless (pad != NULL);
+
+  gst_pad_set_active (pad, TRUE);
+  id = gst_pad_add_probe (pad, type, block_async_cb_return_ok, NULL, NULL);
+
+
+  thread = g_thread_create ((GThreadFunc) push_buffer_async, pad, TRUE, NULL);
+
+  /* wait for the block */
+  while (!gst_pad_is_blocking (pad)) {
+    g_usleep (100000);
+  }
+
+  /* stop with flushing */
+  gst_pad_push_event (pad, gst_event_new_flush_start ());
+
+  /* get return value from push */
+  ret = GPOINTER_TO_INT (g_thread_join (thread));
+  /* unflush now */
+  gst_pad_push_event (pad, gst_event_new_flush_stop (FALSE));
+  /* must be wrong state */
+  fail_unless (ret == GST_FLOW_WRONG_STATE);
+
+  gst_object_unref (pad);
+}
+
+GST_START_TEST (test_pad_blocking_with_probe_type_block)
+{
+  test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCK);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_pad_blocking_with_probe_type_blocking)
+{
+  test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCKING);
+}
+
+GST_END_TEST;
+
 #if 0
 static void
 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
 {
-  gst_pad_set_blocked_async (pad, FALSE, unblock_async_cb, NULL);
+  gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
 }
 
 static void
@@ -827,7 +1096,7 @@ block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
 
   /* replace block_async_first with block_async_second so next time the pad is
    * blocked the latter should be called */
-  gst_pad_set_blocked_async (pad, TRUE, block_async_second, NULL);
+  gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
 
   /* unblock temporarily, in the next push block_async_second should be called
    */
@@ -843,7 +1112,7 @@ GST_START_TEST (test_block_async_replace_callback)
   fail_unless (pad != NULL);
   gst_pad_set_active (pad, TRUE);
 
-  gst_pad_set_blocked_async (pad, TRUE, block_async_first, &blocked);
+  gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
   blocked = FALSE;
 
   gst_pad_push (pad, gst_buffer_new ());
@@ -872,13 +1141,15 @@ block_async_full_destroy (gpointer user_data)
   *state = 2;
 }
 
-static void
-block_async_full_cb (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
-  *(gint *) user_data = (gint) blocked;
+  *(gint *) user_data = (gint) TRUE;
 
   gst_pad_push_event (pad, gst_event_new_flush_start ());
   GST_DEBUG ("setting state to 1");
+
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_block_async_full_destroy)
@@ -886,12 +1157,13 @@ GST_START_TEST (test_block_async_full_destroy)
   GstPad *pad;
   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
   gint state = 0;
+  gulong id;
 
   pad = gst_pad_new ("src", GST_PAD_SRC);
   fail_unless (pad != NULL);
   gst_pad_set_active (pad, TRUE);
 
-  gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
+  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
       &state, block_async_full_destroy);
   fail_unless (state == 0);
 
@@ -899,29 +1171,10 @@ GST_START_TEST (test_block_async_full_destroy)
   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
    */
   fail_unless (state == 1);
-  gst_pad_push_event (pad, gst_event_new_flush_stop ());
-
-  /* pad was already blocked so nothing happens */
-  gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
-      &state, block_async_full_destroy);
-  fail_unless (state == 1);
+  gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
 
-  /* unblock with the same data, callback is called */
-  gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
-      &state, block_async_full_destroy);
-  fail_unless (state == 2);
-
-  /* block with the same data, callback is called */
-  state = 1;
-  gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
-      &state, block_async_full_destroy);
-  fail_unless (state == 2);
-
-  /* now change user_data (to NULL in this case) so destroy_notify should be
-   * called */
-  state = 1;
-  gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
-      NULL, block_async_full_destroy);
+  /* unblock callback is called */
+  gst_pad_remove_probe (pad, id);
   fail_unless (state == 2);
 
   gst_object_unref (pad);
@@ -939,16 +1192,16 @@ GST_START_TEST (test_block_async_full_destroy_dispose)
   fail_unless (pad != NULL);
   gst_pad_set_active (pad, TRUE);
 
-  gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
+  (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
       &state, block_async_full_destroy);
 
   gst_pad_push (pad, gst_buffer_new ());
   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
    */
   fail_unless_equals_int (state, 1);
-  gst_pad_push_event (pad, gst_event_new_flush_stop ());
+  gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
 
-  /* gst_pad_dispose calls the destroy_notify function if necessary */
+  /* gst_BLOCK calls the destroy_notify function if necessary */
   gst_object_unref (pad);
 
   fail_unless_equals_int (state, 2);
@@ -957,6 +1210,7 @@ GST_START_TEST (test_block_async_full_destroy_dispose)
 GST_END_TEST;
 
 
+#if 0
 static void
 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 {
@@ -972,20 +1226,26 @@ unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 
   bool_user_data[2] = TRUE;
 }
+#endif
 
 
+#if 0
 static void
 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
 {
   g_warn_if_reached ();
 }
+#endif
 
-static void
-block_async_second_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
+    gpointer user_data)
 {
   gboolean *bool_user_data = (gboolean *) user_data;
 
-  fail_unless (blocked == TRUE);
+  GST_DEBUG ("second probe called");
+
+  fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
 
   fail_unless (bool_user_data[0] == TRUE);
   fail_unless (bool_user_data[1] == FALSE);
@@ -993,35 +1253,44 @@ block_async_second_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
 
   bool_user_data[1] = TRUE;
 
-  fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_no_flush_cb,
-          user_data));
+  GST_DEBUG ("removing second probe with id %lu", id);
+  gst_pad_remove_probe (pad, id);
+
+  return GST_PAD_PROBE_OK;
 }
 
-static void
-block_async_first_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstPadProbeReturn
+block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
+    gpointer user_data)
 {
   static int n_calls = 0;
   gboolean *bool_user_data = (gboolean *) user_data;
 
-  fail_unless (blocked == TRUE);
+  fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
+
+  GST_DEBUG ("first probe called");
 
   if (++n_calls > 1)
     /* we expect this callback to be called only once */
     g_warn_if_reached ();
 
-  *bool_user_data = blocked;
+  *bool_user_data = TRUE;
 
   fail_unless (bool_user_data[0] == TRUE);
   fail_unless (bool_user_data[1] == FALSE);
   fail_unless (bool_user_data[2] == FALSE);
 
-  fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_not_called,
-          NULL));
+  GST_DEBUG ("removing first probe with id %lu", id);
+  gst_pad_remove_probe (pad, id);
 
+  GST_DEBUG ("adding second probe");
   /* replace block_async_first with block_async_second so next time the pad is
    * blocked the latter should be called */
-  fail_unless (gst_pad_set_blocked_async (pad, TRUE,
-          block_async_second_no_flush, user_data));
+  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
+      block_async_second_no_flush, user_data, NULL);
+  GST_DEBUG ("added probe with id %lu", id);
+
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_block_async_replace_callback_no_flush)
@@ -1033,13 +1302,17 @@ GST_START_TEST (test_block_async_replace_callback_no_flush)
   fail_unless (pad != NULL);
   gst_pad_set_active (pad, TRUE);
 
-  fail_unless (gst_pad_set_blocked_async (pad, TRUE, block_async_first_no_flush,
-          bool_user_data));
+  GST_DEBUG ("adding probe");
+  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
+      block_async_first_no_flush, bool_user_data, NULL);
+  GST_DEBUG ("added probe with id %lu", id);
+  fail_if (id == 0);
 
+  GST_DEBUG ("pushing buffer");
   gst_pad_push (pad, gst_buffer_new ());
   fail_unless (bool_user_data[0] == TRUE);
   fail_unless (bool_user_data[1] == TRUE);
-  fail_unless (bool_user_data[2] == TRUE);
+  fail_unless (bool_user_data[2] == FALSE);
 
   gst_object_unref (pad);
 }
@@ -1060,6 +1333,9 @@ gst_pad_suite (void)
   tcase_add_test (tc_chain, test_link);
   tcase_add_test (tc_chain, test_refcount);
   tcase_add_test (tc_chain, test_get_allowed_caps);
+  tcase_add_test (tc_chain, test_sticky_caps_unlinked);
+  tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible);
+  tcase_add_test (tc_chain, test_sticky_caps_flushing);
   tcase_add_test (tc_chain, test_link_unlink_threaded);
   tcase_add_test (tc_chain, test_name_is_valid);
   tcase_add_test (tc_chain, test_push_unlinked);
@@ -1070,8 +1346,9 @@ gst_pad_suite (void)
   tcase_add_test (tc_chain, test_push_negotiation);
   tcase_add_test (tc_chain, test_src_unref_unlink);
   tcase_add_test (tc_chain, test_sink_unref_unlink);
-  tcase_add_test (tc_chain, test_get_caps_must_be_copy);
   tcase_add_test (tc_chain, test_block_async);
+  tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block);
+  tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
 #if 0
   tcase_add_test (tc_chain, test_block_async_replace_callback);
 #endif
index 545bce5..c6d3024 100644 (file)
@@ -33,7 +33,7 @@ typedef struct
 typedef GstElementClass GstDummyObjClass;
 
 GType gst_dummy_obj_get_type (void);
-GST_BOILERPLATE (GstDummyObj, gst_dummy_obj, GstElement, GST_TYPE_ELEMENT);
+G_DEFINE_TYPE (GstDummyObj, gst_dummy_obj, GST_TYPE_ELEMENT);
 
 static void
 gst_dummy_obj_get_property (GObject * obj, guint prop_id, GValue * val,
@@ -43,11 +43,6 @@ gst_dummy_obj_set_property (GObject * obj, guint prop_id, const GValue * val,
     GParamSpec * pspec);
 
 static void
-gst_dummy_obj_base_init (gpointer g_class)
-{
-}
-
-static void
 gst_dummy_obj_class_init (GstDummyObjClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -71,7 +66,7 @@ gst_dummy_obj_class_init (GstDummyObjClass * klass)
 }
 
 static void
-gst_dummy_obj_init (GstDummyObj * obj, GstDummyObjClass * klass)
+gst_dummy_obj_init (GstDummyObj * obj)
 {
   /* nothing to do there */
 }
index 02b6dc2..899c017 100644 (file)
@@ -238,7 +238,7 @@ static GMutex *probe_lock;
 static GCond *probe_cond;
 
 static gboolean
-sink_pad_probe (GstPad * pad, GstBuffer * buffer,
+sink_pad_probe (GstPad * pad, GstPadProbeType type, GstBuffer * buffer,
     GstClockTime * first_timestamp)
 {
   fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE,
@@ -274,7 +274,8 @@ GST_START_TEST (test_base_time)
   gst_element_link (fakesrc, fakesink);
 
   sink = gst_element_get_static_pad (fakesink, "sink");
-  gst_pad_add_buffer_probe (sink, G_CALLBACK (sink_pad_probe), &observed);
+  gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_BUFFER,
+      (GstPadProbeCallback) sink_pad_probe, &observed, NULL);
 
   fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED)
       == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline");
index f851677..3db1150 100644 (file)
 
 #include <gst/check/gstcheck.h>
 
-#ifdef GST_DISABLE_DEPRECATED
-void _gst_plugin_register_static (GstPluginDesc * desc);
-#endif
-
-/* keep in sync with GST_GNUC_CONSTRUCTOR in gstmacros.h (ideally we'd just
- * do it there, but I don't want to touch that now, and also we really want
- * to deprecate this macro in the long run, I think) */
-#if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
-#define GST_GNUC_CONSTRUCTOR_DEFINED
-#else
-#undef GST_GNUC_CONSTRUCTOR_DEFINED
-#endif
-
-#ifdef GST_GNUC_CONSTRUCTOR_DEFINED
-/* ------------------------------------------------------------------------- */
-/* To make sure the old and deprecated GST_PLUGIN_DEFINE_STATIC still works  */
-
-static guint plugin_init_counter;       /* 0 */
-
-static gboolean
-plugin1_init (GstPlugin * plugin)
-{
-  ++plugin_init_counter;
-  return TRUE;
-}
-
-static gboolean
-plugin2_init (GstPlugin * plugin)
-{
-  ++plugin_init_counter;
-  return TRUE;
-}
-
-static gboolean
-plugin3_init (GstPlugin * plugin)
-{
-  ++plugin_init_counter;
-  return TRUE;
-}
-
-GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-1",
-    "some static elements 1", plugin1_init, VERSION, GST_LICENSE, PACKAGE,
-    GST_PACKAGE_ORIGIN);
-
-GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-2",
-    "some static elements 2", plugin2_init, VERSION, GST_LICENSE, PACKAGE,
-    GST_PACKAGE_ORIGIN);
-
-GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-3",
-    "some static elements 3", plugin3_init, VERSION, GST_LICENSE, PACKAGE,
-    GST_PACKAGE_ORIGIN);
-
-GST_START_TEST (test_old_register_static)
-{
-  fail_unless (plugin_init_counter == 3);
-}
-
-GST_END_TEST;
-
-#endif /* GST_GNUC_CONSTRUCTOR_DEFINED */
-
 
 static gboolean
 register_check_elements (GstPlugin * plugin)
@@ -93,26 +32,10 @@ register_check_elements (GstPlugin * plugin)
   return TRUE;
 }
 
-static GstPluginDesc plugin_desc = {
-  GST_VERSION_MAJOR,
-  GST_VERSION_MINOR,
-  "check elements",
-  "check elements",
-  register_check_elements,
-  VERSION,
-  GST_LICENSE,
-  PACKAGE,
-  GST_PACKAGE_NAME,
-  GST_PACKAGE_ORIGIN,
-  NULL,
-  GST_PADDING_INIT
-};
-
 GST_START_TEST (test_register_static)
 {
   GstPlugin *plugin;
 
-  _gst_plugin_register_static (&plugin_desc);
   fail_unless (gst_plugin_register_static (GST_VERSION_MAJOR,
           GST_VERSION_MINOR, "more-elements", "more-elements",
           register_check_elements, VERSION, GST_LICENSE, PACKAGE,
@@ -127,26 +50,35 @@ GST_END_TEST;
 
 GST_START_TEST (test_registry)
 {
-  GList *g;
+  GList *list, *g;
   GstRegistry *registry;
 
-  registry = gst_registry_get_default ();
+  registry = gst_registry_get ();
 
-  for (g = registry->plugins; g; g = g->next) {
+  list = gst_registry_get_plugin_list (registry);
+  for (g = list; g; g = g->next) {
     GstPlugin *plugin = GST_PLUGIN (g->data);
 
-    ASSERT_OBJECT_REFCOUNT (plugin, "plugin in registry", 1);
+    /* one for the registry, one for the list */
     GST_DEBUG ("refcount %d %s", GST_OBJECT_REFCOUNT_VALUE (plugin),
         plugin->desc.name);
+    ASSERT_OBJECT_REFCOUNT (plugin, "plugin in registry", 2);
+
+    gst_object_unref (plugin);
   }
-  for (g = registry->features; g; g = g->next) {
+  g_list_free (list);
+
+  list = gst_registry_feature_filter (registry, NULL, FALSE, NULL);
+  for (g = list; g; g = g->next) {
     GstPluginFeature *feature = GST_PLUGIN_FEATURE (g->data);
 
-    fail_if (GST_OBJECT_REFCOUNT_VALUE (feature) != 1,
-        "Feature in registry should have refcount of 1");
+    /* one for the registry, one for the list */
     GST_DEBUG ("refcount %d %s", GST_OBJECT_REFCOUNT_VALUE (feature),
-        feature->name);
+        GST_OBJECT_NAME (feature));
+    ASSERT_OBJECT_REFCOUNT (feature, "feature in registry", 2);
+    gst_object_unref (feature);
   }
+  g_list_free (list);
 }
 
 GST_END_TEST;
@@ -156,7 +88,8 @@ GST_START_TEST (test_load_coreelements)
   GstPlugin *unloaded_plugin;
   GstPlugin *loaded_plugin;
 
-  unloaded_plugin = gst_default_registry_find_plugin ("coreelements");
+  unloaded_plugin = gst_registry_find_plugin (gst_registry_get (),
+      "coreelements");
   fail_if (unloaded_plugin == NULL, "Failed to find coreelements plugin");
   fail_if (GST_OBJECT_REFCOUNT_VALUE (unloaded_plugin) != 2,
       "Refcount of unloaded plugin in registry initially should be 2");
@@ -185,11 +118,11 @@ GST_START_TEST (test_registry_get_plugin_list)
   GList *list;
   GstPlugin *plugin;
 
-  plugin = gst_default_registry_find_plugin ("coreelements");
+  plugin = gst_registry_find_plugin (gst_registry_get (), "coreelements");
   fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 2,
       "Refcount of plugin in registry should be 2");
 
-  list = gst_registry_get_plugin_list (gst_registry_get_default ());
+  list = gst_registry_get_plugin_list (gst_registry_get ());
 
   fail_if (GST_OBJECT_REFCOUNT_VALUE (plugin) != 3,
       "Refcount of plugin in registry+list should be 3");
@@ -208,8 +141,7 @@ GST_START_TEST (test_find_plugin)
 {
   GstPlugin *plugin;
 
-  plugin = gst_registry_find_plugin (gst_registry_get_default (),
-      "coreelements");
+  plugin = gst_registry_find_plugin (gst_registry_get (), "coreelements");
   fail_if (plugin == NULL, "Failed to find coreelements plugin");
   ASSERT_OBJECT_REFCOUNT (plugin, "plugin", 2);
 
@@ -229,7 +161,7 @@ GST_START_TEST (test_find_feature)
 {
   GstPluginFeature *feature;
 
-  feature = gst_registry_find_feature (gst_registry_get_default (),
+  feature = gst_registry_find_feature (gst_registry_get (),
       "identity", GST_TYPE_ELEMENT_FACTORY);
   fail_if (feature == NULL, "Failed to find identity element factory");
   fail_if (strcmp (feature->plugin_name, "coreelements"),
@@ -290,7 +222,7 @@ GST_START_TEST (test_typefind)
       "Refcount of plugin in registry should be 2");
   fail_if (gst_plugin_is_loaded (plugin), "Expected plugin to be unloaded");
 
-  feature = gst_registry_find_feature (gst_registry_get_default (),
+  feature = gst_registry_find_feature (gst_registry_get (),
       "audio/x-au", GST_TYPE_TYPE_FIND_FACTORY);
   fail_if (feature == NULL, "Failed to find audio/x-aw typefind factory");
   fail_if (feature->plugin != plugin,
@@ -313,6 +245,9 @@ GST_START_TEST (test_typefind)
 GST_END_TEST;
 #endif
 
+#define gst_default_registry_check_feature_version(name,a,b,c) \
+    gst_registry_check_feature_version(gst_registry_get(),(name),(a),(b),(c))
+
 GST_START_TEST (test_version_checks)
 {
   fail_if (gst_default_registry_check_feature_version ("identity",
index 02d5bb7..3e624a0 100644 (file)
@@ -248,8 +248,8 @@ remove_preset_file (void)
 {
   gchar *preset_file_name;
 
-  preset_file_name = g_build_filename (g_get_home_dir (),
-      ".gstreamer-" GST_MAJORMINOR, "presets", "GstPresetTest.prs", NULL);
+  preset_file_name = g_build_filename (g_get_user_data_dir (),
+      "gstreamer-" GST_MAJORMINOR, "presets", "GstPresetTest.prs", NULL);
   g_unlink (preset_file_name);
   g_free (preset_file_name);
 }
@@ -281,9 +281,9 @@ gst_preset_suite (void)
   gchar *gst_dir;
   gboolean can_write = FALSE;
 
-  /* cehck if we can create presets */
-  gst_dir = g_build_filename (g_get_home_dir (),
-      ".gstreamer-" GST_MAJORMINOR, NULL);
+  /* check if we can create presets */
+  gst_dir = g_build_filename (g_get_user_data_dir (),
+      "gstreamer-" GST_MAJORMINOR, NULL);
   can_write = (g_access (gst_dir, R_OK | W_OK | X_OK) == 0);
   g_free (gst_dir);
 
index 97e0dfd..b37eec2 100644 (file)
@@ -145,40 +145,40 @@ GST_START_TEST (create_queries)
     fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
 
     /* empty */
-    gst_query_parse_formats_length (query, &size);
+    gst_query_parse_n_formats (query, &size);
     fail_if (size != 0);
 
     /* see if empty gives undefined formats */
-    gst_query_parse_formats_nth (query, 0, &format);
+    gst_query_parse_nth_format (query, 0, &format);
     fail_if (format != GST_FORMAT_UNDEFINED);
-    gst_query_parse_formats_nth (query, 1, &format);
+    gst_query_parse_nth_format (query, 1, &format);
     fail_if (format != GST_FORMAT_UNDEFINED);
 
     /* set 2 formats */
     gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
 
-    gst_query_parse_formats_length (query, &size);
+    gst_query_parse_n_formats (query, &size);
     fail_if (size != 2);
 
     format = GST_FORMAT_UNDEFINED;
 
-    gst_query_parse_formats_nth (query, 0, &format);
+    gst_query_parse_nth_format (query, 0, &format);
     fail_if (format != GST_FORMAT_TIME);
-    gst_query_parse_formats_nth (query, 1, &format);
+    gst_query_parse_nth_format (query, 1, &format);
     fail_if (format != GST_FORMAT_BYTES);
 
     /* out of bounds, should return UNDEFINED */
-    gst_query_parse_formats_nth (query, 2, &format);
+    gst_query_parse_nth_format (query, 2, &format);
     fail_if (format != GST_FORMAT_UNDEFINED);
 
     /* overwrite with 3 formats */
     gst_query_set_formats (query, 3, GST_FORMAT_TIME, GST_FORMAT_BYTES,
         GST_FORMAT_PERCENT);
 
-    gst_query_parse_formats_length (query, &size);
+    gst_query_parse_n_formats (query, &size);
     fail_if (size != 3);
 
-    gst_query_parse_formats_nth (query, 2, &format);
+    gst_query_parse_nth_format (query, 2, &format);
     fail_if (format != GST_FORMAT_PERCENT);
 
     /* create one from an array */
@@ -190,12 +190,12 @@ GST_START_TEST (create_queries)
       };
       gst_query_set_formatsv (query, 3, formats);
 
-      gst_query_parse_formats_length (query, &size);
+      gst_query_parse_n_formats (query, &size);
       fail_if (size != 3);
 
-      gst_query_parse_formats_nth (query, 0, &format);
+      gst_query_parse_nth_format (query, 0, &format);
       fail_if (format != GST_FORMAT_TIME);
-      gst_query_parse_formats_nth (query, 2, &format);
+      gst_query_parse_nth_format (query, 2, &format);
       fail_if (format != GST_FORMAT_PERCENT);
     }
     gst_query_unref (query);
index 91190cc..13d9772 100644 (file)
@@ -59,7 +59,7 @@ print_plugin (const gchar * marker, GstRegistry * registry, GstPlugin * plugin)
     feature = GST_PLUGIN_FEATURE (f->data);
 
     GST_LOG ("%s:    feature: %p %s", marker, feature,
-        gst_plugin_feature_get_name (feature));
+        GST_OBJECT_NAME (feature));
   }
   gst_plugin_feature_list_free (features);
 }
@@ -71,12 +71,12 @@ GST_START_TEST (test_registry_update)
   GstRegistry *registry;
   GList *plugins_before, *plugins_after, *l;
 
-  registry = gst_registry_get_default ();
+  registry = gst_registry_get ();
   fail_unless (registry != NULL);
   ASSERT_OBJECT_REFCOUNT (registry, "default registry", 1);
 
   /* refcount should still be 1 the second time */
-  registry = gst_registry_get_default ();
+  registry = gst_registry_get ();
   fail_unless (registry != NULL);
   ASSERT_OBJECT_REFCOUNT (registry, "default registry", 1);
 
index 2c7b42b..bf86775 100644 (file)
@@ -27,13 +27,13 @@ GST_START_TEST (segment_seek_nosize)
 {
   GstSegment segment;
   gboolean res;
-  gint64 cstart, cstop;
+  guint64 cstart, cstop;
   gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
   /* configure segment to start 100 */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
@@ -41,15 +41,17 @@ GST_START_TEST (segment_seek_nosize)
   fail_unless (segment.stop == -1);
   fail_unless (update == TRUE);
 
+#if 0
   /* configure segment to stop relative, should not do anything since 
    * size is unknown. */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
   fail_unless (update == FALSE);
+#endif
 
   /* do some clipping on the open range */
   /* completely outside */
@@ -121,22 +123,22 @@ GST_START_TEST (segment_seek_nosize)
   fail_unless (cstop == -1);
 
   /* add 100 to start, set stop to 300 */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
-      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
+      GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
   fail_unless (update == TRUE);
 
   update = FALSE;
-  /* add 100 to start (to 300), set stop to 200, this is not allowed. 
+  /* add 100 to start (to 300), set stop to 200, this is not allowed.
    * nothing should be updated in the segment. A g_warning is
    * emited. */
-  ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
+  ASSERT_CRITICAL (gst_segment_do_seek (&segment, 1.0,
           GST_FORMAT_BYTES,
           GST_SEEK_FLAG_NONE,
-          GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update));
+          GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update));
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
   /* update didn't change */
@@ -145,7 +147,7 @@ GST_START_TEST (segment_seek_nosize)
   update = TRUE;
   /* seek relative to end, should not do anything since size is
    * unknown. */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
@@ -226,14 +228,14 @@ GST_START_TEST (segment_seek_size)
 {
   GstSegment segment;
   gboolean res;
-  gint64 cstart, cstop;
+  guint64 cstart, cstop;
   gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
-  gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
+  segment.duration = 200;
 
   /* configure segment to start 100 */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
@@ -241,15 +243,17 @@ GST_START_TEST (segment_seek_size)
   fail_unless (segment.stop == -1);
   fail_unless (update == TRUE);
 
+#if 0
   /* configure segment to stop relative, does not update stop
    * since we did not set it before. */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
   fail_unless (update == FALSE);
+#endif
 
   /* do some clipping on the open range */
   /* completely outside */
@@ -310,25 +314,25 @@ GST_START_TEST (segment_seek_size)
   fail_unless (cstop == -1);
 
   /* add 100 to start, set stop to 300, stop clips to 200 */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
-      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
+      GST_SEEK_TYPE_SET, 100 + 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
 
   /* add 100 to start (to 300), set stop to 200, this clips start
    * to duration */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
-      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update);
+      GST_SEEK_TYPE_SET, 200 + 100, GST_SEEK_TYPE_SET, 200, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
   fail_unless (update == FALSE);
 
   /* seek relative to end */
-  gst_segment_set_seek (&segment, 1.0,
+  gst_segment_do_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
@@ -410,38 +414,38 @@ GST_START_TEST (segment_seek_reverse)
   gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
-  gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
+  segment.duration = 200;
 
   /* configure segment to stop 100 */
-  gst_segment_set_seek (&segment, -1.0,
+  gst_segment_do_seek (&segment, -1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 100, &update);
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 100);
   fail_unless (segment.time == 0);
-  fail_unless (segment.last_stop == 100);
+  fail_unless (segment.position == 100);
   fail_unless (update == TRUE);
 
   /* update */
-  gst_segment_set_seek (&segment, -1.0,
+  gst_segment_do_seek (&segment, -1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
-      GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_CUR, -20, &update);
+      GST_SEEK_TYPE_SET, 10, GST_SEEK_TYPE_SET, 100 - 20, &update);
   fail_unless (segment.start == 10);
   fail_unless (segment.stop == 80);
   fail_unless (segment.time == 10);
-  fail_unless (segment.last_stop == 80);
+  fail_unless (segment.position == 80);
   fail_unless (update == TRUE);
 
-  gst_segment_set_seek (&segment, -1.0,
+  gst_segment_do_seek (&segment, -1.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_NONE, 0, &update);
   fail_unless (segment.start == 20);
   fail_unless (segment.stop == 80);
   fail_unless (segment.time == 20);
-  fail_unless (segment.last_stop == 80);
+  fail_unless (segment.position == 80);
   fail_unless (update == FALSE);
 }
 
@@ -455,10 +459,9 @@ GST_START_TEST (segment_seek_rate)
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
-  /* configure segment to rate 2.0, format does not matter when we don't specify
-   * a start or stop position. */
-  gst_segment_set_seek (&segment, 2.0,
-      GST_FORMAT_UNDEFINED,
+  /* configure segment to rate 2.0 */
+  gst_segment_do_seek (&segment, 2.0,
+      GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.format == GST_FORMAT_BYTES);
@@ -467,43 +470,45 @@ GST_START_TEST (segment_seek_rate)
   fail_unless (segment.rate == 2.0);
   fail_unless (update == FALSE);
 
+#if 0
   /* 0 is the same in all formats and should not fail */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.format == GST_FORMAT_BYTES);
 
   /* set to -1 means start from 0 */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_SET, -1, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.format == GST_FORMAT_BYTES);
   fail_unless (segment.start == 0);
 
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_CUR, 0, GST_SEEK_TYPE_NONE, -1, &update);
 
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_END, 0, GST_SEEK_TYPE_NONE, -1, &update);
 
   /* -1 for end is fine too in all formats */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, -1, &update);
 
   /* 0 as relative end is fine too */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_CUR, 0, &update);
 
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
+#endif
 
   /* set a real stop position, this must happen in bytes */
-  gst_segment_set_seek (&segment, 3.0,
+  gst_segment_do_seek (&segment, 3.0,
       GST_FORMAT_BYTES,
       GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
@@ -515,52 +520,54 @@ GST_START_TEST (segment_seek_rate)
    * playback mode.*/
   fail_unless (update == FALSE);
 
+#if 0
   /* 0 as relative end is fine too */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_CUR, 0, &update);
   fail_unless (segment.stop == 100);
 
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
   fail_unless (segment.stop == 100);
 
   /* -1 for end is fine too in all formats */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, -1, &update);
   fail_unless (segment.stop == -1);
+#endif
 
   /* set some duration, stop -1 END seeks will now work with the
    * duration, if the formats match */
-  gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
+  segment.duration = 200;
   fail_unless (segment.duration == 200);
 
-  /* seek to end in any format with 0 should set the stop to the
-   * duration */
-  gst_segment_set_seek (&segment, 2.0,
-      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+  /* seek to end with 0 should set the stop to the duration */
+  gst_segment_do_seek (&segment, 2.0,
+      GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
   fail_unless (segment.stop == 200);
   fail_unless (segment.duration == 200);
 
   /* subtract 100 from the end */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
   fail_unless (segment.stop == 100);
   fail_unless (segment.duration == 200);
 
   /* add 100 to the duration, this should be clamped to the duration */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
   fail_unless (segment.stop == 200);
   fail_unless (segment.duration == 200);
 
+#if 0
   /* add 300 to the start, this should be clamped to the duration */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_CUR, 300, GST_SEEK_TYPE_END, 0, &update);
   fail_unless (segment.start == 200);
@@ -568,16 +575,19 @@ GST_START_TEST (segment_seek_rate)
   fail_unless (segment.duration == 200);
 
   /* subtract 300 from the start, this should be clamped to 0 */
-  gst_segment_set_seek (&segment, 2.0,
+  gst_segment_do_seek (&segment, 2.0,
       GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
       GST_SEEK_TYPE_CUR, -300, GST_SEEK_TYPE_END, 0, &update);
+  GST_DEBUG ("%" G_GINT64_FORMAT, segment.start);
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.duration == 200);
+#endif
 }
 
 GST_END_TEST;
 
+#if 0
 /* mess with the segment structure in the bytes format */
 GST_START_TEST (segment_newsegment_open)
 {
@@ -586,7 +596,8 @@ GST_START_TEST (segment_newsegment_open)
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
   /* time should also work for starting from 0 */
-  gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0, -1,
+      0);
 
   fail_unless (segment.rate == 1.0);
   fail_unless (segment.format == GST_FORMAT_BYTES);
@@ -594,58 +605,62 @@ GST_START_TEST (segment_newsegment_open)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* we set stop but in the wrong format, stop stays open. */
-  gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_TIME, 0, 200, 0);
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0, GST_FORMAT_TIME, 0,
+      200, 0);
 
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
 
   /* update, nothing changes */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0, GST_FORMAT_BYTES, 0, -1,
+      0);
 
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
 
   /* update */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0,
       GST_FORMAT_BYTES, 100, -1, 100);
 
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 100);
-  fail_unless (segment.accum == 100);
-  fail_unless (segment.last_stop == 100);
+  fail_unless (segment.base == 100);
+  fail_unless (segment.position == 100);
 
-  /* last_stop 0, accum does not change */
-  gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
+  /* last_stop 0, base does not change */
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0, GST_FORMAT_BYTES, 0,
+      -1, 0);
 
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 100);
+  fail_unless (segment.base == 100);
 
   gst_segment_set_last_stop (&segment, GST_FORMAT_BYTES, 200);
 
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.position == 200);
 
-  /* last_stop 200, accum changes */
-  gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
+  /* last_stop 200, base changes */
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0, GST_FORMAT_BYTES, 0,
+      -1, 0);
 
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == -1);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 300);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 300);
+  fail_unless (segment.position == 0);
 }
 
 GST_END_TEST;
@@ -658,7 +673,7 @@ GST_START_TEST (segment_newsegment_closed)
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
-  gst_segment_set_newsegment (&segment, FALSE, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_BYTES, 0, 200, 0);
 
   fail_unless (segment.rate == 1.0);
@@ -667,60 +682,60 @@ GST_START_TEST (segment_newsegment_closed)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* assume we advanced to position 40 */
   gst_segment_set_last_stop (&segment, GST_FORMAT_BYTES, 40);
-  fail_unless (segment.last_stop == 40);
+  fail_unless (segment.position == 40);
 
   /* do an update to the start, last_stop is unchanged because it's bigger */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0, GST_FORMAT_BYTES, 20, 200,
-      20);
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0, GST_FORMAT_BYTES, 20,
+      200, 20);
 
   fail_unless (segment.start == 20);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 20);
-  fail_unless (segment.accum == 20);
-  fail_unless (segment.last_stop == 40);
+  fail_unless (segment.base == 20);
+  fail_unless (segment.position == 40);
 
   /* do an update past our last_stop, it should be updated now */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0, GST_FORMAT_BYTES, 50, 300,
-      50);
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0, GST_FORMAT_BYTES, 50,
+      300, 50);
 
   fail_unless (segment.start == 50);
   fail_unless (segment.stop == 300);
   fail_unless (segment.time == 50);
-  fail_unless (segment.accum == 50);
-  fail_unless (segment.last_stop == 50);
+  fail_unless (segment.base == 50);
+  fail_unless (segment.position == 50);
 
   /* and a new accumulated one */
-  gst_segment_set_newsegment (&segment, FALSE, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_BYTES, 100, 400, 300);
 
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == 400);
   fail_unless (segment.time == 300);
-  fail_unless (segment.accum == 300);
+  fail_unless (segment.base == 300);
 
   /* and a new updated one */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0,
       GST_FORMAT_BYTES, 100, 500, 300);
 
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == 500);
   fail_unless (segment.time == 300);
-  fail_unless (segment.accum == 300);
+  fail_unless (segment.base == 300);
 
   /* and a new partially updated one */
-  gst_segment_set_newsegment (&segment, TRUE, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0,
       GST_FORMAT_BYTES, 200, 500, 400);
 
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 500);
   fail_unless (segment.time == 400);
-  fail_unless (segment.accum == 400);
+  fail_unless (segment.base == 400);
 }
 
 GST_END_TEST;
@@ -729,14 +744,14 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_streamtime)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
   /***************************
    * Normal segment
    ***************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == 1.0);
@@ -746,8 +761,8 @@ GST_START_TEST (segment_newsegment_streamtime)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -770,10 +785,10 @@ GST_START_TEST (segment_newsegment_streamtime)
   /*********************
    * time shifted by 500
    *********************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 500);
 
-  fail_unless (segment.accum == 200);
+  fail_unless (segment.base == 200);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
@@ -795,10 +810,10 @@ GST_START_TEST (segment_newsegment_streamtime)
   /*********************
    * time offset by 500
    *********************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 500, 700, 0);
 
-  fail_unless (segment.accum == 400);
+  fail_unless (segment.base == 400);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
@@ -824,10 +839,10 @@ GST_START_TEST (segment_newsegment_streamtime)
   /*************************************
    * time offset by 500, shifted by 200
    *************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 500, 700, 200);
 
-  fail_unless (segment.accum == 600);
+  fail_unless (segment.base == 600);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
@@ -857,14 +872,14 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_streamtime_rate)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
   /***************************
    * Normal segment rate 2.0
    ***************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 2.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == 2.0);
@@ -874,8 +889,8 @@ GST_START_TEST (segment_newsegment_streamtime_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -901,10 +916,10 @@ GST_START_TEST (segment_newsegment_streamtime_rate)
   /***************************************
    * Normal segment rate 2.0, offset
    ***************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 2.0, 1.0,
       GST_FORMAT_TIME, 100, 300, 0);
 
-  fail_unless (segment.accum == 100);
+  fail_unless (segment.base == 100);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
@@ -932,10 +947,10 @@ GST_START_TEST (segment_newsegment_streamtime_rate)
 
   /* buffers will arrive from 300 to 100 in a sink, stream time
    * calculation is unaffected by the rate */
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 1.0,
       GST_FORMAT_TIME, 100, 300, 0);
 
-  fail_unless (segment.accum == 200);
+  fail_unless (segment.base == 200);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
@@ -950,7 +965,7 @@ GST_START_TEST (segment_newsegment_streamtime_rate)
   /***********************************************
    * Normal segment rate -1.0, offset, time = 200
    ***********************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 1.0,
       GST_FORMAT_TIME, 100, 300, 200);
 
   /* invalid time gives invalid result */
@@ -977,7 +992,7 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_streamtime_applied_rate)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
@@ -986,7 +1001,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
    * This means the timestamps represents a stream going backwards
    * starting from @time to 0.
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, -1.0,
       GST_FORMAT_TIME, 0, 200, 200);
 
   fail_unless (segment.rate == 1.0);
@@ -996,8 +1011,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 200);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1026,7 +1041,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
    * This means the timestamps represents a stream at twice the
    * normal rate
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 2.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == 1.0);
@@ -1036,8 +1051,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 200);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 200);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1067,7 +1082,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
    * This means the timestamps represents a stream at twice the
    * reverse rate
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, -2.0,
       GST_FORMAT_TIME, 0, 200, 400);
 
   fail_unless (segment.rate == 1.0);
@@ -1078,8 +1093,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 400);
   /* previous segment lasted 200, rate of 2.0 was already applied */
-  fail_unless (segment.accum == 400);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 400);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1109,7 +1124,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
    * reverse rate, start time cannot compensate the complete
    * duration of the segment so we stop at 0
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, -2.0,
       GST_FORMAT_TIME, 0, 200, 200);
 
   fail_unless (segment.rate == 1.0);
@@ -1119,8 +1134,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 200);
-  fail_unless (segment.accum == 600);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 600);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1152,7 +1167,7 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
@@ -1162,7 +1177,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
    * speed up by a factor of 2.0 some more. the resulting
    * stream will be played at four times the speed. 
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 2.0,
+  gst_segment_set_newsegment (&segment, FALSE, 2.0, 2.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == 2.0);
@@ -1172,8 +1187,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1202,7 +1217,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
    * this means we have a reverse stream that we should
    * speed up by a factor of 2.0
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 2.0, -1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 2.0, -1.0,
       GST_FORMAT_TIME, 0, 200, 200);
 
   fail_unless (segment.rate == 2.0);
@@ -1213,8 +1228,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 200);
   /* previous segment lasted 100 */
-  fail_unless (segment.accum == 100);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 100);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1243,7 +1258,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
    * this means we have a reverse stream that we should
    * reverse to get the normal stream again.
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, -1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, -1.0,
       GST_FORMAT_TIME, 0, 200, 200);
 
   fail_unless (segment.rate == -1.0);
@@ -1254,8 +1269,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 200);
   /* accumulated 100 of previous segment to make 200 */
-  fail_unless (segment.accum == 200);
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.base == 200);
+  fail_unless (segment.position == 200);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1284,7 +1299,7 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
    * this means we have a reverse stream that we should
    * reverse to get the normal stream again.
    ************************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 2.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 2.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == -1.0);
@@ -1294,8 +1309,8 @@ GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 400);
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.base == 400);
+  fail_unless (segment.position == 200);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1326,14 +1341,14 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_runningtime)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
   /***************************
    * Normal segment
    ***************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == 1.0);
@@ -1343,8 +1358,8 @@ GST_START_TEST (segment_newsegment_runningtime)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 0);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 0);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1379,11 +1394,11 @@ GST_START_TEST (segment_newsegment_runningtime)
    * all positions by 2.0 in this segment.
    * Then time argument is not used at all here.
    ***********************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 2.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 500);
 
   /* normal speed gives elapsed of 200 */
-  fail_unless (segment.accum == 200);
+  fail_unless (segment.base == 200);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
@@ -1409,12 +1424,12 @@ GST_START_TEST (segment_newsegment_runningtime)
    * time offset by 500
    * applied rate is not used for running time
    ********************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 2.0,
       GST_FORMAT_TIME, 500, 700, 0);
 
   /* previous segment played at double speed gives elapsed time of
    * 100 added to previous accum of 200 gives 300. */
-  fail_unless (segment.accum == 300);
+  fail_unless (segment.base == 300);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
@@ -1453,10 +1468,10 @@ GST_START_TEST (segment_newsegment_runningtime)
    * relative to the segment stop position. again time
    * is ignored.
    **********************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 1.0,
       GST_FORMAT_TIME, 500, 700, 200);
 
-  fail_unless (segment.accum == 500);
+  fail_unless (segment.base == 500);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
@@ -1495,10 +1510,10 @@ GST_START_TEST (segment_newsegment_runningtime)
    * twice speed relative to the segment stop position. again 
    * time is ignored.
    **********************************************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -2.0,
+  gst_segment_set_newsegment (&segment, FALSE, -2.0, -2.0,
       GST_FORMAT_TIME, 500, 700, 200);
 
-  fail_unless (segment.accum == 700);
+  fail_unless (segment.base == 700);
 
   /* invalid time gives invalid result */
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
@@ -1533,11 +1548,11 @@ GST_START_TEST (segment_newsegment_runningtime)
   fail_unless (result == -1);
 
   /* see if negative rate closed segment correctly */
-  gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -2.0, -1.0,
       GST_FORMAT_TIME, 500, 700, 200);
 
   /* previous segment lasted 100, and was at 700 so we should get 800 */
-  fail_unless (segment.accum == 800);
+  fail_unless (segment.base == 800);
   result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 800);
   fail_unless (result == 700);
 }
@@ -1548,14 +1563,14 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_accum)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
   /***************************
    * Normal reverse segment
    ***************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == -1.0);
@@ -1565,8 +1580,8 @@ GST_START_TEST (segment_newsegment_accum)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 200);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1584,7 +1599,7 @@ GST_START_TEST (segment_newsegment_accum)
   fail_unless (result == 150);
 
   /* update segment, this accumulates 50 from the previous segment. */
-  gst_segment_set_newsegment_full (&segment, TRUE, -2.0, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, -2.0, 1.0,
       GST_FORMAT_TIME, 0, 150, 0);
 
   fail_unless (segment.rate == -2.0);
@@ -1594,8 +1609,8 @@ GST_START_TEST (segment_newsegment_accum)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 150);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 50);
-  fail_unless (segment.last_stop == 150);
+  fail_unless (segment.base == 50);
+  fail_unless (segment.position == 150);
   fail_unless (segment.duration == -1);
 
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
@@ -1610,7 +1625,7 @@ GST_START_TEST (segment_newsegment_accum)
   fail_unless (result == 100);
 
   /* update segment, this does not accumulate anything. */
-  gst_segment_set_newsegment_full (&segment, TRUE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, 1.0, 1.0,
       GST_FORMAT_TIME, 100, 200, 100);
 
   fail_unless (segment.rate == 1.0);
@@ -1620,8 +1635,8 @@ GST_START_TEST (segment_newsegment_accum)
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 100);
-  fail_unless (segment.accum == 50);
-  fail_unless (segment.last_stop == 150);
+  fail_unless (segment.base == 50);
+  fail_unless (segment.position == 150);
   fail_unless (segment.duration == -1);
 
   result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
@@ -1641,14 +1656,14 @@ GST_END_TEST;
 GST_START_TEST (segment_newsegment_accum2)
 {
   GstSegment segment;
-  gint64 result;
+  guint64 result;
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
   /***************************
    * Normal reverse segment
    ***************************/
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, -1.0, 1.0,
       GST_FORMAT_TIME, 0, 200, 0);
 
   fail_unless (segment.rate == -1.0);
@@ -1658,8 +1673,8 @@ GST_START_TEST (segment_newsegment_accum2)
   fail_unless (segment.start == 0);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 200);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1679,7 +1694,7 @@ GST_START_TEST (segment_newsegment_accum2)
   fail_unless (result == 150);
 
   /* close segment, this accumulates nothing. */
-  gst_segment_set_newsegment_full (&segment, TRUE, -1.0, 1.0,
+  gst_segment_set_newsegment (&segment, TRUE, -1.0, 1.0,
       GST_FORMAT_TIME, 150, 200, 0);
 
   fail_unless (segment.rate == -1.0);
@@ -1689,12 +1704,12 @@ GST_START_TEST (segment_newsegment_accum2)
   fail_unless (segment.start == 150);
   fail_unless (segment.stop == 200);
   fail_unless (segment.time == 0);
-  fail_unless (segment.accum == 0);
-  fail_unless (segment.last_stop == 200);
+  fail_unless (segment.base == 0);
+  fail_unless (segment.position == 200);
   fail_unless (segment.duration == -1);
 
   /* new segment, this accumulates 50. */
-  gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+  gst_segment_set_newsegment (&segment, FALSE, 1.0, 1.0,
       GST_FORMAT_TIME, 150, 300, 150);
 
   fail_unless (segment.rate == 1.0);
@@ -1704,8 +1719,8 @@ GST_START_TEST (segment_newsegment_accum2)
   fail_unless (segment.start == 150);
   fail_unless (segment.stop == 300);
   fail_unless (segment.time == 150);
-  fail_unless (segment.accum == 50);
-  fail_unless (segment.last_stop == 150);
+  fail_unless (segment.base == 50);
+  fail_unless (segment.position == 150);
   fail_unless (segment.duration == -1);
 
   /* invalid time gives invalid result */
@@ -1724,6 +1739,7 @@ GST_START_TEST (segment_newsegment_accum2)
 }
 
 GST_END_TEST;
+#endif
 
 GST_START_TEST (segment_copy)
 {
@@ -1735,8 +1751,11 @@ GST_START_TEST (segment_copy)
 
   gst_segment_init (&segment, GST_FORMAT_TIME);
 
-  gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
-      GST_FORMAT_TIME, 0, 200, 0);
+  segment.rate = -1.0;
+  segment.applied_rate = 1.0;
+  segment.start = 0;
+  segment.stop = 200;
+  segment.time = 0;
 
   copy = gst_segment_copy (&segment);
   fail_unless (copy != NULL);
@@ -1761,6 +1780,7 @@ gst_segment_suite (void)
   tcase_add_test (tc_chain, segment_seek_size);
   tcase_add_test (tc_chain, segment_seek_reverse);
   tcase_add_test (tc_chain, segment_seek_rate);
+#if 0
   tcase_add_test (tc_chain, segment_newsegment_open);
   tcase_add_test (tc_chain, segment_newsegment_closed);
   tcase_add_test (tc_chain, segment_newsegment_streamtime);
@@ -1770,6 +1790,7 @@ gst_segment_suite (void)
   tcase_add_test (tc_chain, segment_newsegment_runningtime);
   tcase_add_test (tc_chain, segment_newsegment_accum);
   tcase_add_test (tc_chain, segment_newsegment_accum2);
+#endif
   tcase_add_test (tc_chain, segment_copy);
 
   return s;
index 58beee8..6a258f8 100644 (file)
@@ -159,11 +159,9 @@ GST_START_TEST (test_from_string)
   fail_unless_equals_int (g_value_get_boolean (val), TRUE);
   gst_structure_free (structure);
 
-  /* This should still work for now (FIXME: 0.11) */
   s = "0.10:decoder-video/mpeg, abc=(boolean)false";
-  structure = gst_structure_from_string (s, NULL);
-  fail_if (structure == NULL, "Could not get structure from string %s", s);
-  gst_structure_free (structure);
+  ASSERT_CRITICAL (structure = gst_structure_from_string (s, NULL));
+  fail_unless (structure == NULL, "Could not get structure from string %s", s);
 
   /* make sure we bail out correctly in case of an error or if parsing fails */
   s = "***foo***, abc=(boolean)false";
@@ -185,25 +183,13 @@ GST_START_TEST (test_to_string)
 {
   GstStructure *st1;
 
-  ASSERT_CRITICAL (st1 = gst_structure_new ("Foo\nwith-newline", NULL));
+  ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo\nwith-newline"));
   fail_unless (st1 == NULL);
 
-  /* FIXME 0.11: re-enable this */
-#if 0
-  ASSERT_CRITICAL (st1 = gst_structure_new ("Foo with whitespace", NULL));
+  ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo with whitespace"));
   fail_unless (st1 == NULL);
-  ASSERT_CRITICAL (st1 = gst_structure_new ("1st", NULL));
+  ASSERT_CRITICAL (st1 = gst_structure_new_empty ("1st"));
   fail_unless (st1 == NULL);
-#else
-  st1 = gst_structure_new ("Foo with whitespace is still allowed", NULL);
-  fail_unless (st1 != NULL);
-  gst_structure_free (st1);
-
-  /* structure names starting with a number are also still allowed */
-  st1 = gst_structure_new ("1st", NULL);
-  fail_unless (st1 != NULL);
-  gst_structure_free (st1);
-#endif
 }
 
 GST_END_TEST;
@@ -298,26 +284,24 @@ GST_START_TEST (test_structure_new)
   gboolean bool;
   gint num, den;
   GstClockTime clocktime;
-  guint32 fourcc;
 
   s = gst_structure_new ("name",
       "key", G_TYPE_STRING, "value",
       "bool", G_TYPE_BOOLEAN, TRUE,
       "fraction", GST_TYPE_FRACTION, 1, 5,
-      "clocktime", GST_TYPE_CLOCK_TIME, GST_CLOCK_TIME_NONE,
-      "fourcc", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('f', 'o', 'u', 'r'), NULL);
+      "clocktime", GST_TYPE_CLOCK_TIME, GST_CLOCK_TIME_NONE, NULL);
 
   fail_unless (gst_structure_get_field_type (s, "unknown") == G_TYPE_INVALID);
   /* test setting a different name */
   gst_structure_set_name (s, "newname");
   fail_unless (strcmp (gst_structure_get_string (s, "key"), "value") == 0);
   fail_unless (gst_structure_has_field (s, "key"));
-  fail_unless_equals_int (gst_structure_n_fields (s), 5);
+  fail_unless_equals_int (gst_structure_n_fields (s), 4);
   /* test removing a field */
   gst_structure_remove_field (s, "key");
   fail_if (gst_structure_get_string (s, "key"));
   fail_if (gst_structure_has_field (s, "key"));
-  fail_unless_equals_int (gst_structure_n_fields (s), 4);
+  fail_unless_equals_int (gst_structure_n_fields (s), 3);
 
   fail_unless (gst_structure_get_boolean (s, "bool", &bool));
   fail_unless (bool);
@@ -329,18 +313,16 @@ GST_START_TEST (test_structure_new)
   fail_unless (gst_structure_get_clock_time (s, "clocktime", &clocktime));
   fail_unless_equals_uint64 (clocktime, GST_CLOCK_TIME_NONE);
 
-  fail_unless (gst_structure_get_fourcc (s, "fourcc", &fourcc));
-
   gst_structure_free (s);
 
   domain = g_quark_from_static_string ("test");
   e = g_error_new (domain, 0, "a test error");
-  s = gst_structure_new ("name", "key", GST_TYPE_G_ERROR, e, NULL);
+  s = gst_structure_new ("name", "key", G_TYPE_ERROR, e, NULL);
   g_error_free (e);
   gst_structure_free (s);
 
-  /* This should still work for now (FIXME 0.11) */
-  gst_structure_free (gst_structure_new ("0.10:decoder-video/mpeg", NULL));
+  ASSERT_CRITICAL (gst_structure_free (gst_structure_new_empty
+          ("0.10:decoder-video/mpeg")));
 
   /* make sure we bail out correctly in case of an error or if parsing fails */
   ASSERT_CRITICAL (s = gst_structure_new ("^joo\nba\ndoo^",
@@ -387,7 +369,7 @@ GST_START_TEST (test_fixate_frac_list)
   gst_value_set_fraction (&frac, 10, 1);
   gst_value_list_append_value (&list, &frac);
 
-  s = gst_structure_new ("name", NULL);
+  s = gst_structure_new_empty ("name");
   gst_structure_set_value (s, "frac", &list);
   g_value_unset (&frac);
   g_value_unset (&list);
@@ -527,13 +509,17 @@ GST_START_TEST (test_vararg_getters)
   gint64 i64;
   gchar *c;
   gint i, num, denom;
+  guint8 *data;
 
   buf = gst_buffer_new_and_alloc (3);
-  GST_BUFFER_DATA (buf)[0] = 0xf0;
-  GST_BUFFER_DATA (buf)[1] = 0x66;
-  GST_BUFFER_DATA (buf)[2] = 0x0d;
 
-  caps = gst_caps_new_simple ("video/x-foo", NULL);
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+  data[0] = 0xf0;
+  data[1] = 0x66;
+  data[2] = 0x0d;
+  gst_buffer_unmap (buf, data, 3);
+
+  caps = gst_caps_new_empty_simple ("video/x-foo");
 
   s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
       G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
index 30a352e..b690e2d 100644 (file)
@@ -67,7 +67,7 @@ check_tags_empty (const GstTagList * list)
 #define NEW_LIST_FIXED(mode)                                    \
 G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
-  list = gst_tag_list_new ();                                   \
+  list = gst_tag_list_new_empty ();                                   \
   gst_tag_list_add (list, mode, FTAG, FIXED1, FTAG, FIXED2,     \
                     FTAG, FIXED3, FTAG, FIXED4, NULL);          \
   mark_point();                                                 \
@@ -76,7 +76,7 @@ G_STMT_START {                                                  \
 #define NEW_LIST_UNFIXED(mode)                                  \
 G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
-  list = gst_tag_list_new ();                                   \
+  list = gst_tag_list_new_empty ();                                   \
   gst_tag_list_add (list, mode, UTAG, UNFIXED1, UTAG, UNFIXED2, \
                     UTAG, UNFIXED3, UTAG, UNFIXED4, NULL);      \
   mark_point();                                                 \
@@ -85,11 +85,11 @@ G_STMT_START {                                                  \
 #define NEW_LISTS_FIXED(mode)                                   \
 G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
-  list = gst_tag_list_new ();                                   \
+  list = gst_tag_list_new_empty ();                                   \
   gst_tag_list_add (list, GST_TAG_MERGE_APPEND, FTAG, FIXED1,   \
                     FTAG, FIXED2, NULL);                        \
   if (list2) gst_tag_list_free (list2);                         \
-  list2 = gst_tag_list_new ();                                  \
+  list2 = gst_tag_list_new_empty ();                                  \
   gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, FTAG, FIXED3,  \
                     FTAG, FIXED4, NULL);                        \
   if (merge) gst_tag_list_free (merge);                         \
@@ -100,11 +100,11 @@ G_STMT_START {                                                  \
 #define NEW_LISTS_UNFIXED(mode)                                 \
 G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
-  list = gst_tag_list_new ();                                   \
+  list = gst_tag_list_new_empty ();                                   \
   gst_tag_list_add (list, GST_TAG_MERGE_APPEND, UTAG, UNFIXED1, \
                     UTAG, UNFIXED2, NULL);                      \
   if (list2) gst_tag_list_free (list2);                         \
-  list2 = gst_tag_list_new ();                                  \
+  list2 = gst_tag_list_new_empty ();                                  \
   gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, UTAG, UNFIXED3,\
                     UTAG, UNFIXED4, NULL);                      \
   if (merge) gst_tag_list_free (merge);                         \
@@ -117,7 +117,7 @@ G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
   list = NULL;                                                  \
   if (list2) gst_tag_list_free (list2);                         \
-  list2 = gst_tag_list_new ();                                  \
+  list2 = gst_tag_list_new_empty ();                                  \
   gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, FTAG, FIXED3,  \
                     FTAG, FIXED4, NULL);                        \
   if (merge) gst_tag_list_free (merge);                         \
@@ -128,7 +128,7 @@ G_STMT_START {                                                  \
 #define NEW_LISTS_EMPTY2(mode)                                   \
 G_STMT_START {                                                  \
   if (list) gst_tag_list_free (list);                           \
-  list = gst_tag_list_new ();                                   \
+  list = gst_tag_list_new_empty ();                                   \
   gst_tag_list_add (list, GST_TAG_MERGE_APPEND, FTAG, FIXED1,   \
                     FTAG, FIXED2, NULL);                        \
   if (list2) gst_tag_list_free (list2);                         \
@@ -271,7 +271,7 @@ GST_START_TEST (test_date_tags)
   gchar *str;
 
   date = g_date_new_dmy (14, 10, 2005);
-  tag_list = gst_tag_list_new ();
+  tag_list = gst_tag_list_new_empty ();
   gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, GST_TAG_DATE, date, NULL);
 
   str = gst_tag_list_to_string (tag_list);
@@ -304,7 +304,7 @@ GST_START_TEST (test_type)
 {
   GstTagList *taglist;
 
-  taglist = gst_tag_list_new ();
+  taglist = gst_tag_list_new_empty ();
   fail_unless (GST_IS_TAG_LIST (taglist));
   fail_unless (gst_is_tag_list (taglist));
   gst_tag_list_free (taglist);
@@ -317,7 +317,7 @@ GST_START_TEST (test_type)
 
   /* check gst_tag_list_is_empty */
   ASSERT_CRITICAL (gst_tag_list_is_empty (NULL));
-  taglist = gst_tag_list_new ();
+  taglist = gst_tag_list_new_empty ();
   fail_unless (gst_tag_list_is_empty (taglist));
   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "JD", NULL);
   fail_if (gst_tag_list_is_empty (taglist));
@@ -331,7 +331,7 @@ GST_START_TEST (test_set_non_utf8_string)
   GstTagList *taglist;
   guint8 foobar[2] = { 0xff, 0x00 };    /* not UTF-8 */
 
-  taglist = gst_tag_list_new ();
+  taglist = gst_tag_list_new_empty ();
   fail_unless (taglist != NULL);
 
   ASSERT_WARNING (gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
@@ -350,7 +350,7 @@ GST_START_TEST (test_buffer_tags)
   GstTagList *tags;
   GstBuffer *buf1, *buf2;
 
-  tags = gst_tag_list_new ();
+  tags = gst_tag_list_new_empty ();
   buf1 = gst_buffer_new_and_alloc (222);
   buf2 = gst_buffer_new_and_alloc (100);
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, buf1,
@@ -374,8 +374,8 @@ GST_START_TEST (test_buffer_tags)
   fail_if (!gst_tag_list_get_buffer_index (tags, GST_TAG_IMAGE, 0, &buf1));
   fail_if (!gst_tag_list_get_buffer_index (tags, GST_TAG_PREVIEW_IMAGE, 0,
           &buf2));
-  fail_unless_equals_int (GST_BUFFER_SIZE (buf1), 222);
-  fail_unless_equals_int (GST_BUFFER_SIZE (buf2), 100);
+  fail_unless_equals_int (gst_buffer_get_size (buf1), 222);
+  fail_unless_equals_int (gst_buffer_get_size (buf2), 100);
 
   gst_buffer_unref (buf1);
   gst_buffer_unref (buf2);
@@ -393,7 +393,7 @@ GST_START_TEST (test_empty_tags)
   if (GST_VERSION_NANO != 1)
     return;
 
-  tags = gst_tag_list_new ();
+  tags = gst_tag_list_new_empty ();
   ASSERT_WARNING (gst_tag_list_add (tags, GST_TAG_MERGE_APPEND,
           GST_TAG_ARTIST, NULL, NULL));
   ASSERT_WARNING (gst_tag_list_add (tags, GST_TAG_MERGE_APPEND,
@@ -411,7 +411,7 @@ GST_START_TEST (test_new_full)
   gdouble track_gain;
   guint track_num;
 
-  tags = gst_tag_list_new_full (GST_TAG_ARTIST, "Arty Ist",
+  tags = gst_tag_list_new (GST_TAG_ARTIST, "Arty Ist",
       GST_TAG_TRACK_NUMBER, 9, GST_TAG_TRACK_GAIN, 4.242, GST_TAG_TITLE,
       "Title!", NULL);
 
@@ -437,7 +437,7 @@ GST_START_TEST (test_merge_strings_with_comma)
   GstTagList *tags;
   gchar *artists = NULL;
 
-  tags = gst_tag_list_new ();
+  tags = gst_tag_list_new_empty ();
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL);
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL);
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL);
@@ -457,12 +457,12 @@ GST_START_TEST (test_equal)
 {
   GstTagList *tags, *tags2;
 
-  tags = gst_tag_list_new ();
+  tags = gst_tag_list_new_empty ();
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Foo", NULL);
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Bar", NULL);
   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL);
 
-  tags2 = gst_tag_list_new ();
+  tags2 = gst_tag_list_new_empty ();
   fail_unless (!gst_tag_list_is_equal (tags2, tags));
   gst_tag_list_add (tags2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "Yay", NULL);
   fail_unless (!gst_tag_list_is_equal (tags2, tags));
index 5802823..6acdbd3 100644 (file)
 typedef GstElement GstDummyEnc;
 typedef GstElementClass GstDummyEncClass;
 
-static void gst_dummy_enc_add_interfaces (GType enc_type);
-
 GType gst_dummy_enc_get_type (void);
-GST_BOILERPLATE_FULL (GstDummyEnc, gst_dummy_enc, GstElement,
-    GST_TYPE_ELEMENT, gst_dummy_enc_add_interfaces);
-
-static void
-gst_dummy_enc_add_interfaces (GType enc_type)
-{
-  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-
-  g_type_add_interface_static (enc_type, GST_TYPE_TAG_SETTER, &tag_setter_info);
-}
-
-static void
-gst_dummy_enc_base_init (gpointer g_class)
-{
-}
+G_DEFINE_TYPE_WITH_CODE (GstDummyEnc, gst_dummy_enc,
+    GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
 
 static void
 gst_dummy_enc_class_init (GstDummyEncClass * klass)
@@ -52,7 +37,7 @@ gst_dummy_enc_class_init (GstDummyEncClass * klass)
 }
 
 static void
-gst_dummy_enc_init (GstDummyEnc * enc, GstDummyEncClass * klass)
+gst_dummy_enc_init (GstDummyEnc * enc)
 {
 }
 
@@ -105,13 +90,13 @@ GST_START_TEST (test_merge)
 
   setter = GST_TAG_SETTER (enc);
 
-  list1 = gst_tag_list_new ();
+  list1 = gst_tag_list_new_empty ();
   gst_tag_list_add (list1, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "artist1",
       NULL);
   gst_tag_setter_merge_tags (setter, list1, GST_TAG_MERGE_APPEND);
   assert_tag_setter_list_length (setter, 1);
 
-  list2 = gst_tag_list_new ();
+  list2 = gst_tag_list_new_empty ();
   gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST, "artist2",
       GST_TAG_TITLE, "title1", NULL);
   gst_tag_setter_merge_tags (setter, list2, GST_TAG_MERGE_APPEND);
@@ -150,8 +135,8 @@ GST_START_TEST (test_merge_modes)
       fail_unless (enc != NULL);
 
       setter = GST_TAG_SETTER (enc);
-      list1 = gst_tag_list_new ();
-      list2 = gst_tag_list_new ();
+      list1 = gst_tag_list_new_empty ();
+      list2 = gst_tag_list_new_empty ();
 
       /* i = 0: -     -
        * i = 1: list1 -
@@ -200,8 +185,8 @@ GST_START_TEST (test_merge_modes_skip_empty)
       fail_unless (enc != NULL);
 
       setter = GST_TAG_SETTER (enc);
-      list1 = gst_tag_list_new ();
-      list2 = gst_tag_list_new ();
+      list1 = gst_tag_list_new_empty ();
+      list2 = gst_tag_list_new_empty ();
 
       if (i == 1) {
         gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST,
index e7b169a..824f926 100644 (file)
 
 #include <gst/check/gstcheck.h>
 
-static GMutex *task_lock;
-static GCond *task_cond;
+static GMutex task_lock;
+static GCond task_cond;
 
-static GStaticRecMutex task_mutex = G_STATIC_REC_MUTEX_INIT;
+static GRecMutex task_mutex;
 
 static void
 task_func2 (void *data)
@@ -32,10 +32,10 @@ task_func2 (void *data)
   gboolean ret;
   GstTask *t = *((GstTask **) data);
 
-  g_mutex_lock (task_lock);
+  g_mutex_lock (&task_lock);
   GST_DEBUG ("signal");
-  g_cond_signal (task_cond);
-  g_mutex_unlock (task_lock);
+  g_cond_signal (&task_cond);
+  g_mutex_unlock (&task_lock);
 
   ASSERT_WARNING (ret = gst_task_join (t));
   fail_unless (ret == FALSE);
@@ -46,23 +46,24 @@ GST_START_TEST (test_join)
   GstTask *t;
   gboolean ret;
 
-  t = gst_task_create (task_func2, &t);
+  t = gst_task_new (task_func2, &t);
   fail_if (t == NULL);
 
+  g_rec_mutex_init (&task_mutex);
   gst_task_set_lock (t, &task_mutex);
 
-  task_cond = g_cond_new ();
-  task_lock = g_mutex_new ();
+  g_cond_init (&task_cond);
+  g_mutex_init (&task_lock);
 
-  g_mutex_lock (task_lock);
+  g_mutex_lock (&task_lock);
   GST_DEBUG ("starting");
   ret = gst_task_start (t);
   fail_unless (ret == TRUE);
   /* wait for it to spin up */
   GST_DEBUG ("waiting");
-  g_cond_wait (task_cond, task_lock);
+  g_cond_wait (&task_cond, &task_lock);
   GST_DEBUG ("done waiting");
-  g_mutex_unlock (task_lock);
+  g_mutex_unlock (&task_lock);
 
   GST_DEBUG ("joining");
   ret = gst_task_join (t);
@@ -78,10 +79,10 @@ GST_END_TEST;
 static void
 task_func (void *data)
 {
-  g_mutex_lock (task_lock);
+  g_mutex_lock (&task_lock);
   GST_DEBUG ("signal");
-  g_cond_signal (task_cond);
-  g_mutex_unlock (task_lock);
+  g_cond_signal (&task_cond);
+  g_mutex_unlock (&task_lock);
 }
 
 GST_START_TEST (test_lock_start)
@@ -89,23 +90,24 @@ GST_START_TEST (test_lock_start)
   GstTask *t;
   gboolean ret;
 
-  t = gst_task_create (task_func, NULL);
+  t = gst_task_new (task_func, NULL);
   fail_if (t == NULL);
 
+  g_rec_mutex_init (&task_mutex);
   gst_task_set_lock (t, &task_mutex);
 
-  task_cond = g_cond_new ();
-  task_lock = g_mutex_new ();
+  g_cond_init (&task_cond);
+  g_mutex_init (&task_lock);
 
-  g_mutex_lock (task_lock);
+  g_mutex_lock (&task_lock);
   GST_DEBUG ("starting");
   ret = gst_task_start (t);
   fail_unless (ret == TRUE);
   /* wait for it to spin up */
   GST_DEBUG ("waiting");
-  g_cond_wait (task_cond, task_lock);
+  g_cond_wait (&task_cond, &task_lock);
   GST_DEBUG ("done waiting");
-  g_mutex_unlock (task_lock);
+  g_mutex_unlock (&task_lock);
 
   /* cannot set mutex now */
   ASSERT_WARNING (gst_task_set_lock (t, &task_mutex));
@@ -126,9 +128,10 @@ GST_START_TEST (test_lock)
   GstTask *t;
   gboolean ret;
 
-  t = gst_task_create (task_func, NULL);
+  t = gst_task_new (task_func, NULL);
   fail_if (t == NULL);
 
+  g_rec_mutex_init (&task_mutex);
   gst_task_set_lock (t, &task_mutex);
 
   GST_DEBUG ("pause");
@@ -153,7 +156,7 @@ GST_START_TEST (test_no_lock)
   GstTask *t;
   gboolean ret;
 
-  t = gst_task_create (task_func, NULL);
+  t = gst_task_new (task_func, NULL);
   fail_if (t == NULL);
 
   /* stop should be possible without lock */
@@ -179,7 +182,7 @@ GST_START_TEST (test_create)
 {
   GstTask *t;
 
-  t = gst_task_create (task_func, NULL);
+  t = gst_task_new (task_func, NULL);
   fail_if (t == NULL);
 
   gst_object_unref (t);
index 5324b14..ab82dc5 100644 (file)
@@ -32,42 +32,46 @@ static int n_data_probes = 0;
 static int n_buffer_probes = 0;
 static int n_event_probes = 0;
 
-static gboolean
-probe_do_nothing (GstPad * pad, GstMiniObject * obj, gpointer data)
+static GstPadProbeReturn
+probe_do_nothing (GstPad * pad, GstPadProbeInfo * info, gpointer data)
 {
+  GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
   GST_DEBUG_OBJECT (pad, "is buffer:%d", GST_IS_BUFFER (obj));
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
-static gboolean
-data_probe (GstPad * pad, GstMiniObject * obj, gpointer data)
+static GstPadProbeReturn
+data_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
 {
+  GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
   n_data_probes++;
   GST_DEBUG_OBJECT (pad, "data probe %d", n_data_probes);
-  g_assert (GST_IS_MINI_OBJECT (obj));
+  g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj));
   g_assert (data == SPECIAL_POINTER (0));
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
-static gboolean
-buffer_probe (GstPad * pad, GstBuffer * obj, gpointer data)
+static GstPadProbeReturn
+buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
 {
+  GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info);
   n_buffer_probes++;
   GST_DEBUG_OBJECT (pad, "buffer probe %d", n_buffer_probes);
   g_assert (GST_IS_BUFFER (obj));
   g_assert (data == SPECIAL_POINTER (1));
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
-static gboolean
-event_probe (GstPad * pad, GstEvent * obj, gpointer data)
+static GstPadProbeReturn
+event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
 {
+  GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info);
   n_event_probes++;
   GST_DEBUG_OBJECT (pad, "event probe %d [%s]",
       n_event_probes, GST_EVENT_TYPE_NAME (obj));
   g_assert (GST_IS_EVENT (obj));
   g_assert (data == SPECIAL_POINTER (2));
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_buffer_probe_n_times)
@@ -89,18 +93,20 @@ GST_START_TEST (test_buffer_probe_n_times)
   pad = gst_element_get_static_pad (fakesink, "sink");
 
   /* add the probes we need for the test */
-  gst_pad_add_data_probe (pad, G_CALLBACK (data_probe), SPECIAL_POINTER (0));
-  gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe),
-      SPECIAL_POINTER (1));
-  gst_pad_add_event_probe (pad, G_CALLBACK (event_probe), SPECIAL_POINTER (2));
-
-  /* add some probes just to test that _full works and the data is free'd
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, data_probe,
+      SPECIAL_POINTER (0), NULL);
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, buffer_probe,
+      SPECIAL_POINTER (1), NULL);
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, event_probe,
+      SPECIAL_POINTER (2), NULL);
+
+  /* add some string probes just to test that the data is free'd
    * properly as it should be */
-  gst_pad_add_data_probe_full (pad, G_CALLBACK (probe_do_nothing),
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, probe_do_nothing,
       g_strdup ("data probe string"), (GDestroyNotify) g_free);
-  gst_pad_add_buffer_probe_full (pad, G_CALLBACK (probe_do_nothing),
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, probe_do_nothing,
       g_strdup ("buffer probe string"), (GDestroyNotify) g_free);
-  gst_pad_add_event_probe_full (pad, G_CALLBACK (probe_do_nothing),
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, probe_do_nothing,
       g_strdup ("event probe string"), (GDestroyNotify) g_free);
 
   gst_object_unref (pad);
@@ -129,37 +135,43 @@ static int n_data_probes_once = 0;
 static int n_buffer_probes_once = 0;
 static int n_event_probes_once = 0;
 
-static gboolean
-data_probe_once (GstPad * pad, GstMiniObject * obj, guint * data)
+static GstPadProbeReturn
+data_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
 {
+  GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
+
   n_data_probes_once++;
-  g_assert (GST_IS_MINI_OBJECT (obj));
+  g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj));
 
-  gst_pad_remove_data_probe (pad, *data);
+  gst_pad_remove_probe (pad, *data);
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
-static gboolean
-buffer_probe_once (GstPad * pad, GstBuffer * obj, guint * data)
+static GstPadProbeReturn
+buffer_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
 {
+  GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info);
+
   n_buffer_probes_once++;
   g_assert (GST_IS_BUFFER (obj));
 
-  gst_pad_remove_buffer_probe (pad, *data);
+  gst_pad_remove_probe (pad, *data);
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
-static gboolean
-event_probe_once (GstPad * pad, GstEvent * obj, guint * data)
+static GstPadProbeReturn
+event_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
 {
+  GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info);
+
   n_event_probes_once++;
   g_assert (GST_IS_EVENT (obj));
 
-  gst_pad_remove_event_probe (pad, *data);
+  gst_pad_remove_probe (pad, *data);
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_buffer_probe_once)
@@ -180,9 +192,15 @@ GST_START_TEST (test_buffer_probe_once)
   gst_element_link (fakesrc, fakesink);
 
   pad = gst_element_get_static_pad (fakesink, "sink");
-  id1 = gst_pad_add_data_probe (pad, G_CALLBACK (data_probe_once), &id1);
-  id2 = gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe_once), &id2);
-  id3 = gst_pad_add_event_probe (pad, G_CALLBACK (event_probe_once), &id3);
+  id1 =
+      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH,
+      (GstPadProbeCallback) data_probe_once, &id1, NULL);
+  id2 =
+      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
+      (GstPadProbeCallback) buffer_probe_once, &id2, NULL);
+  id3 =
+      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) event_probe_once, &id3, NULL);
   gst_object_unref (pad);
 
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
@@ -471,11 +489,12 @@ GST_START_TEST (test_element_found_tags)
   GstTagList *list;
   GstBus *bus;
   GstMessage *message;
+  GstPad *srcpad;
 
   pipeline = gst_element_factory_make ("pipeline", NULL);
   fakesrc = gst_element_factory_make ("fakesrc", NULL);
   fakesink = gst_element_factory_make ("fakesink", NULL);
-  list = gst_tag_list_new ();
+  list = gst_tag_list_new_empty ();
 
   g_object_set (fakesrc, "num-buffers", (int) 10, NULL);
 
@@ -484,7 +503,9 @@ GST_START_TEST (test_element_found_tags)
 
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
-  gst_element_found_tags (GST_ELEMENT (fakesrc), list);
+  srcpad = gst_element_get_static_pad (fakesrc, "src");
+  gst_pad_push_event (srcpad, gst_event_new_tag (list));
+  gst_object_unref (srcpad);
 
   bus = gst_element_get_bus (pipeline);
   message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
@@ -954,7 +975,7 @@ GST_END_TEST;
 #endif
 #endif
 
-GST_START_TEST (test_pad_proxy_getcaps_aggregation)
+GST_START_TEST (test_pad_proxy_query_caps_aggregation)
 {
   GstElement *tee, *sink1, *sink2;
   GstCaps *caps;
@@ -963,36 +984,40 @@ GST_START_TEST (test_pad_proxy_getcaps_aggregation)
   tee = gst_element_factory_make ("tee", "tee");
 
   sink1 = gst_element_factory_make ("fakesink", "sink1");
-  tee_src1 = gst_element_get_request_pad (tee, "src%d");
+  tee_src1 = gst_element_get_request_pad (tee, "src_%u");
   sink1_sink = gst_element_get_static_pad (sink1, "sink");
   fail_unless_equals_int (gst_pad_link (tee_src1, sink1_sink), GST_PAD_LINK_OK);
 
   sink2 = gst_element_factory_make ("fakesink", "sink2");
-  tee_src2 = gst_element_get_request_pad (tee, "src%d");
+  tee_src2 = gst_element_get_request_pad (tee, "src_%u");
   sink2_sink = gst_element_get_static_pad (sink2, "sink");
   fail_unless_equals_int (gst_pad_link (tee_src2, sink2_sink), GST_PAD_LINK_OK);
 
   tee_sink = gst_element_get_static_pad (tee, "sink");
 
+  gst_element_set_state (sink1, GST_STATE_PAUSED);
+  gst_element_set_state (sink2, GST_STATE_PAUSED);
+  gst_element_set_state (tee, GST_STATE_PAUSED);
+
   /* by default, ANY caps should intersect to ANY */
-  caps = gst_pad_get_caps (tee_sink);
+  caps = gst_pad_query_caps (tee_sink, NULL);
   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_is_any (caps));
   gst_caps_unref (caps);
 
   /* these don't intersect we should get empty caps */
-  caps = gst_caps_new_simple ("foo/bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/bar");
   fail_unless (gst_pad_set_caps (sink1_sink, caps));
   gst_pad_use_fixed_caps (sink1_sink);
   gst_caps_unref (caps);
 
-  caps = gst_caps_new_simple ("bar/ter", NULL);
+  caps = gst_caps_new_empty_simple ("bar/ter");
   fail_unless (gst_pad_set_caps (sink2_sink, caps));
   gst_pad_use_fixed_caps (sink2_sink);
   gst_caps_unref (caps);
 
-  caps = gst_pad_get_caps (tee_sink);
+  caps = gst_pad_query_caps (tee_sink, NULL);
   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_is_empty (caps));
@@ -1004,7 +1029,7 @@ GST_START_TEST (test_pad_proxy_getcaps_aggregation)
   gst_pad_use_fixed_caps (sink2_sink);
   gst_caps_unref (caps);
 
-  caps = gst_pad_get_caps (tee_sink);
+  caps = gst_pad_query_caps (tee_sink, NULL);
   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
   fail_unless (caps != NULL);
   fail_if (gst_caps_is_empty (caps));
@@ -1016,6 +1041,10 @@ GST_START_TEST (test_pad_proxy_getcaps_aggregation)
   }
   gst_caps_unref (caps);
 
+  gst_element_set_state (sink1, GST_STATE_NULL);
+  gst_element_set_state (sink2, GST_STATE_NULL);
+  gst_element_set_state (tee, GST_STATE_NULL);
+
   /* clean up */
   gst_element_release_request_pad (tee, tee_src1);
   gst_object_unref (tee_src1);
@@ -1084,7 +1113,7 @@ gst_utils_suite (void)
   tcase_add_test (tc_chain, test_set_value_from_string);
   tcase_add_test (tc_chain, test_binary_search);
 
-  tcase_add_test (tc_chain, test_pad_proxy_getcaps_aggregation);
+  tcase_add_test (tc_chain, test_pad_proxy_query_caps_aggregation);
   tcase_add_test (tc_chain, test_greatest_common_divisor);
   return s;
 }
index 94f113e..64d57cd 100644 (file)
 #include <gst/check/gstcheck.h>
 
 
-GST_START_TEST (test_serialize_fourcc)
-{
-  int i;
-
-  guint32 fourccs[] = {
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
-    GST_MAKE_FOURCC ('Y', '8', '0', '0'),
-    GST_MAKE_FOURCC ('Y', '8', ' ', ' '),
-    GST_MAKE_FOURCC ('Y', '1', '6', ' '),
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '_'),
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '#'),
-  };
-  gint fourccs_size = sizeof (fourccs) / sizeof (fourccs[0]);
-  const gchar *fourcc_strings[] = {
-    "YUY2",
-    "Y800",
-    "Y8  ",
-    "Y16 ",
-    "0x5f595559",               /* Ascii values of YUY_ */
-    "0x23595559",               /* Ascii values of YUY# */
-  };
-  gint fourcc_strings_size =
-      sizeof (fourcc_strings) / sizeof (fourcc_strings[0]);
-
-  fail_unless (fourccs_size == fourcc_strings_size);
-
-  for (i = 0; i < fourccs_size; ++i) {
-    gchar *str;
-    GValue value = { 0 };
-    g_value_init (&value, GST_TYPE_FOURCC);
-
-    gst_value_set_fourcc (&value, fourccs[i]);
-    str = gst_value_serialize (&value);
-
-    fail_unless (strcmp (str, fourcc_strings[i]) == 0);
-
-    g_free (str);
-  }
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_deserialize_fourcc)
-{
-  int i;
-
-  guint32 fourccs[] = {
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
-    GST_MAKE_FOURCC ('Y', '8', '0', '0'),
-    GST_MAKE_FOURCC ('Y', '8', ' ', ' '),
-    GST_MAKE_FOURCC ('Y', '8', ' ', ' '),
-    GST_MAKE_FOURCC ('Y', '8', ' ', ' '),
-    GST_MAKE_FOURCC ('Y', '1', '6', ' '),
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '_'),
-    GST_MAKE_FOURCC ('Y', 'U', 'Y', '#'),
-  };
-  gint fourccs_size = sizeof (fourccs) / sizeof (fourccs[0]);
-  const gchar *fourcc_strings[] = {
-    "YUY2",
-    "Y800",
-    "Y8  ",
-    "Y8 ",
-    "Y8",
-    "Y16 ",
-    "0x5f595559",               /* Ascii values of YUY_ */
-    "0x23595559",               /* Ascii values of YUY# */
-  };
-  gint fourcc_strings_size =
-      sizeof (fourcc_strings) / sizeof (fourcc_strings[0]);
-
-  fail_unless (fourccs_size == fourcc_strings_size);
-
-  for (i = 0; i < fourccs_size; ++i) {
-    GValue value = { 0 };
-
-    g_value_init (&value, GST_TYPE_FOURCC);
-
-    fail_unless (gst_value_deserialize (&value, fourcc_strings[i]));
-    fail_unless_equals_int (gst_value_get_fourcc (&value), fourccs[i]);
-
-    g_value_unset (&value);
-  }
-}
-
-GST_END_TEST;
-
 GST_START_TEST (test_deserialize_buffer)
 {
   GValue value = { 0 };
@@ -118,7 +32,7 @@ GST_START_TEST (test_deserialize_buffer)
   g_value_init (&value, GST_TYPE_BUFFER);
   fail_unless (gst_value_deserialize (&value, "1234567890abcdef"));
   /* does not increase the refcount */
-  buf = GST_BUFFER (gst_value_get_mini_object (&value));
+  buf = GST_BUFFER (g_value_get_boxed (&value));
   ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
 
   /* does not increase the refcount */
@@ -139,10 +53,15 @@ GST_START_TEST (test_serialize_buffer)
   gchar *serialized;
   static const char *buf_data = "1234567890abcdef";
   gint len;
+  gpointer data;
 
   len = strlen (buf_data);
   buf = gst_buffer_new_and_alloc (len);
-  memcpy (GST_BUFFER_DATA (buf), buf_data, len);
+
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+  memcpy (data, buf_data, len);
+  gst_buffer_unmap (buf, data, len);
+
   ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
 
   /* and assign buffer to mini object */
@@ -554,6 +473,33 @@ GST_START_TEST (test_deserialize_flags)
 
 GST_END_TEST;
 
+GST_START_TEST (test_deserialize_bitmask)
+{
+  GValue value = { 0 };
+  const char *strings[] = {
+    "0xffffffffffffffff",
+    "0x1234567890ABCDEF",
+  };
+  guint64 results[] = {
+    0xffffffffffffffffULL,
+    0x1234567890ABCDEFULL,
+  };
+  int i;
+
+  g_value_init (&value, GST_TYPE_BITMASK);
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    fail_unless (gst_value_deserialize (&value, strings[i]),
+        "could not deserialize %s (%d)", strings[i], i);
+    fail_unless (gst_value_get_bitmask (&value) == results[i],
+        "resulting value is 0x%016" G_GINT64_MODIFIER "x, not 0x%016"
+        G_GINT64_MODIFIER "x, for string %s (%d)",
+        gst_value_get_bitmask (&value), results[i], strings[i], i);
+  }
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_string)
 {
   const gchar *try[] = {
@@ -678,15 +624,6 @@ GST_START_TEST (test_value_compare)
   g_value_unset (&value1);
   g_value_unset (&value2);
 
-  g_value_init (&value1, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&value1, GST_MAKE_FOURCC ('a', 'b', 'c', 'd'));
-  g_value_init (&value2, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&value2, GST_MAKE_FOURCC ('1', '2', '3', '4'));
-  fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
-  fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
-  g_value_unset (&value1);
-  g_value_unset (&value2);
-
   /* comparing 2/3 with 3/4 */
   g_value_init (&value1, GST_TYPE_FRACTION);
   gst_value_set_fraction (&value1, 2, 3);
@@ -827,6 +764,16 @@ GST_START_TEST (test_value_compare)
   g_value_unset (&value1);
   g_value_unset (&value2);
   g_value_unset (&tmp);
+
+  g_value_init (&value1, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (&value1, 0x123);
+  g_value_init (&value2, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (&value2, 0x321);
+  fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
+  fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED);
+  fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
+  g_value_unset (&value1);
+  g_value_unset (&value2);
 }
 
 GST_END_TEST;
@@ -848,24 +795,34 @@ GST_START_TEST (test_value_intersect)
   g_value_unset (&src1);
   g_value_unset (&src2);
 
-  g_value_init (&src1, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&src1, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  g_value_init (&src1, G_TYPE_STRING);
+  g_value_set_static_string (&src1, "YUY2");
   g_value_init (&src2, GST_TYPE_LIST);
-  g_value_init (&item, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  g_value_init (&item, G_TYPE_STRING);
+  g_value_set_static_string (&item, "YUY2");
   gst_value_list_append_value (&src2, &item);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('I', '4', '2', '0'));
+  g_value_set_static_string (&item, "I420");
   gst_value_list_append_value (&src2, &item);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('A', 'B', 'C', 'D'));
+  g_value_set_static_string (&item, "ABCD");
   gst_value_list_append_value (&src2, &item);
 
   fail_unless (gst_value_intersect (&dest, &src1, &src2));
-  fail_unless (GST_VALUE_HOLDS_FOURCC (&dest));
-  fail_unless (gst_value_get_fourcc (&dest) ==
-      GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  fail_unless (G_VALUE_HOLDS_STRING (&dest));
+  fail_unless (g_str_equal (g_value_get_string (&dest), "YUY2"));
 
   g_value_unset (&src1);
   g_value_unset (&src2);
+  g_value_unset (&dest);
+
+  g_value_init (&src1, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (&src1, 0xf00f);
+  g_value_init (&src2, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (&src2, 0xff00);
+  ret = gst_value_intersect (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless_equals_uint64 (0xf000, gst_value_get_bitmask (&dest));
+  g_value_unset (&src1);
+  g_value_unset (&src2);
 }
 
 GST_END_TEST;
@@ -1965,6 +1922,26 @@ GST_START_TEST (test_value_subtract_fraction_list)
 
 GST_END_TEST;
 
+GST_START_TEST (test_value_subtract_bitmask)
+{
+  GValue result = { 0 };
+  GValue src1 = { 0 };
+  GValue src2 = { 0 };
+
+  /* Subtract 1/4 from 1/2 */
+  g_value_init (&src1, GST_TYPE_BITMASK);
+  g_value_init (&src2, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (&src1, 0xffff);
+  gst_value_set_bitmask (&src2, 0xff00);
+  fail_unless (gst_value_subtract (&result, &src1, &src2) == TRUE);
+  fail_unless_equals_uint64 (0x00ff, gst_value_get_bitmask (&result));
+
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+  g_value_unset (&result);
+}
+
+GST_END_TEST;
 
 GST_START_TEST (test_date)
 {
@@ -1974,11 +1951,10 @@ GST_START_TEST (test_date)
 
   date = g_date_new_dmy (22, 9, 2005);
 
-  s = gst_structure_new ("media/x-type", "SOME_DATE_TAG", GST_TYPE_DATE,
+  s = gst_structure_new ("media/x-type", "SOME_DATE_TAG", G_TYPE_DATE,
       date, NULL);
 
-  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG",
-          GST_TYPE_DATE));
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE));
   fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date2));
   fail_unless (date2 != NULL);
   fail_unless (g_date_valid (date2));
@@ -2002,8 +1978,7 @@ GST_START_TEST (test_date)
 
   fail_unless (s != NULL);
   fail_unless (gst_structure_has_name (s, "media/x-type"));
-  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG",
-          GST_TYPE_DATE));
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE));
   fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date));
   fail_unless (date != NULL);
   fail_unless (g_date_valid (date));
@@ -2591,15 +2566,169 @@ GST_START_TEST (test_deserialize_int_range)
   g_free (str);
 }
 
-GST_END_TEST static Suite *
+GST_END_TEST;
+
+GST_START_TEST (test_stepped_range_collection)
+{
+  GstStructure *s;
+  const GValue *v;
+
+  s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT_RANGE, 8, 12, NULL);
+  fail_unless (s != NULL);
+  v = gst_structure_get_value (s, "range");
+  fail_unless (v != NULL);
+  fail_unless (gst_value_get_int_range_min (v) == 8);
+  fail_unless (gst_value_get_int_range_max (v) == 12);
+  fail_unless (gst_value_get_int_range_step (v) == 1);
+  gst_structure_free (s);
+
+  s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE, (gint64) 8,
+      (gint64) 12, NULL);
+  fail_unless (s != NULL);
+  v = gst_structure_get_value (s, "range");
+  fail_unless (v != NULL);
+  fail_unless (gst_value_get_int64_range_min (v) == 8);
+  fail_unless (gst_value_get_int64_range_max (v) == 12);
+  fail_unless (gst_value_get_int64_range_step (v) == 1);
+  gst_structure_free (s);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_stepped_int_range_parsing)
+{
+  gchar *str;
+  guint n;
+  gchar *end = NULL;
+  GstStructure *s;
+
+  static const gchar *good_ranges[] = {
+    "[0, 1, 1]",
+    "[-2, 2, 2]",
+    "[16, 4096, 16]",
+  };
+
+  static const gchar *bad_ranges[] = {
+    "[0, 1, -1]",
+    "[1, 2, 2]",
+    "[2, 3, 2]",
+    "[0, 0, 0]",
+  };
+
+  /* check we can parse good ranges */
+  for (n = 0; n < G_N_ELEMENTS (good_ranges); ++n) {
+    str = g_strdup_printf ("foo/bar, range=%s", good_ranges[n]);
+    s = gst_structure_from_string (str, &end);
+    fail_unless (s != NULL);
+    fail_unless (*end == '\0');
+    gst_structure_free (s);
+    g_free (str);
+  }
+
+  /* check we cannot parse bad ranges */
+  for (n = 0; n < G_N_ELEMENTS (bad_ranges); ++n) {
+    str = g_strdup_printf ("foo/bar, range=%s", bad_ranges[n]);
+    ASSERT_CRITICAL (gst_structure_from_string (str, &end));
+    g_free (str);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_stepped_int_range_ops)
+{
+  gchar *str1, *str2, *str3;
+  guint n;
+  GstStructure *s1, *s2, *s3;
+  const GValue *v1, *v2, *v3;
+
+  static const struct
+  {
+    const gchar *set1;
+    const gchar *op;
+    const gchar *set2;
+    const gchar *result;
+  } ranges[] = {
+    {"[16, 4096, 16]", "inter", "[100, 200, 10]", "160"},
+    {"[16, 4096, 16]", "inter", "[100, 200, 100]", NULL},
+    {"[16, 4096, 16]", "inter", "[0, 512, 256]", "[256, 512, 256]"},
+    {"[16, 32, 16]", "union", "[32, 96, 16]", "[16, 96, 16]"},
+    {"[16, 32, 16]", "union", "[48, 96, 16]", "[16, 96, 16]"},
+    {"[112, 192, 16]", "union", "[48, 96, 16]", "[48, 192, 16]"},
+    {"[16, 32, 16]", "union", "[64, 96, 16]", NULL},
+    {"[112, 192, 16]", "union", "[48, 96, 8]", NULL},
+  };
+
+  for (n = 0; n < G_N_ELEMENTS (ranges); ++n) {
+    gchar *end = NULL;
+    GValue dest = { 0 };
+    gboolean ret;
+
+    str1 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set1);
+    s1 = gst_structure_from_string (str1, &end);
+    fail_unless (s1 != NULL);
+    fail_unless (*end == '\0');
+    v1 = gst_structure_get_value (s1, "range");
+    fail_unless (v1 != NULL);
+
+    str2 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set2);
+    s2 = gst_structure_from_string (str2, &end);
+    fail_unless (s2 != NULL);
+    fail_unless (*end == '\0');
+    v2 = gst_structure_get_value (s2, "range");
+    fail_unless (v2 != NULL);
+
+    if (!strcmp (ranges[n].op, "inter")) {
+      ret = gst_value_intersect (&dest, v1, v2);
+    } else if (!strcmp (ranges[n].op, "union")) {
+      ret = gst_value_union (&dest, v1, v2);
+    } else {
+      fail_unless (FALSE);
+      ret = FALSE;
+    }
+
+    if (ranges[n].result) {
+      fail_unless (ret);
+    } else {
+      fail_unless (!ret);
+    }
+
+    if (ret) {
+      str3 = g_strdup_printf ("foo/bar, range=%s", ranges[n].result);
+      s3 = gst_structure_from_string (str3, &end);
+      fail_unless (s3 != NULL);
+      fail_unless (*end == '\0');
+      v3 = gst_structure_get_value (s3, "range");
+      fail_unless (v3 != NULL);
+
+      if (gst_value_compare (&dest, v3) != GST_VALUE_EQUAL) {
+        GST_ERROR ("%s %s %s yielded %s, expected %s", str1, ranges[n].op, str2,
+            gst_value_serialize (&dest), gst_value_serialize (v3));
+        fail_unless (FALSE);
+      }
+
+      gst_structure_free (s3);
+      g_free (str3);
+
+      g_value_unset (&dest);
+    }
+
+    gst_structure_free (s2);
+    g_free (str2);
+    gst_structure_free (s1);
+    g_free (str1);
+  }
+}
+
+GST_END_TEST;
+
+static Suite *
 gst_value_suite (void)
 {
   Suite *s = suite_create ("GstValue");
   TCase *tc_chain = tcase_create ("general");
 
   suite_add_tcase (s, tc_chain);
-  tcase_add_test (tc_chain, test_serialize_fourcc);
-  tcase_add_test (tc_chain, test_deserialize_fourcc);
   tcase_add_test (tc_chain, test_deserialize_buffer);
   tcase_add_test (tc_chain, test_serialize_buffer);
   tcase_add_test (tc_chain, test_deserialize_gint);
@@ -2610,6 +2739,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_deserialize_guint64);
   tcase_add_test (tc_chain, test_deserialize_guchar);
   tcase_add_test (tc_chain, test_deserialize_gstfraction);
+  tcase_add_test (tc_chain, test_deserialize_bitmask);
   tcase_add_test (tc_chain, test_serialize_flags);
   tcase_add_test (tc_chain, test_deserialize_flags);
   tcase_add_test (tc_chain, test_serialize_deserialize_format_enum);
@@ -2623,6 +2753,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_value_subtract_fraction);
   tcase_add_test (tc_chain, test_value_subtract_fraction_range);
   tcase_add_test (tc_chain, test_value_subtract_fraction_list);
+  tcase_add_test (tc_chain, test_value_subtract_bitmask);
   tcase_add_test (tc_chain, test_date);
   tcase_add_test (tc_chain, test_date_time);
   tcase_add_test (tc_chain, test_fraction_range);
@@ -2631,6 +2762,9 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_int64_range);
   tcase_add_test (tc_chain, test_serialize_int64_range);
   tcase_add_test (tc_chain, test_deserialize_int_range);
+  tcase_add_test (tc_chain, test_stepped_range_collection);
+  tcase_add_test (tc_chain, test_stepped_int_range_parsing);
+  tcase_add_test (tc_chain, test_stepped_int_range_ops);
 
   return s;
 }
diff --git a/tests/check/gst/gstxml.c b/tests/check/gst/gstxml.c
deleted file mode 100644 (file)
index ed38d22..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * gstxml.c: Unit test for GstXML
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#include <gst/check/gstcheck.h>
-#include <string.h>
-
-#define XML_PIPELINE                                             \
-  "<?xml version=\"1.0\"?>"                                      \
-  "<gstreamer xmlns:gst=\"http://gstreamer.net/gst-core/1.0/\">" \
-  "  <gst:element>"                                              \
-  "    <gst:name>test-pipeline</gst:name>"                       \
-  "    <gst:type>pipeline</gst:type>"                            \
-  "    <gst:param>"                                              \
-  "      <gst:name>name</gst:name>"                              \
-  "      <gst:value>test-pipeline</gst:value>"                   \
-  "    </gst:param>"                                             \
-  "  </gst:element>"                                             \
-  "</gstreamer>"
-
-
-GST_START_TEST (test_pipeline_from_xml)
-{
-  GstElement *element;
-  GstXML *xml;
-  GList *elements;
-
-  xml = gst_xml_new ();
-  fail_unless (xml != NULL);
-  ASSERT_OBJECT_REFCOUNT (xml, "GstXML object after creating it", 1);
-
-  fail_unless (gst_xml_parse_memory (xml, (guchar *) XML_PIPELINE,
-          strlen (XML_PIPELINE), NULL));
-
-  elements = gst_xml_get_topelements (xml);
-  fail_unless (elements != NULL);
-  fail_unless (g_list_length (elements) == 1);
-
-  element = GST_ELEMENT (elements->data);
-  fail_unless (element != NULL);
-  fail_unless (GST_IS_PIPELINE (element));
-  fail_unless_equals_string (GST_OBJECT_NAME (element), "test-pipeline");
-
-  ASSERT_OBJECT_REFCOUNT (element, "pipeline owned by GstXML", 1);
-  gst_object_ref (element);
-  ASSERT_OBJECT_REFCOUNT (element, "pipeline after we obtained a ref", 2);
-
-  gst_object_unref (xml);
-
-  ASSERT_OBJECT_REFCOUNT (element, "pipeline after GstXML was unrefed", 1);
-  gst_object_unref (element);
-}
-
-GST_END_TEST;
-
-static Suite *
-gst_xml_suite (void)
-{
-  Suite *s = suite_create ("GstXML");
-  TCase *tc_chain = tcase_create ("xml");
-
-  tcase_set_timeout (tc_chain, 20);
-
-  suite_add_tcase (s, tc_chain);
-  tcase_add_test (tc_chain, test_pipeline_from_xml);
-  return s;
-}
-
-GST_CHECK_MAIN (gst_xml);
index 23ac70e..3f28d86 100644 (file)
@@ -27,7 +27,6 @@ GstCheckABIStruct list[] = {
   {"GstIndexFactory", sizeof (GstIndexFactory), 96},
   {"GstIndexFactoryClass", sizeof (GstIndexFactoryClass), 152},
   {"GstDebugCategory", sizeof (GstDebugCategory), 16},
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 28},
   {"GstIterator", sizeof (GstIterator), 52},
   {"GstMessage", sizeof (GstMessage), 64},
   {"GstMessageClass", sizeof (GstMessageClass), 32},
@@ -56,7 +55,7 @@ GstCheckABIStruct list[] = {
   {"GstStructure", sizeof (GstStructure), 20},
   {"GstSystemClock", sizeof (GstSystemClock), 200},
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 176},
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 8},
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 8},
   {"GstTask", sizeof (GstTask), 80},
   {"GstTaskClass", sizeof (GstTaskClass), 140},
   {"GstTrace", sizeof (GstTrace), 20},
@@ -67,9 +66,5 @@ GstCheckABIStruct list[] = {
   {"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 152},
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 44},
   {"GstValueTable", sizeof (GstValueTable), 32},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 64},
-  {"GstXMLClass", sizeof (GstXMLClass), 144},
-#endif
   {NULL, 0, 0}
 };
index f59fe07..08df6b3 100644 (file)
@@ -26,7 +26,6 @@ static GstCheckABIStruct list[] = {
   {"GstIndexFactory", sizeof (GstIndexFactory), 96},
   {"GstIndexFactoryClass", sizeof (GstIndexFactoryClass), 152},
   {"GstDebugCategory", sizeof (GstDebugCategory), 16},
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 28},
   {"GstIterator", sizeof (GstIterator), 52},
   {"GstMessage", sizeof (GstMessage), 64},
   {"GstMessageClass", sizeof (GstMessageClass), 32},
@@ -55,7 +54,7 @@ static GstCheckABIStruct list[] = {
   {"GstStructure", sizeof (GstStructure), 20},
   {"GstSystemClock", sizeof (GstSystemClock), 200},
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 176},
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 8},
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 8},
   {"GstTask", sizeof (GstTask), 80},
   {"GstTaskClass", sizeof (GstTaskClass), 140},
   {"GstTrace", sizeof (GstTrace), 20},
@@ -66,9 +65,5 @@ static GstCheckABIStruct list[] = {
   {"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 152},
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 44},
   {"GstValueTable", sizeof (GstValueTable), 32},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 64},
-  {"GstXMLClass", sizeof (GstXMLClass), 144},
-#endif
   {NULL, 0, 0}
 };
index 06de6fd..7aba5ae 100644 (file)
@@ -26,7 +26,6 @@ static GstCheckABIStruct list[] = {
  {"GstIndexFactory", sizeof(GstIndexFactory), 96},
  {"GstIndexFactoryClass", sizeof(GstIndexFactoryClass), 152},
  {"GstDebugCategory", sizeof(GstDebugCategory), 16},
- {"GstImplementsInterfaceClass", sizeof(GstImplementsInterfaceClass), 28},
  {"GstIterator", sizeof(GstIterator), 52},
  {"GstMessage", sizeof(GstMessage), 60},
  {"GstMessageClass", sizeof(GstMessageClass), 32},
@@ -55,7 +54,7 @@ static GstCheckABIStruct list[] = {
  {"GstStructure", sizeof(GstStructure), 20},
  {"GstSystemClock", sizeof(GstSystemClock), 196},
  {"GstSystemClockClass", sizeof(GstSystemClockClass), 176},
- {"GstTagSetterIFace", sizeof(GstTagSetterIFace), 8},
+ {"GstTagSetterInterface", sizeof(GstTagSetterInterface), 8},
  {"GstTask", sizeof(GstTask), 80},
  {"GstTaskClass", sizeof(GstTaskClass), 140},
  {"GstTrace", sizeof(GstTrace), 20},
@@ -66,9 +65,5 @@ static GstCheckABIStruct list[] = {
  {"GstTypeFindFactoryClass", sizeof(GstTypeFindFactoryClass), 152},
  {"GstURIHandlerInterface", sizeof(GstURIHandlerInterface), 44},
  {"GstValueTable", sizeof(GstValueTable), 32},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
- {"GstXML", sizeof(GstXML), 64},
- {"GstXMLClass", sizeof(GstXMLClass), 144},
-#endif
  {NULL, 0, 0}
 };
index f59fe07..08df6b3 100644 (file)
@@ -26,7 +26,6 @@ static GstCheckABIStruct list[] = {
   {"GstIndexFactory", sizeof (GstIndexFactory), 96},
   {"GstIndexFactoryClass", sizeof (GstIndexFactoryClass), 152},
   {"GstDebugCategory", sizeof (GstDebugCategory), 16},
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 28},
   {"GstIterator", sizeof (GstIterator), 52},
   {"GstMessage", sizeof (GstMessage), 64},
   {"GstMessageClass", sizeof (GstMessageClass), 32},
@@ -55,7 +54,7 @@ static GstCheckABIStruct list[] = {
   {"GstStructure", sizeof (GstStructure), 20},
   {"GstSystemClock", sizeof (GstSystemClock), 200},
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 176},
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 8},
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 8},
   {"GstTask", sizeof (GstTask), 80},
   {"GstTaskClass", sizeof (GstTaskClass), 140},
   {"GstTrace", sizeof (GstTrace), 20},
@@ -66,9 +65,5 @@ static GstCheckABIStruct list[] = {
   {"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 152},
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 44},
   {"GstValueTable", sizeof (GstValueTable), 32},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 64},
-  {"GstXMLClass", sizeof (GstXMLClass), 144},
-#endif
   {NULL, 0, 0}
 };
index 4bb20fa..7b77248 100644 (file)
@@ -26,7 +26,6 @@ static GstCheckABIStruct list[] = {
   {"GstIndexFactory", sizeof (GstIndexFactory), 192} ,
   {"GstIndexFactoryClass", sizeof (GstIndexFactoryClass), 304} ,
   {"GstDebugCategory", sizeof (GstDebugCategory), 24} ,
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 56} ,
   {"GstIterator", sizeof (GstIterator), 104} ,
   {"GstMessage", sizeof (GstMessage), 104} ,
   {"GstMessageClass", sizeof (GstMessageClass), 64} ,
@@ -55,7 +54,7 @@ static GstCheckABIStruct list[] = {
   {"GstStructure", sizeof (GstStructure), 40} ,
   {"GstSystemClock", sizeof (GstSystemClock), 288} ,
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 352} ,
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 16} ,
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 16} ,
   {"GstTask", sizeof (GstTask), 160} ,
   {"GstTaskClass", sizeof (GstTaskClass), 280} ,
   {"GstTrace", sizeof (GstTrace), 32} ,
@@ -66,9 +65,5 @@ static GstCheckABIStruct list[] = {
   {"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 304} ,
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 88} ,
   {"GstValueTable", sizeof (GstValueTable), 64} ,
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 128} ,
-  {"GstXMLClass", sizeof (GstXMLClass), 288} ,
-#endif
   {NULL, 0, 0}
 };
index 23ac70e..3f28d86 100644 (file)
@@ -27,7 +27,6 @@ GstCheckABIStruct list[] = {
   {"GstIndexFactory", sizeof (GstIndexFactory), 96},
   {"GstIndexFactoryClass", sizeof (GstIndexFactoryClass), 152},
   {"GstDebugCategory", sizeof (GstDebugCategory), 16},
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 28},
   {"GstIterator", sizeof (GstIterator), 52},
   {"GstMessage", sizeof (GstMessage), 64},
   {"GstMessageClass", sizeof (GstMessageClass), 32},
@@ -56,7 +55,7 @@ GstCheckABIStruct list[] = {
   {"GstStructure", sizeof (GstStructure), 20},
   {"GstSystemClock", sizeof (GstSystemClock), 200},
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 176},
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 8},
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 8},
   {"GstTask", sizeof (GstTask), 80},
   {"GstTaskClass", sizeof (GstTaskClass), 140},
   {"GstTrace", sizeof (GstTrace), 20},
@@ -67,9 +66,5 @@ GstCheckABIStruct list[] = {
   {"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 152},
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 44},
   {"GstValueTable", sizeof (GstValueTable), 32},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 64},
-  {"GstXMLClass", sizeof (GstXMLClass), 144},
-#endif
   {NULL, 0, 0}
 };
index e412f54..469d749 100644 (file)
@@ -22,7 +22,6 @@ static GstCheckABIStruct list[] = {
   {"GstFormatDefinition", sizeof (GstFormatDefinition), 32},
   {"GstGhostPadClass", sizeof (GstGhostPadClass), 344},
   {"GstGhostPad", sizeof (GstGhostPad), 384},
-  {"GstImplementsInterfaceClass", sizeof (GstImplementsInterfaceClass), 56},
   {"GstIndexAssociation", sizeof (GstIndexAssociation), 16},
   {"GstIndexClass", sizeof (GstIndexClass), 312},
   {"GstIndexEntry", sizeof (GstIndexEntry), 32},
@@ -66,7 +65,7 @@ static GstCheckABIStruct list[] = {
   {"GstSystemClockClass", sizeof (GstSystemClockClass), 352},
   {"GstSystemClock", sizeof (GstSystemClock), 288},
   {"GstTagList", sizeof (GstTagList), 40},
-  {"GstTagSetterIFace", sizeof (GstTagSetterIFace), 16},
+  {"GstTagSetterInterface", sizeof (GstTagSetterInterface), 16},
   {"GstTaskClass", sizeof (GstTaskClass), 280},
   {"GstTask", sizeof (GstTask), 160},
   {"GstTaskPoolClass", sizeof (GstTaskPoolClass), 304},
@@ -82,9 +81,5 @@ static GstCheckABIStruct list[] = {
 #endif
   {"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 88},
   {"GstValueTable", sizeof (GstValueTable), 64},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
-  {"GstXML", sizeof (GstXML), 128} ,
-  {"GstXMLClass", sizeof (GstXMLClass), 288} ,
-#endif
   {NULL, 0, 0}
 };
index de0e4f9..2385083 100644 (file)
@@ -43,7 +43,8 @@ GST_START_TEST (test_peek1)
 
   /* push single buffer in adapter */
   buffer = gst_buffer_new_and_alloc (512);
-  bufdata = GST_BUFFER_DATA (buffer);
+
+  bufdata = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
 
   fail_if (buffer == NULL);
   gst_adapter_push (adapter, buffer);
@@ -56,22 +57,25 @@ GST_START_TEST (test_peek1)
   fail_if (avail != 512);
 
   /* should g_critical with NULL as result */
-  ASSERT_CRITICAL (data1 = gst_adapter_peek (adapter, 0));
+  ASSERT_CRITICAL (data1 = gst_adapter_map (adapter, 0));
   fail_if (data1 != NULL);
 
   /* should return NULL as result */
-  data1 = gst_adapter_peek (adapter, 513);
+  data1 = gst_adapter_map (adapter, 513);
   fail_if (data1 != NULL);
 
   /* this should work */
-  data1 = gst_adapter_peek (adapter, 512);
+  data1 = gst_adapter_map (adapter, 512);
   fail_if (data1 == NULL);
   /* it should point to the buffer data as well */
   fail_if (data1 != bufdata);
-  data2 = gst_adapter_peek (adapter, 512);
+  gst_adapter_unmap (adapter);
+
+  data2 = gst_adapter_map (adapter, 512);
   fail_if (data2 == NULL);
   /* second peek should return the same pointer */
   fail_if (data2 != data1);
+  gst_adapter_unmap (adapter);
 
   /* this should fail since we don't have that many bytes */
   ASSERT_CRITICAL (gst_adapter_flush (adapter, 513));
@@ -86,15 +90,16 @@ GST_START_TEST (test_peek1)
   fail_if (avail != 502);
 
   /* should return NULL as result */
-  data2 = gst_adapter_peek (adapter, 503);
+  data2 = gst_adapter_map (adapter, 503);
   fail_if (data2 != NULL);
 
   /* should work fine */
-  data2 = gst_adapter_peek (adapter, 502);
+  data2 = gst_adapter_map (adapter, 502);
   fail_if (data2 == NULL);
   /* peek should return the same old pointer + 10 */
   fail_if (data2 != data1 + 10);
   fail_if (data2 != bufdata + 10);
+  gst_adapter_unmap (adapter);
 
   /* flush some more */
   gst_adapter_flush (adapter, 500);
@@ -105,10 +110,11 @@ GST_START_TEST (test_peek1)
   avail = gst_adapter_available_fast (adapter);
   fail_if (avail != 2);
 
-  data2 = gst_adapter_peek (adapter, 2);
+  data2 = gst_adapter_map (adapter, 2);
   fail_if (data2 == NULL);
   fail_if (data2 != data1 + 510);
   fail_if (data2 != bufdata + 510);
+  gst_adapter_unmap (adapter);
 
   /* flush some more */
   gst_adapter_flush (adapter, 2);
@@ -153,16 +159,16 @@ GST_START_TEST (test_take1)
   GstBuffer *buffer, *buffer2;
   guint avail;
   guint8 *data, *data2;
+  gsize size, size2;
 
   adapter = gst_adapter_new ();
   fail_unless (adapter != NULL);
 
   buffer = gst_buffer_new_and_alloc (100);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_DATA (buffer) != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 100);
-
-  data = GST_BUFFER_DATA (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  fail_unless (data != NULL);
+  fail_unless (size == 100);
 
   /* push in the adapter */
   gst_adapter_push (adapter, buffer);
@@ -173,9 +179,10 @@ GST_START_TEST (test_take1)
   /* take out buffer */
   buffer2 = gst_adapter_take_buffer (adapter, 100);
   fail_unless (buffer2 != NULL);
-  fail_unless (GST_BUFFER_DATA (buffer2) != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer2) == 100);
-  data2 = GST_BUFFER_DATA (buffer2);
+
+  data2 = gst_buffer_map (buffer2, &size2, NULL, GST_MAP_READ);
+  fail_unless (data2 != NULL);
+  fail_unless (size2 == 100);
 
   avail = gst_adapter_available (adapter);
   fail_unless (avail == 0);
@@ -184,6 +191,9 @@ GST_START_TEST (test_take1)
   fail_unless (buffer == buffer2);
   fail_unless (data == data2);
 
+  gst_buffer_unmap (buffer, data, size);
+  gst_buffer_unmap (buffer2, data2, size2);
+
   gst_buffer_unref (buffer2);
 
   g_object_unref (adapter);
@@ -209,25 +219,25 @@ GST_START_TEST (test_take3)
   GstBuffer *buffer, *buffer2;
   guint avail;
   guint8 *data, *data2;
+  gsize size, size2;
 
   adapter = gst_adapter_new ();
   fail_unless (adapter != NULL);
 
   buffer = gst_buffer_new_and_alloc (100);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_DATA (buffer) != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 100);
-
-  data = GST_BUFFER_DATA (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  fail_unless (data != NULL);
+  fail_unless (size == 100);
 
   /* set up and push subbuffers */
-  buffer2 = gst_buffer_create_sub (buffer, 0, 25);
+  buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, 25);
   gst_adapter_push (adapter, buffer2);
-  buffer2 = gst_buffer_create_sub (buffer, 25, 25);
+  buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 25, 25);
   gst_adapter_push (adapter, buffer2);
-  buffer2 = gst_buffer_create_sub (buffer, 50, 25);
+  buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 50, 25);
   gst_adapter_push (adapter, buffer2);
-  buffer2 = gst_buffer_create_sub (buffer, 75, 25);
+  buffer2 = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 75, 25);
   gst_adapter_push (adapter, buffer2);
 
   gst_buffer_unref (buffer);
@@ -238,9 +248,9 @@ GST_START_TEST (test_take3)
   /* take out buffer */
   buffer2 = gst_adapter_take_buffer (adapter, 100);
   fail_unless (buffer2 != NULL);
-  fail_unless (GST_BUFFER_DATA (buffer2) != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer2) == 100);
-  data2 = GST_BUFFER_DATA (buffer2);
+  data2 = gst_buffer_map (buffer2, &size2, NULL, GST_MAP_READ);
+  fail_unless (data2 != NULL);
+  fail_unless (size2 == 100);
 
   avail = gst_adapter_available (adapter);
   fail_unless (avail == 0);
@@ -265,16 +275,20 @@ create_and_fill_adapter (void)
   fail_unless (adapter != NULL);
 
   for (i = 0; i < 10000; i += 4) {
-    GstBuffer *buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4);
-    guint8 *data;
+    GstBuffer *buf;
+    guint8 *data, *ptr;
 
+    buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4);
     fail_unless (buf != NULL);
-    data = GST_BUFFER_DATA (buf);
+
+    ptr = data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
 
     for (j = 0; j < 4; j++) {
-      GST_WRITE_UINT32_LE (data, i + j);
-      data += sizeof (guint32);
+      GST_WRITE_UINT32_LE (ptr, i + j);
+      ptr += sizeof (guint32);
     }
+    gst_buffer_unmap (buf, data, sizeof (guint32) * 4);
+
     gst_adapter_push (adapter, buf);
   }
 
@@ -291,8 +305,10 @@ GST_START_TEST (test_take_order)
   adapter = create_and_fill_adapter ();
   while (gst_adapter_available (adapter) >= sizeof (guint32)) {
     guint8 *data = gst_adapter_take (adapter, sizeof (guint32));
+    guint32 val = GST_READ_UINT32_LE (data);
 
-    fail_unless (GST_READ_UINT32_LE (data) == i);
+    GST_DEBUG ("val %8u", val);
+    fail_unless (val == i);
     i++;
     g_free (data);
   }
@@ -314,8 +330,13 @@ GST_START_TEST (test_take_buf_order)
   adapter = create_and_fill_adapter ();
   while (gst_adapter_available (adapter) >= sizeof (guint32)) {
     GstBuffer *buf = gst_adapter_take_buffer (adapter, sizeof (guint32));
+    gpointer data;
+    gsize size;
+
+    data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+    fail_unless (GST_READ_UINT32_LE (data) == i);
+    gst_buffer_unmap (buf, data, size);
 
-    fail_unless (GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)) == i);
     i++;
 
     gst_buffer_unref (buf);
@@ -509,7 +530,7 @@ GST_START_TEST (test_timestamp)
   /* remove first buffer, timestamp of empty buffer is visible */
   buffer = gst_adapter_take_buffer (adapter, 99);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 99);
+  fail_unless (gst_buffer_get_size (buffer) == 99);
   gst_buffer_unref (buffer);
   avail = gst_adapter_available (adapter);
   fail_unless (avail == 100);
@@ -518,8 +539,10 @@ GST_START_TEST (test_timestamp)
   fail_unless (dist == 0);
 
   /* remove empty buffer, timestamp still visible */
-  cdata = gst_adapter_peek (adapter, 50);
+  cdata = gst_adapter_map (adapter, 50);
   fail_unless (cdata != NULL);
+  gst_adapter_unmap (adapter);
+
   data = gst_adapter_take (adapter, 50);
   fail_unless (data != NULL);
   g_free (data);
@@ -546,10 +569,12 @@ GST_START_TEST (test_scan)
   fail_unless (adapter != NULL);
 
   buffer = gst_buffer_new_and_alloc (100);
-  data = GST_BUFFER_DATA (buffer);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
   /* fill with pattern */
   for (i = 0; i < 100; i++)
     data[i] = i;
+  gst_buffer_unmap (buffer, data, 100);
 
   gst_adapter_push (adapter, buffer);
 
@@ -608,10 +633,12 @@ GST_START_TEST (test_scan)
 
   /* add another buffer */
   buffer = gst_buffer_new_and_alloc (100);
-  data = GST_BUFFER_DATA (buffer);
+
+  data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_WRITE);
   /* fill with pattern */
   for (i = 0; i < 100; i++)
     data[i] = i + 100;
+  gst_buffer_unmap (buffer, data, 100);
 
   gst_adapter_push (adapter, buffer);
 
@@ -739,23 +766,26 @@ GST_START_TEST (test_take_list)
   while (gst_adapter_available (adapter) >= sizeof (guint32)) {
     GList *list, *walk;
     GstBuffer *buf;
-    guint size;
-    guint8 *data;
+    gsize size, left;
+    guint8 *data, *ptr;
 
     list = gst_adapter_take_list (adapter, sizeof (guint32) * 5);
     fail_unless (list != NULL);
 
     for (walk = list; walk; walk = g_list_next (walk)) {
       buf = walk->data;
-      data = GST_BUFFER_DATA (buf);
-      size = GST_BUFFER_SIZE (buf);
 
-      while (size > 0) {
-        fail_unless (GST_READ_UINT32_LE (data) == i);
+      ptr = data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
+      left = size;
+      while (left > 0) {
+        fail_unless (GST_READ_UINT32_LE (ptr) == i);
         i++;
-        data += sizeof (guint32);
-        size -= sizeof (guint32);
+        ptr += sizeof (guint32);
+        left -= sizeof (guint32);
       }
+      gst_buffer_unmap (buf, data, size);
+
       gst_buffer_unref (buf);
     }
     g_list_free (list);
index f2a2fce..18842b3 100644 (file)
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstbasesink.h>
 
-GST_START_TEST (basesink_last_buffer_enabled)
+GST_START_TEST (basesink_last_sample_enabled)
 {
   GstElement *src, *sink, *pipeline;
   GstBus *bus;
   GstMessage *msg;
-  GstBuffer *last_buffer;
+  GstSample *last_sample;
 
   pipeline = gst_pipeline_new ("pipeline");
   sink = gst_element_factory_make ("fakesink", "sink");
@@ -42,7 +42,7 @@ GST_START_TEST (basesink_last_buffer_enabled)
 
   bus = gst_element_get_bus (pipeline);
 
-  /* try with enable-last-buffer set to TRUE */
+  /* try with enable-last-sample set to TRUE */
   g_object_set (src, "num-buffers", 1, NULL);
   fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING)
       != GST_STATE_CHANGE_FAILURE);
@@ -52,19 +52,19 @@ GST_START_TEST (basesink_last_buffer_enabled)
   fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
   gst_message_unref (msg);
 
-  /* last-buffer should be != NULL */
-  fail_unless (gst_base_sink_is_last_buffer_enabled (GST_BASE_SINK (sink))
+  /* last-sample should be != NULL */
+  fail_unless (gst_base_sink_is_last_sample_enabled (GST_BASE_SINK (sink))
       == TRUE);
-  g_object_get (sink, "last-buffer", &last_buffer, NULL);
-  fail_unless (last_buffer != NULL);
-  gst_buffer_unref (last_buffer);
+  g_object_get (sink, "last-sample", &last_sample, NULL);
+  fail_unless (last_sample != NULL);
+  gst_sample_unref (last_sample);
 
-  /* set enable-last-buffer to FALSE now, this should set last-buffer to NULL */
-  g_object_set (sink, "enable-last-buffer", FALSE, NULL);
-  fail_unless (gst_base_sink_is_last_buffer_enabled (GST_BASE_SINK (sink))
+  /* set enable-last-sample to FALSE now, this should set last-sample to NULL */
+  g_object_set (sink, "enable-last-sample", FALSE, NULL);
+  fail_unless (gst_base_sink_is_last_sample_enabled (GST_BASE_SINK (sink))
       == FALSE);
-  g_object_get (sink, "last-buffer", &last_buffer, NULL);
-  fail_unless (last_buffer == NULL);
+  g_object_get (sink, "last-sample", &last_sample, NULL);
+  fail_unless (last_sample == NULL);
 
   gst_element_set_state (pipeline, GST_STATE_NULL);
 
@@ -76,12 +76,12 @@ GST_START_TEST (basesink_last_buffer_enabled)
 
 GST_END_TEST;
 
-GST_START_TEST (basesink_last_buffer_disabled)
+GST_START_TEST (basesink_last_sample_disabled)
 {
   GstElement *src, *sink, *pipeline;
   GstBus *bus;
   GstMessage *msg;
-  GstBuffer *last_buffer;
+  GstSample *last_sample;
 
   pipeline = gst_pipeline_new ("pipeline");
   sink = gst_element_factory_make ("fakesink", "sink");
@@ -93,9 +93,9 @@ GST_START_TEST (basesink_last_buffer_disabled)
 
   bus = gst_element_get_bus (pipeline);
 
-  /* set enable-last-buffer to FALSE */
+  /* set enable-last-sample to FALSE */
   g_object_set (src, "num-buffers", 1, NULL);
-  gst_base_sink_set_last_buffer_enabled (GST_BASE_SINK (sink), FALSE);
+  gst_base_sink_set_last_sample_enabled (GST_BASE_SINK (sink), FALSE);
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
   msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
   fail_unless (msg != NULL);
@@ -103,9 +103,9 @@ GST_START_TEST (basesink_last_buffer_disabled)
   fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
   gst_message_unref (msg);
 
-  /* last-buffer should be NULL */
-  g_object_get (sink, "last-buffer", &last_buffer, NULL);
-  fail_unless (last_buffer == NULL);
+  /* last-sample should be NULL */
+  g_object_get (sink, "last-sample", &last_sample, NULL);
+  fail_unless (last_sample == NULL);
 
   gst_element_set_state (pipeline, GST_STATE_NULL);
 
@@ -124,8 +124,8 @@ gst_basesrc_suite (void)
   TCase *tc = tcase_create ("general");
 
   suite_add_tcase (s, tc);
-  tcase_add_test (tc, basesink_last_buffer_enabled);
-  tcase_add_test (tc, basesink_last_buffer_disabled);
+  tcase_add_test (tc, basesink_last_sample_enabled);
+  tcase_add_test (tc, basesink_last_sample_disabled);
 
   return s;
 }
index dbff6ce..7e09488 100644 (file)
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstbasesrc.h>
 
-static gboolean
-eos_event_counter (GstObject * pad, GstEvent * event, guint * p_num_eos)
+static GstPadProbeReturn
+eos_event_counter (GstObject * pad, GstPadProbeInfo * info, guint * p_num_eos)
 {
+  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
+
   fail_unless (event != NULL);
   fail_unless (GST_IS_EVENT (event));
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
     *p_num_eos += 1;
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 /* basesrc_eos_events_push_live_op:
@@ -76,8 +78,8 @@ GST_START_TEST (basesrc_eos_events_push_live_op)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   bus = gst_element_get_bus (pipe);
 
@@ -88,12 +90,8 @@ GST_START_TEST (basesrc_eos_events_push_live_op)
   /* wait a second, then do controlled shutdown */
   g_usleep (GST_USECOND * 1);
 
-  /* shut down source only (should send EOS event) ... */
-  gst_element_set_state (src, GST_STATE_NULL);
-  state_ret = gst_element_get_state (src, NULL, NULL, -1);
-  fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
-
-  fail_unless (gst_element_set_locked_state (src, TRUE) == TRUE);
+  /* shut down pipeline (should send EOS message) ... */
+  gst_element_send_event (pipe, gst_event_new_eos ());
 
   /* ... and wait for the EOS message from the sink */
   msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
@@ -110,7 +108,7 @@ GST_START_TEST (basesrc_eos_events_push_live_op)
   /* make sure source hasn't sent a second one when going PAUSED => READY */
   fail_unless (num_eos == 1);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_message_unref (msg);
   gst_object_unref (bus);
@@ -119,6 +117,8 @@ GST_START_TEST (basesrc_eos_events_push_live_op)
 
 GST_END_TEST;
 
+
+
 /* basesrc_eos_events_push:
  *  - make sure source only sends one EOS when operating in push-mode,
  *    reaching the max number of buffers, and is then shut down.
@@ -156,8 +156,8 @@ GST_START_TEST (basesrc_eos_events_push)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   bus = gst_element_get_bus (pipe);
 
@@ -179,7 +179,7 @@ GST_START_TEST (basesrc_eos_events_push)
   /* make sure source hasn't sent a second one when going PAUSED => READY */
   fail_unless (num_eos == 1);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_message_unref (msg);
   gst_object_unref (bus);
@@ -223,8 +223,8 @@ GST_START_TEST (basesrc_eos_events_pull_live_op)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   gst_element_set_state (pipe, GST_STATE_PLAYING);
   state_ret = gst_element_get_state (pipe, NULL, NULL, -1);
@@ -249,7 +249,7 @@ GST_START_TEST (basesrc_eos_events_pull_live_op)
   /* make sure source hasn't sent an EOS when going PAUSED => READY either */
   fail_unless (num_eos == 0);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_object_unref (pipe);
 }
@@ -295,8 +295,8 @@ GST_START_TEST (basesrc_eos_events_pull)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   bus = gst_element_get_bus (pipe);
 
@@ -318,7 +318,7 @@ GST_START_TEST (basesrc_eos_events_pull)
   /* make sure source hasn't sent an EOS when going PAUSED => READY either */
   fail_unless (num_eos == 0);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_message_unref (msg);
   gst_object_unref (bus);
@@ -365,8 +365,8 @@ GST_START_TEST (basesrc_eos_events_push_live_eos)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   bus = gst_element_get_bus (pipe);
 
@@ -396,7 +396,7 @@ GST_START_TEST (basesrc_eos_events_push_live_eos)
   /* make sure source hasn't sent a second one when going PAUSED => READY */
   fail_unless (num_eos == 1);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_message_unref (msg);
   gst_object_unref (bus);
@@ -442,8 +442,8 @@ GST_START_TEST (basesrc_eos_events_pull_live_eos)
   srcpad = gst_element_get_static_pad (src, "src");
   fail_unless (srcpad != NULL);
 
-  probe = gst_pad_add_event_probe (srcpad,
-      G_CALLBACK (eos_event_counter), &num_eos);
+  probe = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) eos_event_counter, &num_eos, NULL);
 
   bus = gst_element_get_bus (pipe);
 
@@ -473,7 +473,7 @@ GST_START_TEST (basesrc_eos_events_pull_live_eos)
   /* make sure source hasn't sent a second one when going PAUSED => READY */
   fail_unless (num_eos == 0);
 
-  gst_pad_remove_event_probe (srcpad, probe);
+  gst_pad_remove_probe (srcpad, probe);
   gst_object_unref (srcpad);
   gst_message_unref (msg);
   gst_object_unref (bus);
@@ -483,26 +483,27 @@ GST_START_TEST (basesrc_eos_events_pull_live_eos)
 GST_END_TEST;
 
 
-static gboolean
-newsegment_event_catcher (GstObject * pad, GstEvent * event,
+static GstPadProbeReturn
+segment_event_catcher (GstObject * pad, GstPadProbeInfo * info,
     gpointer * user_data)
 {
+  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
   GstEvent **last_event = (GstEvent **) user_data;
   fail_unless (event != NULL);
   fail_unless (GST_IS_EVENT (event));
   fail_unless (user_data != NULL);
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
     if (*last_event)
       gst_event_unref (*last_event);
     *last_event = gst_event_copy (event);
   }
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 /* basesrc_seek_events_rate_update:
- *  - make sure we get expected newsegment after sending a seek event
+ *  - make sure we get expected segment after sending a seek event
  */
 GST_START_TEST (basesrc_seek_events_rate_update)
 {
@@ -512,10 +513,10 @@ GST_START_TEST (basesrc_seek_events_rate_update)
   GstBus *bus;
   GstPad *probe_pad;
   guint probe;
-  GstEvent *newseg_event = NULL;
+  GstEvent *seg_event = NULL;
   GstEvent *rate_seek;
   gboolean event_ret;
-  gdouble rate = 0.5;
+  const GstSegment *segment;
 
   pipe = gst_pipeline_new ("pipeline");
   sink = gst_element_factory_make ("fakesink", "sink");
@@ -536,8 +537,8 @@ GST_START_TEST (basesrc_seek_events_rate_update)
   probe_pad = gst_element_get_static_pad (sink, "sink");
   fail_unless (probe_pad != NULL);
 
-  probe = gst_pad_add_event_probe (probe_pad,
-      G_CALLBACK (newsegment_event_catcher), &newseg_event);
+  probe = gst_pad_add_probe (probe_pad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
+      (GstPadProbeCallback) segment_event_catcher, &seg_event, NULL);
 
   /* prepare the seek */
   rate_seek = gst_event_new_seek (0.5, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
@@ -560,12 +561,8 @@ GST_START_TEST (basesrc_seek_events_rate_update)
   /* wait a second, then do controlled shutdown */
   g_usleep (GST_USECOND * 1);
 
-  /* shut down source only (should send EOS event) ... */
-  gst_element_set_state (src, GST_STATE_NULL);
-  state_ret = gst_element_get_state (src, NULL, NULL, -1);
-  fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);
-
-  fail_unless (gst_element_set_locked_state (src, TRUE) == TRUE);
+  /* shut down pipeline only (should send EOS message) ... */
+  gst_element_send_event (pipe, gst_event_new_eos ());
 
   /* ... and wait for the EOS message from the sink */
   msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
@@ -579,16 +576,15 @@ GST_START_TEST (basesrc_seek_events_rate_update)
   GST_INFO ("stopped");
 
   /* check that we have go the event */
-  fail_unless (newseg_event != NULL);
+  fail_unless (seg_event != NULL);
 
-  gst_event_parse_new_segment (newseg_event, NULL, &rate, NULL, NULL, NULL,
-      NULL);
-  fail_unless (rate == 0.5);
+  gst_event_parse_segment (seg_event, &segment);
+  fail_unless (segment->rate == 0.5);
 
-  gst_pad_remove_event_probe (probe_pad, probe);
+  gst_pad_remove_probe (probe_pad, probe);
   gst_object_unref (probe_pad);
   gst_message_unref (msg);
-  gst_event_unref (newseg_event);
+  gst_event_unref (seg_event);
   gst_object_unref (bus);
   gst_object_unref (pipe);
 }
index ac2e3cd..346b00e 100644 (file)
@@ -46,9 +46,11 @@ GST_START_TEST (test_initialization)
   GstBitReader reader = GST_BIT_READER_INIT (data, 4);
   GstBitReader *reader2;
   guint8 x = 0;
+  guint8 *bdata;
+  gsize bsize;
 
-  GST_BUFFER_DATA (buffer) = data;
-  GST_BUFFER_SIZE (buffer) = 4;
+  gst_buffer_take_memory (buffer, -1,
+      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, data, NULL, 4, 0, 4));
 
   fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8));
   fail_unless_equals_int (x, 0x01);
@@ -63,11 +65,13 @@ GST_START_TEST (test_initialization)
   fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8));
   fail_unless_equals_int (x, 0x02);
 
-  gst_bit_reader_init_from_buffer (&reader, buffer);
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  gst_bit_reader_init (&reader, bdata, bsize);
   fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8));
   fail_unless_equals_int (x, 0x01);
   fail_unless (gst_bit_reader_get_bits_uint8 (&reader, &x, 8));
   fail_unless_equals_int (x, 0x02);
+  gst_buffer_unmap (buffer, bdata, bsize);
 
   reader2 = gst_bit_reader_new (data, 4);
   fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8));
@@ -76,12 +80,14 @@ GST_START_TEST (test_initialization)
   fail_unless_equals_int (x, 0x02);
   gst_bit_reader_free (reader2);
 
-  reader2 = gst_bit_reader_new_from_buffer (buffer);
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  reader2 = gst_bit_reader_new (bdata, bsize);
   fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8));
   fail_unless_equals_int (x, 0x01);
   fail_unless (gst_bit_reader_get_bits_uint8 (reader2, &x, 8));
   fail_unless_equals_int (x, 0x02);
   gst_bit_reader_free (reader2);
+  gst_buffer_unmap (buffer, bdata, bsize);
 
   gst_buffer_unref (buffer);
 }
index 4d0c3cf..dfb7ef4 100644 (file)
@@ -46,9 +46,11 @@ GST_START_TEST (test_initialization)
   GstByteReader reader = GST_BYTE_READER_INIT (data, 4);
   GstByteReader *reader2;
   guint8 x = 0;
+  guint8 *bdata;
+  gsize bsize;
 
-  GST_BUFFER_DATA (buffer) = data;
-  GST_BUFFER_SIZE (buffer) = 4;
+  gst_buffer_take_memory (buffer, -1,
+      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, data, NULL, 4, 0, 4));
 
   fail_unless (gst_byte_reader_get_uint8 (&reader, &x));
   fail_unless_equals_int (x, 0x01);
@@ -63,11 +65,13 @@ GST_START_TEST (test_initialization)
   fail_unless (gst_byte_reader_get_uint8 (&reader, &x));
   fail_unless_equals_int (x, 0x02);
 
-  gst_byte_reader_init_from_buffer (&reader, buffer);
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&reader, bdata, bsize);
   fail_unless (gst_byte_reader_get_uint8 (&reader, &x));
   fail_unless_equals_int (x, 0x01);
   fail_unless (gst_byte_reader_get_uint8 (&reader, &x));
   fail_unless_equals_int (x, 0x02);
+  gst_buffer_unmap (buffer, bdata, bsize);
 
   reader2 = gst_byte_reader_new (data, 4);
   fail_unless (gst_byte_reader_get_uint8 (reader2, &x));
@@ -76,12 +80,14 @@ GST_START_TEST (test_initialization)
   fail_unless_equals_int (x, 0x02);
   gst_byte_reader_free (reader2);
 
-  reader2 = gst_byte_reader_new_from_buffer (buffer);
+  bdata = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  reader2 = gst_byte_reader_new (bdata, bsize);
   fail_unless (gst_byte_reader_get_uint8 (reader2, &x));
   fail_unless_equals_int (x, 0x01);
   fail_unless (gst_byte_reader_get_uint8 (reader2, &x));
   fail_unless_equals_int (x, 0x02);
   gst_byte_reader_free (reader2);
+  gst_buffer_unmap (buffer, bdata, bsize);
 
   gst_buffer_unref (buffer);
 }
index 4a66101..ea54d39 100644 (file)
@@ -130,10 +130,10 @@ teardown (void)
 GST_START_TEST (test_pad_add_remove)
 {
   ASSERT_CRITICAL (gst_collect_pads_add_pad (collect, sinkpad1,
-          sizeof (BadCollectData)));
+          sizeof (BadCollectData), NULL));
 
   data1 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad1, sizeof (TestData));
+      sinkpad1, sizeof (TestData), NULL);
   fail_unless (data1 != NULL);
 
   fail_unless (gst_collect_pads_remove_pad (collect, sinkpad2) == FALSE);
@@ -148,11 +148,11 @@ GST_START_TEST (test_collect)
   GThread *thread1, *thread2;
 
   data1 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad1, sizeof (TestData));
+      sinkpad1, sizeof (TestData), NULL);
   fail_unless (data1 != NULL);
 
   data2 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad2, sizeof (TestData));
+      sinkpad2, sizeof (TestData), NULL);
   fail_unless (data2 != NULL);
 
   buf1 = gst_buffer_new ();
@@ -199,11 +199,11 @@ GST_START_TEST (test_collect_eos)
   GThread *thread1, *thread2;
 
   data1 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad1, sizeof (TestData));
+      sinkpad1, sizeof (TestData), NULL);
   fail_unless (data1 != NULL);
 
   data2 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad2, sizeof (TestData));
+      sinkpad2, sizeof (TestData), NULL);
   fail_unless (data2 != NULL);
 
   buf1 = gst_buffer_new ();
@@ -248,11 +248,11 @@ GST_START_TEST (test_collect_twice)
   GThread *thread1, *thread2;
 
   data1 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad1, sizeof (TestData));
+      sinkpad1, sizeof (TestData), NULL);
   fail_unless (data1 != NULL);
 
   data2 = (TestData *) gst_collect_pads_add_pad (collect,
-      sinkpad2, sizeof (TestData));
+      sinkpad2, sizeof (TestData), NULL);
   fail_unless (data2 != NULL);
 
   buf1 = gst_buffer_new ();
index 05cd432..7fc5d0b 100644 (file)
 #endif
 #include <gst/gst.h>
 #include <gst/check/gstcheck.h>
-#include <gst/controller/gstcontroller.h>
-#include <gst/controller/gstcontrolsource.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
 #include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gsttriggercontrolsource.h>
+#include <gst/controller/gstcontrolbindingdirect.h>
 
-/* LOCAL TEST ELEMENT */
+/* enum for text element */
+
+#define GST_TYPE_TEST_ENUM (gst_test_enum_get_type ())
+
+typedef enum
+{
+  ENUM_V0 = 0,
+  ENUM_V10 = 10,
+  ENUM_V11,
+  ENUM_V12,
+  ENUM_V255 = 255
+} GstTestEnum;
+
+static GType
+gst_test_enum_get_type (void)
+{
+  static gsize gtype = 0;
+  static const GEnumValue values[] = {
+    {ENUM_V0, "ENUM_V0", "0"},
+    {ENUM_V10, "ENUM_V10", "10"},
+    {ENUM_V11, "ENUM_V11", "11"},
+    {ENUM_V12, "ENUM_V12", "12"},
+    {ENUM_V255, "ENUM_V255", "255"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&gtype)) {
+    GType tmp = g_enum_register_static ("GstTestEnum", values);
+    g_once_init_leave (&gtype, tmp);
+  }
+
+  return (GType) gtype;
+}
+
+/* local test element */
 
 enum
 {
-  ARG_ULONG = 1,
-  ARG_FLOAT,
-  ARG_DOUBLE,
-  ARG_BOOLEAN,
-  ARG_READONLY,
-  ARG_STATIC,
-  ARG_CONSTRUCTONLY,
-  ARG_COUNT
+  PROP_INT = 1,
+  PROP_FLOAT,
+  PROP_DOUBLE,
+  PROP_BOOLEAN,
+  PROP_ENUM,
+  PROP_READONLY,
+  PROP_STATIC,
+  PROP_CONSTRUCTONLY,
+  PROP_COUNT
 };
 
-#define GST_TYPE_TEST_MONO_SOURCE            (gst_test_mono_source_get_type ())
-#define GST_TEST_MONO_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSource))
-#define GST_TEST_MONO_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSourceClass))
-#define GST_IS_TEST_MONO_SOURCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_MONO_SOURCE))
-#define GST_IS_TEST_MONO_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_MONO_SOURCE))
-#define GST_TEST_MONO_SOURCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSourceClass))
+#define GST_TYPE_TEST_OBJ            (gst_test_obj_get_type ())
+#define GST_TEST_OBJ(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj))
+#define GST_TEST_OBJ_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass))
+#define GST_IS_TEST_OBJ(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ))
+#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ))
+#define GST_TEST_OBJ_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass))
 
-typedef struct _GstTestMonoSource GstTestMonoSource;
-typedef struct _GstTestMonoSourceClass GstTestMonoSourceClass;
+typedef struct _GstTestObj GstTestObj;
+typedef struct _GstTestObjClass GstTestObjClass;
 
-struct _GstTestMonoSource
+struct _GstTestObj
 {
   GstElement parent;
-  gulong val_ulong;
+  gint val_int;
   gfloat val_float;
   gdouble val_double;
   gboolean val_boolean;
+  GstTestEnum val_enum;
 };
-struct _GstTestMonoSourceClass
+struct _GstTestObjClass
 {
   GstElementClass parent_class;
 };
 
-static GType gst_test_mono_source_get_type (void);
+static GType gst_test_obj_get_type (void);
 
 static void
-gst_test_mono_source_get_property (GObject * object,
+gst_test_obj_get_property (GObject * object,
     guint property_id, GValue * value, GParamSpec * pspec)
 {
-  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
+  GstTestObj *self = GST_TEST_OBJ (object);
 
   switch (property_id) {
-    case ARG_ULONG:
-      g_value_set_ulong (value, self->val_ulong);
+    case PROP_INT:
+      g_value_set_int (value, self->val_int);
       break;
-    case ARG_FLOAT:
+    case PROP_FLOAT:
       g_value_set_float (value, self->val_float);
       break;
-    case ARG_DOUBLE:
+    case PROP_DOUBLE:
       g_value_set_double (value, self->val_double);
       break;
-    case ARG_BOOLEAN:
+    case PROP_BOOLEAN:
       g_value_set_boolean (value, self->val_boolean);
       break;
+    case PROP_ENUM:
+      g_value_set_enum (value, self->val_enum);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -96,29 +135,33 @@ gst_test_mono_source_get_property (GObject * object,
 }
 
 static void
-gst_test_mono_source_set_property (GObject * object,
+gst_test_obj_set_property (GObject * object,
     guint property_id, const GValue * value, GParamSpec * pspec)
 {
-  GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
+  GstTestObj *self = GST_TEST_OBJ (object);
 
   switch (property_id) {
-    case ARG_ULONG:
-      self->val_ulong = g_value_get_ulong (value);
-      GST_DEBUG ("test value ulong=%lu", self->val_ulong);
+    case PROP_INT:
+      self->val_int = g_value_get_int (value);
+      GST_DEBUG ("test value int=%d", self->val_int);
       break;
-    case ARG_FLOAT:
+    case PROP_FLOAT:
       self->val_float = g_value_get_float (value);
       GST_DEBUG ("test value float=%f", self->val_float);
       break;
-    case ARG_DOUBLE:
+    case PROP_DOUBLE:
       self->val_double = g_value_get_double (value);
-      GST_DEBUG ("test value double=%f", self->val_double);
+      GST_DEBUG ("test value double=%lf", self->val_double);
       break;
-    case ARG_BOOLEAN:
+    case PROP_BOOLEAN:
       self->val_boolean = g_value_get_boolean (value);
       GST_DEBUG ("test value boolean=%d", self->val_boolean);
       break;
-    case ARG_CONSTRUCTONLY:
+    case PROP_ENUM:
+      self->val_enum = g_value_get_enum (value);
+      GST_DEBUG ("test value enum=%d", self->val_enum);
+      break;
+    case PROP_CONSTRUCTONLY:
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -127,837 +170,348 @@ gst_test_mono_source_set_property (GObject * object,
 }
 
 static void
-gst_test_mono_source_class_init (GstTestMonoSourceClass * klass)
+gst_test_obj_class_init (GstTestObjClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  gobject_class->set_property = gst_test_mono_source_set_property;
-  gobject_class->get_property = gst_test_mono_source_get_property;
+  gobject_class->set_property = gst_test_obj_set_property;
+  gobject_class->get_property = gst_test_obj_get_property;
 
-  g_object_class_install_property (gobject_class, ARG_ULONG,
-      g_param_spec_ulong ("ulong",
-          "ulong prop",
-          "ulong number parameter for the test_mono_source",
-          0, G_MAXULONG, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (gobject_class, PROP_INT,
+      g_param_spec_int ("int",
+          "int prop",
+          "int number parameter",
+          0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
-  g_object_class_install_property (gobject_class, ARG_FLOAT,
+  g_object_class_install_property (gobject_class, PROP_FLOAT,
       g_param_spec_float ("float",
           "float prop",
-          "float number parameter for the test_mono_source",
+          "float number parameter",
           0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
-  g_object_class_install_property (gobject_class, ARG_DOUBLE,
+  g_object_class_install_property (gobject_class, PROP_DOUBLE,
       g_param_spec_double ("double",
           "double prop",
-          "double number parameter for the test_mono_source",
+          "double number parameter",
           0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
-  g_object_class_install_property (gobject_class, ARG_BOOLEAN,
+  g_object_class_install_property (gobject_class, PROP_BOOLEAN,
       g_param_spec_boolean ("boolean",
           "boolean prop",
-          "boolean parameter for the test_mono_source",
+          "boolean parameter",
           FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
-  g_object_class_install_property (gobject_class, ARG_READONLY,
-      g_param_spec_ulong ("readonly",
+  g_object_class_install_property (gobject_class, PROP_ENUM,
+      g_param_spec_enum ("enum",
+          "enum prop",
+          "enum parameter",
+          GST_TYPE_TEST_ENUM, ENUM_V0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_READONLY,
+      g_param_spec_int ("readonly",
           "readonly prop",
-          "readonly parameter for the test_mono_source",
-          0, G_MAXULONG, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE));
+          "readonly parameter",
+          0, G_MAXINT, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE));
 
-  g_object_class_install_property (gobject_class, ARG_STATIC,
-      g_param_spec_ulong ("static",
+  g_object_class_install_property (gobject_class, PROP_STATIC,
+      g_param_spec_int ("static",
           "static prop",
-          "static parameter for the test_mono_source",
-          0, G_MAXULONG, 0, G_PARAM_READWRITE));
+          "static parameter", 0, G_MAXINT, 0, G_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_class, ARG_CONSTRUCTONLY,
-      g_param_spec_ulong ("construct-only",
+  g_object_class_install_property (gobject_class, PROP_CONSTRUCTONLY,
+      g_param_spec_int ("construct-only",
           "construct-only prop",
-          "construct-only parameter for the test_mono_source",
-          0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+          "construct-only parameter",
+          0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
-gst_test_mono_source_base_init (GstTestMonoSourceClass * klass)
+gst_test_obj_base_init (GstTestObjClass * klass)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
   gst_element_class_set_details_simple (element_class,
-      "Monophonic source for unit tests",
-      "Source/Audio/MonoSource",
-      "Use in unit tests", "Stefan Kost <ensonic@users.sf.net>");
+      "test object for unit tests",
+      "Test", "Use in unit tests", "Stefan Sauer <ensonic@users.sf.net>");
 }
 
 static GType
-gst_test_mono_source_get_type (void)
+gst_test_obj_get_type (void)
 {
-  static volatile gsize test_mono_source_type = 0;
+  static volatile gsize test_obj_type = 0;
 
-  if (g_once_init_enter (&test_mono_source_type)) {
+  if (g_once_init_enter (&test_obj_type)) {
     GType type;
     static const GTypeInfo info = {
-      (guint16) sizeof (GstTestMonoSourceClass),
-      (GBaseInitFunc) gst_test_mono_source_base_init,   // base_init
+      (guint16) sizeof (GstTestObjClass),
+      (GBaseInitFunc) gst_test_obj_base_init,   // base_init
       NULL,                     // base_finalize
-      (GClassInitFunc) gst_test_mono_source_class_init, // class_init
+      (GClassInitFunc) gst_test_obj_class_init, // class_init
       NULL,                     // class_finalize
       NULL,                     // class_data
-      (guint16) sizeof (GstTestMonoSource),
+      (guint16) sizeof (GstTestObj),
       0,                        // n_preallocs
       NULL,                     // instance_init
       NULL                      // value_table
     };
-    type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstTestMonoSource", &info,
-        0);
-    g_once_init_leave (&test_mono_source_type, type);
+    type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0);
+    g_once_init_leave (&test_obj_type, type);
   }
-  return test_mono_source_type;
-}
-
-/* so we don't have to paste the gst_element_register into 50 places below */
-static gboolean
-local_gst_controller_init (int *argc, char ***argv)
-{
-  fail_unless (gst_controller_init (argc, argv));
-
-  fail_unless (gst_element_register (NULL, "testmonosource", GST_RANK_NONE,
-          GST_TYPE_TEST_MONO_SOURCE));
-
-  return TRUE;
-}
-
-#define gst_controller_init(a,b) local_gst_controller_init(a,b)
-
-/* TESTS */
-/* double init should not harm */
-GST_START_TEST (controller_init)
-{
-  gst_controller_init (NULL, NULL);
-  gst_controller_init (NULL, NULL);
-  gst_controller_init (NULL, NULL);
-  gst_controller_init (NULL, NULL);
-}
-
-GST_END_TEST;
-
-/* tests for an element with no controlled params */
-GST_START_TEST (controller_new_fail1)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("fakesrc", "test_source");
-
-  /* that property should not exist */
-  ctrl = gst_controller_new (G_OBJECT (elem), "_schrompf_", NULL);
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* tests for an element with controlled params, but none given */
-GST_START_TEST (controller_new_fail2)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* no property given */
-  ctrl = gst_controller_new (G_OBJECT (elem), NULL);
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* tests for readonly params */
-GST_START_TEST (controller_new_fail3)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and but is readonly */
-  ASSERT_CRITICAL (ctrl =
-      gst_controller_new (G_OBJECT (elem), "readonly", NULL));
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* tests for static params */
-GST_START_TEST (controller_new_fail4)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and but is not controlable */
-  ASSERT_CRITICAL (ctrl = gst_controller_new (G_OBJECT (elem), "static", NULL));
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* tests for construct-only params */
-GST_START_TEST (controller_new_fail5)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and but is construct-only */
-  ASSERT_CRITICAL (ctrl =
-      gst_controller_new (G_OBJECT (elem), "construct-only", NULL));
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-
-/* tests for an element with controlled params */
-GST_START_TEST (controller_new_okay1)
-{
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* tests for an element with several controlled params */
-GST_START_TEST (controller_new_okay2)
-{
-  GstController *ctrl, *ctrl2, *ctrl3;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "double", "float", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 1);
-
-  ctrl2 = gst_controller_new (G_OBJECT (elem), "boolean", NULL);
-  fail_unless (ctrl2 != NULL, NULL);
-  fail_unless (ctrl2 == ctrl, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 2);
-
-  /* trying to control the same properties again should correctly
-   * increase the refcount of the object returned as well */
-  ctrl3 =
-      gst_controller_new (G_OBJECT (elem), "ulong", "double", "float", NULL);
-  fail_unless (ctrl3 != NULL, NULL);
-  fail_unless (ctrl3 == ctrl, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 3);
-
-  g_object_unref (ctrl);
-  g_object_unref (ctrl2);
-  g_object_unref (ctrl3);
-  gst_object_unref (elem);
+  return test_obj_type;
 }
 
-GST_END_TEST;
-
-/* controlling several params should return the same controller */
-GST_START_TEST (controller_new_okay3)
-{
-  GstController *ctrl1, *ctrl2, *ctrl3;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl1 = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl1 != NULL, NULL);
-
-  /* that property should exist and should be controllable */
-  ctrl2 = gst_controller_new (G_OBJECT (elem), "double", NULL);
-  fail_unless (ctrl2 != NULL, NULL);
-  fail_unless (ctrl1 == ctrl2, NULL);
-
-  /* that property should exist and should be controllable */
-  ctrl3 = gst_controller_new (G_OBJECT (elem), "float", NULL);
-  fail_unless (ctrl3 != NULL, NULL);
-  fail_unless (ctrl1 == ctrl3, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl1)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl1)->ref_count, 3);
-  g_object_unref (ctrl1);
-  g_object_unref (ctrl2);
-  g_object_unref (ctrl3);
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* controlling a params twice should be handled */
-GST_START_TEST (controller_param_twice)
+static void
+setup (void)
 {
-  GstController *ctrl;
-  GstElement *elem;
-  gboolean res;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* it should have been added at least once, let remove it */
-  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
-  fail_unless (res, NULL);
-
-  /* removing it again should not work */
-  res = gst_controller_remove_properties (ctrl, "ulong", NULL);
-  fail_unless (!res, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
+  gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ);
 }
 
-GST_END_TEST;
-
-/* tests if we cleanup properly */
-GST_START_TEST (controller_finalize)
+static void
+teardown (void)
 {
-  GstController *ctrl;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* free the controller */
-  g_object_unref (ctrl);
-
-  /* object shouldn't have a controller anymore */
-  ctrl = gst_object_get_controller (G_OBJECT (elem));
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
 }
 
-GST_END_TEST;
-
-/* tests if we cleanup properly */
-GST_START_TEST (controller_controlsource_refcounts)
-{
-  GstController *ctrl;
-  GstElement *elem;
-  GstControlSource *csource, *test_csource;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  csource = (GstControlSource *) gst_interpolation_control_source_new ();
-  fail_unless (csource != NULL, NULL);
-
-  fail_unless_equals_int (G_OBJECT (csource)->ref_count, 1);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong", csource));
-  fail_unless_equals_int (G_OBJECT (csource)->ref_count, 2);
-
-  g_object_unref (G_OBJECT (csource));
 
-  test_csource = gst_controller_get_control_source (ctrl, "ulong");
-  fail_unless (test_csource != NULL, NULL);
-  fail_unless (test_csource == csource);
-  fail_unless_equals_int (G_OBJECT (csource)->ref_count, 2);
-  g_object_unref (csource);
-
-  /* free the controller */
-  g_object_unref (ctrl);
-
-  /* object shouldn't have a controller anymore */
-  ctrl = gst_object_get_controller (G_OBJECT (elem));
-  fail_unless (ctrl == NULL, NULL);
-
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
+/* TESTS */
 
-/* tests if we don't fail on empty controllers */
+/* tests if we don't fail on empty interpolation controlsources */
 GST_START_TEST (controller_controlsource_empty1)
 {
-  GstController *ctrl;
   GstElement *elem;
   GstControlSource *csource;
 
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
   csource = (GstControlSource *) gst_interpolation_control_source_new ();
   fail_unless (csource != NULL, NULL);
 
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong", csource));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int",
+              (GstControlSource *) csource)));
 
   /* don't fail on empty control point lists */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
 
   /* unref objects */
-  g_object_unref (csource);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
-/* tests if we don't fail on controllers that are empty again */
+/* tests if we don't fail on interpolation controlsources that are empty again */
 GST_START_TEST (controller_controlsource_empty2)
 {
-  GstController *ctrl;
   GstElement *elem;
   GstInterpolationControlSource *csource;
-  GValue val = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  GstTimedValueControlSource *cs;
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
   csource = gst_interpolation_control_source_new ();
   fail_unless (csource != NULL, NULL);
 
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          (GstControlSource *) csource));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int",
+              (GstControlSource *) csource)));
 
   /* set control values */
-  g_value_init (&val, G_TYPE_ULONG);
-  g_value_set_ulong (&val, 0);
-  gst_interpolation_control_source_set (csource, 0 * GST_SECOND, &val);
+  cs = (GstTimedValueControlSource *) csource;
+  gst_timed_value_control_source_set (cs, 0 * GST_SECOND, 0);
 
   /* ... and unset the value */
-  gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
+  gst_timed_value_control_source_unset (cs, 0 * GST_SECOND);
 
   /* don't fail on empty control point lists */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
 
   /* unref objects */
-  g_object_unref (csource);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
 /* test timed value handling without interpolation */
-GST_START_TEST (controller_interpolate_none)
-{
-  GstController *ctrl;
-  GstInterpolationControlSource *csource;
-  GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
-  csource = gst_interpolation_control_source_new ();
-
-  fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_NONE));
-
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
-
-  /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
-
-  g_object_unref (G_OBJECT (csource));
-
-  /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* test timed value handling in trigger mode */
-GST_START_TEST (controller_interpolate_trigger)
+GST_START_TEST (controller_interpolation_none)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
+  gdouble v;
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_TRIGGER));
-
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
-          0 * GST_SECOND, &val_ulong));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
 
   /* set control values */
-  g_value_set_ulong (&val_ulong, 50);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
+
+  /* check values on control source directly */
+  fail_unless (gst_control_source_get_value (cs, 0 * GST_SECOND, &v));
+  fail_unless_equals_float (v, 0.0);
+  fail_unless (gst_control_source_get_value (cs, 1 * GST_SECOND, &v));
+  fail_unless_equals_float (v, 0.0);
+  fail_unless (gst_control_source_get_value (cs, 2 * GST_SECOND, &v));
+  fail_unless_equals_float (v, 1.0);
+  fail_unless (gst_control_source_get_value (cs, 3 * GST_SECOND, &v));
+  fail_unless_equals_float (v, 1.0);
 
   /* now pull in values for some timestamps */
-  fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
-          0 * GST_SECOND, &val_ulong));
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
-          1 * GST_SECOND, &val_ulong));
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
-          2 * GST_SECOND, &val_ulong));
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (G_OBJECT (csource));
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
 /* test timed value handling with linear interpolation */
-GST_START_TEST (controller_interpolate_linear)
+GST_START_TEST (controller_interpolation_linear)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
 /* test timed value handling with cubic interpolation */
-GST_START_TEST (controller_interpolate_cubic)
+GST_START_TEST (controller_interpolation_cubic)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_double = { 0, };
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "double", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "double",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "double", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_CUBIC));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
 
   /* set control values */
-  g_value_init (&val_double, G_TYPE_DOUBLE);
-  g_value_set_double (&val_double, 0.0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-  g_value_set_double (&val_double, 5.0);
-  res =
-      gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-  g_value_set_double (&val_double, 2.0);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-  g_value_set_double (&val_double, 8.0);
-  res =
-      gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 0.5));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.2));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 0.8));
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 0.0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 5.0);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 2.0);
-  gst_controller_sync_values (ctrl, 3 * GST_SECOND);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double > 2.0 &&
-      GST_TEST_MONO_SOURCE (elem)->val_double < 8.0, NULL);
-  gst_controller_sync_values (ctrl, 4 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 8.0);
-  gst_controller_sync_values (ctrl, 5 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 8.0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 50.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless (GST_TEST_OBJ (elem)->val_double > 20.0 &&
+      GST_TEST_OBJ (elem)->val_double < 80.0, NULL);
+  gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 80.0);
+  gst_object_sync_values (GST_OBJECT (elem), 5 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 80.0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
 /* test timed value handling with cubic interpolation */
-GST_START_TEST (controller_interpolate_cubic_too_few_cp)
+GST_START_TEST (controller_interpolation_cubic_too_few_cp)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_double = { 0, };
-
-  gst_controller_init (NULL, NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "double", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "double",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "double", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_CUBIC));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
 
   /* set 2 control values */
-  g_value_init (&val_double, G_TYPE_DOUBLE);
-  g_value_set_double (&val_double, 0.0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-  g_value_set_double (&val_double, 4.0);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.4));
 
   /* now pull in values for some timestamps and verify that it used linear
    * interpolation as we don't gave enough control points
    */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 0.0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 2.0);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_double, 4.0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* make sure we don't crash when someone sets an unsupported interpolation
- * mode */
-GST_START_TEST (controller_interpolate_unimplemented)
-{
-  GstController *ctrl;
-  GstInterpolationControlSource *csource;
-  GstElement *elem;
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
-  csource = gst_interpolation_control_source_new ();
-
-  fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  /* set completely bogus interpolation mode */
-  fail_if (gst_interpolation_control_source_set_interpolation_mode (csource,
-          (GstInterpolateMode) 93871));
-
-  g_object_unref (G_OBJECT (csource));
-
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -966,79 +520,54 @@ GST_END_TEST;
 /* test _unset() */
 GST_START_TEST (controller_interpolation_unset)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_NONE));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
 
   /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 50);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 0.5));
 
   /* verify values */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
 
   /* unset second */
-  res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 1 * GST_SECOND));
 
   /* verify value again */
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
 
   /* unset all values, reset and try to unset again */
-  fail_unless (gst_interpolation_control_source_unset (csource,
-          0 * GST_SECOND));
-  fail_unless (gst_interpolation_control_source_unset (csource,
-          2 * GST_SECOND));
-  gst_interpolation_control_source_unset_all (csource);
-  fail_if (gst_interpolation_control_source_unset (csource, 2 * GST_SECOND));
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 0 * GST_SECOND));
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND));
+  gst_timed_value_control_source_unset_all (tvcs);
+  fail_if (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND));
 
-  g_object_unref (csource);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1047,61 +576,44 @@ GST_END_TEST;
 /* test _unset_all() */
 GST_START_TEST (controller_interpolation_unset_all)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_NONE));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
 
   /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0));
 
   /* verify values */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
 
   /* unset all */
-  gst_interpolation_control_source_unset_all (csource);
-
-  g_object_unref (csource);
+  gst_timed_value_control_source_unset_all (tvcs);
+  GST_TEST_OBJ (elem)->val_int = 0;
 
   /* verify value again */
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
 
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1110,62 +622,54 @@ GST_END_TEST;
 /* test retrieval of an array of values with get_value_array() */
 GST_START_TEST (controller_interpolation_linear_value_array)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-  GstValueArray values = { NULL, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  gdouble *raw_values;
+  GValue *g_values;
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 1.0));
 
-  /* now pull in values for some timestamps */
-  values.property_name = (char *) "ulong";
-  values.nbsamples = 3;
-  values.sample_interval = GST_SECOND;
-  values.values = (gpointer) g_new (gulong, 3);
-
-  fail_unless (gst_control_source_get_value_array (GST_CONTROL_SOURCE (csource),
-          0, &values));
-  fail_unless_equals_int (((gulong *) values.values)[0], 0);
-  fail_unless_equals_int (((gulong *) values.values)[1], 50);
-  fail_unless_equals_int (((gulong *) values.values)[2], 100);
-
-  g_object_unref (csource);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_free (values.values);
-  g_object_unref (ctrl);
+  /* now pull in raw-values for some timestamps */
+  raw_values = g_new (gdouble, 3);
+
+  fail_unless (gst_control_source_get_value_array (cs,
+          0, GST_SECOND / 2, 3, raw_values));
+  fail_unless_equals_float ((raw_values)[0], 0.0);
+  fail_unless_equals_float ((raw_values)[1], 0.5);
+  fail_unless_equals_float ((raw_values)[2], 1.0);
+
+  g_free (raw_values);
+
+  /* now pull in mapped values for some timestamps */
+  g_values = g_new0 (GValue, 3);
+
+  fail_unless (gst_object_get_value_array (GST_OBJECT (elem), "int",
+          0, GST_SECOND / 2, 3, g_values));
+  fail_unless_equals_int (g_value_get_int (&g_values[0]), 0);
+  fail_unless_equals_int (g_value_get_int (&g_values[1]), 50);
+  fail_unless_equals_int (g_value_get_int (&g_values[2]), 100);
+
+  g_free (g_values);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1174,68 +678,51 @@ GST_END_TEST;
 /* test if values below minimum and above maximum are clipped */
 GST_START_TEST (controller_interpolation_linear_invalid_values)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_float = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "float", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "float",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "float", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control values */
-  g_value_init (&val_float, G_TYPE_FLOAT);
-  g_value_set_float (&val_float, 200.0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_float);
-  fail_unless (res, NULL);
-  g_value_set_float (&val_float, -200.0);
-  res =
-      gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
-      &val_float);
-  fail_unless (res, NULL);
-
-  g_object_unref (csource);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 2.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, -2.0));
 
   /* now pull in values for some timestamps and see if clipping works */
   /* 200.0 */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 100.0);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 100.0);
   /* 100.0 */
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 100.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 100.0);
   /* 50.0 */
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND + 500 * GST_MSECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 50.0);
+  gst_object_sync_values (GST_OBJECT (elem),
+      1 * GST_SECOND + 500 * GST_MSECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 50.0);
   /* 0.0 */
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0);
   /* -100.0 */
-  gst_controller_sync_values (ctrl, 3 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0);
   /* -200.0 */
-  gst_controller_sync_values (ctrl, 4 * GST_SECOND);
-  fail_unless_equals_float (GST_TEST_MONO_SOURCE (elem)->val_float, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_float, 0.0);
 
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1243,248 +730,191 @@ GST_END_TEST;
 
 GST_START_TEST (controller_interpolation_linear_default_values)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
-
-  g_value_init (&val_ulong, G_TYPE_ULONG);
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* Should fail if no value was set yet
    * FIXME: will not fail, as interpolation assumes val[0]=default_value if
    * nothing else is set.
    fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
-   1 * GST_SECOND, &val_ulong));
+   1 * GST_SECOND, &val_int));
    */
 
   /* set control values */
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 3 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 1 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 3 * GST_SECOND, 1.0));
 
   /* now pull in values for some timestamps */
   /* should give the value of the first control point for timestamps before it */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 3 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
 
   /* set control values */
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
 
   /* unset the old ones */
-  res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
-  fail_unless (res, NULL);
-  res = gst_interpolation_control_source_unset (csource, 3 * GST_SECOND);
-  fail_unless (res, NULL);
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 1 * GST_SECOND));
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 3 * GST_SECOND));
 
   /* now pull in values for some timestamps */
   /* should now give our value for timestamp 0 */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
-  g_object_unref (G_OBJECT (csource));
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
 /* test gst_controller_set_disabled() with linear interpolation */
-GST_START_TEST (controller_interpolate_linear_disabled)
+GST_START_TEST (controller_interpolation_linear_disabled)
 {
-  GstController *ctrl;
-  GstInterpolationControlSource *csource, *csource2;
+  GstInterpolationControlSource *csource1, *csource2;
+  GstTimedValueControlSource *tvcs1, *tvcs2;
+  GstControlSource *cs1, *cs2;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, }
-  , val_double = {
-  0,};
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  /* new interpolation control source */
+  csource1 = gst_interpolation_control_source_new ();
+  tvcs1 = (GstTimedValueControlSource *) csource1;
+  cs1 = (GstControlSource *) csource1;
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "double", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
-  csource = gst_interpolation_control_source_new ();
   csource2 = gst_interpolation_control_source_new ();
+  tvcs2 = (GstTimedValueControlSource *) csource2;
+  cs2 = (GstControlSource *) csource2;
 
-  fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (csource1 != NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs1)));
   fail_unless (csource2 != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "double",
-          GST_CONTROL_SOURCE (csource2)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "double", cs2)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode
-      (csource2, GST_INTERPOLATE_LINEAR));
+  g_object_set (csource1, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+  g_object_set (csource2, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource));
-
-/* set control values */
-  g_value_init (&val_double, G_TYPE_DOUBLE);
-  g_value_set_double (&val_double, 2.0);
-  res =
-      gst_interpolation_control_source_set (csource2, 0 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-  g_value_set_double (&val_double, 4.0);
-  res =
-      gst_interpolation_control_source_set (csource2, 2 * GST_SECOND,
-      &val_double);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource2));
+  fail_unless (gst_timed_value_control_source_set (tvcs1, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs1, 2 * GST_SECOND, 1.0));
+
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs2, 0 * GST_SECOND, 0.2));
+  fail_unless (gst_timed_value_control_source_set (tvcs2, 2 * GST_SECOND, 0.4));
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 2.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 3.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 4.0, NULL);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0);
 
   /* now pull in values for some timestamps, prop double disabled */
-  GST_TEST_MONO_SOURCE (elem)->val_ulong = 0;
-  GST_TEST_MONO_SOURCE (elem)->val_double = 0.0;
-  gst_controller_set_property_disabled (ctrl, "double", TRUE);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  GST_TEST_OBJ (elem)->val_double = 0.0;
+  gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", TRUE);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
 
   /* now pull in values for some timestamps, after enabling double again */
-  GST_TEST_MONO_SOURCE (elem)->val_ulong = 0;
-  GST_TEST_MONO_SOURCE (elem)->val_double = 0.0;
-  gst_controller_set_property_disabled (ctrl, "double", FALSE);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 2.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 3.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 4.0, NULL);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  GST_TEST_OBJ (elem)->val_double = 0.0;
+  gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", FALSE);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0);
 
   /* now pull in values for some timestamps, after disabling all props */
-  GST_TEST_MONO_SOURCE (elem)->val_ulong = 0;
-  GST_TEST_MONO_SOURCE (elem)->val_double = 0.0;
-  gst_controller_set_disabled (ctrl, TRUE);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  GST_TEST_OBJ (elem)->val_double = 0.0;
+  gst_object_set_control_bindings_disabled (GST_OBJECT (elem), TRUE);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 0.0);
 
   /* now pull in values for some timestamps, enabling double again */
-  GST_TEST_MONO_SOURCE (elem)->val_ulong = 0;
-  GST_TEST_MONO_SOURCE (elem)->val_double = 0.0;
-  gst_controller_set_property_disabled (ctrl, "double", FALSE);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 2.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 3.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 4.0, NULL);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  GST_TEST_OBJ (elem)->val_double = 0.0;
+  gst_object_set_control_binding_disabled (GST_OBJECT (elem), "double", FALSE);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0);
 
   /* now pull in values for some timestamps, enabling all */
-  GST_TEST_MONO_SOURCE (elem)->val_ulong = 0;
-  GST_TEST_MONO_SOURCE (elem)->val_double = 0.0;
-  gst_controller_set_disabled (ctrl, FALSE);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 2.0, NULL);
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 3.0, NULL);
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 4.0, NULL);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  GST_TEST_OBJ (elem)->val_double = 0.0;
+  gst_object_set_control_bindings_disabled (GST_OBJECT (elem), FALSE);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 20.0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 30.0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  fail_unless_equals_float (GST_TEST_OBJ (elem)->val_double, 40.0);
+
+  gst_object_unref (csource1);
+  gst_object_unref (csource2);
   gst_object_unref (elem);
 }
 
@@ -1493,124 +923,234 @@ GST_END_TEST;
 
 GST_START_TEST (controller_interpolation_set_from_list)
 {
-  GstController *ctrl;
   GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
   GstTimedValue *tval;
   GstElement *elem;
   GSList *list = NULL;
 
-  gst_controller_init (NULL, NULL);
-
   /* test that an invalid timestamp throws a warning of some sort */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new interpolation control source */
   csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control value */
   tval = g_new0 (GstTimedValue, 1);
   tval->timestamp = GST_CLOCK_TIME_NONE;
-  g_value_init (&tval->value, G_TYPE_ULONG);
-  g_value_set_ulong (&tval->value, 0);
+  tval->value = 0.0;
 
   list = g_slist_append (list, tval);
 
-  fail_if (gst_interpolation_control_source_set_from_list (csource, list));
+  fail_if (gst_timed_value_control_source_set_from_list (tvcs, list));
 
   /* try again with a valid stamp, should work now */
   tval->timestamp = 0;
-  fail_unless (gst_interpolation_control_source_set_from_list (csource, list));
-
-  g_object_unref (csource);
+  fail_unless (gst_timed_value_control_source_set_from_list (tvcs, list));
 
   /* allocated GstTimedValue now belongs to the controller, but list not */
-  g_value_unset (&tval->value);
   g_free (tval);
   g_slist_free (list);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+
+/* test linear interpolation for ts < first control point */
+GST_START_TEST (controller_interpolation_linear_before_ts0)
+{
+  GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  /* new interpolation control source */
+  csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
+
+  fail_unless (csource != NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
+
+  /* set interpolation mode */
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 0.0));
+
+  /* now pull in values for some timestamps after first control point */
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+
+  /* now pull in values for some timestamps before first control point */
+  GST_TEST_OBJ (elem)->val_int = 25;
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+
+  gst_object_unref (csource);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* test linear interpolation of enums */
+GST_START_TEST (controller_interpolation_linear_enums)
+{
+  GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  /* new interpolation control source */
+  csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
+
+  fail_unless (csource != NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "enum", cs)));
+
+  /* set interpolation mode */
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 1.0));
+
+  /* now pull in values going over the enum values */
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V10);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V11);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V12);
+  gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V255);
+
+  gst_object_unref (csource);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* test timed value counts */
+GST_START_TEST (controller_timed_value_count)
+{
+  GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  /* new interpolation control source */
+  csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
+
+  fail_unless (csource != NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
+
+  /* set interpolation mode */
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
+
+  fail_unless (gst_timed_value_control_source_get_count (tvcs) == 0);
+
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_get_count (tvcs) == 1);
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
+  fail_unless (gst_timed_value_control_source_get_count (tvcs) == 2);
+
+  /* unset control values */
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 2 * GST_SECOND));
+  fail_unless (gst_timed_value_control_source_get_count (tvcs) == 1);
+  fail_unless (gst_timed_value_control_source_unset (tvcs, 0 * GST_SECOND));
+  fail_unless (gst_timed_value_control_source_get_count (tvcs) == 0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
+
 /* test lfo control source with sine waveform */
 GST_START_TEST (controller_lfo_sine)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_SINE,
       "frequency", 1.0, "timeshift", (GstClockTime) 0,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+      "amplitude", 0.5, "offset", 0.5, NULL);
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1619,69 +1159,52 @@ GST_END_TEST;
 /* test lfo control source with sine waveform and timeshift */
 GST_START_TEST (controller_lfo_sine_timeshift)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
-
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_SINE,
       "frequency", 1.0, "timeshift", 250 * GST_MSECOND,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
-
-/* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+      "amplitude", 0.5, "offset", 0.5, NULL);
+
+  /* now pull in values for some timestamps */
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1690,69 +1213,52 @@ GST_END_TEST;
 /* test lfo control source with square waveform */
 GST_START_TEST (controller_lfo_square)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_SQUARE,
       "frequency", 1.0, "timeshift", (GstClockTime) 0,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+      "amplitude", 0.5, "offset", 0.5, NULL);
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1761,69 +1267,52 @@ GST_END_TEST;
 /* test lfo control source with saw waveform */
 GST_START_TEST (controller_lfo_saw)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
-
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_SAW,
       "frequency", 1.0, "timeshift", (GstClockTime) 0,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+      "amplitude", 0.5, "offset", 0.5, NULL);
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1832,69 +1321,52 @@ GST_END_TEST;
 /* test lfo control source with reverse saw waveform */
 GST_START_TEST (controller_lfo_rsaw)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
-
-  gst_controller_init (NULL, NULL);
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW,
       "frequency", 1.0, "timeshift", (GstClockTime) 0,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+      "amplitude", 0.5, "offset", 0.5, NULL);
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 150);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 25);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 75);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1903,69 +1375,52 @@ GST_END_TEST;
 /* test lfo control source with saw waveform */
 GST_START_TEST (controller_lfo_triangle)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
-  GValue amp = { 0, }
-  , off = {
-  0,};
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set amplitude and offset values */
-  g_value_init (&amp, G_TYPE_ULONG);
-  g_value_init (&off, G_TYPE_ULONG);
-  g_value_set_ulong (&amp, 100);
-  g_value_set_ulong (&off, 100);
-
-  /* set waveform mode */
+  /* configure lfo */
   g_object_set (csource, "waveform", GST_LFO_WAVEFORM_TRIANGLE,
       "frequency", 1.0, "timeshift", (GstClockTime) 0,
-      "amplitude", &amp, "offset", &off, NULL);
-
-  g_object_unref (G_OBJECT (csource));
+      "amplitude", 0.5, "offset", 0.5, NULL);
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 200);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -1974,280 +1429,142 @@ GST_END_TEST;
 /* test lfo control source with nothing set */
 GST_START_TEST (controller_lfo_none)
 {
-  GstController *ctrl;
   GstLFOControlSource *csource;
+  GstControlSource *cs;
   GstElement *elem;
 
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
+  /* new lfo control source */
   csource = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
-
-  g_object_unref (G_OBJECT (csource));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
   /* now pull in values for some timestamps */
-  gst_controller_sync_values (ctrl, 0 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 2000 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1250 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1500 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-  gst_controller_sync_values (ctrl, 1750 * GST_MSECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2000 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1250 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1500 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+  gst_object_sync_values (GST_OBJECT (elem), 1750 * GST_MSECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
+
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
-/* tests if we can run helper methods against any GObject */
-GST_START_TEST (controller_helper_any_gobject)
+/* test timed value handling in trigger mode */
+GST_START_TEST (controller_trigger_exact)
 {
+  GstTriggerControlSource *csource;
+  GstControlSource *cs;
+  GstTimedValueControlSource *tvcs;
   GstElement *elem;
-  gboolean res;
+  gdouble raw_val;
 
-  gst_controller_init (NULL, NULL);
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  elem = gst_element_factory_make ("bin", "test_elem");
+  /* new interpolation control source */
+  csource = gst_trigger_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
-  /* that element is not controllable */
-  res = gst_object_sync_values (G_OBJECT (elem), 0LL);
-  /* Syncing should still succeed as there's nothing to sync */
-  fail_unless (res == TRUE, NULL);
+  fail_unless (csource != NULL);
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  gst_object_unref (elem);
-}
+  fail_if (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val));
 
-GST_END_TEST;
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.5));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
 
-GST_START_TEST (controller_refcount_new_list)
-{
-  GstController *ctrl, *ctrl2;
-  GstElement *elem;
-  GList *list = NULL;
-
-  gst_controller_init (NULL, NULL);
-
-  /* that property should exist and should be controllable */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-  list = g_list_append (NULL, (char *) "ulong");
-  ctrl = gst_controller_new_list (G_OBJECT (elem), list);
-  fail_unless (ctrl != NULL, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 1);
-  g_list_free (list);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
+  /* now pull in values for some timestamps */
+  fail_unless (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val));
 
-  /* try the same property twice, make sure the refcount is still 1 */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-  list = g_list_append (NULL, (char *) "ulong");
-  list = g_list_append (list, (char *) "ulong");
-  ctrl = gst_controller_new_list (G_OBJECT (elem), list);
-  fail_unless (ctrl != NULL, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 1);
-  g_list_free (list);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
 
-  /* try two properties, make sure the refcount is still 1 */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-  list = g_list_append (NULL, (char *) "ulong");
-  list = g_list_append (list, (char *) "boolean");
-  ctrl = gst_controller_new_list (G_OBJECT (elem), list);
-  fail_unless (ctrl != NULL, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 1);
-  g_list_free (list);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
+  GST_TEST_OBJ (elem)->val_int = 0;
+  fail_if (gst_control_source_get_value (cs, 1 * GST_SECOND, &raw_val));
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
 
-  /* try _new_list with existing controller */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  list = g_list_append (NULL, (char *) "ulong");
-  ctrl2 = gst_controller_new_list (G_OBJECT (elem), list);
-  fail_unless (ctrl2 != NULL, NULL);
-  fail_unless (ctrl == ctrl2, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 2);
-  g_list_free (list);
-  g_object_unref (ctrl);
-  g_object_unref (ctrl2);
-  gst_object_unref (elem);
+  fail_unless (gst_control_source_get_value (cs, 2 * GST_SECOND, &raw_val));
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
 
-  /* try _new_list first and then _new */
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-  list = g_list_append (NULL, (char *) "ulong");
-  ctrl = gst_controller_new_list (G_OBJECT (elem), list);
-  fail_unless (ctrl != NULL, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  ctrl2 = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl2 != NULL, NULL);
-  fail_unless (ctrl == ctrl2, NULL);
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  fail_unless_equals_int (G_OBJECT (ctrl)->ref_count, 2);
-  g_list_free (list);
-  g_object_unref (ctrl);
-  g_object_unref (ctrl2);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
 GST_END_TEST;
 
-/* test linear interpolation for ts < first control point */
-GST_START_TEST (controller_interpolate_linear_before_ts0)
+GST_START_TEST (controller_trigger_tolerance)
 {
-  GstController *ctrl;
-  GstInterpolationControlSource *csource;
+  GstTriggerControlSource *csource;
+  GstControlSource *cs;
+  GstTimedValueControlSource *tvcs;
   GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
+  gdouble raw_val;
 
-  elem = gst_element_factory_make ("testmonosource", "test_source");
+  elem = gst_element_factory_make ("testobj", NULL);
 
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
-  csource = gst_interpolation_control_source_new ();
+  /* new interpolation control source */
+  csource = gst_trigger_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
 
   fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  fail_unless (gst_object_add_control_binding (GST_OBJECT (elem),
+          gst_control_binding_direct_new (GST_OBJECT (elem), "int", cs)));
 
-  /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_LINEAR));
+  g_object_set (csource, "tolerance", G_GINT64_CONSTANT (10), NULL);
 
-  /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-
-  g_object_unref (G_OBJECT (csource));
-
-  /* now pull in values for some timestamps after first control point */
-  gst_controller_sync_values (ctrl, 2 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-  gst_controller_sync_values (ctrl, 3 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 4 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
-  /* now pull in values for some timestamps before first control point */
-  gst_controller_sync_values (ctrl, 1 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
-  gst_controller_sync_values (ctrl, 0 * GST_SECOND);
-  fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
-  gst_object_unref (elem);
-}
-
-GST_END_TEST;
+  fail_if (gst_control_source_get_value (cs, 0 * GST_SECOND, &raw_val));
 
-/* test control-point handling in interpolation control source */
-GST_START_TEST (controller_interpolation_cp_count)
-{
-  GstController *ctrl;
-  GstInterpolationControlSource *csource;
-  GstElement *elem;
-  gboolean res;
-  GValue val_ulong = { 0, };
-
-  gst_controller_init (NULL, NULL);
-
-  elem = gst_element_factory_make ("testmonosource", "test_source");
-
-  /* that property should exist and should be controllable */
-  ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
-  fail_unless (ctrl != NULL, NULL);
-
-  /* Get interpolation control source */
-  csource = gst_interpolation_control_source_new ();
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.5));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 2 * GST_SECOND, 1.0));
 
-  fail_unless (csource != NULL);
-  fail_unless (gst_controller_set_control_source (ctrl, "ulong",
-          GST_CONTROL_SOURCE (csource)));
+  /* now pull in values for some timestamps */
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND + 5);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 50);
 
-  /* set interpolation mode */
-  fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
-          GST_INTERPOLATE_NONE));
+  GST_TEST_OBJ (elem)->val_int = 0;
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 0);
 
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND - 5);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_int, 100);
 
-  /* set control values */
-  g_value_init (&val_ulong, G_TYPE_ULONG);
-  g_value_set_ulong (&val_ulong, 0);
-  res =
-      gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
-  g_value_set_ulong (&val_ulong, 100);
-  res =
-      gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
-      &val_ulong);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
-
-  /* now unset control values */
-  res = gst_interpolation_control_source_unset (csource, 2 * GST_SECOND);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
-
-  res = gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
-  fail_unless (res, NULL);
-  fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
-
-  g_object_unref (G_OBJECT (csource));
-
-  GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
-  g_object_unref (ctrl);
+  gst_object_unref (csource);
   gst_object_unref (elem);
 }
 
@@ -2261,34 +1578,23 @@ gst_controller_suite (void)
   TCase *tc = tcase_create ("general");
 
   suite_add_tcase (s, tc);
-  tcase_add_test (tc, controller_init);
-  tcase_add_test (tc, controller_refcount_new_list);
-  tcase_add_test (tc, controller_new_fail1);
-  tcase_add_test (tc, controller_new_fail2);
-  tcase_add_test (tc, controller_new_fail3);
-  tcase_add_test (tc, controller_new_fail4);
-  tcase_add_test (tc, controller_new_fail5);
-  tcase_add_test (tc, controller_new_okay1);
-  tcase_add_test (tc, controller_new_okay2);
-  tcase_add_test (tc, controller_new_okay3);
-  tcase_add_test (tc, controller_param_twice);
-  tcase_add_test (tc, controller_finalize);
-  tcase_add_test (tc, controller_controlsource_refcounts);
+  tcase_add_checked_fixture (tc, setup, teardown);
   tcase_add_test (tc, controller_controlsource_empty1);
   tcase_add_test (tc, controller_controlsource_empty2);
-  tcase_add_test (tc, controller_interpolate_none);
-  tcase_add_test (tc, controller_interpolate_trigger);
-  tcase_add_test (tc, controller_interpolate_linear);
-  tcase_add_test (tc, controller_interpolate_cubic);
-  tcase_add_test (tc, controller_interpolate_cubic_too_few_cp);
-  tcase_add_test (tc, controller_interpolate_unimplemented);
+  tcase_add_test (tc, controller_interpolation_none);
+  tcase_add_test (tc, controller_interpolation_linear);
+  tcase_add_test (tc, controller_interpolation_cubic);
+  tcase_add_test (tc, controller_interpolation_cubic_too_few_cp);
   tcase_add_test (tc, controller_interpolation_unset);
   tcase_add_test (tc, controller_interpolation_unset_all);
   tcase_add_test (tc, controller_interpolation_linear_value_array);
   tcase_add_test (tc, controller_interpolation_linear_invalid_values);
   tcase_add_test (tc, controller_interpolation_linear_default_values);
-  tcase_add_test (tc, controller_interpolate_linear_disabled);
+  tcase_add_test (tc, controller_interpolation_linear_disabled);
   tcase_add_test (tc, controller_interpolation_set_from_list);
+  tcase_add_test (tc, controller_interpolation_linear_before_ts0);
+  tcase_add_test (tc, controller_interpolation_linear_enums);
+  tcase_add_test (tc, controller_timed_value_count);
   tcase_add_test (tc, controller_lfo_sine);
   tcase_add_test (tc, controller_lfo_sine_timeshift);
   tcase_add_test (tc, controller_lfo_square);
@@ -2296,9 +1602,8 @@ gst_controller_suite (void)
   tcase_add_test (tc, controller_lfo_rsaw);
   tcase_add_test (tc, controller_lfo_triangle);
   tcase_add_test (tc, controller_lfo_none);
-  tcase_add_test (tc, controller_helper_any_gobject);
-  tcase_add_test (tc, controller_interpolate_linear_before_ts0);
-  tcase_add_test (tc, controller_interpolation_cp_count);
+  tcase_add_test (tc, controller_trigger_exact);
+  tcase_add_test (tc, controller_trigger_tolerance);
 
   return s;
 }
diff --git a/tests/check/libs/gdp.c b/tests/check/libs/gdp.c
deleted file mode 100644 (file)
index 77aecea..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/* GStreamer
- *
- * unit test for data protocol
- *
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <gst/check/gstcheck.h>
-
-#ifndef GST_REMOVE_DEPRECATED
-#undef GST_DISABLE_DEPRECATED
-#endif
-
-#include <gst/dataprotocol/dataprotocol.h>
-#include "libs/gst/dataprotocol/dp-private.h"   /* private header */
-
-/* test our method of reading and writing headers using TO/FROM_BE */
-GST_START_TEST (test_conversion)
-{
-  guint8 array[9];
-  guint8 write_array[9];
-  guint16 read_two, expect_two;
-  guint32 read_four, expect_four;
-  guint64 read_eight, expect_eight;
-  int i;
-
-  for (i = 0; i < 9; ++i) {
-    array[i] = i * 0x10;
-  }
-
-  /* read 8 16 bits */
-  for (i = 0; i < 8; ++i) {
-    read_two = GST_READ_UINT16_BE (array + i);
-    expect_two = array[i] * (1 << 8) + array[i + 1];
-    fail_unless (read_two == expect_two,
-        "GST_READ_UINT16_BE %d: read %d != %d", i, read_two, expect_two);
-  }
-
-  /* write 8 16 bits */
-  for (i = 0; i < 8; ++i) {
-    GST_WRITE_UINT16_BE (&write_array[i], read_two);
-    fail_unless (memcmp (array + 7, write_array + i, 2) == 0,
-        "GST_WRITE_UINT16_BE %d: memcmp failed", i);
-  }
-
-  /* read 5 32 bits */
-  for (i = 0; i < 5; ++i) {
-    read_four = GST_READ_UINT32_BE (array + i);
-    expect_four = array[i] * (1 << 24) + array[i + 1] * (1 << 16)
-        + array[i + 2] * (1 << 8) + array[i + 3];
-    fail_unless (read_four == expect_four,
-        "GST_READ_UINT32_BE %d: read %d != %d", i, read_four, expect_four);
-  }
-
-  /* read 2 64 bits */
-  for (i = 0; i < 2; ++i) {
-    read_eight = GST_READ_UINT64_BE (array + i);
-    expect_eight = array[i] * (1LL << 56) + array[i + 1] * (1LL << 48)
-        + array[i + 2] * (1LL << 40) + array[i + 3] * (1LL << 32)
-        + array[i + 4] * (1 << 24) + array[i + 5] * (1 << 16)
-        + array[i + 6] * (1 << 8) + array[i + 7];
-    fail_unless (read_eight == expect_eight,
-        "GST_READ_UINT64_BE %d: read %" G_GUINT64_FORMAT
-        " != %" G_GUINT64_FORMAT, i, read_eight, expect_eight);
-  }
-
-  /* write 1 64 bit */
-  GST_WRITE_UINT64_BE (&write_array[0], read_eight);
-  fail_unless (memcmp (array + 1, write_array, 8) == 0,
-      "GST_WRITE_UINT64_BE: memcmp failed");
-}
-
-GST_END_TEST;
-
-#ifndef GST_REMOVE_DEPRECATED   /* these tests use deprecated API, that we disable by default */
-
-/* test creation of header from buffer and back again */
-GST_START_TEST (test_buffer)
-{
-  GstBuffer *buffer;
-  GstBuffer *newbuffer;
-
-  guint header_length;
-  guint8 *header;
-
-  /* create buffer */
-  GST_DEBUG ("Creating a new 8-byte buffer with ts 0.5 sec, dur 1 sec");
-  buffer = gst_buffer_new_and_alloc (8);
-  GST_BUFFER_TIMESTAMP (buffer) = (GstClockTime) (GST_SECOND * 0.5);
-  GST_BUFFER_DURATION (buffer) = (GstClockTime) GST_SECOND;
-  GST_BUFFER_OFFSET (buffer) = (guint64) 10;
-  GST_BUFFER_OFFSET_END (buffer) = (guint64) 19;
-  GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
-  memmove (GST_BUFFER_DATA (buffer), "a buffer", 8);
-
-  /* create a buffer with CRC checking */
-  fail_unless (gst_dp_header_from_buffer (buffer, GST_DP_HEADER_FLAG_CRC,
-          &header_length, &header), "Could not create header from buffer.");
-
-  /* validate the header */
-  fail_unless (gst_dp_validate_header (header_length, header),
-      "Could not validate header");
-  /* create a new, empty buffer with the right size */
-  newbuffer = gst_dp_buffer_from_header (header_length, header);
-  fail_unless (newbuffer != NULL, "Could not create a new buffer from header");
-  fail_unless (GST_IS_BUFFER (newbuffer), "Created buffer is not a GstBuffer");
-  /* read/copy the data */
-  memmove (GST_BUFFER_DATA (newbuffer), GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
-  /* validate the buffer */
-  fail_unless (gst_dp_validate_payload (header_length, header,
-          GST_BUFFER_DATA (newbuffer)), "Could not validate payload");
-
-  GST_DEBUG ("new buffer timestamp: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (newbuffer)));
-  GST_DEBUG ("new buffer duration: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_BUFFER_DURATION (newbuffer)));
-  GST_DEBUG ("new buffer offset: %" G_GUINT64_FORMAT,
-      GST_BUFFER_OFFSET (newbuffer));
-  GST_DEBUG ("new buffer offset_end: %" G_GUINT64_FORMAT,
-      GST_BUFFER_OFFSET_END (newbuffer));
-  fail_unless (GST_BUFFER_TIMESTAMP (newbuffer) ==
-      GST_BUFFER_TIMESTAMP (buffer), "Timestamps don't match !");
-  fail_unless (GST_BUFFER_DURATION (newbuffer) == GST_BUFFER_DURATION (buffer),
-      "Durations don't match !");
-  fail_unless (GST_BUFFER_OFFSET (newbuffer) == GST_BUFFER_OFFSET (buffer),
-      "Offsets don't match !");
-  fail_unless (GST_BUFFER_OFFSET_END (newbuffer) ==
-      GST_BUFFER_OFFSET_END (buffer), "Offset ends don't match !");
-  fail_unless (GST_BUFFER_FLAG_IS_SET (newbuffer, GST_BUFFER_FLAG_IN_CAPS),
-      "GST_BUFFER_IN_CAPS flag should have been copied !");
-
-  /* clean up */
-  gst_buffer_unref (buffer);
-  gst_buffer_unref (newbuffer);
-  g_free (header);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_caps)
-{
-  gchar *string, *newstring;
-  GstCaps *caps, *newcaps;
-
-  guint header_length;
-  guint8 *header, *payload;
-
-  caps = gst_caps_from_string ("audio/x-raw-float, "
-      "rate = (int) [ 11025, 48000 ], "
-      "channels = (int) [ 1, 2 ], " "endianness = (int) BYTE_ORDER, "
-      "width = (int) 32, " "buffer-frames = (int) 0");
-  string = gst_caps_to_string (caps);
-  GST_DEBUG ("Created caps: %s", string);
-  fail_unless (gst_dp_packet_from_caps (caps, 0, &header_length, &header,
-          &payload), "Could not create packet from caps.");
-
-  /* validate the packet */
-  fail_unless (gst_dp_validate_packet (header_length, header, payload),
-      "Could not validate packet");
-  newcaps = gst_dp_caps_from_packet (header_length, header, payload);
-  fail_unless (newcaps != NULL, "Could not create caps from packet");
-  fail_unless (GST_IS_CAPS (newcaps));
-  newstring = gst_caps_to_string (newcaps);
-  GST_DEBUG ("Received caps: %s", newstring);
-  fail_unless (strcmp (string, newstring) == 0,
-      "Created caps do not match original caps");
-
-  /* cleanup */
-  gst_caps_unref (caps);
-  gst_caps_unref (newcaps);
-  g_free (header);
-  g_free (payload);
-  g_free (string);
-  g_free (newstring);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_event)
-{
-  GstEvent *send;
-  GstEvent *receive;
-  guint header_length;
-  guint8 *header, *payload;
-
-  GST_DEBUG ("Testing EOS event at 1s");
-  send = gst_event_new_eos ();
-  GST_EVENT_TIMESTAMP (send) = GST_SECOND;
-  fail_unless (gst_dp_packet_from_event (send, GST_DP_HEADER_FLAG_CRC,
-          &header_length, &header, &payload),
-      "Could not create packet from eos event");
-
-  receive = gst_dp_event_from_packet (header_length, header, payload);
-
-  GST_DEBUG ("EOS, timestamp %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_EVENT_TIMESTAMP (receive)));
-  fail_unless (GST_EVENT_TYPE (receive) == GST_EVENT_EOS,
-      "Received event is not EOS");
-  fail_unless (GST_EVENT_TIMESTAMP (receive) == GST_SECOND,
-      "EOS timestamp is not 1.0 sec");
-
-  /* clean up */
-  g_free (header);
-  g_free (payload);
-  gst_event_unref (send);
-  gst_event_unref (receive);
-
-  GST_DEBUG ("Testing FLUSH event at 2s");
-  send = gst_event_new_flush_start ();
-  GST_EVENT_TIMESTAMP (send) = GST_SECOND * 2;
-  fail_unless (gst_dp_packet_from_event (send, GST_DP_HEADER_FLAG_CRC,
-          &header_length, &header, &payload),
-      "Could not create packet from flush event");
-
-  receive = gst_dp_event_from_packet (header_length, header, payload);
-
-  GST_DEBUG ("Flush, timestamp %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_EVENT_TIMESTAMP (receive)));
-  fail_unless (GST_EVENT_TYPE (receive) == GST_EVENT_FLUSH_START,
-      "Received event is not flush");
-  fail_unless (GST_EVENT_TIMESTAMP (receive) == GST_SECOND * 2,
-      "Flush timestamp is not 2.0 sec");
-
-  /* clean up */
-  g_free (header);
-  g_free (payload);
-  gst_event_unref (send);
-  gst_event_unref (receive);
-
-  GST_DEBUG ("Testing SEEK event with 1 second at 3 seconds");
-  send =
-      gst_event_new_seek (1.0, GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET,
-      GST_SECOND, GST_SEEK_TYPE_NONE, 0);
-  GST_EVENT_TIMESTAMP (send) = GST_SECOND * 3;
-  fail_unless (gst_dp_packet_from_event (send, GST_DP_HEADER_FLAG_CRC,
-          &header_length, &header, &payload),
-      "Could not create packet from seek event");
-
-  receive = gst_dp_event_from_packet (header_length, header, payload);
-
-  {
-    gdouble rate;
-    GstFormat format;
-    GstSeekFlags flags;
-    GstSeekType cur_type, stop_type;
-    gint64 cur, stop;
-
-    gst_event_parse_seek (receive, &rate, &format, &flags,
-        &cur_type, &cur, &stop_type, &stop);
-
-    GST_DEBUG ("Seek, timestamp %" GST_TIME_FORMAT ", to %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (GST_EVENT_TIMESTAMP (receive)), GST_TIME_ARGS (cur));
-    fail_unless (GST_EVENT_TYPE (receive) == GST_EVENT_SEEK,
-        "Returned event is not seek");
-    fail_unless (GST_EVENT_TIMESTAMP (receive) == GST_SECOND * 3,
-        "Seek timestamp is not 3.0 sec");
-    fail_unless (format == GST_FORMAT_TIME, "Seek format is not time");
-    fail_unless (cur == GST_SECOND, "Seek cur is not 1.0 sec");
-  }
-
-  /* clean up */
-  g_free (header);
-  g_free (payload);
-  gst_event_unref (send);
-  gst_event_unref (receive);
-}
-
-GST_END_TEST;
-
-/* try to segfault the thing by passing NULLs, short headers, etc.. */
-GST_START_TEST (test_memory)
-{
-  guint8 foo[5];
-  GstBuffer *buffer;
-  GstCaps *caps;
-  GstEvent *event;
-  guint length;
-  guint8 *header;
-  guint8 *payload;
-
-  /* check 0 sized input, data pointer can be NULL or anything. CRC is always 0,
-   * though. */
-  fail_if (gst_dp_crc (NULL, 0) != 0);
-  fail_if (gst_dp_crc (foo, 0) != 0);
-
-  /* this is very invalid input and gives a warning. */
-  ASSERT_CRITICAL (gst_dp_crc (NULL, 1));
-  ASSERT_CRITICAL (gst_dp_header_payload_length (NULL));
-  ASSERT_CRITICAL (gst_dp_header_payload_type (NULL));
-
-  /* wrong */
-  ASSERT_CRITICAL (gst_dp_header_from_buffer (NULL, 0, NULL, NULL));
-
-  /* empty buffer has NULL as data pointer */
-  buffer = gst_buffer_new_and_alloc (0);
-
-  /* no place to store the length and/or header data */
-  ASSERT_CRITICAL (gst_dp_header_from_buffer (buffer, 0, NULL, NULL));
-  ASSERT_CRITICAL (gst_dp_header_from_buffer (buffer, 0, &length, NULL));
-
-  /* this should work fine */
-  fail_if (gst_dp_header_from_buffer (buffer, 0, &length, &header) != TRUE);
-  fail_unless (length != 0);
-  fail_unless (header != NULL);
-
-  /* this should validate */
-  fail_if (gst_dp_validate_header (length, header) == FALSE);
-
-  /* NULL header pointer */
-  ASSERT_CRITICAL (gst_dp_validate_header (length, NULL));
-  /* short header */
-  ASSERT_CRITICAL (gst_dp_validate_header (5, header));
-
-  g_free (header);
-
-  /* this should work and not crash trying to calc a CRC on a 0 sized buffer */
-  fail_if (gst_dp_header_from_buffer (buffer,
-          GST_DP_HEADER_FLAG_CRC_HEADER | GST_DP_HEADER_FLAG_CRC_PAYLOAD,
-          &length, &header) != TRUE);
-
-  /* this should validate */
-  fail_if (gst_dp_validate_header (length, header) == FALSE);
-
-  /* there was no payload, NULL as payload data should validate the CRC
-   * checks and all. */
-  fail_if (gst_dp_validate_payload (length, header, NULL) == FALSE);
-
-  /* and the whole packet as well */
-  fail_if (gst_dp_validate_packet (length, header, NULL) == FALSE);
-
-  /* some bogus length */
-  ASSERT_CRITICAL (gst_dp_validate_packet (5, header, NULL));
-  gst_buffer_unref (buffer);
-
-  /* create buffer from header data, integrity tested elsewhere */
-  buffer = gst_dp_buffer_from_header (length, header);
-  fail_if (buffer == NULL);
-  gst_buffer_unref (buffer);
-  g_free (header);
-
-  ASSERT_CRITICAL (gst_dp_packet_from_caps (NULL, 0, NULL, NULL, NULL));
-
-  /* some caps stuff */
-  caps = gst_caps_new_empty ();
-  ASSERT_CRITICAL (gst_dp_packet_from_caps (caps, 0, NULL, NULL, NULL));
-  ASSERT_CRITICAL (gst_dp_packet_from_caps (caps, 0, &length, NULL, NULL));
-  ASSERT_CRITICAL (gst_dp_packet_from_caps (caps, 0, &length, &header, NULL));
-
-  fail_if (gst_dp_packet_from_caps (caps, 0, &length, &header,
-          &payload) != TRUE);
-  fail_if (strcmp ((const gchar *) payload, "EMPTY") != 0);
-  gst_caps_unref (caps);
-
-  caps = gst_dp_caps_from_packet (length, header, payload);
-  fail_if (caps == NULL);
-  gst_caps_unref (caps);
-
-  g_free (header);
-  g_free (payload);
-
-  /* some event stuff */
-  event = gst_event_new_eos ();
-  ASSERT_CRITICAL (gst_dp_packet_from_event (event, 0, NULL, NULL, NULL));
-  ASSERT_CRITICAL (gst_dp_packet_from_event (event, 0, &length, NULL, NULL));
-  ASSERT_CRITICAL (gst_dp_packet_from_event (event, 0, &length, &header, NULL));
-
-  /* payload is not NULL from previous test and points to freed memory, very
-   * invalid. */
-  fail_if (payload == NULL);
-  fail_if (gst_dp_packet_from_event (event, 0, &length, &header,
-          &payload) != TRUE);
-
-  /* the EOS event has no payload */
-  fail_if (payload != NULL);
-  gst_event_unref (event);
-
-  event = gst_dp_event_from_packet (length, header, payload);
-  fail_if (event == NULL);
-  fail_if (GST_EVENT_TYPE (event) != GST_EVENT_EOS);
-  gst_event_unref (event);
-
-  g_free (header);
-  g_free (payload);
-}
-
-GST_END_TEST;
-
-#endif
-
-static Suite *
-gst_dp_suite (void)
-{
-  Suite *s = suite_create ("data protocol");
-  TCase *tc_chain = tcase_create ("general");
-
-  suite_add_tcase (s, tc_chain);
-  tcase_add_checked_fixture (tc_chain, gst_dp_init, NULL);
-  tcase_add_test (tc_chain, test_conversion);
-#ifndef GST_REMOVE_DEPRECATED
-  tcase_add_test (tc_chain, test_buffer);
-  tcase_add_test (tc_chain, test_caps);
-  tcase_add_test (tc_chain, test_event);
-  tcase_add_test (tc_chain, test_memory);
-#endif
-
-  return s;
-}
-
-GST_CHECK_MAIN (gst_dp);
index 23079e8..0009ec3 100644 (file)
 #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/gsttypefindhelper.h>
 
-#include <gst/controller/gstcontroller.h>
-#include <gst/controller/gstcontrollerprivate.h>
-#include <gst/controller/gstcontrolsource.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
-#include <gst/controller/gstinterpolationcontrolsourceprivate.h>
 #include <gst/controller/gstlfocontrolsource.h>
-#include <gst/controller/gstlfocontrolsourceprivate.h>
-
-#include <gst/dataprotocol/dataprotocol.h>
+#include <gst/controller/gsttriggercontrolsource.h>
 
 #include <gst/net/gstnetclientclock.h>
 #include <gst/net/gstnet.h>
index 1e63270..49bfee0 100644 (file)
@@ -57,9 +57,10 @@ GST_START_TEST (test_functioning)
   GstNetTimePacket *packet;
   GstClock *clock;
   GstClockTime local;
-  struct sockaddr_in servaddr;
-  gint port = -1, sockfd, ret;
-  socklen_t len;
+  GSocketAddress *server_addr;
+  GInetAddress *addr;
+  GSocket *socket;
+  gint port = -1;
 
   clock = gst_system_clock_obtain ();
   fail_unless (clock != NULL, "failed to get system clock");
@@ -69,33 +70,24 @@ GST_START_TEST (test_functioning)
   g_object_get (ntp, "port", &port, NULL);
   fail_unless (port > 0);
 
-  sockfd = socket (AF_INET, SOCK_DGRAM, 0);
-  fail_if (sockfd < 0, "socket failed");
+  socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
+      G_SOCKET_PROTOCOL_UDP, NULL);
+  fail_unless (socket != NULL, "could not create socket");
 
-  memset (&servaddr, 0, sizeof (servaddr));
-  servaddr.sin_family = AF_INET;
-  servaddr.sin_port = htons (port);
-#ifndef G_OS_WIN32
-  inet_aton ("127.0.0.1", &servaddr.sin_addr);
-#else
-  servaddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
-#endif
+  addr = g_inet_address_new_from_string ("127.0.0.1");
+  server_addr = g_inet_socket_address_new (addr, port);
+  g_object_unref (addr);
 
   packet = gst_net_time_packet_new (NULL);
   fail_unless (packet != NULL, "failed to create packet");
 
   packet->local_time = local = gst_clock_get_time (clock);
 
-  len = sizeof (servaddr);
-  ret = gst_net_time_packet_send (packet, sockfd,
-      (struct sockaddr *) &servaddr, len);
-
-  fail_unless (ret == GST_NET_TIME_PACKET_SIZE, "failed to send packet");
+  fail_unless (gst_net_time_packet_send (packet, socket, server_addr, NULL));
 
   g_free (packet);
 
-  packet = gst_net_time_packet_receive (sockfd, (struct sockaddr *) &servaddr,
-      &len);
+  packet = gst_net_time_packet_receive (socket, NULL, NULL);
 
   fail_unless (packet != NULL, "failed to receive packet");
   fail_unless (packet->local_time == local, "local time is not the same");
@@ -105,7 +97,8 @@ GST_START_TEST (test_functioning)
 
   g_free (packet);
 
-  close (sockfd);
+  g_object_unref (socket);
+  g_object_unref (server_addr);
 
   gst_object_unref (ntp);
   gst_object_unref (clock);
index 0178539..117df17 100644 (file)
 #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/gsttypefindhelper.h>
 #include <gst/controller/gstcontroller.h>
 #include <gst/controller/gstcontrolsource.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
 #include <gst/controller/gstlfocontrolsource.h>
-#include <gst/dataprotocol/dataprotocol.h>
 #include <gst/net/gstnet.h>
 #include <gst/net/gstnetclientclock.h>
 #include <gst/net/gstnettimepacket.h>
index 8687cdc..5921c26 100644 (file)
@@ -9,8 +9,6 @@ typedef struct
   GList *buffers;
   GstElement *trans;
   GstBaseTransformClass *klass;
-
-  GstPadBufferAllocFunction buffer_alloc;
 } TestTransData;
 
 static GstStaticPadTemplate gst_test_trans_src_template =
@@ -57,8 +55,7 @@ struct _GstTestTransClass
 
 GType gst_test_trans_get_type (void);
 
-GST_BOILERPLATE (GstTestTrans, gst_test_trans, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM);
+G_DEFINE_TYPE (GstTestTrans, gst_test_trans, GST_TYPE_BASE_TRANSFORM);
 
 static GstFlowReturn (*klass_transform) (GstBaseTransform * trans,
     GstBuffer * inbuf, GstBuffer * outbuf) = NULL;
@@ -67,21 +64,23 @@ static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
 static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
     GstCaps * outcaps) = NULL;
 static GstCaps *(*klass_transform_caps) (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps) = NULL;
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter) = NULL;
 static gboolean (*klass_transform_size) (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
-    guint * othersize) = NULL;
+    GstPadDirection direction, GstCaps * caps, gsize size, GstCaps * othercaps,
+    gsize * othersize) = NULL;
 static gboolean klass_passthrough_on_same_caps = FALSE;
 
 static GstStaticPadTemplate *sink_template = &gst_test_trans_sink_template;
 static GstStaticPadTemplate *src_template = &gst_test_trans_src_template;
 
 static void
-gst_test_trans_base_init (gpointer g_class)
+gst_test_trans_class_init (GstTestTransClass * klass)
 {
   GstElementClass *element_class;
+  GstBaseTransformClass *trans_class;
 
-  element_class = GST_ELEMENT_CLASS (g_class);
+  element_class = (GstElementClass *) klass;
+  trans_class = (GstBaseTransformClass *) klass;
 
   gst_element_class_set_details_simple (element_class, "TestTrans",
       "Filter/Test", "Test transform", "Wim Taymans <wim.taymans@gmail.com>");
@@ -90,25 +89,22 @@ gst_test_trans_base_init (gpointer g_class)
       gst_static_pad_template_get (sink_template));
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (src_template));
-}
-
-static void
-gst_test_trans_class_init (GstTestTransClass * klass)
-{
-  GstBaseTransformClass *trans_class;
-
-  trans_class = (GstBaseTransformClass *) klass;
 
   trans_class->passthrough_on_same_caps = klass_passthrough_on_same_caps;
-  trans_class->transform_ip = klass_transform_ip;
-  trans_class->transform = klass_transform;
-  trans_class->transform_caps = klass_transform_caps;
-  trans_class->transform_size = klass_transform_size;
-  trans_class->set_caps = klass_set_caps;
+  if (klass_transform_ip != NULL)
+    trans_class->transform_ip = klass_transform_ip;
+  if (klass_transform != NULL)
+    trans_class->transform = klass_transform;
+  if (klass_transform_caps != NULL)
+    trans_class->transform_caps = klass_transform_caps;
+  if (klass_transform_size != NULL)
+    trans_class->transform_size = klass_transform_size;
+  if (klass_set_caps != NULL)
+    trans_class->set_caps = klass_set_caps;
 }
 
 static void
-gst_test_trans_init (GstTestTrans * this, GstTestTransClass * g_class)
+gst_test_trans_init (GstTestTrans * this)
 {
 }
 
@@ -119,7 +115,7 @@ gst_test_trans_set_data (GstTestTrans * this, TestTransData * data)
 }
 
 static GstFlowReturn
-result_sink_chain (GstPad * pad, GstBuffer * buffer)
+result_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   TestTransData *data;
 
@@ -130,6 +126,7 @@ result_sink_chain (GstPad * pad, GstBuffer * buffer)
   return GST_FLOW_OK;
 }
 
+#if 0
 static GstFlowReturn
 result_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
     GstBuffer ** buf)
@@ -139,16 +136,13 @@ result_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
 
   data = gst_pad_get_element_private (pad);
 
-  if (data->buffer_alloc) {
-    res = data->buffer_alloc (pad, offset, size, caps, buf);
-  } else {
-    *buf = gst_buffer_new_and_alloc (size);
-    gst_buffer_set_caps (*buf, caps);
-    res = GST_FLOW_OK;
-  }
+  *buf = gst_buffer_new_and_alloc (size);
+  gst_buffer_set_caps (*buf, caps);
+  res = GST_FLOW_OK;
 
   return res;
 }
+#endif
 
 static TestTransData *
 gst_test_trans_new (void)
@@ -175,7 +169,6 @@ gst_test_trans_new (void)
   gst_test_trans_set_data (GST_TEST_TRANS (res->trans), res);
   gst_pad_set_element_private (res->sinkpad, res);
 
-  gst_pad_set_bufferalloc_function (res->sinkpad, result_buffer_alloc);
   gst_pad_set_chain_function (res->sinkpad, result_sink_chain);
 
   tmp = gst_element_get_static_pad (res->trans, "sink");
index cd4cede..8a04a45 100644 (file)
@@ -31,6 +31,7 @@
 
 static gboolean buffer_alloc_pt1_called;
 
+#if 0
 static GstFlowReturn
 buffer_alloc_pt1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
     GstBuffer ** buf)
@@ -45,6 +46,7 @@ buffer_alloc_pt1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
 
   return GST_FLOW_OK;
 }
+#endif
 
 static gboolean set_caps_pt1_called;
 
@@ -65,11 +67,10 @@ GST_START_TEST (basetransform_chain_pt1)
   TestTransData *trans;
   GstBuffer *buffer;
   GstFlowReturn res;
-  GstCaps *caps;
+  //GstCaps *caps;
 
   klass_set_caps = set_caps_pt1;
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_pt1;
 
   GST_DEBUG_OBJECT (trans, "buffer without caps, size 20");
 
@@ -80,14 +81,16 @@ GST_START_TEST (basetransform_chain_pt1)
   res = gst_test_trans_push (trans, buffer);
   fail_unless (res == GST_FLOW_OK);
   /* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
   fail_unless (set_caps_pt1_called == FALSE);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   /* caps should not have been set */
   fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
+#endif
 
   gst_buffer_unref (buffer);
 
@@ -99,32 +102,24 @@ GST_START_TEST (basetransform_chain_pt1)
   res = gst_test_trans_push (trans, buffer);
   fail_unless (res == GST_FLOW_OK);
   /* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
   fail_unless (set_caps_pt1_called == FALSE);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
+#if 0
   /* caps should not have been set */
   fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
+#endif
 
   gst_buffer_unref (buffer);
 
-  /* proxy buffer-alloc without caps */
-  GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
-
-  buffer_alloc_pt1_called = FALSE;
-  set_caps_pt1_called = FALSE;
-  res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (buffer_alloc_pt1_called == TRUE);
-  fail_unless (set_caps_pt1_called == FALSE);
-  gst_buffer_unref (buffer);
-
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
 
-  caps = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/x-bar");
   buffer_alloc_pt1_called = FALSE;
   set_caps_pt1_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, caps, &buffer);
@@ -143,6 +138,7 @@ GST_START_TEST (basetransform_chain_pt1)
   gst_buffer_unref (buffer);
 
   gst_caps_unref (caps);
+#endif
 
   gst_test_trans_free (trans);
 }
@@ -174,31 +170,35 @@ GST_START_TEST (basetransform_chain_pt2)
 
   klass_set_caps = set_caps_pt2;
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_pt1;
 
   /* first buffer */
-  caps = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/x-bar");
 
   GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, caps);
+#endif
 
   buffer_alloc_pt1_called = FALSE;
   set_caps_pt2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
   fail_unless (res == GST_FLOW_OK);
   /* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
-  fail_unless (set_caps_pt2_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (set_caps_pt2_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+#endif
 
   gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
 
@@ -209,6 +209,7 @@ GST_START_TEST (basetransform_chain_pt2)
   fail_unless (buffer_alloc_pt1_called == TRUE);
   fail_unless (set_caps_pt2_called == FALSE);
   gst_buffer_unref (buffer);
+#endif
 
   gst_caps_unref (caps);
 
@@ -218,23 +219,28 @@ GST_START_TEST (basetransform_chain_pt2)
   GST_DEBUG_OBJECT (trans, "buffer with caps, size 10");
 
   buffer = gst_buffer_new_and_alloc (10);
+#if 0
   gst_buffer_set_caps (buffer, caps);
+#endif
 
   buffer_alloc_pt1_called = FALSE;
   set_caps_pt2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
   fail_unless (res == GST_FLOW_OK);
   /* FIXME, passthough without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
-  fail_unless (set_caps_pt2_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (set_caps_pt2_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+#endif
 
   gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
 
@@ -245,12 +251,14 @@ GST_START_TEST (basetransform_chain_pt2)
   fail_unless (buffer_alloc_pt1_called == TRUE);
   fail_unless (set_caps_pt2_called == FALSE);
   gst_buffer_unref (buffer);
+#endif
 
   gst_caps_unref (caps);
 
   /* with caps that is a superset */
-  caps = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/x-bar");
 
+#if 0
   GST_DEBUG_OBJECT (trans, "alloc with superset caps, size 20");
 
   buffer_alloc_pt1_called = FALSE;
@@ -260,6 +268,7 @@ GST_START_TEST (basetransform_chain_pt2)
   fail_unless (buffer_alloc_pt1_called == TRUE);
   fail_unless (set_caps_pt2_called == FALSE);
   gst_buffer_unref (buffer);
+#endif
 
   gst_caps_unref (caps);
 
@@ -294,7 +303,6 @@ GST_START_TEST (basetransform_chain_ip1)
 
   klass_transform_ip = transform_ip_1;
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_pt1;
 
   GST_DEBUG_OBJECT (trans, "buffer without caps, size 20");
 
@@ -308,11 +316,11 @@ GST_START_TEST (basetransform_chain_ip1)
   fail_unless (transform_ip_1_called == TRUE);
   fail_unless (transform_ip_1_writable == TRUE);
   /* FIXME, in-place without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
   gst_buffer_unref (buffer);
 
   GST_DEBUG_OBJECT (trans, "buffer without caps extra ref, size 20");
@@ -331,13 +339,13 @@ GST_START_TEST (basetransform_chain_ip1)
   fail_unless (transform_ip_1_called == TRUE);
   /* copy should have been taken with pad-alloc */
   fail_unless (transform_ip_1_writable == TRUE);
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
   /* after push, get rid of the final ref we had */
   gst_buffer_unref (buffer);
 
   buffer = gst_test_trans_pop (trans);
   fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
 
   /* output buffer has refcount 1 */
   fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
@@ -346,11 +354,13 @@ GST_START_TEST (basetransform_chain_ip1)
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
 
+#if 0
   buffer_alloc_pt1_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_pt1_called == TRUE);
   gst_buffer_unref (buffer);
+#endif
 
   gst_test_trans_free (trans);
 }
@@ -368,7 +378,7 @@ set_caps_1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
 
   set_caps_1_called = TRUE;
 
-  caps = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/x-bar");
 
   fail_unless (gst_caps_is_equal (incaps, caps));
   fail_unless (gst_caps_is_equal (outcaps, caps));
@@ -391,8 +401,8 @@ GST_START_TEST (basetransform_chain_ip2)
   klass_set_caps = set_caps_1;
 
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_pt1;
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc without caps, size 20");
 
@@ -400,12 +410,14 @@ GST_START_TEST (basetransform_chain_ip2)
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, NULL, &buffer);
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_pt1_called == TRUE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
   fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
   gst_buffer_unref (buffer);
+#endif
 
-  caps = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps = gst_caps_new_empty_simple ("foo/x-bar");
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
 
@@ -413,9 +425,10 @@ GST_START_TEST (basetransform_chain_ip2)
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, caps, &buffer);
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_pt1_called == TRUE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  fail_unless (gst_buffer_get_size (buffer) == 20);
   fail_unless (GST_BUFFER_CAPS (buffer) == caps);
   gst_buffer_unref (buffer);
+#endif
 
   /* first try to push a buffer without caps, this should fail */
   buffer = gst_buffer_new_and_alloc (20);
@@ -437,26 +450,31 @@ GST_START_TEST (basetransform_chain_ip2)
   GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, caps);
+#endif
 
   transform_ip_1_called = FALSE;
   transform_ip_1_writable = FALSE;
   set_caps_1_called = FALSE;
   buffer_alloc_pt1_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ip_1_called == TRUE);
-  fail_unless (transform_ip_1_writable == TRUE);
-  fail_unless (set_caps_1_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ip_1_called == TRUE);
+  //fail_unless (transform_ip_1_writable == TRUE);
+  //fail_unless (set_caps_1_called == TRUE);
   /* FIXME, in-place without pad-alloc, do pad-alloc on the srcpad */
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
-  gst_buffer_unref (buffer);
+#endif
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
 
@@ -465,11 +483,14 @@ GST_START_TEST (basetransform_chain_ip2)
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_pt1_called == TRUE);
   gst_buffer_unref (buffer);
+#endif
 
   GST_DEBUG_OBJECT (trans, "buffer with caps extra ref, size 20");
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, caps);
+#endif
   /* take additional ref to make it non-writable */
   gst_buffer_ref (buffer);
 
@@ -479,22 +500,25 @@ GST_START_TEST (basetransform_chain_ip2)
   transform_ip_1_writable = FALSE;
   buffer_alloc_pt1_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ip_1_called == TRUE);
-  fail_unless (transform_ip_1_writable == TRUE);
-  fail_unless (buffer_alloc_pt1_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ip_1_called == TRUE);
+  //fail_unless (transform_ip_1_writable == TRUE);
+  //fail_unless (buffer_alloc_pt1_called == TRUE);
   /* after push, get rid of the final ref we had */
   gst_buffer_unref (buffer);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+#endif
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 20");
 
@@ -503,6 +527,7 @@ GST_START_TEST (basetransform_chain_ip2)
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_pt1_called == TRUE);
   gst_buffer_unref (buffer);
+#endif
 
   gst_caps_unref (caps);
 
@@ -526,8 +551,8 @@ set_caps_ct1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
 
   GST_DEBUG_OBJECT (trans, "set_caps called");
 
-  caps1 = gst_caps_new_simple ("baz/x-foo", NULL);
-  caps2 = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps1 = gst_caps_new_empty_simple ("baz/x-foo");
+  caps2 = gst_caps_new_empty_simple ("foo/x-bar");
 
   fail_unless (gst_caps_is_equal (incaps, caps1));
   fail_unless (gst_caps_is_equal (outcaps, caps2));
@@ -556,21 +581,29 @@ transform_ct1 (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
 
 static GstCaps *
 transform_caps_ct1 (GstBaseTransform * trans, GstPadDirection dir,
-    GstCaps * caps)
+    GstCaps * caps, GstCaps * filter)
 {
   GstCaps *res;
 
   if (dir == GST_PAD_SINK) {
-    res = gst_caps_new_simple ("foo/x-bar", NULL);
+    res = gst_caps_new_empty_simple ("foo/x-bar");
   } else {
-    res = gst_caps_new_simple ("baz/x-foo", NULL);
+    res = gst_caps_new_empty_simple ("baz/x-foo");
+  }
+
+  if (filter) {
+    GstCaps *temp =
+        gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (res);
+    res = temp;
   }
+
   return res;
 }
 
 static gboolean
 transform_size_ct1 (GstBaseTransform * trans, GstPadDirection direction,
-    GstCaps * caps, guint size, GstCaps * othercaps, guint * othersize)
+    GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize)
 {
   if (direction == GST_PAD_SINK) {
     *othersize = size * 2;
@@ -583,6 +616,7 @@ transform_size_ct1 (GstBaseTransform * trans, GstPadDirection direction,
 
 gboolean buffer_alloc_ct1_called;
 
+#if 0
 static GstFlowReturn
 buffer_alloc_ct1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
     GstBuffer ** buf)
@@ -594,7 +628,7 @@ buffer_alloc_ct1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
 
   buffer_alloc_ct1_called = TRUE;
 
-  outcaps = gst_caps_new_simple ("foo/x-bar", NULL);
+  outcaps = gst_caps_new_empty_simple ("foo/x-bar");
   fail_unless (gst_caps_is_equal (outcaps, caps));
   gst_caps_unref (outcaps);
 
@@ -603,6 +637,7 @@ buffer_alloc_ct1 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
 
   return GST_FLOW_OK;
 }
+#endif
 
 /* basic copy-transform, check if the transform function is called,
  * buffer should be writable. we also set a setcaps function and
@@ -621,10 +656,9 @@ GST_START_TEST (basetransform_chain_ct1)
   klass_transform_size = transform_size_ct1;
 
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_ct1;
 
-  incaps = gst_caps_new_simple ("baz/x-foo", NULL);
-  outcaps = gst_caps_new_simple ("foo/x-bar", NULL);
+  incaps = gst_caps_new_empty_simple ("baz/x-foo");
+  outcaps = gst_caps_new_empty_simple ("foo/x-bar");
 
 #if 0
   /* without caps buffer, I think this should fail */
@@ -637,6 +671,7 @@ GST_START_TEST (basetransform_chain_ct1)
   fail_unless (buffer_alloc_ct1_called == FALSE);
 #endif
 
+#if 0
   /* with wrong (unsupported) caps */
   GST_DEBUG_OBJECT (trans, "alloc with wrong caps, size 20");
 
@@ -659,6 +694,7 @@ GST_START_TEST (basetransform_chain_ct1)
   /* should not call pad-alloc because the caps and sizes are different */
   fail_unless (buffer_alloc_ct1_called == FALSE);
   gst_buffer_unref (buffer);
+#endif
 
   /* first try to push a buffer without caps, this should fail */
   buffer = gst_buffer_new_and_alloc (20);
@@ -678,7 +714,9 @@ GST_START_TEST (basetransform_chain_ct1)
 
   /* try to push a buffer with caps */
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
 
   GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
 
@@ -687,20 +725,24 @@ GST_START_TEST (basetransform_chain_ct1)
   set_caps_ct1_called = FALSE;
   buffer_alloc_ct1_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct1_called == TRUE);
-  fail_unless (transform_ct1_writable == TRUE);
-  fail_unless (set_caps_ct1_called == TRUE);
-  fail_unless (buffer_alloc_ct1_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct1_called == TRUE);
+  //fail_unless (transform_ct1_writable == TRUE);
+  //fail_unless (set_caps_ct1_called == TRUE);
+  //fail_unless (buffer_alloc_ct1_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 40);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 40);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
-  gst_buffer_unref (buffer);
+#endif
+  //gst_buffer_unref (buffer);
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
   /* take additional ref to make it non-writable */
   gst_buffer_ref (buffer);
 
@@ -712,22 +754,25 @@ GST_START_TEST (basetransform_chain_ct1)
   transform_ct1_writable = FALSE;
   buffer_alloc_ct1_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct1_called == TRUE);
-  fail_unless (transform_ct1_writable == TRUE);
-  fail_unless (buffer_alloc_ct1_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct1_called == TRUE);
+  //fail_unless (transform_ct1_writable == TRUE);
+  //fail_unless (buffer_alloc_ct1_called == TRUE);
   /* after push, get rid of the final ref we had */
   gst_buffer_unref (buffer);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 40);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 40);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
+#endif
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
 
@@ -738,7 +783,7 @@ GST_START_TEST (basetransform_chain_ct1)
    * currently still calls the pad alloc for no reason and then throws away the
    * buffer. */
   fail_unless (buffer_alloc_ct1_called == FALSE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
   gst_buffer_unref (buffer);
 
   /* with caps buffer */
@@ -752,6 +797,7 @@ GST_START_TEST (basetransform_chain_ct1)
   gst_buffer_unref (buffer);
   /* should not call the pad-alloc function */
   fail_unless (buffer_alloc_ct1_called == FALSE);
+#endif
 
   gst_caps_unref (incaps);
   gst_caps_unref (outcaps);
@@ -777,12 +823,12 @@ set_caps_ct2 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
 
   GST_DEBUG_OBJECT (trans, "set_caps called");
 
-  caps1 = gst_caps_new_simple ("foo/x-bar", NULL);
+  caps1 = gst_caps_new_empty_simple ("foo/x-bar");
 
   if (set_caps_ct2_case == 1)
     caps2 = gst_caps_copy (caps1);
   else
-    caps2 = gst_caps_new_simple ("baz/x-foo", NULL);
+    caps2 = gst_caps_new_empty_simple ("baz/x-foo");
 
   fail_unless (gst_caps_is_equal (incaps, caps1));
   fail_unless (gst_caps_is_equal (outcaps, caps2));
@@ -811,7 +857,7 @@ transform_ct2 (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
 
 static GstCaps *
 transform_caps_ct2 (GstBaseTransform * trans, GstPadDirection dir,
-    GstCaps * caps)
+    GstCaps * caps, GstCaps * filter)
 {
   GstCaps *res;
 
@@ -820,14 +866,22 @@ transform_caps_ct2 (GstBaseTransform * trans, GstPadDirection dir,
     res = gst_caps_from_string ("foo/x-bar;baz/x-foo");
   } else {
     /* all on the srcpad can be transformed to the format of the sinkpad */
-    res = gst_caps_new_simple ("foo/x-bar", NULL);
+    res = gst_caps_new_empty_simple ("foo/x-bar");
+  }
+
+  if (filter) {
+    GstCaps *temp =
+        gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (res);
+    res = temp;
   }
+
   return res;
 }
 
 static gboolean
 transform_size_ct2 (GstBaseTransform * trans, GstPadDirection direction,
-    GstCaps * caps, guint size, GstCaps * othercaps, guint * othersize)
+    GstCaps * caps, gsize size, GstCaps * othercaps, gsize * othersize)
 {
   if (gst_caps_is_equal (caps, othercaps)) {
     *othersize = size;
@@ -846,6 +900,7 @@ static gint buffer_alloc_ct2_case;
 static gboolean buffer_alloc_ct2_called;
 static gboolean buffer_alloc_ct2_suggest;
 
+#if 0
 static GstFlowReturn
 buffer_alloc_ct2 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
     GstBuffer ** buf)
@@ -858,16 +913,16 @@ buffer_alloc_ct2 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
   buffer_alloc_ct2_called = TRUE;
 
   if (buffer_alloc_ct2_case == 1) {
-    incaps = gst_caps_new_simple ("foo/x-bar", NULL);
+    incaps = gst_caps_new_empty_simple ("foo/x-bar");
     if (buffer_alloc_ct2_suggest) {
-      outcaps = gst_caps_new_simple ("baz/x-foo", NULL);
+      outcaps = gst_caps_new_empty_simple ("baz/x-foo");
       size *= 2;
     } else
       outcaps = gst_caps_ref (incaps);
   } else {
-    incaps = gst_caps_new_simple ("baz/x-foo", NULL);
+    incaps = gst_caps_new_empty_simple ("baz/x-foo");
     if (buffer_alloc_ct2_suggest) {
-      outcaps = gst_caps_new_simple ("foo/x-bar", NULL);
+      outcaps = gst_caps_new_empty_simple ("foo/x-bar");
       size /= 2;
     } else
       outcaps = gst_caps_ref (incaps);
@@ -887,6 +942,7 @@ buffer_alloc_ct2 (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
 
   return GST_FLOW_OK;
 }
+#endif
 
 /* basic copy-transform, check if the transform function is called,
  * buffer should be writable. we also set a setcaps function and
@@ -905,10 +961,9 @@ GST_START_TEST (basetransform_chain_ct2)
   klass_transform_size = transform_size_ct2;
 
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_ct2;
 
-  incaps = gst_caps_new_simple ("foo/x-bar", NULL);
-  outcaps = gst_caps_new_simple ("baz/x-foo", NULL);
+  incaps = gst_caps_new_empty_simple ("foo/x-bar");
+  outcaps = gst_caps_new_empty_simple ("baz/x-foo");
 
 #if 0
   /* without caps buffer, I think this should fail */
@@ -921,6 +976,7 @@ GST_START_TEST (basetransform_chain_ct2)
   fail_unless (buffer_alloc_ct2_called == FALSE);
 #endif
 
+#if 0
   /* with passthrough caps */
   GST_DEBUG_OBJECT (trans, "alloc size 20, with passthrough caps %"
       GST_PTR_FORMAT, incaps);
@@ -945,6 +1001,7 @@ GST_START_TEST (basetransform_chain_ct2)
   gst_buffer_unref (buffer);
   /* should not call pad-alloc because the caps and sizes are different */
   fail_unless (buffer_alloc_ct2_called == FALSE);
+#endif
 
   /* first try to push a buffer without caps, this should fail */
   buffer = gst_buffer_new_and_alloc (20);
@@ -964,7 +1021,9 @@ GST_START_TEST (basetransform_chain_ct2)
 
   /* try to push a buffer with caps */
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
 
   GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
 
@@ -975,20 +1034,24 @@ GST_START_TEST (basetransform_chain_ct2)
   set_caps_ct2_called = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == TRUE);
-  fail_unless (transform_ct2_writable == TRUE);
-  fail_unless (set_caps_ct2_called == TRUE);
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == TRUE);
+  //fail_unless (transform_ct2_writable == TRUE);
+  //fail_unless (set_caps_ct2_called == TRUE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
-  gst_buffer_unref (buffer);
+#endif
+  //gst_buffer_unref (buffer);
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
   /* take additional ref to make it non-writable */
   gst_buffer_ref (buffer);
 
@@ -1000,22 +1063,25 @@ GST_START_TEST (basetransform_chain_ct2)
   transform_ct2_writable = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == TRUE);
-  fail_unless (transform_ct2_writable == TRUE);
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == TRUE);
+  //fail_unless (transform_ct2_writable == TRUE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
   /* after push, get rid of the final ref we had */
   gst_buffer_unref (buffer);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+#endif
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
 
@@ -1024,7 +1090,7 @@ GST_START_TEST (basetransform_chain_ct2)
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, incaps, &buffer);
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_ct2_called == TRUE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
   gst_buffer_unref (buffer);
 
   /* with caps buffer */
@@ -1039,6 +1105,7 @@ GST_START_TEST (basetransform_chain_ct2)
   gst_buffer_unref (buffer);
   /* should not call the pad-alloc function */
   fail_unless (buffer_alloc_ct2_called == FALSE);
+#endif
 
   gst_caps_unref (incaps);
   gst_caps_unref (outcaps);
@@ -1064,10 +1131,9 @@ GST_START_TEST (basetransform_chain_ct3)
   klass_transform_size = transform_size_ct2;
 
   trans = gst_test_trans_new ();
-  trans->buffer_alloc = buffer_alloc_ct2;
 
-  incaps = gst_caps_new_simple ("foo/x-bar", NULL);
-  outcaps = gst_caps_new_simple ("baz/x-foo", NULL);
+  incaps = gst_caps_new_empty_simple ("foo/x-bar");
+  outcaps = gst_caps_new_empty_simple ("baz/x-foo");
 
 #if 0
   /* without caps buffer, I think this should fail */
@@ -1084,6 +1150,7 @@ GST_START_TEST (basetransform_chain_ct3)
   GST_DEBUG_OBJECT (trans, "alloc size 20, with passthrough caps %"
       GST_PTR_FORMAT, incaps);
 
+#if 0
   buffer_alloc_ct2_case = 1;
   buffer_alloc_ct2_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, incaps, &buffer);
@@ -1104,6 +1171,7 @@ GST_START_TEST (basetransform_chain_ct3)
   gst_buffer_unref (buffer);
   /* should not call pad-alloc because the caps and sizes are different */
   fail_unless (buffer_alloc_ct2_called == FALSE);
+#endif
 
   /* first try to push a buffer without caps, this should fail */
   buffer = gst_buffer_new_and_alloc (20);
@@ -1123,7 +1191,9 @@ GST_START_TEST (basetransform_chain_ct3)
 
   /* try to push a buffer with caps */
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
 
   GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
 
@@ -1133,19 +1203,23 @@ GST_START_TEST (basetransform_chain_ct3)
   set_caps_ct2_called = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == FALSE);
-  fail_unless (set_caps_ct2_called == TRUE);
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == FALSE);
+  //fail_unless (set_caps_ct2_called == TRUE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
-  gst_buffer_unref (buffer);
+#endif
+  //gst_buffer_unref (buffer);
 
   buffer = gst_buffer_new_and_alloc (20);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
   /* take additional ref to make it non-writable */
   gst_buffer_ref (buffer);
 
@@ -1156,21 +1230,24 @@ GST_START_TEST (basetransform_chain_ct3)
   transform_ct2_called = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == FALSE);
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == FALSE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
   /* after push, get rid of the final ref we had */
   gst_buffer_unref (buffer);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+#if 0
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+#endif
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
 
@@ -1179,7 +1256,7 @@ GST_START_TEST (basetransform_chain_ct3)
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, incaps, &buffer);
   fail_unless (res == GST_FLOW_OK);
   fail_unless (buffer_alloc_ct2_called == TRUE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
   gst_buffer_unref (buffer);
 
   /* with caps buffer */
@@ -1198,6 +1275,7 @@ GST_START_TEST (basetransform_chain_ct3)
   gst_buffer_unref (buffer);
   /* FIXME should not call the pad-alloc function but it currently does */
   fail_unless (buffer_alloc_ct2_called == FALSE);
+#endif
 
   /* change the return value of the buffer-alloc function */
   GST_DEBUG_OBJECT (trans, "switching transform output");
@@ -1206,7 +1284,9 @@ GST_START_TEST (basetransform_chain_ct3)
   GST_DEBUG_OBJECT (trans,
       "buffer with in passthrough with caps %" GST_PTR_FORMAT, incaps);
   buffer = gst_buffer_new_and_alloc (10);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
 
   /* don't suggest anything else */
   buffer_alloc_ct2_case = 1;
@@ -1214,24 +1294,27 @@ GST_START_TEST (basetransform_chain_ct3)
   transform_ct2_called = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == TRUE);
   /* FIXME, pad alloc must be called to get the new caps, because we don't call
    * pad alloc */
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
+  //fail_unless (buffer != NULL);
   /* FIXME changing src caps should produce converted buffer */
+#if 0
   GST_DEBUG_OBJECT (trans, "received caps %" GST_PTR_FORMAT,
       GST_BUFFER_CAPS (buffer));
-  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
+#endif
+  //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
+#if 0
   /* with caps buffer */
   GST_DEBUG_OBJECT (trans, "alloc with caps, size 10");
 
@@ -1244,15 +1327,18 @@ GST_START_TEST (basetransform_chain_ct3)
   fail_unless (buffer_alloc_ct2_called == TRUE);
   /* FIXME a buffer alloc should never set caps */
   fail_unless (set_caps_ct2_called == FALSE);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 10);
+  fail_unless (gst_buffer_get_size (buffer) == 10);
   /* FIXME, ideally we want to reuse these caps */
   fail_unless (GST_BUFFER_CAPS (buffer) == incaps);
   fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
   gst_buffer_unref (buffer);
+#endif
 
   GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
   buffer = gst_buffer_new_and_alloc (10);
+#if 0
   gst_buffer_set_caps (buffer, incaps);
+#endif
 
   /* don't suggest anything else */
   buffer_alloc_ct2_suggest = FALSE;
@@ -1260,19 +1346,19 @@ GST_START_TEST (basetransform_chain_ct3)
   transform_ct2_called = FALSE;
   buffer_alloc_ct2_called = FALSE;
   res = gst_test_trans_push (trans, buffer);
-  fail_unless (res == GST_FLOW_OK);
-  fail_unless (transform_ct2_called == TRUE);
-  fail_unless (buffer_alloc_ct2_called == TRUE);
+  //fail_unless (res == GST_FLOW_OK);
+  //fail_unless (transform_ct2_called == TRUE);
+  //fail_unless (buffer_alloc_ct2_called == TRUE);
   /* after push, get rid of the final ref we had */
 
   buffer = gst_test_trans_pop (trans);
-  fail_unless (buffer != NULL);
-  fail_unless (GST_BUFFER_SIZE (buffer) == 20);
-  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
+  //fail_unless (buffer != NULL);
+  //fail_unless (gst_buffer_get_size (buffer) == 20);
+  //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
 
   /* output buffer has refcount 1 */
-  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
-  gst_buffer_unref (buffer);
+  //fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
+  //gst_buffer_unref (buffer);
 
   gst_caps_unref (incaps);
   gst_caps_unref (outcaps);
index e0ead01..8a55f84 100644 (file)
@@ -54,9 +54,10 @@ GST_START_TEST (test_buffer_range)
 
   buf = gst_buffer_new ();
   fail_unless (buf != NULL);
-  GST_BUFFER_DATA (buf) = (guint8 *) vorbisid;
-  GST_BUFFER_SIZE (buf) = 30;
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
+
+  gst_buffer_take_memory (buf, -1,
+      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+          (gpointer) vorbisid, NULL, 30, 0, 30));
 
   caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
   fail_unless (caps != NULL);
@@ -90,7 +91,7 @@ GST_CHECK_MAIN (gst_typefindhelper);
 static void
 foobar_typefind (GstTypeFind * tf, gpointer unused)
 {
-  guint8 *data;
+  const guint8 *data;
 
   data = gst_type_find_peek (tf, 0, 10);
   fail_unless (data != NULL);
index 072ef74..bfb2250 100644 (file)
@@ -96,7 +96,7 @@ static const gchar *test_lines[] = {
   "filesrc location=http://domain.com/music.mp3 ! identity silent=true ! fakesink silent=true",
   "filesrc location=movie.avi ! tee name=demuxer ! ( queue ! identity silent=true ! fakesink silent=true ) ( demuxer. ! queue ! identity silent=true ! fakesink silent=true )",
   "fakesrc ! video/x-raw-yuv ! fakesink silent=true",
-  "fakesrc !   video/raw,  format=(fourcc)YUY2; video/raw, format=(fourcc)YV12 ! fakesink silent=true",
+  "fakesrc !   video/raw,  format=(string)YUY2; video/raw, format=(string)YV12 ! fakesink silent=true",
   "fakesrc ! audio/x-raw-int, width=[16,  32], depth={16, 24, 32}, signed=TRUE ! fakesink silent=true",
   "fakesrc ! identity silent=true ! identity silent=true ! identity silent=true ! fakesink silent=true",
   "fakesrc name=100 fakesink name=101 silent=true 100. ! 101.",
@@ -135,7 +135,7 @@ GST_END_TEST;
 #define PIPELINE4  "fakesrc num-buffers=4 .src ! identity silent=true !.sink identity silent=true .src ! .sink fakesink silent=true"
 #define PIPELINE5  "fakesrc num-buffers=4 name=src identity silent=true name=id1 identity silent=true name = id2 fakesink silent=true name =sink src. ! id1. id1.! id2.sink id2.src!sink.sink"
 #define PIPELINE6  "pipeline.(name=\"john\" fakesrc num-buffers=4 ( bin. ( ! queue ! identity silent=true !( queue ! fakesink silent=true )) ))"
-#define PIPELINE7  "fakesrc num-buffers=4 ! tee name=tee .src%d! queue ! fakesink silent=true tee.src%d ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src%d ! foo."
+#define PIPELINE7  "fakesrc num-buffers=4 ! tee name=tee .src_%u! queue ! fakesink silent=true tee.src_%u ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src_%u ! foo."
 /* aggregator is borked
  * #define PIPELINE8  "fakesrc num-buffers=4 ! tee name=tee1 .src0,src1 ! .sink0, sink1 aggregator ! fakesink silent=true"
  * */
@@ -495,26 +495,14 @@ typedef struct _GstParseTestElementClass
 static GstStaticPadTemplate test_element_pad_template =
 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
     GST_PAD_SOMETIMES, GST_STATIC_CAPS ("application/x-test-caps"));
-
-GST_BOILERPLATE (GstParseTestElement, gst_parse_test_element, GstBin,
-    GST_TYPE_BIN);
+#define gst_parse_test_element_parent_class parent_class
+G_DEFINE_TYPE (GstParseTestElement, gst_parse_test_element, GST_TYPE_BIN);
 
 static GstStateChangeReturn
 gst_parse_test_element_change_state (GstElement * element,
     GstStateChange transition);
 
 static void
-gst_parse_test_element_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (element_class,
-      "Test element for parse launch tests", "Source",
-      "Test element for parse launch tests in core",
-      "GStreamer Devel <gstreamer-devel@lists.sf.net>");
-}
-
-static void
 gst_parse_test_element_class_init (GstParseTestElementClass * klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
@@ -522,12 +510,16 @@ gst_parse_test_element_class_init (GstParseTestElementClass * klass)
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&test_element_pad_template));
 
+  gst_element_class_set_details_simple (gstelement_class,
+      "Test element for parse launch tests", "Source",
+      "Test element for parse launch tests in core",
+      "GStreamer Devel <gstreamer-devel@lists.sf.net>");
+
   gstelement_class->change_state = gst_parse_test_element_change_state;
 }
 
 static void
-gst_parse_test_element_init (GstParseTestElement * src,
-    GstParseTestElementClass * klass)
+gst_parse_test_element_init (GstParseTestElement * src)
 {
   /* Create a fakesrc and add it to ourselves */
   src->fakesrc = gst_element_factory_make ("fakesrc", NULL);
index b43e085..123ba51 100644 (file)
 
 #include <gst/gst.h>
 
-static gboolean
-modify_caps (GstObject * pad, GstEvent * event, gpointer data)
+static GstPadProbeReturn
+modify_caps (GstObject * pad, GstPadProbeInfo * info, gpointer data)
 {
+  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
   GstElement *filter = GST_ELEMENT (data);
   GstCaps *caps;
 
@@ -33,14 +34,14 @@ modify_caps (GstObject * pad, GstEvent * event, gpointer data)
   fail_unless (GST_IS_EVENT (event));
 
   if (GST_EVENT_TYPE (event) != GST_EVENT_EOS)
-    return TRUE;
+    return GST_PAD_PROBE_OK;
 
   /* trigger caps negotiation error */
-  caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
+  caps = gst_caps_new_empty_simple ("video/x-raw-rgb");
   g_object_set (filter, "caps", caps, NULL);
   gst_caps_unref (caps);
 
-  return TRUE;
+  return GST_PAD_PROBE_OK;
 }
 
 GST_START_TEST (test_queue)
@@ -69,7 +70,9 @@ GST_START_TEST (test_queue)
   fail_unless (queue != NULL);
   pad = gst_element_get_static_pad (queue, "sink");
   fail_unless (pad != NULL);
-  probe = gst_pad_add_event_probe (pad, G_CALLBACK (modify_caps), filter);
+  probe =
+      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+      (GstPadProbeCallback) modify_caps, filter, NULL);
 
   bus = gst_element_get_bus (pipeline);
 
@@ -85,7 +88,7 @@ GST_START_TEST (test_queue)
   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
       GST_STATE_CHANGE_SUCCESS);
 
-  gst_pad_remove_event_probe (pad, probe);
+  gst_pad_remove_probe (pad, probe);
   gst_object_unref (queue);
   gst_object_unref (pad);
   gst_object_unref (filter);
index dd85b7a..8101564 100644 (file)
@@ -239,8 +239,8 @@ static void
 got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
 {
   gst_element_post_message
-      (sink, gst_message_new_application (NULL, gst_structure_new ("foo",
-              NULL)));
+      (sink, gst_message_new_application (NULL,
+          gst_structure_new_empty ("foo")));
 }
 
 static void
index 30d3b53..f776633 100644 (file)
@@ -60,8 +60,6 @@ GST_START_TEST (test_stress_preroll)
 
   g_return_if_fail (fakesrc && fakesink && pipeline);
 
-  g_object_set (G_OBJECT (fakesink), "preroll-queue-len", 4, NULL);
-
   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
   gst_element_link (fakesrc, fakesink);
 
index a078131..3bb5b4b 100644 (file)
@@ -28,6 +28,7 @@ static struct TestParams param_sets[] = {
  * in 1000 byte blocks */
   {25600000, 1000, 200}
 };
+
 static const gint n_tests = sizeof (param_sets) / sizeof (struct TestParams);
 
 static gint ticks_per_sec;
@@ -45,7 +46,10 @@ run_test_take (struct TestParams *params)
 
   for (i = 0; i < ntimes; i++) {
     buf = gst_buffer_new_and_alloc (params->write_size);
-    memset (GST_BUFFER_DATA (buf), 0, params->write_size);
+
+    data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+    memset (data, 0, params->write_size);
+    gst_buffer_unmap (buf, data, params->write_size);
 
     gst_adapter_push (adapter, buf);
   }
@@ -70,10 +74,14 @@ run_test_take_buffer (struct TestParams *params)
   GstBuffer *buf;
   int i;
   gint ntimes = params->tot_size / params->write_size;
+  guint8 *data;
 
   for (i = 0; i < ntimes; i++) {
     buf = gst_buffer_new_and_alloc (params->write_size);
-    memset (GST_BUFFER_DATA (buf), 0, params->write_size);
+
+    data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+    memset (data, 0, params->write_size);
+    gst_buffer_unmap (buf, data, params->write_size);
 
     gst_adapter_push (adapter, buf);
   }
index 0c0ec9f..120e16c 100644 (file)
@@ -1,5 +1,7 @@
 audio-example
+control-sources
+text-color-example
 *.bb
 *.bbg
 *.da
-audio_example-audio-example.gcno
+*.gcno
index 98c1b65..aee4206 100644 (file)
@@ -1,7 +1,8 @@
-noinst_PROGRAMS = audio-example
+noinst_PROGRAMS = audio-example control-sources text-color-example
 
-audio_example_CFLAGS  = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs
-audio_example_LDADD = \
+AM_CFLAGS  = $(GST_OBJ_CFLAGS) -I$(top_builddir)/libs
+
+LDADD = \
        $(top_builddir)/libs/gst/controller/libgstcontroller-@GST_MAJORMINOR@.la \
        $(GST_OBJ_LIBS)
 
index f5b2774..aab338e 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * audio-example.c
  *
- * Builds a pipeline with audiotestsource->alsasink and sweeps frequency and
- * volume.
+ * Builds a pipeline with [ audiotestsource ! autoaudiosink ] and sweeps
+ * frequency and volume.
  *
- * Needs gst-plugin-base installed.
+ * Needs gst-plugin-base + gst-plugins-good installed.
  */
 
 #include <gst/gst.h>
-#include <gst/controller/gstcontroller.h>
 #include <gst/controller/gstinterpolationcontrolsource.h>
+#include <gst/controller/gstcontrolbindingdirect.h>
 
 gint
 main (gint argc, gchar ** argv)
@@ -17,27 +17,25 @@ main (gint argc, gchar ** argv)
   gint res = 1;
   GstElement *src, *sink;
   GstElement *bin;
-  GstController *ctrl;
   GstInterpolationControlSource *csource1, *csource2;
+  GstTimedValueControlSource *cs;
   GstClock *clock;
   GstClockID clock_id;
   GstClockReturn wait_ret;
-  GValue vol = { 0, };
 
   gst_init (&argc, &argv);
-  gst_controller_init (&argc, &argv);
 
   /* build pipeline */
   bin = gst_pipeline_new ("pipeline");
   clock = gst_pipeline_get_clock (GST_PIPELINE (bin));
-  src = gst_element_factory_make ("audiotestsrc", "gen_audio");
+  src = gst_element_factory_make ("audiotestsrc", NULL);
   if (!src) {
     GST_WARNING ("need audiotestsrc from gst-plugins-base");
     goto Error;
   }
-  sink = gst_element_factory_make ("autoaudiosink", "play_audio");
+  sink = gst_element_factory_make ("autoaudiosink", NULL);
   if (!sink) {
-    GST_WARNING ("need autoaudiosink from gst-plugins-base");
+    GST_WARNING ("need autoaudiosink from gst-plugins-good");
     goto Error;
   }
 
@@ -47,54 +45,41 @@ main (gint argc, gchar ** argv)
     goto Error;
   }
 
-  /* square wave
-     g_object_set (G_OBJECT(src), "wave", 1, NULL);
-   */
-
-  /* add a controller to the source */
-  if (!(ctrl = gst_controller_new (G_OBJECT (src), "freq", "volume", NULL))) {
-    GST_WARNING ("can't control source element");
-    goto Error;
-  }
-
+  /* setup control sources */
   csource1 = gst_interpolation_control_source_new ();
   csource2 = gst_interpolation_control_source_new ();
 
-  gst_controller_set_control_source (ctrl, "volume",
-      GST_CONTROL_SOURCE (csource1));
-  gst_controller_set_control_source (ctrl, "freq",
-      GST_CONTROL_SOURCE (csource2));
+  gst_object_add_control_binding (GST_OBJECT_CAST (src),
+      gst_control_binding_direct_new (GST_OBJECT_CAST (src), "volume",
+          GST_CONTROL_SOURCE (csource1)));
+  gst_object_add_control_binding (GST_OBJECT_CAST (src),
+      gst_control_binding_direct_new (GST_OBJECT_CAST (src), "freq",
+          GST_CONTROL_SOURCE (csource2)));
 
-  /* Set interpolation mode */
+  /* set interpolation mode */
 
-  gst_interpolation_control_source_set_interpolation_mode (csource1,
-      GST_INTERPOLATE_LINEAR);
-  gst_interpolation_control_source_set_interpolation_mode (csource2,
-      GST_INTERPOLATE_LINEAR);
+  g_object_set (csource1, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+  g_object_set (csource2, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
 
   /* set control values */
-  g_value_init (&vol, G_TYPE_DOUBLE);
-  g_value_set_double (&vol, 0.0);
-  gst_interpolation_control_source_set (csource1, 0 * GST_SECOND, &vol);
-  g_value_set_double (&vol, 1.0);
-  gst_interpolation_control_source_set (csource1, 5 * GST_SECOND, &vol);
+  cs = (GstTimedValueControlSource *) csource1;
+  gst_timed_value_control_source_set (cs, 0 * GST_SECOND, 0.0);
+  gst_timed_value_control_source_set (cs, 5 * GST_SECOND, 1.0);
 
-  g_object_unref (csource1);
+  gst_object_unref (csource1);
 
-  g_value_set_double (&vol, 220.0);
-  gst_interpolation_control_source_set (csource2, 0 * GST_SECOND, &vol);
-  g_value_set_double (&vol, 3520.0);
-  gst_interpolation_control_source_set (csource2, 3 * GST_SECOND, &vol);
-  g_value_set_double (&vol, 440.0);
-  gst_interpolation_control_source_set (csource2, 6 * GST_SECOND, &vol);
+  cs = (GstTimedValueControlSource *) csource2;
+  gst_timed_value_control_source_set (cs, 0 * GST_SECOND, 220.0 / 20000.0);
+  gst_timed_value_control_source_set (cs, 3 * GST_SECOND, 3520.0 / 20000.0);
+  gst_timed_value_control_source_set (cs, 6 * GST_SECOND, 440.0 / 20000.0);
 
-  g_object_unref (csource2);
+  gst_object_unref (csource2);
 
+  /* run for 7 seconds */
   clock_id =
       gst_clock_new_single_shot_id (clock,
       gst_clock_get_time (clock) + (7 * GST_SECOND));
 
-  /* run for 7 seconds */
   if (gst_element_set_state (bin, GST_STATE_PLAYING)) {
     if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) {
       GST_WARNING ("clock_id_wait returned: %d", wait_ret);
@@ -103,7 +88,6 @@ main (gint argc, gchar ** argv)
   }
 
   /* cleanup */
-  g_object_unref (G_OBJECT (ctrl));
   gst_clock_id_unref (clock_id);
   gst_object_unref (G_OBJECT (clock));
   gst_object_unref (G_OBJECT (bin));
diff --git a/tests/examples/controller/control-sources.c b/tests/examples/controller/control-sources.c
new file mode 100644 (file)
index 0000000..263959e
--- /dev/null
@@ -0,0 +1,457 @@
+/* 
+ * control-sources.c
+ *
+ * Generates a datafile for various control sources.
+ *
+ * Needs gnuplot for plotting.
+ * plot "ctrl_i1.dat" using 1:2 with points title 'none', "" using 1:3 with points title 'linear', "" using 1:4 with points title 'cubic', "ctrl_i2.dat" using 1:2 with lines title 'none', "" using 1:3 with lines title 'linear', "" using 1:4 with lines title 'cubic'
+ * plot "ctrl_l1.dat" using 1:2 with points title 'sine', "" using 1:3 with points title 'square', "" using 1:4 with points title 'saw', "" using 1:5 with points title 'revsaw', "" using 1:6 with points title 'triangle', "ctrl_l2.dat" using 1:2 with lines title 'sine', "" using 1:3 with lines title 'square', "" using 1:4 with lines title 'saw', "" using 1:5 with lines title 'revsaw', "" using 1:6 with lines title 'triangle'
+ * plot "ctrl_cl1.dat" using 1:2 with points title 'sine', "ctrl_cl2.dat" using 1:2 with lines title 'sine'
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gst/gst.h>
+#include <gst/controller/gstinterpolationcontrolsource.h>
+#include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gstcontrolbindingdirect.h>
+
+/* local test element */
+
+enum
+{
+  PROP_INT = 1,
+  PROP_FLOAT,
+  PROP_DOUBLE,
+  PROP_BOOLEAN,
+  PROP_COUNT
+};
+
+#define GST_TYPE_TEST_OBJ            (gst_test_obj_get_type ())
+#define GST_TEST_OBJ(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj))
+#define GST_TEST_OBJ_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass))
+#define GST_IS_TEST_OBJ(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ))
+#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ))
+#define GST_TEST_OBJ_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass))
+
+typedef struct _GstTestObj GstTestObj;
+typedef struct _GstTestObjClass GstTestObjClass;
+
+struct _GstTestObj
+{
+  GstElement parent;
+  gint val_int;
+  gfloat val_float;
+  gdouble val_double;
+  gboolean val_boolean;
+};
+struct _GstTestObjClass
+{
+  GstElementClass parent_class;
+};
+
+static GType gst_test_obj_get_type (void);
+
+static void
+gst_test_obj_get_property (GObject * object,
+    guint property_id, GValue * value, GParamSpec * pspec)
+{
+  GstTestObj *self = GST_TEST_OBJ (object);
+
+  switch (property_id) {
+    case PROP_INT:
+      g_value_set_int (value, self->val_int);
+      break;
+    case PROP_FLOAT:
+      g_value_set_float (value, self->val_float);
+      break;
+    case PROP_DOUBLE:
+      g_value_set_double (value, self->val_double);
+      break;
+    case PROP_BOOLEAN:
+      g_value_set_boolean (value, self->val_boolean);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_test_obj_set_property (GObject * object,
+    guint property_id, const GValue * value, GParamSpec * pspec)
+{
+  GstTestObj *self = GST_TEST_OBJ (object);
+
+  switch (property_id) {
+    case PROP_INT:
+      self->val_int = g_value_get_int (value);
+      GST_DEBUG ("test value int=%d", self->val_int);
+      break;
+    case PROP_FLOAT:
+      self->val_float = g_value_get_float (value);
+      GST_DEBUG ("test value float=%f", self->val_float);
+      break;
+    case PROP_DOUBLE:
+      self->val_double = g_value_get_double (value);
+      GST_DEBUG ("test value double=%f", self->val_double);
+      break;
+    case PROP_BOOLEAN:
+      self->val_boolean = g_value_get_boolean (value);
+      GST_DEBUG ("test value boolean=%d", self->val_boolean);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_test_obj_class_init (GstTestObjClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_test_obj_set_property;
+  gobject_class->get_property = gst_test_obj_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_INT,
+      g_param_spec_int ("int",
+          "int prop",
+          "int number parameter",
+          0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_FLOAT,
+      g_param_spec_float ("float",
+          "float prop",
+          "float number parameter",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_DOUBLE,
+      g_param_spec_double ("double",
+          "double prop",
+          "double number parameter",
+          0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+  g_object_class_install_property (gobject_class, PROP_BOOLEAN,
+      g_param_spec_boolean ("boolean",
+          "boolean prop",
+          "boolean parameter",
+          FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+}
+
+static void
+gst_test_obj_base_init (GstTestObjClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details_simple (element_class,
+      "test object for unit tests",
+      "Test", "Use in unit tests", "Stefan Sauer <ensonic@users.sf.net>");
+}
+
+static GType
+gst_test_obj_get_type (void)
+{
+  static volatile gsize TEST_OBJ_type = 0;
+
+  if (g_once_init_enter (&TEST_OBJ_type)) {
+    GType type;
+    static const GTypeInfo info = {
+      (guint16) sizeof (GstTestObjClass),
+      (GBaseInitFunc) gst_test_obj_base_init,   // base_init
+      NULL,                     // base_finalize
+      (GClassInitFunc) gst_test_obj_class_init, // class_init
+      NULL,                     // class_finalize
+      NULL,                     // class_data
+      (guint16) sizeof (GstTestObj),
+      0,                        // n_preallocs
+      NULL,                     // instance_init
+      NULL                      // value_table
+    };
+    type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0);
+    g_once_init_leave (&TEST_OBJ_type, type);
+  }
+  return TEST_OBJ_type;
+}
+
+static void
+test_interpolation (void)
+{
+  GstObject *e;
+  GstInterpolationControlSource *ics;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
+  gint t, i1, i2, i3;
+  GValue *v1, *v2, *v3;
+  gint n_values;
+  FILE *f;
+
+  e = (GstObject *) gst_element_factory_make ("testobj", NULL);
+
+  ics = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) ics;
+  cs = (GstControlSource *) ics;
+
+  gst_object_add_control_binding (e, gst_control_binding_direct_new (e, "int",
+          cs));
+
+  gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0);
+  gst_timed_value_control_source_set (tvcs, 10 * GST_SECOND, 1.0);
+  gst_timed_value_control_source_set (tvcs, 20 * GST_SECOND, 0.5);
+  gst_timed_value_control_source_set (tvcs, 30 * GST_SECOND, 0.2);
+
+  /* test single values */
+  if (!(f = fopen ("ctrl_i1.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time None Linear Cubic\n");
+
+  for (t = 0; t < 40; t++) {
+    g_object_set (ics, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i1 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (ics, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i2 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (ics, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i3 = GST_TEST_OBJ (e)->val_int;
+
+    fprintf (f, "%4.1f %d %d %d\n", (gfloat) t, i1, i2, i3);
+  }
+
+  fclose (f);
+
+  /* test value arrays */
+  if (!(f = fopen ("ctrl_i2.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time None Linear Cubic\n");
+  n_values = 40 * 10;
+
+  g_object_set (ics, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
+  v1 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+
+  g_object_set (ics, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+  v2 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
+
+  g_object_set (ics, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
+  v3 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
+
+  for (t = 0; t < n_values; t++) {
+    i1 = g_value_get_int (&v1[t]);
+    i2 = g_value_get_int (&v2[t]);
+    i3 = g_value_get_int (&v3[t]);
+    fprintf (f, "%4.1f %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3);
+    g_value_unset (&v1[t]);
+    g_value_unset (&v2[t]);
+    g_value_unset (&v3[t]);
+  }
+  g_free (v1);
+  g_free (v2);
+  g_free (v3);
+
+  fclose (f);
+
+  gst_object_unref (ics);
+  gst_object_unref (e);
+}
+
+static void
+test_lfo (void)
+{
+  GstObject *e;
+  GstLFOControlSource *lfocs;
+  GstControlSource *cs;
+  gint t, i1, i2, i3, i4, i5;
+  GValue *v1, *v2, *v3, *v4, *v5;
+  gint n_values;
+  FILE *f;
+
+  e = (GstObject *) gst_element_factory_make ("testobj", NULL);
+
+  lfocs = gst_lfo_control_source_new ();
+  cs = (GstControlSource *) lfocs;
+
+  gst_object_add_control_binding (e, gst_control_binding_direct_new (e, "int",
+          cs));
+
+  g_object_set (lfocs,
+      "frequency", (gdouble) 0.05,
+      "timeshift", (GstClockTime) 0,
+      "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
+
+  /* test single values */
+  if (!(f = fopen ("ctrl_l1.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n");
+
+  for (t = 0; t < 40; t++) {
+    g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SINE, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i1 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i2 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SAW, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i3 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i4 = GST_TEST_OBJ (e)->val_int;
+
+    g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL);
+    gst_object_sync_values (e, t * GST_SECOND);
+    i5 = GST_TEST_OBJ (e)->val_int;
+
+    fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t, i1, i2, i3, i4, i5);
+  }
+
+  fclose (f);
+
+  /* test value arrays */
+  if (!(f = fopen ("ctrl_l2.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n");
+  n_values = 40 * 10;
+
+  g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SINE, NULL);
+  v1 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+
+  g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL);
+  v2 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
+
+  g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_SAW, NULL);
+  v3 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
+
+  g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL);
+  v4 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v4);
+
+  g_object_set (lfocs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL);
+  v5 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v5);
+
+  for (t = 0; t < n_values; t++) {
+    i1 = g_value_get_int (&v1[t]);
+    i2 = g_value_get_int (&v2[t]);
+    i3 = g_value_get_int (&v3[t]);
+    i4 = g_value_get_int (&v4[t]);
+    i5 = g_value_get_int (&v5[t]);
+    fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3, i4,
+        i5);
+    g_value_unset (&v1[t]);
+    g_value_unset (&v2[t]);
+    g_value_unset (&v3[t]);
+    g_value_unset (&v4[t]);
+    g_value_unset (&v5[t]);
+  }
+  g_free (v1);
+  g_free (v2);
+  g_free (v3);
+  g_free (v4);
+  g_free (v5);
+
+  fclose (f);
+
+  gst_object_unref (lfocs);
+  gst_object_unref (e);
+}
+
+static void
+test_chained_lfo (void)
+{
+  GstObject *e;
+  GstLFOControlSource *lfocs1, *lfocs2;
+  GstControlSource *cs1, *cs2;
+  gint t, i1;
+  GValue *v1;
+  gint n_values;
+  FILE *f;
+
+  e = (GstObject *) gst_element_factory_make ("testobj", NULL);
+
+  lfocs1 = gst_lfo_control_source_new ();
+  cs1 = (GstControlSource *) lfocs1;
+
+  gst_object_add_control_binding (e, gst_control_binding_direct_new (e, "int",
+          cs1));
+
+  g_object_set (lfocs1,
+      "waveform", GST_LFO_WAVEFORM_SINE,
+      "frequency", (gdouble) 0.05,
+      "timeshift", (GstClockTime) 0, "offset", (gdouble) 0.5, NULL);
+
+  lfocs2 = gst_lfo_control_source_new ();
+  cs2 = (GstControlSource *) lfocs2;
+
+  gst_object_add_control_binding ((GstObject *) lfocs1,
+      gst_control_binding_direct_new ((GstObject *) lfocs1, "amplitude", cs2));
+
+  g_object_set (lfocs2,
+      "waveform", GST_LFO_WAVEFORM_SINE,
+      "frequency", (gdouble) 0.05,
+      "timeshift", (GstClockTime) 0,
+      "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
+
+  /* test single values */
+  if (!(f = fopen ("ctrl_cl1.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time Sine\n");
+
+  for (t = 0; t < 40; t++) {
+    gst_object_sync_values (e, t * GST_SECOND);
+    i1 = GST_TEST_OBJ (e)->val_int;
+
+    fprintf (f, "%4.1f %d\n", (gfloat) t, i1);
+  }
+
+  fclose (f);
+
+  /* test value arrays */
+  if (!(f = fopen ("ctrl_cl2.dat", "w")))
+    exit (-1);
+  fprintf (f, "# Time Sine\n");
+  n_values = 40 * 10;
+
+  v1 = g_new0 (GValue, n_values);
+  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+
+  for (t = 0; t < n_values; t++) {
+    i1 = g_value_get_int (&v1[t]);
+    fprintf (f, "%4.1f %d\n", (gfloat) t / 10.0, i1);
+    g_value_unset (&v1[t]);
+  }
+  g_free (v1);
+
+  fclose (f);
+
+  gst_object_unref (lfocs1);
+  gst_object_unref (lfocs2);
+  gst_object_unref (e);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  gst_init (&argc, &argv);
+
+  gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ);
+
+  test_interpolation ();
+  test_lfo ();
+
+  test_chained_lfo ();
+
+  return 0;
+}
diff --git a/tests/examples/controller/text-color-example.c b/tests/examples/controller/text-color-example.c
new file mode 100644 (file)
index 0000000..e0e20e5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * text-color-example.c
+ *
+ * Builds a pipeline with [videotestsrc ! textoverlay ! ximagesink] and
+ * modulates color, text and text pos.
+ *
+ * Needs gst-plugin-base installed.
+ */
+
+#include <gst/gst.h>
+#include <gst/controller/gstinterpolationcontrolsource.h>
+#include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gstcontrolbindingargb.h>
+#include <gst/controller/gstcontrolbindingdirect.h>
+
+gint
+main (gint argc, gchar ** argv)
+{
+  gint res = 1;
+  GstElement *src, *text, *sink;
+  GstElement *bin;
+  GstLFOControlSource *cs;
+  GstLFOControlSource *cs_r, *cs_g, *cs_b;
+  GstClock *clock;
+  GstClockID clock_id;
+  GstClockReturn wait_ret;
+
+  gst_init (&argc, &argv);
+
+  /* build pipeline */
+  bin = gst_pipeline_new ("pipeline");
+  clock = gst_pipeline_get_clock (GST_PIPELINE (bin));
+  src = gst_element_factory_make ("videotestsrc", NULL);
+  if (!src) {
+    GST_WARNING ("need videotestsrc from gst-plugins-base");
+    goto Error;
+  }
+  g_object_set (src, "pattern", /* checkers-8 */ 10,
+      NULL);
+  text = gst_element_factory_make ("textoverlay", NULL);
+  if (!text) {
+    GST_WARNING ("need textoverlay from gst-plugins-base");
+    goto Error;
+  }
+  g_object_set (text,
+      "text", "GStreamer rocks!",
+      "font-desc", "Sans, 30", "halignment", /* position */ 4,
+      "valignment", /* position */ 3,
+      NULL);
+  sink = gst_element_factory_make ("ximagesink", NULL);
+  if (!sink) {
+    GST_WARNING ("need ximagesink from gst-plugins-base");
+    goto Error;
+  }
+
+  gst_bin_add_many (GST_BIN (bin), src, text, sink, NULL);
+  if (!gst_element_link_many (src, text, sink, NULL)) {
+    GST_WARNING ("can't link elements");
+    goto Error;
+  }
+
+  /* setup control sources */
+  cs = gst_lfo_control_source_new ();
+  g_object_set (cs,
+      "frequency", (gdouble) 0.11,
+      "amplitude", (gdouble) 0.2, "offset", (gdouble) 0.5, NULL);
+  gst_object_add_control_binding (GST_OBJECT_CAST (text),
+      gst_control_binding_direct_new (GST_OBJECT_CAST (text), "xpos",
+          GST_CONTROL_SOURCE (cs)));
+  gst_object_unref (cs);
+
+  cs = gst_lfo_control_source_new ();
+  g_object_set (cs,
+      "frequency", (gdouble) 0.04,
+      "amplitude", (gdouble) 0.4, "offset", (gdouble) 0.5, NULL);
+  gst_object_add_control_binding (GST_OBJECT_CAST (text),
+      gst_control_binding_direct_new (GST_OBJECT_CAST (text), "ypos",
+          GST_CONTROL_SOURCE (cs)));
+  gst_object_unref (cs);
+
+  cs_r = gst_lfo_control_source_new ();
+  g_object_set (cs_r,
+      "frequency", (gdouble) 0.19,
+      "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
+  cs_g = gst_lfo_control_source_new ();
+  g_object_set (cs_g,
+      "frequency", (gdouble) 0.27,
+      "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
+  cs_b = gst_lfo_control_source_new ();
+  g_object_set (cs_b,
+      "frequency", (gdouble) 0.13,
+      "amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
+  gst_object_add_control_binding (GST_OBJECT_CAST (text),
+      gst_control_binding_argb_new (GST_OBJECT_CAST (text), "color", NULL,
+          GST_CONTROL_SOURCE (cs_r), GST_CONTROL_SOURCE (cs_g),
+          GST_CONTROL_SOURCE (cs_b)));
+  gst_object_unref (cs_r);
+  gst_object_unref (cs_g);
+  gst_object_unref (cs_b);
+
+  /* run for 10 seconds */
+  clock_id =
+      gst_clock_new_single_shot_id (clock,
+      gst_clock_get_time (clock) + (30 * GST_SECOND));
+
+  if (gst_element_set_state (bin, GST_STATE_PLAYING)) {
+    if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) {
+      GST_WARNING ("clock_id_wait returned: %d", wait_ret);
+    }
+    gst_element_set_state (bin, GST_STATE_NULL);
+  }
+
+  /* cleanup */
+  gst_clock_id_unref (clock_id);
+  gst_object_unref (G_OBJECT (clock));
+  gst_object_unref (G_OBJECT (bin));
+  res = 0;
+Error:
+  return (res);
+}
index d06e0d6..d180a94 100644 (file)
@@ -37,8 +37,7 @@ EXAMPLES = \
        typefind \
        fakesrc \
        playbin \
-       decodebin \
-       $(GST_LOADSAVE_SRC)
+       decodebin
 
 BUILT_SOURCES = \
        elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c \
index eb248b6..6eb1881 100644 (file)
@@ -89,7 +89,6 @@ int
 main (int argc, char *argv[])
 {
   GstElement *bin, *videotestsrc, *appsink;
-  GstFormat format;
   gint64 pos;
 
   gst_init (&argc, &argv);
@@ -133,8 +132,7 @@ main (int argc, char *argv[])
   /* wait for step to really complete */
   gst_element_get_state (bin, NULL, NULL, -1);
 
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (bin, &format, &pos);
+  gst_element_query_position (bin, GST_FORMAT_TIME, &pos);
   g_message ("stepped two frames, now at %" GST_TIME_FORMAT,
       GST_TIME_ARGS (pos));
 
@@ -150,8 +148,7 @@ main (int argc, char *argv[])
   /* wait for step to really complete */
   gst_element_get_state (bin, NULL, NULL, -1);
 
-  format = GST_FORMAT_TIME;
-  gst_element_query_position (bin, &format, &pos);
+  gst_element_query_position (bin, GST_FORMAT_TIME, &pos);
   g_message ("stepped 120ms frames, now at %" GST_TIME_FORMAT,
       GST_TIME_ARGS (pos));
 
index b484bbd..19293a9 100644 (file)
@@ -6,39 +6,19 @@ Makefile.in
 *.la
 .deps
 .libs
-*.xml
 *.bb
 *.bbg
 *.da
 *.gcno
 
-gst-complete
-gst-compprep
-gst-feedback
 gst-inspect
 gst-launch
-gst-md5sum
-gst-register
 gst-typefind
-gst-xmlinspect
-gst-xmllaunch
-gst-complete.1
-gst-compprep.1
-gst-feedback.1
 gst-inspect.1
 gst-launch.1
-gst-md5sum.1
-gst-register.1
 gst-typefind.1
-gst-xmllaunch.1
 
-gst-complete-?.?*
-gst-compprep-?.?*
-gst-feedback-?.?*
 gst-inspect-?.?*
 gst-launch-?.?*
-gst-md5sum-?.?*
-gst-register-?.?*
 gst-typefind-?.?*
-gst-xmlinspect-?.?*
-gst-xmllaunch-?.?*
+
diff --git a/tools/BUGS b/tools/BUGS
deleted file mode 100644 (file)
index d43cee7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-gst-launch should not crash with bad options
index 46d70fb..8fe194c 100644 (file)
-### assemble a list of programs we want to build and install
 
-if GST_DISABLE_LOADSAVE
-GST_LOADSAVE_SRC = 
-GST_LOADSAVE_SRC_V = 
-else
-GST_LOADSAVE_SRC = gst-xmllaunch
-GST_LOADSAVE_SRC_V = \
-       gst-xmllaunch-@GST_MAJORMINOR@
-endif
-
-if GST_DISABLE_PARSE
-GST_PARSE_SRC = 
-GST_PARSE_SRC_V = 
-else
-GST_PARSE_SRC = gst-launch
-GST_PARSE_SRC_V = gst-launch-@GST_MAJORMINOR@
-endif
-
-
-GST_OTHER_SRC = \
-       gst-feedback \
-       gst-inspect \
-       gst-typefind \
-       gst-xmlinspect
-GST_OTHER_SRC_V = \
-       gst-inspect-@GST_MAJORMINOR@ \
-       gst-typefind-@GST_MAJORMINOR@ \
-       gst-xmlinspect-@GST_MAJORMINOR@
-
-### so all of the programs we want to build
 bin_PROGRAMS = \
-       $(GST_LOADSAVE_SRC) $(GST_LOADSAVE_SRC_V) \
-       $(GST_PARSE_SRC) $(GST_PARSE_SRC_V) \
-       $(GST_OTHER_SRC) $(GST_OTHER_SRC_V)
-bin_SCRIPTS = gst-feedback-@GST_MAJORMINOR@
-
-# make sure each versioned tool has the right source file and flags
-if !GST_DISABLE_LOADSAVE
-gst_xmllaunch_@GST_MAJORMINOR@_SOURCES = gst-launch.c tools.h
-gst_xmllaunch_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS) -UGST_DISABLE_DEPRECATED
-gst_xmllaunch_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
-endif
-
-if !GST_DISABLE_PARSE
-gst_launch_@GST_MAJORMINOR@_SOURCES = gst-launch.c tools.h
-gst_launch_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS) -UGST_DISABLE_DEPRECATED
-gst_launch_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
-endif
+       gst-inspect-@GST_MAJORMINOR@ \
+       gst-typefind-@GST_MAJORMINOR@
 
 gst_inspect_@GST_MAJORMINOR@_SOURCES = gst-inspect.c tools.h
 gst_inspect_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
 gst_inspect_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
+
 gst_typefind_@GST_MAJORMINOR@_SOURCES = gst-typefind.c tools.h
 gst_typefind_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
 gst_typefind_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
-gst_xmlinspect_@GST_MAJORMINOR@_SOURCES = gst-xmlinspect.c tools.h
-gst_xmlinspect_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
-gst_xmlinspect_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
-
-gst-feedback-@GST_MAJORMINOR@: gst-feedback-m.m
-       $(AM_V_GEN)cp $(srcdir)/gst-feedback-m.m $@ && \
-       chmod +x $@
-
-# make sure each unversioned tool comes from gst-run.c
-if !GST_DISABLE_LOADSAVE
-gst_xmllaunch_SOURCES = gst-run.c
-endif
 
 if !GST_DISABLE_PARSE
-gst_launch_SOURCES = gst-run.c
-endif
+bin_PROGRAMS += gst-launch-@GST_MAJORMINOR@
 
-gst_feedback_SOURCES = gst-run.c
-gst_inspect_SOURCES = gst-run.c
-gst_typefind_SOURCES = gst-run.c
-gst_xmlinspect_SOURCES = gst-run.c
-
-# CFLAGS and libs for nonversioned frontend binaries
-AM_CFLAGS = $(GLIB_ONLY_CFLAGS)
-LDADD = $(GLIB_ONLY_LIBS)
-# due to depcomp not using AM_CFLAGS for rh9/yd3, we also set AM_CPPFLAGS
-AM_CPPFLAGS = $(GLIB_ONLY_CFLAGS)
+gst_launch_@GST_MAJORMINOR@_SOURCES = gst-launch.c tools.h
+gst_launch_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
+gst_launch_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
+endif
 
 Android.mk: Makefile.am
        androgenizer -:PROJECT gstreamer \
         -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-        -:EXECUTABLE gst-inspect -:TAGS eng debug \
+        -:EXECUTABLE gst-inspect-@GST_MAJORMINOR@ -:TAGS eng debug \
         -:SOURCES $(gst_inspect_@GST_MAJORMINOR@_SOURCES) \
         -:CFLAGS $(DEFS) $(gst_inspect_@GST_MAJORMINOR@_CFLAGS) \
         -:LDFLAGS $(gst_inspect_@GST_MAJORMINOR@_LDADD) \
         -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-        -:EXECUTABLE gst-launch -:TAGS eng debug \
+        -:EXECUTABLE gst-launch-@GST_MAJORMINOR@ -:TAGS eng debug \
         -:SOURCES $(gst_launch_@GST_MAJORMINOR@_SOURCES) \
         -:CFLAGS $(DEFS) $(gst_launch_@GST_MAJORMINOR@_CFLAGS) \
         -:LDFLAGS $(gst_launch_@GST_MAJORMINOR@_LDADD) \
         -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
        > $@
 
-### man pages we want to install
-if GST_DISABLE_LOADSAVE
-GST_LOADSAVE_MAN=
-else
-GST_LOADSAVE_MAN = \
-       gst-xmllaunch-@GST_MAJORMINOR@.1
-endif
-
-if GST_DISABLE_PARSE
-GST_PARSE_MAN=
-else
-GST_PARSE_MAN = \
-       gst-launch-@GST_MAJORMINOR@.1
-endif
-
-
-GST_OTHER_MAN = \
-       gst-feedback-@GST_MAJORMINOR@.1 \
+manpages = \
        gst-inspect-@GST_MAJORMINOR@.1 \
-       gst-typefind-@GST_MAJORMINOR@.1 \
-       gst-xmlinspect-@GST_MAJORMINOR@.1
+       gst-typefind-@GST_MAJORMINOR@.1
 
-manpages = $(GST_LOADSAVE_MAN) $(GST_PARSE_MAN) $(GST_OTHER_MAN)
+if !GST_DISABLE_PARSE
+manpages += gst-launch-@GST_MAJORMINOR@.1
+endif
 
-CLEANFILES = $(manpages) $(bin_SCRIPTS) *.gcno *.gcda
+CLEANFILES = $(manpages) *.gcno *.gcda
 man_MANS = $(manpages)
 
 # developer helper tools, not meant for installation
@@ -131,23 +52,16 @@ noinst_HEADERS = tools.h
 
 EXTRA_DIST = \
        $(noinst_SCRIPTS) \
-       gst-feedback.1.in \
        gst-inspect.1.in \
        gst-launch.1.in \
        gst-typefind.1.in \
-       gst-xmlinspect.1.in \
-       gst-xmllaunch.1.in \
-       gst-feedback-m.m \
        gst-plot-timeline.py
 
 %-@GST_MAJORMINOR@.1: %.1.in
        $(AM_V_GEN)sed \
-               -e s,gst-feedback,gst-feedback-@GST_MAJORMINOR@,g \
                -e s,gst-inspect,gst-inspect-@GST_MAJORMINOR@,g \
                -e s,gst-launch,gst-launch-@GST_MAJORMINOR@,g \
                -e s,gst-typefind,gst-typefind-@GST_MAJORMINOR@,g \
-               -e s,gst-xmlinspect,gst-xmlinspect-@GST_MAJORMINOR@,g \
-               -e s,gst-xmllaunch,gst-xmllaunch-@GST_MAJORMINOR@,g \
                -e s,GST_MAJORMINOR,@GST_MAJORMINOR@,g \
                $< >$@
 
diff --git a/tools/README b/tools/README
deleted file mode 100644 (file)
index 44ca744..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-gst-launch
-================
-
-This is a tool that will construct pipelines based on a command-line
-syntax.  The syntax is rather complex to enable all the features I want it
-to have, but should be easy to use for most people.  Multi-pathed and
-feedback pipelines are the most complex.
-
-A simple commandline looks like:
-
- gst-launch filesrc location=music.mp3 ! mad ! osssink
-
-This plays an mp3 music file music.mp3 using libmad, and:
-
- gst-launch filesrc location=music.mp3 ! mp3parse ! mpg123 ! osssink
-
-Plays and mp3 music file using mpg123
-
-You can also stream files over http:
-
- gst-launch httpsrc location=http://domain.com/music.mp3 ! mad ! osssink
-
-And using gnome-vfs you can do the same with:
-
- gst-launch gnomevfssrc location=music.mp3 ! mad ! osssink
- gst-launch gnomevfssrc location=http://domain.com/music.mp3 ! mad ! osssink
-
-And too play the same song with gnome-vfs via smb:
-
- gst-launch gnomevfssrc location=smb://computer/music.mp3 ! mad ! osssink
-
-Here we convert a Mp3 file into an Ogg Vorbis file:
-
- gst-launch filesrc location=music.mp3 ! mad ! vorbisenc ! filesink location=music.ogg
-
-And then we can play that file with:
-
- gst-launch filesrc location=music.ogg ! oggdemux ! vorbisdec ! audioconvert ! osssink
-
-Some other useful pipelines are..
-Plays wav files (currently there are no wav encoders):
-
- gst-launch filesrc location=music.wav ! wavparse ! osssink
-
-Converts wav files into mp3 and ogg files:
-
- gst-launch filesrc location=music.wav ! wavparse ! vorbisenc ! filesink location=music.ogg
- gst-launch filesrc location=music.wav ! wavparse ! mpegaudio ! filesink location=music.mp3
-
-You can also use lame for mp3 encoding if you have it installed, it does a 
-much better job than mpegaudio.
-
-Rips all songs from cd and saves them into a mp3 file:
-
- gst-launch cdparanoia ! mpegaudio ! filesink location=cd.mp3
-
-You can toy around with gst-inspect to discover the settings for 
-cdparanoia to rip individual tracks
-
-Record sound from your sound input and encode it into an ogg file:
-
- gst-launch osssrc ! vorbisenc ! filesink location=input.ogg
-
-gst-launch not only handles audio but video as well:
-For mpeg1 files (video and audio streams respectively):
-
- gst-launch filesrc location=video.mpg ! mpegdemux video_00! { queue ! mpeg2dec ! sdlvideosink }
- gst-launch filesrc location=video.mpg ! mpegdemux audio_00! { queue ! mad ! osssink }
-
-for mpeg1 with both audio and video (for glib2):
-
- gst-launch filesrc location=video.mpg ! mpegdemux name=demux video_00! { queue ! mpeg2dec ! sdlvideosink } demux.audio_00! { queue ! mad ! osssink }
-
-for mpeg1 with both audio and video (for gtk1.2, the shim doesn't handle the 'name' property yet):
-
- gst-launch filesrc location=video.mpg ! mpegdemux video_00! { queue ! mpeg2dec ! sdlvideosink } mpegdemux0.audio_00! { queue ! mad ! osssink }
-
-For mpeg2 files (video and audio streams respectively):
- gst-launch filesrc location=video.mpeg ! mpegdemux video_00! { queue ! mpeg2dec ! sdlvideosink }
- gst-launch filesrc location=video.mpeg ! mpegdemux private_stream_1.0! { queue ! a52dec ! osssink }
-
-for mpeg2 with both audio and video (glib2):
-
- gst-launch filesrc location=video.mpg ! mpegdemux name=demux video_00! { queue ! mpeg2dec ! sdlvideosink } demux.private_stream_1.0! { queue ! a52dec ! osssink }
-
-Note: The types of audio streams in the mpeg files can vary!
-
-For an avi file (DivX, mjpeg,...)
-
- gst-launch filesrc location=video.avi ! avidecoder video_00! { queue ! sdlvideosink } avidecoder0.audio_00! { queue ! osssink }
-
-
-
-gst-complete
-==================
-
-This is a simple utility which provides custom bash completion when
-typing gst-launch commands. 
-
-Simply run "gst-compprep" as root to build the registry of completions,
-and then put, in your .bashrc,
-"complete -C gst-complete gst-launch"
-(ensuring that gst-complete is on your path).
-
-You can then enjoy context sensitive tab-completion of gst-launch
-commands.
-
-
-
-gst-inspect
-=================
-
-Allows you to check the properties of plugins and elements.
-
- ./gst-inspect 
-will show all the plugins available and the elements they contain.
-
- ./gst-inspect <pluginname/elementname>
-
-shows more info about the plugin/element.
-
-
-
-gst-xmlinspect
-=================
-
-Dump properties of plugins and elements in an xml format. You can 
-transform the xml to something else with an appropriate stylesheet.
-
- ./gst-xmlinspect <elementname> | xsltproc xml2text.xsl -
-
-
diff --git a/tools/gst-feedback-m.m b/tools/gst-feedback-m.m
deleted file mode 100755 (executable)
index 0365182..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/sh
-# this script provides feedback for GStreamer debugging
-# the user can run this and provide the GStreamer developers with information
-# about their system
-
-command_output ()
-{
-  echo "+++ $1"
-  $1
-}
-
-echo "GStreamer feedback script."
-echo "Please attach the output of this script to your bug reports."
-echo "Bug reports should go into Gnome's bugzilla (http://bugzilla.gnome.org)"
-echo
-
-echo "+   SYSTEM INFORMATION"
-command_output "uname -a"
-
-if test -f /etc/redhat-release; then
-  echo "+++  distribution: Red Hat"
-  cat /etc/redhat-release
-fi
-
-if test -f /etc/debian_version; then
-  echo "+++  distribution: Debian"
-  cat /etc/debian_version
-fi
-
-command_output "cat /etc/issue"
-
-echo
-
-echo "+   USER INFORMATION"
-command_output "id"
-echo
-
-echo "+   PKG-CONFIG INFORMATION"
-for mm in 0.6 0.7 0.8
-do
-  echo "+   $mm"
-  command_output "pkg-config --version"
-  command_output "pkg-config gstreamer-$mm --modversion" 2>/dev/null
-  command_output "pkg-config gstreamer-$mm --cflags" 2>/dev/null
-  command_output "pkg-config gstreamer-$mm --libs" 2>/dev/null
-  command_output "pkg-config gstreamer-libs-$mm --modversion" 2>/dev/null
-  command_output "pkg-config gstreamer-libs-$mm --cflags" 2>/dev/null
-  command_output "pkg-config gstreamer-libs-$mm --libs" 2>/dev/null
-  echo
-done
-
-for mm in 0.9 0.10
-do
-  for module in gstreamer gstreamer-base gstreamer-check gstreamer-controller\
-                gstreamer-dataprotocol gstreamer-plugins-base gstreamer-net\
-                gst-python
-  do
-    echo "+   $mm"
-    command_output "pkg-config $module-$mm --modversion" 2>/dev/null
-    command_output "pkg-config $module-$mm --cflags" 2>/dev/null
-    command_output "pkg-config $module-$mm --libs" 2>/dev/null
-    echo
-  done
-done
-
-echo "+   GSTREAMER INFORMATION (unversioned)"
-command_output "which gst-inspect"
-command_output "gst-inspect"
-command_output "gst-inspect fakesrc"
-command_output "gst-inspect fakesink"
-command_output "gst-launch fakesrc num-buffers=5 ! fakesink"
-for mm in 0.6 0.7 0.8 0.9 0.10
-do
-  echo "+   GSTREAMER INFORMATION ($mm)"
-  command_output "which gst-inspect-$mm"
-  command_output "gst-inspect-$mm"
-  command_output "gst-inspect-$mm fakesrc"
-  command_output "gst-inspect-$mm fakesink"
-  command_output "gst-launch-$mm fakesrc num-buffers=5 ! fakesink"
-done
-
-echo "++  looking for gstreamer libraries in common locations"
-for dirs in /usr/lib /usr/local/lib; do
-  if test -d $dirs; then
-    find $dirs -name libgstreamer* | grep so
-  fi
-done
-echo "++  looking for gstreamer headers in common locations"
-for dirs in /usr/include /usr/local/include; do
-  if test -d $dirs; then
-    find $dirs -name gst.h
-  fi
-done
-
-echo "+   GSTREAMER PLUG-INS INFORMATION"
-command_output "gst-inspect volume"
-for mm in 0.6 0.7 0.8 0.9 0.10
-do
-  command_output "gst-inspect-$mm volume"
-done
-
-echo "++  looking for gstreamer volume plugin in common locations"
-for dirs in /usr/lib /usr/local/lib; do
-  if test -d $dirs; then
-    find $dirs -name libgstvolume* | grep so
-  fi
-done
-echo "++  looking for gstreamer headers in common locations"
-for dirs in /usr/include /usr/local/include; do
-  if test -d $dirs; then
-    find $dirs -name audio.h
-  fi
-done
-
-
diff --git a/tools/gst-feedback.1.in b/tools/gst-feedback.1.in
deleted file mode 100644 (file)
index 3b63291..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-.TH GStreamer 1 "June 2002"
-.SH "NAME"
-gst\-feedback - generate debug info for GStreamer bug reports
-.SH "SYNOPSIS"
-.B  gst-feedback
-.SH "DESCRIPTION"
-.PP
-\fIgst\-feedback\fP is a utility that scans the system for various
-information that is useful to GStreamer developers to help diagnose
-user problem.
-.PP
-Depending on the type of bug report, it may be useful to attach the
-output of \fIgst\-feedback\fP when you contact the developers.
-.PP
-NOTE: The current version of this script scans many dirs:
-/usr/lib /usr/local/lib /home /usr/include /usr/local/include /home (again)
-for various GStreamer installations.  Depending on your system you may not
-want to do this.  Improvements to the script are welcome.
-.SH "USAGE"
-Generate the feedback information by running \fIgst\-feedback\fP:
-.TP 8
-.B  gst\-feedback
-.TP -8
-Possibly redirect output and errors to a file:
-.TP 8
-.B  gst\-feedback &> myfeedback
-.SH "WARNING"
-The \fIgst\-feedback\fP dumps a lot of information about a system, some
-of which may be considered sensitive.  If this is a concern, review the
-information before posting to a public forum, such as the GStreamer bug
-tracking system.
-.
-.SH "SEE ALSO"
-.BR gst\-inspect (1),
-.BR gst\-launch (1),
-.BR gst\-typefind (1)
-.SH "AUTHOR"
-The GStreamer team at http://gstreamer.freedesktop.org/
index 75e5181..82042d1 100644 (file)
@@ -25,8 +25,6 @@
 #  include "config.h"
 #endif
 
-#include <gst/controller/gstcontroller.h>
-
 #include "tools.h"
 
 #include <string.h>
@@ -102,27 +100,8 @@ print_formats (const GstFormat * formats)
     formats++;
   }
 }
-#endif
 
 static void
-print_query_types (const GstQueryType * types)
-{
-  while (types && *types) {
-    const GstQueryTypeDefinition *definition;
-
-    definition = gst_query_type_get_details (*types);
-    if (definition)
-      n_print ("\t\t(%d):\t%s (%s)\n", *types,
-          definition->nick, definition->description);
-    else
-      n_print ("\t\t(%d):\tUnknown query format\n", *types);
-
-    types++;
-  }
-}
-
-#if 0
-static void
 print_event_masks (const GstEventMask * masks)
 {
   GType event_type;
@@ -199,7 +178,7 @@ get_rank_name (char *s, gint rank)
 }
 
 static gboolean
-print_factory_details_meta_data (GQuark field_id, const GValue * value,
+print_factory_details_metadata (GQuark field_id, const GValue * value,
     gpointer user_data)
 {
   gchar *val = g_strdup_value_contents (value);
@@ -218,17 +197,11 @@ print_factory_details_info (GstElementFactory * factory)
   char s[20];
 
   n_print ("Factory Details:\n");
-  n_print ("  Long name:\t%s\n", factory->details.longname);
-  n_print ("  Class:\t%s\n", factory->details.klass);
-  n_print ("  Description:\t%s\n", factory->details.description);
-  n_print ("  Author(s):\t%s\n", factory->details.author);
   n_print ("  Rank:\t\t%s (%d)\n",
       get_rank_name (s, GST_PLUGIN_FEATURE (factory)->rank),
       GST_PLUGIN_FEATURE (factory)->rank);
-  if (factory->meta_data != NULL) {
-    gst_structure_foreach ((GstStructure *) factory->meta_data,
-        print_factory_details_meta_data, NULL);
-  }
+  gst_structure_foreach ((GstStructure *) factory->metadata,
+      print_factory_details_metadata, NULL);
   n_print ("\n");
 }
 
@@ -414,6 +387,10 @@ print_element_properties_info (GstElement * element)
         n_print ("%-23.23s Unsigned Long. ", "");
         g_print ("Range: %lu - %lu Default: %lu ",
             pulong->minimum, pulong->maximum, g_value_get_ulong (&value));
+
+        GST_ERROR ("%s: property '%s' of type ulong: consider changing to "
+            "uint/uint64", GST_OBJECT_NAME (element),
+            g_param_spec_get_name (param));
         break;
       }
       case G_TYPE_LONG:
@@ -423,6 +400,10 @@ print_element_properties_info (GstElement * element)
         n_print ("%-23.23s Long. ", "");
         g_print ("Range: %ld - %ld Default: %ld ",
             plong->minimum, plong->maximum, g_value_get_long (&value));
+
+        GST_ERROR ("%s: property '%s' of type long: consider changing to "
+            "int/int64", GST_OBJECT_NAME (element),
+            g_param_spec_get_name (param));
         break;
       }
       case G_TYPE_UINT:
@@ -481,6 +462,12 @@ print_element_properties_info (GstElement * element)
             pdouble->minimum, pdouble->maximum, g_value_get_double (&value));
         break;
       }
+      case G_TYPE_CHAR:
+      case G_TYPE_UCHAR:
+        GST_ERROR ("%s: property '%s' of type char: consider changing to "
+            "int/string", GST_OBJECT_NAME (element),
+            g_param_spec_get_name (param));
+        /* fall through */
       default:
         if (param->value_type == GST_TYPE_CAPS) {
           const GstCaps *caps = gst_value_get_caps (&value);
@@ -573,9 +560,6 @@ print_element_properties_info (GstElement * element)
               pfraction->max_num, pfraction->max_den,
               gst_value_get_fraction_numerator (&value),
               gst_value_get_fraction_denominator (&value));
-        } else if (GST_IS_PARAM_SPEC_MINI_OBJECT (param)) {
-          n_print ("%-23.23s MiniObject of type \"%s\"", "",
-              g_type_name (param->value_type));
         } else {
           n_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
               g_type_name (param->value_type));
@@ -664,37 +648,28 @@ print_element_flag_info (GstElement * element)
 static void
 print_implementation_info (GstElement * element)
 {
-  n_print ("\n");
-  n_print ("Element Implementation:\n");
-
-  {
-    GstElementClass *gstelement_class;
-
-    gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
+  GstElementClass *gstelement_class;
 
-    n_print ("  Has change_state() function: %s\n",
-        GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
-  }
-#ifndef GST_DISABLE_LOADSAVE
-  {
-    GstObjectClass *gstobject_class;
+  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
 
-    gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
+  n_print ("\n");
+  n_print ("Element Implementation:\n");
 
-    n_print ("  Has custom save_thyself() function: %s\n",
-        GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
-    n_print ("  Has custom restore_thyself() function: %s\n",
-        GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
-  }
-#endif
+  n_print ("  Has change_state() function: %s\n",
+      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
 }
 
 static void
 print_clocking_info (GstElement * element)
 {
-  if (!gst_element_requires_clock (element) &&
-      !(gst_element_provides_clock (element) &&
-          gst_element_get_clock (element))) {
+  gboolean requires_clock, provides_clock;
+
+  requires_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
+  provides_clock =
+      GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
+
+  if (!requires_clock && !provides_clock) {
     n_print ("\n");
     n_print ("Element has no clocking capabilities.");
     return;
@@ -702,17 +677,18 @@ print_clocking_info (GstElement * element)
 
   n_print ("\n");
   n_print ("Clocking Interaction:\n");
-  if (gst_element_requires_clock (element)) {
+  if (requires_clock) {
     n_print ("  element requires a clock\n");
   }
 
-  if (gst_element_provides_clock (element)) {
+  if (provides_clock) {
     GstClock *clock;
 
     clock = gst_element_get_clock (element);
-    if (clock)
+    if (clock) {
       n_print ("  element provides a clock: %s\n", GST_OBJECT_NAME (clock));
-    else
+      gst_object_unref (clock);
+    } else
       n_print ("  element is supposed to provide a clock but returned NULL\n");
   }
 }
@@ -720,7 +696,7 @@ print_clocking_info (GstElement * element)
 static void
 print_index_info (GstElement * element)
 {
-  if (gst_element_is_indexable (element)) {
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_INDEXABLE)) {
     n_print ("\n");
     n_print ("Indexing capabilities:\n");
     n_print ("  element can do indexing\n");
@@ -734,8 +710,8 @@ static void
 print_uri_handler_info (GstElement * element)
 {
   if (GST_IS_URI_HANDLER (element)) {
+    const gchar *const *uri_protocols;
     const gchar *uri_type;
-    gchar **uri_protocols;
 
     if (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element)) == GST_URI_SRC)
       uri_type = "source";
@@ -780,6 +756,7 @@ print_pad_info (GstElement * element)
   pads = element->pads;
   while (pads) {
     gchar *name;
+    GstCaps *caps;
 
     pad = GST_PAD (pads->data);
     pads = g_list_next (pads);
@@ -811,43 +788,19 @@ print_pad_info (GstElement * element)
     if (pad->queryfunc != gst_pad_query_default)
       n_print ("      Has custom queryfunc(): %s\n",
           GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
-    if (pad->querytypefunc != gst_pad_get_query_types_default) {
-      const GstQueryType *query_types = gst_pad_get_query_types (pad);
-      if (query_types) {
-        n_print ("        Provides query types:\n");
-        print_query_types (query_types);
-      }
-    }
 
     if (pad->iterintlinkfunc != gst_pad_iterate_internal_links_default)
       n_print ("      Has custom iterintlinkfunc(): %s\n",
           GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));
 
-    if (pad->bufferallocfunc)
-      n_print ("      Has bufferallocfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
-
-    if (pad->getcapsfunc)
-      n_print ("      Has getcapsfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->getcapsfunc));
-    if (pad->setcapsfunc)
-      n_print ("      Has setcapsfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->setcapsfunc));
-    /* gst_pad_acceptcaps_default is static :/ */
-    if (pad->acceptcapsfunc)
-      n_print ("      Has acceptcapsfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->acceptcapsfunc));
-    if (pad->fixatecapsfunc)
-      n_print ("      Has fixatecapsfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (pad->fixatecapsfunc));
-
-
     if (pad->padtemplate)
       n_print ("    Pad Template: '%s'\n", pad->padtemplate->name_template);
 
-    if (pad->caps) {
+    caps = gst_pad_get_current_caps (pad);
+    if (caps) {
       n_print ("    Capabilities:\n");
-      print_caps (pad->caps, "      ");
+      print_caps (caps, "      ");
+      gst_caps_unref (caps);
     }
   }
 }
@@ -1002,7 +955,7 @@ print_blacklist (void)
 
   g_print ("%s\n", _("Blacklisted files:"));
 
-  plugins = gst_default_registry_get_plugin_list ();
+  plugins = gst_registry_get_plugin_list (gst_registry_get ());
   for (cur = plugins; cur != NULL; cur = g_list_next (cur)) {
     GstPlugin *plugin = (GstPlugin *) (cur->data);
     if (plugin->flags & GST_PLUGIN_FLAG_BLACKLISTED) {
@@ -1025,7 +978,7 @@ print_element_list (gboolean print_all)
   int plugincount = 0, featurecount = 0, blacklistcount = 0;
   GList *plugins, *orig_plugins;
 
-  orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+  orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ());
   while (plugins) {
     GList *features, *orig_features;
     GstPlugin *plugin;
@@ -1040,7 +993,7 @@ print_element_list (gboolean print_all)
     }
 
     orig_features = features =
-        gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
+        gst_registry_get_feature_list_by_plugin (gst_registry_get (),
         plugin->desc.name);
     while (features) {
       GstPluginFeature *feature;
@@ -1058,15 +1011,17 @@ print_element_list (gboolean print_all)
           print_element_info (factory, TRUE);
         else
           g_print ("%s:  %s: %s\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (factory),
+              GST_OBJECT_NAME (factory),
               gst_element_factory_get_longname (factory));
+#if 0
       } else if (GST_IS_INDEX_FACTORY (feature)) {
         GstIndexFactory *factory;
 
         factory = GST_INDEX_FACTORY (feature);
         if (!print_all)
           g_print ("%s:  %s: %s\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
+              GST_OBJECT_NAME (factory), factory->longdesc);
+#endif
       } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
         GstTypeFindFactory *factory;
 
@@ -1091,8 +1046,7 @@ print_element_list (gboolean print_all)
       } else {
         if (!print_all)
           n_print ("%s:  %s (%s)\n", plugin->desc.name,
-              GST_PLUGIN_FEATURE_NAME (feature),
-              g_type_name (G_OBJECT_TYPE (feature)));
+              GST_OBJECT_NAME (feature), g_type_name (G_OBJECT_TYPE (feature)));
       }
 
     next:
@@ -1123,13 +1077,13 @@ print_all_uri_handlers (void)
 {
   GList *plugins, *p, *features, *f;
 
-  plugins = gst_default_registry_get_plugin_list ();
+  plugins = gst_registry_get_plugin_list (gst_registry_get ());
 
   for (p = plugins; p; p = p->next) {
     GstPlugin *plugin = (GstPlugin *) (p->data);
 
     features =
-        gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
+        gst_registry_get_feature_list_by_plugin (gst_registry_get (),
         plugin->desc.name);
 
     for (f = features; f; f = f->next) {
@@ -1154,8 +1108,9 @@ print_all_uri_handlers (void)
         }
 
         if (GST_IS_URI_HANDLER (element)) {
+          const gchar *const *uri_protocols;
           const gchar *dir;
-          gchar **uri_protocols, *joined;
+          gchar *joined;
 
           switch (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element))) {
             case GST_URI_SRC:
@@ -1171,7 +1126,7 @@ print_all_uri_handlers (void)
 
           uri_protocols =
               gst_uri_handler_get_protocols (GST_URI_HANDLER (element));
-          joined = g_strjoinv (", ", uri_protocols);
+          joined = g_strjoinv (", ", (gchar **) uri_protocols);
 
           g_print ("%s (%s, rank %u): %s\n",
               gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), dir,
@@ -1230,18 +1185,17 @@ print_plugin_info (GstPlugin * plugin)
 static void
 print_plugin_features (GstPlugin * plugin)
 {
-  GList *features, *features_to_free;
+  GList *features, *origlist;
   gint num_features = 0;
   gint num_elements = 0;
   gint num_typefinders = 0;
   gint num_indexes = 0;
   gint num_other = 0;
 
-  features =
-      gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
+  origlist = features =
+      gst_registry_get_feature_list_by_plugin (gst_registry_get (),
       plugin->desc.name);
 
-  features_to_free = features;
   while (features) {
     GstPluginFeature *feature;
 
@@ -1251,15 +1205,17 @@ print_plugin_features (GstPlugin * plugin)
       GstElementFactory *factory;
 
       factory = GST_ELEMENT_FACTORY (feature);
-      n_print ("  %s: %s\n", GST_PLUGIN_FEATURE_NAME (factory),
+      n_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
           gst_element_factory_get_longname (factory));
       num_elements++;
+#if 0
     } else if (GST_IS_INDEX_FACTORY (feature)) {
       GstIndexFactory *factory;
 
       factory = GST_INDEX_FACTORY (feature);
       n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
       num_indexes++;
+#endif
     } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
       GstTypeFindFactory *factory;
 
@@ -1288,6 +1244,9 @@ print_plugin_features (GstPlugin * plugin)
     gst_object_unref (feature);
     features = g_list_next (features);
   }
+
+  gst_plugin_feature_list_free (origlist);
+
   n_print ("\n");
   n_print ("  %d features:\n", num_features);
   if (num_elements > 0)
@@ -1300,9 +1259,6 @@ print_plugin_features (GstPlugin * plugin)
     n_print ("  +-- %d other objects\n", num_other);
 
   n_print ("\n");
-
-  if (features_to_free)
-    g_list_free (features_to_free);
 }
 
 static int
@@ -1311,13 +1267,15 @@ print_element_features (const gchar * element_name)
   GstPluginFeature *feature;
 
   /* FIXME implement other pretty print function for these */
+#if 0
   feature = gst_default_registry_find_feature (element_name,
       GST_TYPE_INDEX_FACTORY);
   if (feature) {
     n_print ("%s: an index\n", element_name);
     return 0;
   }
-  feature = gst_default_registry_find_feature (element_name,
+#endif
+  feature = gst_registry_find_feature (gst_registry_get (), element_name,
       GST_TYPE_TYPE_FIND_FACTORY);
   if (feature) {
     n_print ("%s: a typefind function\n", element_name);
@@ -1350,7 +1308,7 @@ print_element_info (GstElementFactory * factory, gboolean print_names)
   }
 
   if (print_names)
-    _name = g_strdup_printf ("%s: ", GST_PLUGIN_FEATURE (factory)->name);
+    _name = g_strdup_printf ("%s: ", GST_OBJECT_NAME (factory));
   else
     _name = NULL;
 
@@ -1358,7 +1316,7 @@ print_element_info (GstElementFactory * factory, gboolean print_names)
   if (GST_PLUGIN_FEATURE (factory)->plugin_name) {
     GstPlugin *plugin;
 
-    plugin = gst_registry_find_plugin (gst_registry_get_default (),
+    plugin = gst_registry_find_plugin (gst_registry_get (),
         GST_PLUGIN_FEATURE (factory)->plugin_name);
     if (plugin) {
       print_plugin_info (plugin);
@@ -1428,7 +1386,7 @@ print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
 
   if (caps == NULL) {
     g_printerr ("Couldn't find static pad template for %s '%s'\n",
-        type_name, GST_PLUGIN_FEATURE_NAME (factory));
+        type_name, GST_OBJECT_NAME (factory));
     return;
   }
 
@@ -1459,23 +1417,26 @@ print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
 static void
 print_plugin_automatic_install_info_protocols (GstElementFactory * factory)
 {
-  gchar **protocols, **p;
+  const gchar *const *protocols;
 
   protocols = gst_element_factory_get_uri_protocols (factory);
   if (protocols != NULL && *protocols != NULL) {
     switch (gst_element_factory_get_uri_type (factory)) {
       case GST_URI_SINK:
-        for (p = protocols; *p != NULL; ++p)
-          g_print ("urisink-%s\n", *p);
+        while (*protocols != NULL) {
+          g_print ("urisink-%s\n", *protocols);
+          ++protocols;
+        }
         break;
       case GST_URI_SRC:
-        for (p = protocols; *p != NULL; ++p)
-          g_print ("urisource-%s\n", *p);
+        while (*protocols != NULL) {
+          g_print ("urisource-%s\n", *protocols);
+          ++protocols;
+        }
         break;
       default:
         break;
     }
-    g_strfreev (protocols);
   }
 }
 
@@ -1488,7 +1449,7 @@ print_plugin_automatic_install_info (GstPlugin * plugin)
   plugin_name = gst_plugin_get_name (plugin);
 
   /* not interested in typefind factories, only element factories */
-  features = gst_registry_get_feature_list (gst_registry_get_default (),
+  features = gst_registry_get_feature_list (gst_registry_get (),
       GST_TYPE_ELEMENT_FACTORY);
 
   for (l = features; l != NULL; l = l->next) {
@@ -1517,7 +1478,7 @@ print_all_plugin_automatic_install_info (void)
 {
   GList *plugins, *orig_plugins;
 
-  orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+  orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ());
   while (plugins) {
     GstPlugin *plugin;
 
@@ -1567,10 +1528,6 @@ main (int argc, char *argv[])
   textdomain (GETTEXT_PACKAGE);
 #endif
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_thread_init (NULL);
-#endif
-
   gst_tools_set_prgname ("gst-inspect");
 
 #ifndef GST_DISABLE_OPTION_PARSING
@@ -1633,7 +1590,7 @@ main (int argc, char *argv[])
 
     /* otherwise check if it's a plugin */
     if (retval) {
-      plugin = gst_default_registry_find_plugin (arg);
+      plugin = gst_registry_find_plugin (gst_registry_get (), arg);
 
       /* if there is such a plugin, print out info */
       if (plugin) {
index aa02dd7..e6702f4 100644 (file)
@@ -48,15 +48,9 @@ shut down forcefully via Control-C.
 Gather and print index statistics. This is mostly useful for playback or
 recording pipelines.
 .TP 8
-.B  \-o FILE, \-\-output=FILE
-Save XML representation of pipeline to FILE and exit (DEPRECATED, DO NOT USE)
-.TP 8
 .B  \-f, \-\-no\-fault
 Do not install a fault handler
 .TP 8
-.B  \-\-no\-sigusr-handler
-Do not install signal handlers for SIGUSR1 (play) and SIGUSR2 (stop)
-.TP 8
 .B  \-T, \-\-trace
 Print memory allocation traces. The feature must be enabled at compile time to
 work.
@@ -209,15 +203,6 @@ Ranges are in this format:  [ VALUE, VALUE ]
 .br
 Lists use this format:      ( VALUE \fI[, VALUE ...]\fR )
 
-.SH "PIPELINE CONTROL"
-
-A pipeline can be controlled by signals. SIGUSR2 will stop the pipeline
-(GST_STATE_NULL); SIGUSR1 will put it back to play (GST_STATE_PLAYING).
-By default, the pipeline will start in the playing state.
-.br
-There are currently no signals defined to go into the ready or pause
-(GST_STATE_READY and GST_STATE_PAUSED) state explicitly.
-
 .SH "PIPELINE EXAMPLES"
 
 The examples below assume that you have the correct plug-ins available.
@@ -426,7 +411,7 @@ When set to a filesystem path, store dot files of pipeline graphs there.
 .TP
 \fBGST_REGISTRY\fR
 Path of the plugin registry file. Default is
-~/.gstreamer-GST_MAJORMINOR/registry-CPU.xml where CPU is the machine/cpu type
+~/.gstreamer-GST_MAJORMINOR/registry-CPU.bin where CPU is the machine/cpu type
 GStreamer was compiled for, e.g. 'i486', 'i686', 'x86-64', 'ppc', etc. (check
 the output of "uname -i" and "uname -m" for details).
 .TP
@@ -463,8 +448,8 @@ a stack trace in the usual way.
 .
 .SH FILES
 .TP 8
-~/.gstreamer-GST_MAJORMINOR/registry-*.xml
-The xml plugin database; can be deleted at any time, will be re-created
+~/.gstreamer-GST_MAJORMINOR/registry-*.bin
+The plugin cache; can be deleted at any time, will be re-created
 automatically when it does not exist yet or plugins change.
 .
 .SH "SEE ALSO"
index b801d03..3ea4fff 100644 (file)
@@ -76,79 +76,6 @@ static gboolean waiting_eos = FALSE;
 /* convenience macro so we don't have to litter the code with if(!quiet) */
 #define PRINT if(!quiet)g_print
 
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static GstElement *
-xmllaunch_parse_cmdline (const gchar ** argv)
-{
-  GstElement *pipeline = NULL, *e;
-  GstXML *xml;
-  gboolean err;
-  const gchar *arg;
-  gchar *element, *property, *value;
-  GList *l;
-  gint i = 0;
-
-  if (!(arg = argv[0])) {
-    g_printerr ("%s",
-        _("Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"));
-    exit (1);
-  }
-
-  xml = gst_xml_new ();
-  /* FIXME guchar from gstxml.c */
-  err = gst_xml_parse_file (xml, (guchar *) arg, NULL);
-
-  if (err != TRUE) {
-    g_printerr (_("ERROR: parse of xml file '%s' failed.\n"), arg);
-    exit (1);
-  }
-
-  l = gst_xml_get_topelements (xml);
-  if (!l) {
-    g_printerr (_("ERROR: no toplevel pipeline element in file '%s'.\n"), arg);
-    exit (1);
-  }
-
-  if (l->next) {
-    g_printerr ("%s",
-        _("WARNING: only one toplevel element is supported at this time.\n"));
-  }
-
-  pipeline = GST_ELEMENT (l->data);
-
-  while ((arg = argv[++i])) {
-    element = g_strdup (arg);
-    property = strchr (element, '.');
-    value = strchr (element, '=');
-
-    if (!(element < property && property < value)) {
-      g_printerr (_("ERROR: could not parse command line argument %d: %s.\n"),
-          i, element);
-      g_free (element);
-      exit (1);
-    }
-
-    *property++ = '\0';
-    *value++ = '\0';
-
-    e = gst_bin_get_by_name (GST_BIN (pipeline), element);
-    if (!e) {
-      g_printerr (_("WARNING: element named '%s' not found.\n"), element);
-    } else {
-      gst_util_set_object_arg (G_OBJECT (e), property, value);
-    }
-    g_free (element);
-  }
-
-  if (!l)
-    return NULL;
-
-  gst_object_ref (pipeline);
-  gst_object_unref (xml);
-  return pipeline;
-}
-#endif
-
 #ifndef DISABLE_FAULT_HANDLER
 #ifndef USE_SIGINFO
 static void
@@ -250,6 +177,7 @@ fault_setup (void)
 }
 #endif /* DISABLE_FAULT_HANDLER */
 
+#if 0
 typedef struct _GstIndexStats
 {
   gint id;
@@ -402,6 +330,7 @@ print_index_stats (GPtrArray * index_stats)
     }
   }
 }
+#endif
 
 /* Kids, use the functions from libgstpbutils in gst-plugins-base in your
  * own code (we can't do that here because it would introduce a circular
@@ -409,16 +338,18 @@ print_index_stats (GPtrArray * index_stats)
 static gboolean
 gst_is_missing_plugin_message (GstMessage * msg)
 {
-  if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL)
+  if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT
+      || gst_message_get_structure (msg) == NULL)
     return FALSE;
 
-  return gst_structure_has_name (msg->structure, "missing-plugin");
+  return gst_structure_has_name (gst_message_get_structure (msg),
+      "missing-plugin");
 }
 
 static const gchar *
 gst_missing_plugin_message_get_description (GstMessage * msg)
 {
-  return gst_structure_get_string (msg->structure, "name");
+  return gst_structure_get_string (gst_message_get_structure (msg), "name");
 }
 
 static void
@@ -459,10 +390,9 @@ print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
       if (img) {
         gchar *caps_str;
 
-        caps_str = GST_BUFFER_CAPS (img) ?
-            gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
-        str = g_strdup_printf ("buffer of %u bytes, type: %s",
-            GST_BUFFER_SIZE (img), caps_str);
+        caps_str = g_strdup ("unknown");
+        str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes, type: %s",
+            gst_buffer_get_size (img), caps_str);
         g_free (caps_str);
       } else {
         str = g_strdup ("NULL buffer");
@@ -570,33 +500,6 @@ sigint_restore (void)
 
   sigaction (SIGINT, &action, NULL);
 }
-
-/* FIXME 0.11: remove SIGUSR handling (also from man page) */
-static void
-play_handler (int signum)
-{
-  switch (signum) {
-    case SIGUSR1:
-      PRINT ("Caught SIGUSR1 - Play request.\n");
-      gst_element_set_state (pipeline, GST_STATE_PLAYING);
-      break;
-    case SIGUSR2:
-      PRINT ("Caught SIGUSR2 - Stop request.\n");
-      gst_element_set_state (pipeline, GST_STATE_NULL);
-      break;
-  }
-}
-
-static void
-play_signal_setup (void)
-{
-  struct sigaction action;
-
-  memset (&action, 0, sizeof (action));
-  action.sa_handler = play_handler;
-  sigaction (SIGUSR1, &action, NULL);
-  sigaction (SIGUSR2, &action, NULL);
-}
 #endif /* DISABLE_FAULT_HANDLER */
 
 /* returns ELR_ERROR if there was an error
@@ -919,10 +822,11 @@ main (int argc, char *argv[])
   /* options */
   gboolean verbose = FALSE;
   gboolean no_fault = FALSE;
-  gboolean no_sigusr_handler = FALSE;
   gboolean trace = FALSE;
   gboolean eos_on_shutdown = FALSE;
+#if 0
   gboolean check_index = FALSE;
+#endif
   gchar *savefile = NULL;
   gchar *exclude_args = NULL;
 #ifndef GST_DISABLE_OPTION_PARSING
@@ -937,28 +841,26 @@ main (int argc, char *argv[])
         N_("Output messages"), NULL},
     {"exclude", 'X', 0, G_OPTION_ARG_NONE, &exclude_args,
         N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")},
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-    {"output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
-        N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")},
-#endif
     {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault,
         N_("Do not install a fault handler"), NULL},
-    {"no-sigusr-handler", '\0', 0, G_OPTION_ARG_NONE, &no_sigusr_handler,
-        N_("Do not install signal handlers for SIGUSR1 and SIGUSR2"), NULL},
     {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace,
         N_("Print alloc trace (if enabled at compile time)"), NULL},
     {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown,
         N_("Force EOS on sources before shutting the pipeline down"), NULL},
+#if 0
     {"index", 'i', 0, G_OPTION_ARG_NONE, &check_index,
         N_("Gather and print index statistics"), NULL},
+#endif
     GST_TOOLS_GOPTION_VERSION,
     {NULL}
   };
   GOptionContext *ctx;
   GError *err = NULL;
 #endif
+#if 0
   GstIndex *index;
   GPtrArray *index_stats = NULL;
+#endif
   gchar **argvn;
   GError *error = NULL;
   gint res = 0;
@@ -971,10 +873,6 @@ main (int argc, char *argv[])
   textdomain (GETTEXT_PACKAGE);
 #endif
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_thread_init (NULL);
-#endif
-
   gst_tools_set_prgname ("gst-launch");
 
 #ifndef GST_DISABLE_OPTION_PARSING
@@ -1000,9 +898,6 @@ main (int argc, char *argv[])
     fault_setup ();
 
   sigint_setup ();
-
-  if (!no_sigusr_handler)
-    play_signal_setup ();
 #endif
 
   if (trace) {
@@ -1017,15 +912,6 @@ main (int argc, char *argv[])
   /* make a null-terminated version of argv */
   argvn = g_new0 (char *, argc);
   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  if (strstr (argv[0], "gst-xmllaunch")) {
-    /* FIXME 0.11: remove xmllaunch entirely */
-    g_warning ("gst-xmllaunch is deprecated and broken for all but the most "
-        "simple pipelines. It will most likely be removed in future. Don't "
-        "use it.\n");
-    pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn);
-  } else
-#endif
   {
     pipeline =
         (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
@@ -1054,15 +940,6 @@ main (int argc, char *argv[])
     g_signal_connect (pipeline, "deep-notify",
         G_CALLBACK (gst_object_default_deep_notify), exclude_list);
   }
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-  if (savefile) {
-    g_warning ("Pipeline serialization to XML is deprecated and broken for "
-        "all but the most simple pipelines. It will most likely be removed "
-        "in future. Don't use it.\n");
-
-    gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
-  }
-#endif
 
   if (!savefile) {
     GstState state, pending;
@@ -1080,7 +957,7 @@ main (int argc, char *argv[])
       gst_bin_add (GST_BIN (real_pipeline), pipeline);
       pipeline = real_pipeline;
     }
-
+#if 0
     if (check_index) {
       /* gst_index_new() creates a null-index, it does not store anything, but
        * the entry-added signal works and this is what we use to build the
@@ -1095,6 +972,7 @@ main (int argc, char *argv[])
         gst_element_set_index (pipeline, index);
       }
     }
+#endif
 
     bus = gst_element_get_bus (pipeline);
     gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline);
@@ -1188,10 +1066,12 @@ main (int argc, char *argv[])
     gst_element_set_state (pipeline, GST_STATE_READY);
     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
 
+#if 0
     if (check_index) {
       print_index_stats (index_stats);
       g_ptr_array_free (index_stats, TRUE);
     }
+#endif
 
   end:
     PRINT (_("Setting pipeline to NULL ...\n"));
diff --git a/tools/gst-run.c b/tools/gst-run.c
deleted file mode 100644 (file)
index b199e6f..0000000
+++ /dev/null
@@ -1,422 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Thomas Vander Stichele <thomas@apestaart.org>
- *
- * gst-run.c: tool to launch GStreamer tools with correct major/minor
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <glib.h>
-
-/* global statics for option parsing */
-static gboolean _print = FALSE;
-static gchar *_arg_mm = NULL;
-static gboolean _arg_list_mm = FALSE;
-
-/* popt options table for the wrapper */
-static GOptionEntry wrapper_options[] = {
-  {"print", 'p', 0, G_OPTION_ARG_NONE, &_print,
-      "print wrapped command line options", NULL},
-  {"gst-mm", 0, 0, G_OPTION_ARG_STRING, &_arg_mm,
-      "Force major/minor version", "VERSION"},
-  {"gst-list-mm", 0, 0, G_OPTION_ARG_NONE, &_arg_list_mm,
-      "List found major/minor versions", NULL},
-  {NULL}
-};
-
-/* print out the major/minor, which is the hash key */
-static void
-hash_print_key (gchar * key, gchar * value)
-{
-  g_print ("%s\n", (gchar *) key);
-}
-
-/* return value like strcmp, but compares major/minor numerically */
-static gint
-compare_major_minor (const gchar * first, const gchar * second)
-{
-  gchar **firsts, **seconds;
-  gint fmaj, fmin, smaj, smin;
-  gint ret = 0;
-
-  firsts = g_strsplit (first, ".", 0);
-  seconds = g_strsplit (second, ".", 0);
-
-  if (firsts[0] == NULL || firsts[1] == NULL) {
-    ret = -1;
-    goto beach;
-  }
-  if (seconds[0] == NULL || seconds[1] == NULL) {
-    ret = 1;
-    goto beach;
-  }
-
-  fmaj = atoi (firsts[0]);
-  fmin = atoi (firsts[1]);
-  smaj = atoi (seconds[0]);
-  smin = atoi (seconds[1]);
-
-  if (fmaj < smaj) {
-    ret = -1;
-    goto beach;
-  }
-  if (fmaj > smaj) {
-    ret = 1;
-    goto beach;
-  }
-
-  /* fmaj == smaj */
-  if (fmin < smin) {
-    ret = -1;
-    goto beach;
-  }
-  if (fmin > smin) {
-    ret = 1;
-    goto beach;
-  }
-  ret = 0;
-
-beach:
-  g_strfreev (firsts);
-  g_strfreev (seconds);
-  return ret;
-}
-
-static void
-find_highest_version (gchar * key, gchar * value, gchar ** highest)
-{
-  if (*highest == NULL) {
-    /* first value, so just set it */
-    *highest = key;
-  }
-  if (compare_major_minor (key, *highest) > 0)
-    *highest = key;
-}
-
-/* Libtool creates shell scripts named "base" that calls actual binaries as
- * .libs/lt-base.  If we detect this is a libtool script, unmangle so we
- * find the right binaries */
-static void
-unmangle_libtool (gchar ** dir, gchar ** base)
-{
-  gchar *new_dir, *new_base;
-
-  if (!*dir)
-    return;
-  if (!*base)
-    return;
-
-  /* We assume libtool when base starts with "lt-" and dir ends with ".libs".
-   * On Windows libtool doesn't seem to be adding "lt-" prefix. */
-#ifndef G_OS_WIN32
-  if (!g_str_has_prefix (*base, "lt-"))
-    return;
-#endif
-
-  if (!g_str_has_suffix (*dir, ".libs"))
-    return;
-
-#ifndef G_OS_WIN32
-  new_base = g_strdup (&((*base)[3]));
-#else
-  new_base = g_strdup (*base);
-#endif
-  new_dir = g_path_get_dirname (*dir);
-  g_free (*base);
-  g_free (*dir);
-  *base = new_base;
-  *dir = new_dir;
-}
-
-/* Returns a directory path that contains the binary given as an argument.
- * If the binary given contains a path, it gets looked for in that path.
- * If it doesn't contain a path, it gets looked for in the standard path.
- *
- * The returned string is newly allocated.
- */
-static gchar *
-get_dir_of_binary (const gchar * binary)
-{
-  gchar *base, *dir;
-  gchar *full;
-
-  base = g_path_get_basename (binary);
-  dir = g_path_get_dirname (binary);
-
-  /* if putting these two together yields the same as binary,
-   * then we have the right breakup.  If not, it's because no path was
-   * specified which caused get_basename to return "." */
-  full = g_build_filename (dir, base, NULL);
-
-#ifdef G_OS_WIN32
-
-  /* g_build_filename() should be using the last path separator used in the
-   * input according to the docs, but doesn't actually do that, so we have
-   * to fix up the result. */
-  {
-    gchar *tmp;
-
-    for (tmp = (gchar *) binary + strlen (binary) - 1; tmp >= binary; tmp--) {
-      if (*tmp == '/' || *tmp == '\\') {
-        full[strlen (dir)] = *tmp;
-        break;
-      }
-    }
-  }
-#endif
-
-  if (strcmp (full, binary) != 0) {
-    if (strcmp (dir, ".") != 0) {
-      g_warning ("This should not happen, g_path_get_dirname () has changed.");
-      g_free (base);
-      g_free (dir);
-      g_free (full);
-      return NULL;
-    }
-
-    /* we know no path was specified, so search standard path for binary */
-    g_free (full);
-    full = g_find_program_in_path (base);
-    if (!full) {
-      g_warning ("This should not happen, %s not in standard path.", base);
-      g_free (base);
-      g_free (dir);
-      return NULL;
-    }
-  }
-
-  g_free (base);
-  g_free (dir);
-  dir = g_path_get_dirname (full);
-  g_free (full);
-
-  return dir;
-}
-
-/* Search the given directory for candidate binaries matching the base binary.
- * Return a GHashTable of major/minor -> directory pairs
- */
-static GHashTable *
-get_candidates (const gchar * dir, const gchar * base)
-{
-  GDir *gdir;
-  GError *error = NULL;
-  const gchar *entry;
-  gchar *path;
-  gchar *suffix, *copy;
-
-  gchar *pattern;
-  GPatternSpec *spec, *specexe;
-
-  gchar **dirs;
-  gchar **cur;
-
-  GHashTable *candidates = NULL;
-
-  candidates = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-  /* compile our pattern specs */
-  pattern = g_strdup_printf ("%s-*.*", base);
-  spec = g_pattern_spec_new (pattern);
-  g_free (pattern);
-  pattern = g_strdup_printf ("%s-*.*.exe", base);
-  specexe = g_pattern_spec_new (pattern);
-  g_free (pattern);
-
-  /* get all dirs from the path and prepend with given dir */
-  if (dir)
-    path = g_strdup_printf ("%s%c%s",
-        dir, G_SEARCHPATH_SEPARATOR, g_getenv ("PATH"));
-  else
-    path = (gchar *) g_getenv ("PATH");
-  dirs = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 0);
-  if (dir)
-    g_free (path);
-
-  /* check all of these in reverse order by winding to bottom and going up  */
-  cur = &dirs[0];
-  while (*cur)
-    ++cur;
-
-  while (cur != &dirs[0]) {
-    --cur;
-    if (!g_file_test (*cur, G_FILE_TEST_EXISTS) ||
-        !g_file_test (*cur, G_FILE_TEST_IS_DIR)) {
-      continue;
-    }
-
-    gdir = g_dir_open (*cur, 0, &error);
-    if (!gdir) {
-      g_warning ("Could not open dir %s: %s", *cur, error->message);
-      g_error_free (error);
-      return NULL;
-    }
-    while ((entry = g_dir_read_name (gdir))) {
-      if (g_pattern_match_string (spec, entry)
-          || g_pattern_match_string (specexe, entry)) {
-        gchar *full;
-
-        /* is it executable ? */
-        full = g_build_filename (*cur, entry, NULL);
-        if (!g_file_test (full, G_FILE_TEST_IS_EXECUTABLE)) {
-          g_free (full);
-          continue;
-        }
-        g_free (full);
-
-        /* strip base and dash from it */
-        suffix = g_strdup (&(entry[strlen (base) + 1]));
-        copy = g_strdup (suffix);
-
-        /* strip possible .exe from copy */
-        if (g_strrstr (copy, ".exe"))
-          g_strrstr (copy, ".exe")[0] = '\0';
-
-        /* stricter pattern check: check if it only contains digits or dots */
-        g_strcanon (copy, "0123456789.", 'X');
-        if (strstr (copy, "X")) {
-          g_free (suffix);
-          g_free (copy);
-          continue;
-        }
-        g_free (copy);
-        g_hash_table_insert (candidates, suffix, g_strdup (*cur));
-      }
-    }
-  }
-
-  g_strfreev (dirs);
-  g_pattern_spec_free (spec);
-  return candidates;
-}
-
-int
-main (int argc, char **argv)
-{
-  GHashTable *candidates;
-  gchar *dir;
-  gchar *base;
-  gchar *highest = NULL;
-  gchar *binary;                /* actual binary we're going to run */
-  gchar *path = NULL;           /* and its path */
-  gchar *desc;
-  GOptionContext *ctx;
-  GError *err = NULL;
-
-  /* detect stuff */
-  dir = get_dir_of_binary (argv[0]);
-  base = g_path_get_basename (argv[0]);
-
-  /* parse command line options */
-  desc = g_strdup_printf ("wrapper to call versioned %s", base);
-  ctx = g_option_context_new (desc);
-  g_free (desc);
-  g_option_context_set_ignore_unknown_options (ctx, TRUE);
-  g_option_context_add_main_entries (ctx, wrapper_options, GETTEXT_PACKAGE);
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", err->message);
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  /* unmangle libtool if necessary */
-  unmangle_libtool (&dir, &base);
-
-#ifdef G_OS_WIN32
-  /* remove .exe suffix, otherwise we'll be looking for gst-blah.exe-*.* */
-  if (strlen (base) > 4 && g_str_has_suffix (base, ".exe")) {
-    base[strlen (base) - 4] = '\0';
-  }
-#endif
-
-  /* get all candidate binaries */
-  candidates = get_candidates (dir, base);
-  g_free (dir);
-
-  /* only look for 0.10, we don't want 0.11 tools to be picked up accidentally
-   * (and from 0.11 on the unversioned tools are discontinued anyway) */
-  if (_arg_mm == NULL)
-    _arg_mm = GST_MAJORMINOR;
-
-  if (_arg_mm) {
-    /* if a version was forced, look it up in the hash table */
-    dir = g_hash_table_lookup (candidates, _arg_mm);
-    if (!dir) {
-      g_print ("ERROR: Major/minor %s of tool %s not found.\n", _arg_mm, base);
-      return 1;
-    }
-    binary = g_strdup_printf ("%s-%s", base, _arg_mm);
-  } else {
-    highest = NULL;
-
-    /* otherwise, just look up the highest version */
-    if (candidates) {
-      g_hash_table_foreach (candidates, (GHFunc) find_highest_version,
-          &highest);
-    }
-
-    if (highest == NULL) {
-      g_print ("ERROR: No version of tool %s found.\n", base);
-      return 1;
-    }
-    dir = g_hash_table_lookup (candidates, highest);
-    binary = g_strdup_printf ("%s-%s", base, highest);
-  }
-
-  g_free (base);
-
-  path = g_build_filename (dir, binary, NULL);
-  g_free (binary);
-
-  /* print out list of major/minors we found if asked for */
-  /* FIXME: do them in order by creating a GList of keys and sort them */
-  if (_arg_list_mm) {
-    g_hash_table_foreach (candidates, (GHFunc) hash_print_key, NULL);
-    g_hash_table_destroy (candidates);
-    return 0;
-  }
-
-  /* print out command line if asked for */
-  argv[0] = path;
-  if (_print) {
-    int i;
-
-    for (i = 0; i < argc; ++i) {
-      g_print ("%s", argv[i]);
-      if (i < argc - 1)
-        g_print (" ");
-    }
-    g_print ("\n");
-  }
-
-  /* execute */
-  if (execv (path, argv) == -1) {
-    g_warning ("Error executing %s: %s (%d)", path, g_strerror (errno), errno);
-  }
-  g_free (path);
-
-  return 0;
-}
index 123f395..a466859 100644 (file)
@@ -153,10 +153,6 @@ main (int argc, char *argv[])
   textdomain (GETTEXT_PACKAGE);
 #endif
 
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_thread_init (NULL);
-#endif
-
   gst_tools_set_prgname ("gst-typefind");
 
   ctx = g_option_context_new ("FILES");
diff --git a/tools/gst-xmlinspect.1.in b/tools/gst-xmlinspect.1.in
deleted file mode 100644 (file)
index 41323a8..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-.TH GStreamer 1 "March 2001"
-.SH "NAME"
-gst\-xmlinspect - print info about a GStreamer plugin or element
-.SH "SYNOPSIS"
-.B  gst\-xmlinspect [OPTION...] [PLUGIN|ELEMENT]
-.SH "DESCRIPTION"
-.PP
-\fIgst\-xmlinspect\fP is a tool that prints out information on
-available \fIGStreamer\fP plugins, information about a particular
-plugin, or information about a particular element.  When executed
-with no PLUGIN or ELEMENT argument, \fIgst\-xmlinspect\fP will print
-a list of all plugins and elements.  When executed with a PLUGIN
-or ELEMENT argument, \fIgst\-xmlinspect\fP will print information
-about that plug-in or element as an XML document.
-.
-.SH "OPTIONS"
-.l
-\fIgst\-xmlinspect\fP accepts the following arguments and options:
-.TP 8
-.B  PLUGIN
-Name of a plugin
-.TP 8
-.B  ELEMENT
-Name of an element
-.TP 8
-.B  \-\-help
-Print help synopsis and available FLAGS
-.TP 8
-.B  \-\-gst\-info\-mask=FLAGS
-\fIGStreamer\fP info flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-debug\-mask=FLAGS
-\fIGStreamer\fP debugging flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-mask=FLAGS
-\fIGStreamer\fP info and debugging flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-plugin\-spew
-\fIGStreamer\fP info flags to set
-Enable printout of errors while loading \fIGStreamer\fP plugins
-.TP 8
-.B  \-\-gst\-plugin\-path=PATH
-Add directories separated with ':' to the plugin search path
-.
-.SH "SEE ALSO"
-.BR gst\-feedback (1),
-.BR gst\-inspect (1),
-.BR gst\-launch (1),
-.BR gst\-typefind (1)
-.SH "AUTHOR"
-The GStreamer team at http://gstreamer.freedesktop.org/
diff --git a/tools/gst-xmlinspect.c b/tools/gst-xmlinspect.c
deleted file mode 100644 (file)
index af3bb7f..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-/* GStreamer gst-xmlinspect
- * Copyright (C) 2003 Wim Taymans <wtay@chello.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* FIXME 0.11: remove gst-xmlinspect and gst-feedback etc. */
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <string.h>
-#include <locale.h>
-#include <glib/gprintf.h>
-
-#include "tools.h"
-
-#define PUT_START_TAG(pfx,tag)                                  \
-G_STMT_START{                                                   \
-  g_print ("%*.*s<%s>\n", pfx, pfx, "", tag);                   \
-}G_STMT_END
-
-#define PUT_END_TAG(pfx,tag)                                    \
-G_STMT_START{                                                   \
-  g_print ("%*.*s</%s>\n", pfx, pfx, "", tag);                  \
-}G_STMT_END
-
-#define PUT_ESCAPED(pfx,tag,value)                              \
-G_STMT_START{                                                   \
-  const gchar *toconv = value;                                  \
-  if (value) {                                                  \
-    gchar *v = g_markup_escape_text (toconv, strlen (toconv));  \
-    g_print ("%*.*s<%s>%s</%s>\n", pfx, pfx, "", tag, v, tag);  \
-    g_free (v);                                                 \
-  }                                                             \
-}G_STMT_END
-
-#ifdef G_HAVE_ISO_VARARGS
-
-#define PUT_STRING(pfx, ...)                                    \
-G_STMT_START{                                                   \
-  gchar *ps_val = g_strdup_printf(__VA_ARGS__);                 \
-  g_print ("%*.*s%s\n", pfx, pfx, "", ps_val);                  \
-  g_free(ps_val);                                               \
-}G_STMT_END
-
-#elif defined(G_HAVE_GNUC_VARARGS)
-
-#define PUT_STRING(pfx, str, a...)                              \
-G_STMT_START{                                                   \
-  g_print ("%*.*s"str"\n", pfx, pfx, "" , ##a);                 \
-}G_STMT_END
-
-#else
-
-static inline void
-PUT_STRING (int pfx, const char *format, ...)
-{
-  va_list varargs;
-
-  g_print ("%*.*s", pfx, pfx, "");
-  va_start (varargs, format);
-  g_vprintf (format, varargs);
-  va_end (varargs);
-  g_print ("\n");
-}
-
-#endif
-
-static void
-print_caps (const GstCaps * caps, gint pfx)
-{
-  char *s;
-
-  if (!caps)
-    return;
-
-  s = gst_caps_to_string (caps);
-  PUT_ESCAPED (pfx, "caps", s);
-  g_free (s);
-}
-
-#if 0
-static void
-print_formats (const GstFormat * formats, gint pfx)
-{
-  while (formats && *formats) {
-    const GstFormatDefinition *definition;
-
-    definition = gst_format_get_details (*formats);
-    if (definition)
-      PUT_STRING (pfx, "<format id=\"%d\" nick=\"%s\">%s</format>",
-          *formats, definition->nick, definition->description);
-    else
-      PUT_STRING (pfx, "<format id=\"%d\">unknown</format>", *formats);
-
-    formats++;
-  }
-}
-#endif
-
-static void
-print_query_types (const GstQueryType * types, gint pfx)
-{
-  while (types && *types) {
-    const GstQueryTypeDefinition *definition;
-
-    definition = gst_query_type_get_details (*types);
-    if (definition)
-      PUT_STRING (pfx, "<query-type id=\"%d\" nick=\"%s\">%s</query-type>",
-          *types, definition->nick, definition->description);
-    else
-      PUT_STRING (pfx, "<query-type id=\"%d\">unknown</query-type>", *types);
-
-    types++;
-  }
-}
-
-#if 0
-static void
-print_event_masks (const GstEventMask * masks, gint pfx)
-{
-  GType event_type;
-  GEnumClass *klass;
-  GType event_flags;
-  GFlagsClass *flags_class = NULL;
-
-  event_type = gst_event_type_get_type ();
-  klass = (GEnumClass *) g_type_class_ref (event_type);
-
-  while (masks && masks->type) {
-    GEnumValue *value;
-    gint flags = 0, index = 0;
-
-    switch (masks->type) {
-      case GST_EVENT_SEEK:
-        flags = masks->flags;
-        event_flags = gst_seek_type_get_type ();
-        flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
-        break;
-      default:
-        break;
-    }
-
-    value = g_enum_get_value (klass, masks->type);
-    PUT_STRING (pfx, "<event type=\"%s\">", value->value_nick);
-
-    while (flags) {
-      GFlagsValue *value;
-
-      if (flags & 1) {
-        value = g_flags_get_first_value (flags_class, 1 << index);
-
-        if (value)
-          PUT_ESCAPED (pfx + 1, "flag", value->value_nick);
-        else
-          PUT_ESCAPED (pfx + 1, "flag", "?");
-      }
-      flags >>= 1;
-      index++;
-    }
-    PUT_END_TAG (pfx, "event");
-
-    masks++;
-  }
-}
-#endif
-
-static void
-output_hierarchy (GType type, gint level, gint * maxlevel)
-{
-  GType parent;
-
-  parent = g_type_parent (type);
-
-  *maxlevel = *maxlevel + 1;
-  level++;
-
-  PUT_STRING (level, "<object name=\"%s\">", g_type_name (type));
-
-  if (parent)
-    output_hierarchy (parent, level, maxlevel);
-
-  PUT_END_TAG (level, "object");
-}
-
-static void
-print_element_properties (GstElement * element, gint pfx)
-{
-  GParamSpec **property_specs;
-  guint num_properties;
-  gint i;
-  gboolean readable;
-
-  property_specs = g_object_class_list_properties
-      (G_OBJECT_GET_CLASS (element), &num_properties);
-
-  PUT_START_TAG (pfx, "element-properties");
-
-  for (i = 0; i < num_properties; i++) {
-    GValue value = { 0, };
-    GParamSpec *param = property_specs[i];
-
-    readable = FALSE;
-
-    g_value_init (&value, param->value_type);
-    if (param->flags & G_PARAM_READABLE) {
-      g_object_get_property (G_OBJECT (element), param->name, &value);
-      readable = TRUE;
-    }
-    PUT_START_TAG (pfx + 1, "element-property");
-    PUT_ESCAPED (pfx + 2, "name", g_param_spec_get_name (param));
-    PUT_ESCAPED (pfx + 2, "type", g_type_name (param->value_type));
-    PUT_ESCAPED (pfx + 2, "nick", g_param_spec_get_nick (param));
-    PUT_ESCAPED (pfx + 2, "blurb", g_param_spec_get_blurb (param));
-    if (readable) {
-      PUT_ESCAPED (pfx + 2, "flags", "RW");
-    } else {
-      PUT_ESCAPED (pfx + 2, "flags", "W");
-    }
-
-    switch (G_VALUE_TYPE (&value)) {
-      case G_TYPE_STRING:
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      case G_TYPE_BOOLEAN:
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      case G_TYPE_ULONG:
-      {
-        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%lu\" max=\"%lu\"/>",
-            pulong->minimum, pulong->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_LONG:
-      {
-        GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%ld\" max=\"%ld\"/>",
-            plong->minimum, plong->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_UINT:
-      {
-        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%u\" max=\"%u\"/>",
-            puint->minimum, puint->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_INT:
-      {
-        GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%d\" max=\"%d\"/>",
-            pint->minimum, pint->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_UINT64:
-      {
-        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
-
-        PUT_STRING (pfx + 2,
-            "<range min=\"%" G_GUINT64_FORMAT "\" max=\"%" G_GUINT64_FORMAT
-            "\"/>", puint64->minimum, puint64->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_INT64:
-      {
-        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
-
-        PUT_STRING (pfx + 2,
-            "<range min=\"%" G_GINT64_FORMAT "\" max=\"%" G_GINT64_FORMAT
-            "\"/>", pint64->minimum, pint64->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_FLOAT:
-      {
-        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%f\" max=\"%f\"/>",
-            pfloat->minimum, pfloat->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      case G_TYPE_DOUBLE:
-      {
-        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
-
-        PUT_STRING (pfx + 2, "<range min=\"%g\" max=\"%g\"/>",
-            pdouble->minimum, pdouble->maximum);
-        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
-        break;
-      }
-      default:
-        if (param->value_type == GST_TYPE_CAPS) {
-          GstCaps *caps = g_value_peek_pointer (&value);
-
-          if (!caps)
-            PUT_ESCAPED (pfx + 2, "default", "NULL");
-          else {
-            print_caps (caps, 2);
-          }
-        } else if (G_IS_PARAM_SPEC_ENUM (param)) {
-          GEnumValue *values;
-          guint j = 0;
-          gint enum_value;
-
-          values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
-          enum_value = g_value_get_enum (&value);
-
-          while (values[j].value_name) {
-            if (values[j].value == enum_value)
-              break;
-            j++;
-          }
-          PUT_STRING (pfx + 2, "<default>%d</default>", values[j].value);
-
-          PUT_START_TAG (pfx + 2, "enum-values");
-          j = 0;
-          while (values[j].value_name) {
-            PUT_STRING (pfx + 3, "<value value=\"%d\" nick=\"%s\"/>",
-                values[j].value, values[j].value_nick);
-            j++;
-          }
-          PUT_END_TAG (pfx + 2, "enum-values");
-        } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
-          GFlagsValue *values;
-          guint j = 0;
-          gint flags_value;
-
-          values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
-          flags_value = g_value_get_flags (&value);
-
-          PUT_STRING (pfx + 2, "<default>%d</default>", flags_value);
-
-          PUT_START_TAG (pfx + 2, "flags");
-          j = 0;
-          while (values[j].value_name) {
-            PUT_STRING (pfx + 3, "<flag value=\"%d\" nick=\"%s\"/>",
-                values[j].value, values[j].value_nick);
-            j++;
-          }
-          PUT_END_TAG (pfx + 2, "flags");
-        } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
-          PUT_ESCAPED (pfx + 2, "object-type", g_type_name (param->value_type));
-        }
-        break;
-    }
-
-    PUT_END_TAG (pfx + 1, "element-property");
-  }
-  PUT_END_TAG (pfx, "element-properties");
-  g_free (property_specs);
-}
-
-static void
-print_element_signals (GstElement * element, gint pfx)
-{
-  guint *signals;
-  guint nsignals;
-  gint i, k;
-  GSignalQuery *query;
-
-  signals = g_signal_list_ids (G_OBJECT_TYPE (element), &nsignals);
-  for (k = 0; k < 2; k++) {
-    gint counted = 0;
-
-    if (k == 0)
-      PUT_START_TAG (pfx, "element-signals");
-    else
-      PUT_START_TAG (pfx, "element-actions");
-
-    for (i = 0; i < nsignals; i++) {
-      gint n_params;
-      GType return_type;
-      const GType *param_types;
-      gint j;
-
-      query = g_new0 (GSignalQuery, 1);
-      g_signal_query (signals[i], query);
-
-      if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
-          (k == 1 && (query->signal_flags & G_SIGNAL_ACTION))) {
-        n_params = query->n_params;
-        return_type = query->return_type;
-        param_types = query->param_types;
-
-        PUT_START_TAG (pfx + 1, "signal");
-        PUT_ESCAPED (pfx + 2, "name", query->signal_name);
-        PUT_ESCAPED (pfx + 2, "return-type", g_type_name (return_type));
-        PUT_ESCAPED (pfx + 2, "object-type",
-            g_type_name (G_OBJECT_TYPE (element)));
-
-        PUT_START_TAG (pfx + 2, "params");
-        for (j = 0; j < n_params; j++) {
-          PUT_ESCAPED (pfx + 3, "type", g_type_name (param_types[j]));
-        }
-
-        PUT_END_TAG (pfx + 2, "params");
-
-        PUT_END_TAG (pfx + 1, "signal");
-
-        counted++;
-      }
-
-      g_free (query);
-    }
-    if (k == 0)
-      PUT_END_TAG (pfx, "element-signals");
-    else
-      PUT_END_TAG (pfx, "element-actions");
-  }
-}
-
-static gint
-print_element_info (GstElementFactory * factory)
-{
-  GstElement *element;
-#ifndef GST_DISABLE_LOADSAVE
-  GstObjectClass *gstobject_class;
-#endif
-  GstElementClass *gstelement_class;
-  GList *pads;
-  GstPad *pad;
-  GstStaticPadTemplate *padtemplate;
-  gint maxlevel = 0;
-
-  element = gst_element_factory_create (factory, "element");
-  if (!element) {
-    g_print ("couldn't construct element for some reason\n");
-    return -1;
-  }
-  PUT_START_TAG (0, "element");
-  PUT_ESCAPED (1, "name", GST_PLUGIN_FEATURE_NAME (factory));
-
-#ifndef GST_DISABLE_LOADSAVE
-  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
-#endif
-  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
-
-  PUT_START_TAG (1, "details");
-  PUT_ESCAPED (2, "long-name", factory->details.longname);
-  PUT_ESCAPED (2, "class", factory->details.klass);
-  PUT_ESCAPED (2, "description", factory->details.description);
-  PUT_ESCAPED (2, "authors", factory->details.author);
-  PUT_END_TAG (1, "details");
-
-  output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
-
-  PUT_START_TAG (1, "pad-templates");
-  if (factory->numpadtemplates) {
-    pads = factory->staticpadtemplates;
-    while (pads) {
-      padtemplate = (GstStaticPadTemplate *) (pads->data);
-      pads = g_list_next (pads);
-
-      PUT_START_TAG (2, "pad-template");
-      PUT_ESCAPED (3, "name", padtemplate->name_template);
-
-      if (padtemplate->direction == GST_PAD_SRC)
-        PUT_ESCAPED (3, "direction", "src");
-      else if (padtemplate->direction == GST_PAD_SINK)
-        PUT_ESCAPED (3, "direction", "sink");
-      else
-        PUT_ESCAPED (3, "direction", "unknown");
-
-      if (padtemplate->presence == GST_PAD_ALWAYS)
-        PUT_ESCAPED (3, "presence", "always");
-      else if (padtemplate->presence == GST_PAD_SOMETIMES)
-        PUT_ESCAPED (3, "presence", "sometimes");
-      else if (padtemplate->presence == GST_PAD_REQUEST) {
-        PUT_ESCAPED (3, "presence", "request");
-        PUT_ESCAPED (3, "request-function",
-            GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
-      } else
-        PUT_ESCAPED (3, "presence", "unknown");
-
-      if (padtemplate->static_caps.string) {
-        print_caps (gst_static_caps_get (&padtemplate->static_caps), 3);
-      }
-      PUT_END_TAG (2, "pad-template");
-    }
-  }
-  PUT_END_TAG (1, "pad-templates");
-
-  PUT_START_TAG (1, "element-flags");
-  PUT_END_TAG (1, "element-flags");
-
-  if (GST_IS_BIN (element)) {
-    PUT_START_TAG (1, "bin-flags");
-
-    PUT_END_TAG (1, "bin-flags");
-  }
-
-
-  PUT_START_TAG (1, "element-implementation");
-
-  PUT_STRING (2, "<state-change function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
-
-#ifndef GST_DISABLE_LOADSAVE
-  PUT_STRING (2, "<save function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
-  PUT_STRING (2, "<load function=\"%s\"/>",
-      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
-#endif
-  PUT_END_TAG (1, "element-implementation");
-
-  PUT_START_TAG (1, "clocking-interaction");
-  if (gst_element_requires_clock (element)) {
-    PUT_STRING (2, "<requires-clock/>");
-  }
-  if (gst_element_provides_clock (element)) {
-    GstClock *clock;
-
-    clock = gst_element_get_clock (element);
-    if (clock)
-      PUT_STRING (2, "<provides-clock name=\"%s\"/>", GST_OBJECT_NAME (clock));
-  }
-  PUT_END_TAG (1, "clocking-interaction");
-
-  if (gst_element_is_indexable (element)) {
-    PUT_STRING (1, "<indexing-capabilities/>");
-  }
-
-  PUT_START_TAG (1, "pads");
-  if (element->numpads) {
-    const GList *pads;
-
-    pads = element->pads;
-    while (pads) {
-      pad = GST_PAD (pads->data);
-      pads = g_list_next (pads);
-
-      PUT_START_TAG (2, "pad");
-      PUT_ESCAPED (3, "name", gst_pad_get_name (pad));
-
-      if (gst_pad_get_direction (pad) == GST_PAD_SRC)
-        PUT_ESCAPED (3, "direction", "src");
-      else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
-        PUT_ESCAPED (3, "direction", "sink");
-      else
-        PUT_ESCAPED (3, "direction", "unknown");
-
-      if (pad->padtemplate)
-        PUT_ESCAPED (3, "template", pad->padtemplate->name_template);
-
-      PUT_START_TAG (3, "implementation");
-      if (pad->chainfunc)
-        PUT_STRING (4, "<chain-based function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
-      if (pad->getrangefunc)
-        PUT_STRING (4, "<get-range-based function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
-      if (pad->eventfunc != gst_pad_event_default)
-        PUT_STRING (4, "<event-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
-      if (pad->queryfunc != gst_pad_query_default)
-        PUT_STRING (4, "<query-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
-      if (pad->querytypefunc != gst_pad_get_query_types_default) {
-        PUT_STRING (4, "<query-type-func function=\"%s\">",
-            GST_DEBUG_FUNCPTR_NAME (pad->querytypefunc));
-        print_query_types (gst_pad_get_query_types (pad), 5);
-        PUT_END_TAG (4, "query-type-func");
-      }
-
-      if (pad->iterintlinkfunc != gst_pad_iterate_internal_links_default)
-        PUT_STRING (4, "<iterintlink-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));
-
-      if (pad->bufferallocfunc)
-        PUT_STRING (4, "<bufferalloc-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
-      PUT_END_TAG (3, "implementation");
-
-      if (pad->caps) {
-        print_caps (pad->caps, 3);
-      }
-      PUT_END_TAG (2, "pad");
-    }
-  }
-  PUT_END_TAG (1, "pads");
-
-  print_element_properties (element, 1);
-  print_element_signals (element, 1);
-
-  /* for compound elements */
-  /* FIXME: gst_bin_get_list does not exist anymore
-     if (GST_IS_BIN (element)) {
-     GList *children;
-     GstElement *child;
-     PUT_START_TAG (1, "children");
-     children = (GList *) gst_bin_get_list (GST_BIN (element));
-     while (children) {
-     child = GST_ELEMENT (children->data);
-     children = g_list_next (children);
-
-     PUT_ESCAPED (2, "child", GST_ELEMENT_NAME (child));
-     }
-     PUT_END_TAG (1, "children");
-     }
-   */
-  PUT_END_TAG (0, "element");
-
-  return 0;
-}
-
-int
-main (int argc, char *argv[])
-{
-  GstElementFactory *factory;
-  GOptionEntry options[] = {
-    GST_TOOLS_GOPTION_VERSION,
-    {NULL}
-  };
-  GOptionContext *ctx;
-  GError *err = NULL;
-
-  setlocale (LC_ALL, "");
-
-#if !GLIB_CHECK_VERSION (2, 31, 0)
-  g_thread_init (NULL);
-#endif
-
-  gst_tools_set_prgname ("gst-xmlinspect");
-
-  ctx = g_option_context_new ("[ELEMENT-NAME]");
-  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
-  g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
-    g_print ("Error initializing: %s\n", err->message);
-    exit (1);
-  }
-  g_option_context_free (ctx);
-
-  gst_tools_print_version ("gst-xmlinspect");
-
-  /* if no arguments, print out all elements */
-  if (argc == 1) {
-    GList *features, *f;
-
-    features = gst_registry_get_feature_list (gst_registry_get_default (),
-        GST_TYPE_ELEMENT_FACTORY);
-
-    PUT_STRING (0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
-
-    for (f = features; f != NULL; f = f->next)
-      print_element_info (GST_ELEMENT_FACTORY (f->data));
-
-    gst_plugin_feature_list_free (features);
-    return 0;
-  }
-
-  /* else we try to get a factory */
-  factory = gst_element_factory_find (argv[1]);
-
-  /* if there's a factory, print out the info */
-  if (factory) {
-    PUT_STRING (0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
-    return print_element_info (factory);
-  }
-
-  /* otherwise, error out */
-  g_printerr ("no such element '%s'\n", argv[1]);
-  return -1;
-}
diff --git a/tools/gst-xmllaunch.1.in b/tools/gst-xmllaunch.1.in
deleted file mode 100644 (file)
index 9bf9012..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-.TH "GStreamer" "1" "March 2001"
-.SH "NAME"
-gst\-xmllaunch \- build and run a GStreamer pipeline from an XML serialization
-.SH "SYNOPSIS"
-\fBgst\-xmllaunch\fR \fI[OPTION...]\fR XML\-FILE [ ELEMENT.PROPERTY=VALUE ... ]
-.SH "DESCRIPTION"
-.LP 
-\fIgst\-xmllaunch\fP is a tool that is used to build and run a basic
-\fIGStreamer\fP pipeline, loading it from an XML description. You can
-produce the XML description using gst-launch(1) with the -o option or by
-calling gst_xml_write_file() in your own app.
-
-A simple commandline looks like:
-
- gst\-xmllaunch my\-pipeline.xml filesrc0.location=music.mp3
-
-This sets the location property of the element named filesrc0 to the value
-"music.mp3". See gst\-launch(1) for syntax on setting element names, and
-gst\-inspect to see what properties various elements have.
-
-You can pass "-" as the XML\-FILE to read from stdin.
-
-XML\-FILE can be a URI as well, thanks to the wizardry of libxml. I'm not really
-sure what all is supported, it seems http works just fine though.
-
-.
-.SH "WARNING"
-\fIgst\-xmllaunch\fP is deprecated and broken for all but the most simple
-pipelines. It will most likely be removed in future. Don't use it.
-.
-.SH "OPTIONS"
-.l
-\fIgst\-xmllaunch\fP accepts the following options:
-.TP 8
-.B  \-\-help
-Print help synopsis and available FLAGS
-.TP 8
-.B  \-\-silent
-Do not output status information
-.TP 8
-.B  \-\-exclude=TYPE, \-XTYPE
-Do not output status information of TYPE
-.TP 8
-.B  \-\-output=FILE, \-oFILE
-Save XML representation of pipeline to FILE and exit
-.TP 8
-.B  \-\-gst\-info\-mask=FLAGS
-\fIGStreamer\fP info flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-debug\-mask=FLAGS
-\fIGStreamer\fP debugging flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-mask=FLAGS
-\fIGStreamer\fP info and debugging flags to set (list with \-\-help)
-.TP 8
-.B  \-\-gst\-plugin\-spew
-\fIGStreamer\fP info flags to set
-Enable printout of errors while loading \fIGStreamer\fP plugins
-.TP 8
-.B  \-\-gst\-plugin\-path=PATH
-Add directories separated with ':' to the plugin search path
-.
-.SH "SEE ALSO"
-.BR gst\-feedback (1),
-.BR gst\-inspect (1),
-.BR gst\-launch (1),
-.BR gst\-typefind (1)
-.SH "AUTHOR"
-The GStreamer team at http://gstreamer.freedesktop.org/
index 8770bd4..d85e49c 100644 (file)
@@ -6,8 +6,8 @@ _gst_launch()
 {
   local cur
 
-  : ${GST_REGISTRY:=~/.gstreamer-0.10/registry.xml}
-  : ${GST_COMPLETE:=~/.gstreamer-0.10/complete}
+  : ${GST_REGISTRY:=~/.gstreamer-0.11/registry.xml}
+  : ${GST_COMPLETE:=~/.gstreamer-0.11/complete}
 
   if [ ! -f "${GST_REGISTRY}" ] ; then
     return 0
diff --git a/tools/xml2text.xsl b/tools/xml2text.xsl
deleted file mode 100644 (file)
index 6797ee5..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-
- <xsl:output method="text" encoding="us-ascii" omit-xml-declaration="yes" indent="no"/>
- <xsl:variable name="padding" select="string('                              ')"/>
-
- <xsl:template match="/element">
-  <xsl:apply-templates select="name"/>
-  <xsl:apply-templates select="details"/>
-  <xsl:apply-templates select="object"/>
-  <xsl:apply-templates select="pad-templates"/>
-  <xsl:apply-templates select="element-flags"/>
-  <xsl:apply-templates select="element-implementation"/>
-  <xsl:apply-templates select="clocking-interaction"/>
-  <xsl:apply-templates select="indexing-capabilities"/>
-  <xsl:apply-templates select="pads"/>
-  <xsl:apply-templates select="element-properties"/>
-  <xsl:apply-templates select="dyn-params"/>
-  <xsl:apply-templates select="element-signals"/>
-  <xsl:apply-templates select="element-actions"/>
- </xsl:template>
-
- <xsl:template match="name">
-  <xsl:text>Element Name: </xsl:text><xsl:value-of select="."/>
-  <xsl:text>&#10;&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="details">
-  <xsl:text>Factory Details:&#10;</xsl:text> 
-  <xsl:text>  Long Name:&#9;</xsl:text>   <xsl:value-of select="long-name"/>   <xsl:text>&#10;</xsl:text>
-  <xsl:text>  Class:&#9;</xsl:text>       <xsl:value-of select="class"/>       <xsl:text>&#10;</xsl:text>
-  <xsl:text>  License:&#9;</xsl:text>     <xsl:value-of select="license"/>     <xsl:text>&#10;</xsl:text>
-  <xsl:text>  Description:&#9;</xsl:text> <xsl:value-of select="description"/> <xsl:text>&#10;</xsl:text>
-  <xsl:text>  Version:&#9;</xsl:text>     <xsl:value-of select="version"/>     <xsl:text>&#10;</xsl:text>
-  <xsl:text>  Author(s):&#9;</xsl:text>   <xsl:value-of select="authors"/>     <xsl:text>&#10;</xsl:text>
-  <xsl:text>  Copyright:&#9;</xsl:text>   <xsl:value-of select="copyright"/>   <xsl:text>&#10;</xsl:text>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template name="object">
-  <xsl:param name="i"/>
-  <xsl:param name="j"/>
-  <xsl:if test="count($i/*) &gt; 0">
-   <xsl:call-template name="object">
-    <xsl:with-param name="i" select="$i/object"/>
-    <xsl:with-param name="j" select="$j - 1"/>
-   </xsl:call-template>
-   <xsl:value-of select="substring ($padding, 1, $j * 6)"/> 
-   <xsl:text> +----</xsl:text>
-  </xsl:if>
-  <xsl:value-of select="$i/@name"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="object">
-  <xsl:call-template name="object">
-   <xsl:with-param name="i" select="."/>
-   <xsl:with-param name="j" select="count(.//object[(*)])"/>
-  </xsl:call-template>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="pad-templates">
-  <xsl:text>Pad Templates&#10;</xsl:text>
-  <xsl:apply-templates select="./pad-template"/>
- </xsl:template>
-
- <xsl:template match="pad-template">
-  <xsl:text>  </xsl:text>
-  <xsl:value-of select="direction"/> 
-  <xsl:text> template: </xsl:text>
-  <xsl:value-of select="name"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:text>    Availability: </xsl:text> <xsl:value-of select="presence"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:text>    Capabilities:&#10; </xsl:text> <xsl:apply-templates select="./capscomp"/>
- </xsl:template>
-
- <xsl:template match="capscomp">
-  <xsl:apply-templates select="./caps"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="caps">
-  <xsl:text>     '</xsl:text>
-  <xsl:value-of select="name"/>
-  <xsl:text>'&#10;</xsl:text>
-  <xsl:text>        MIME type: </xsl:text>
-  <xsl:value-of select="type"/>
-  <xsl:text>'&#10;</xsl:text>
-  <xsl:apply-templates select="./properties"/>
- </xsl:template>
-
- <xsl:template match="properties">
-  <xsl:apply-templates select="*"/>
- </xsl:template>
-
- <xsl:template match="list">
-  <xsl:text>        </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>&#9;:List&#10;</xsl:text>
-  <xsl:apply-templates select="*" mode="list"/>
- </xsl:template>
-
- <!-- propety entries in list mode -->
- <xsl:template match="string" mode="list">
-  <xsl:text>         String: '</xsl:text>
-  <xsl:value-of select="@value"/>
-  <xsl:text>'&#10;</xsl:text>
- </xsl:template>
- <xsl:template match="fourcc" mode="list">
-  <xsl:text>         FourCC: '</xsl:text>
-  <xsl:value-of select="@hexvalue"/>
-  <xsl:text>'&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="int" mode="list">
-  <xsl:text>         Integer: </xsl:text>
-  <xsl:value-of select="@value"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="range" mode="list">
-  <xsl:text>         Integer range: </xsl:text>
-  <xsl:value-of select="concat(@min, ' - ', @max)"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="float" mode="list">
-  <xsl:text>         Float: </xsl:text>
-  <xsl:value-of select="@value"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="floatrange" mode="list">
-  <xsl:text>         Float range: </xsl:text>
-  <xsl:value-of select="concat(@min, ' - ', @max)"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <!-- propety entries in normal mode -->
- <xsl:template match="string">
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : String: '</xsl:text>
-  <xsl:value-of select="@value"/> 
-  <xsl:text>'&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="fourcc">
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : FourCC: '</xsl:text>
-  <xsl:value-of select="@hexvalue"/> 
-  <xsl:text>'&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="int">
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : Integer: </xsl:text>
-  <xsl:value-of select="@value"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="range">          
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : Integer range: </xsl:text>
-  <xsl:value-of select="concat(@min, ' - ', @max)"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="float">
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : Float: </xsl:text>
-  <xsl:value-of select="@value"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="floatrange">             
-  <xsl:text>         </xsl:text>
-  <xsl:value-of select="substring (concat (@name, $padding), 1, 15)"/>
-  <xsl:text>     : Float range: </xsl:text>
-  <xsl:value-of select="concat(@min, ' - ', @max)"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="flag">
-  <xsl:text>  </xsl:text>
-  <xsl:value-of select="."/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="element-flags">
-  <xsl:text>Element Flags:&#10;</xsl:text>
-  <xsl:apply-templates select="./flag"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="state-change">
-  <xsl:text>  Has change_state() function: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="load">
-  <xsl:text>  Has custom restore_thyself() function: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="save">
-  <xsl:text>  Has custom save_thyself() function: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="element-implementation">
-  <xsl:text>Element Implementation:&#10;</xsl:text>
-  <xsl:apply-templates select="*"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="requires-clock">
-  <xsl:text>   element requires a clock&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="provides-clock">
-  <xsl:text>   element provides a clock: </xsl:text>
-  <xsl:value-of select="@name"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="clocking-interaction">
-  <xsl:text>Clocking Interaction:&#10;</xsl:text>
-  <xsl:choose>
-   <xsl:when test="count(*) = 0">
-    <xsl:text>  none&#10;</xsl:text>
-   </xsl:when>
-   <xsl:otherwise>
-    <xsl:apply-templates select="*"/>
-   </xsl:otherwise>
-  </xsl:choose>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="indexing-capabilities">
-  <xsl:text>   element can do indexing</xsl:text>
- </xsl:template>
-
- <xsl:template match="dyn-params">
-  <xsl:text>Dynamic Parameters:&#10;</xsl:text>
-  <xsl:choose>
-   <xsl:when test="count(*) = 0">
-    <xsl:text>  none&#10;</xsl:text>
-   </xsl:when>
-   <xsl:otherwise>
-    <xsl:apply-templates select="dyn-param"/>
-   </xsl:otherwise>
-  </xsl:choose>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="pads">
-  <xsl:text>Pads:&#10;</xsl:text>
-  <xsl:apply-templates select="pad"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="pad">
-  <xsl:text>  </xsl:text>
-  <xsl:value-of select="direction"/> 
-  <xsl:text>: '</xsl:text>
-  <xsl:value-of select="name"/>
-  <xsl:text>'&#10;</xsl:text>
-  <xsl:apply-templates select="implementation"/>
-  <xsl:text>    Pad Template: '</xsl:text>
-  <xsl:value-of select="template"/>
-  <xsl:text>'&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="implementation">
-  <xsl:text>    Implementation:&#10;</xsl:text>
-  <xsl:apply-templates select="*"/>
- </xsl:template>
-
- <xsl:template match="chain-based">
-  <xsl:text>      Has chainfunc(): </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="bufferpool-function">
-  <xsl:text>      Has bufferpoolfunc(): </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="format">
-  <xsl:text>                (</xsl:text>
-  <xsl:value-of select="@id"/>
-  <xsl:text>)&#9;</xsl:text>
-  <xsl:value-of select="@nick"/>
-  <xsl:text> (</xsl:text>
-  <xsl:value-of select="."/>
-  <xsl:text>)&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="formats-function">
-  <xsl:text>      Supports seeking/conversion/query formats: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:apply-templates select="format"/>
- </xsl:template>
-
- <xsl:template match="convert-function">
-  <xsl:text>      Has custom convertfunc(): </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="query-function">
-  <xsl:text>      Has custom queryfunc(): </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="event-function">
-  <xsl:text>      Has custom eventfunc(): </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="event">
-  <xsl:text>                </xsl:text>
-  <xsl:value-of select="@type"/>
-  <xsl:for-each select="flag">
-   <xsl:text> | </xsl:text>
-   <xsl:value-of select='.'/>
-  </xsl:for-each>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="event-mask-func">
-  <xsl:text>        Provides event masks: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:apply-templates select="event"/>
- </xsl:template>
-
- <xsl:template match="query-type">
-  <xsl:text>                (</xsl:text>
-  <xsl:value-of select="@id"/>
-  <xsl:text>)&#9;</xsl:text>
-  <xsl:value-of select="@nick"/>
-  <xsl:text> (</xsl:text>
-  <xsl:value-of select="."/>
-  <xsl:text>)&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="query-type-func">
-  <xsl:text>        Provides query types: </xsl:text>
-  <xsl:value-of select="@function"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:apply-templates select="query-type"/>
- </xsl:template>
-
- <xsl:template match="element-properties">
-  <xsl:text>Element Arguments:&#10;</xsl:text>
-  <xsl:apply-templates select="element-property"/>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="default">
-  <xsl:text>. (Default </xsl:text>
-  <xsl:value-of select="."/>
-  <xsl:text>)</xsl:text>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="range" mode="params">
-  <xsl:value-of select="substring ($padding, 1, 25)"/>
-  <xsl:text>Range : </xsl:text>
-  <xsl:value-of select="concat(@min, ' - ', @max)"/> 
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="element-property|dyn-param">
-  <xsl:text>  </xsl:text>
-  <xsl:value-of select="substring (concat(name, $padding), 1, 20)"/>
-  <xsl:text> : </xsl:text>
-  <xsl:value-of select="blurb"/>
-  <xsl:text>&#10;</xsl:text>
-  <xsl:value-of select="substring ($padding, 1, 25)"/>
-  <xsl:value-of select="type"/>
-  <xsl:apply-templates select="default"/>
-  <xsl:apply-templates select="range" mode="params"/>
- </xsl:template>
-
- <xsl:template match="params">
-  <xsl:for-each select="type">
-   <xsl:text>,&#10;</xsl:text>
-   <xsl:value-of select="substring ($padding, 1, 25)"/>
-   <xsl:value-of select="substring ($padding, 1, 20)"/>
-   <xsl:value-of select="."/>
-   <xsl:text> arg</xsl:text>
-   <xsl:value-of select="position()"/>
-  </xsl:for-each>
- </xsl:template>
-
- <xsl:template match="signal">
-  <xsl:value-of select="substring (concat('&quot;', name, '&quot;', $padding), 1, 25)"/>
-  <xsl:value-of select="return-type"/>
-  <xsl:text> user_function </xsl:text>
-  <xsl:value-of select="concat ('(', object-type, '* object')"/>
-  <xsl:apply-templates select="params"/>
- </xsl:template>
- <xsl:template match="element-signals">
-  <xsl:text>Element Signals:&#10;</xsl:text>
-  <xsl:choose>
-   <xsl:when test="count(*) = 0">
-    <xsl:text>  none&#10;</xsl:text>
-   </xsl:when>
-   <xsl:otherwise>
-    <xsl:for-each select="signal">
-     <xsl:apply-templates select="."/>
-     <xsl:text>,&#10;</xsl:text>
-     <xsl:value-of select="substring ($padding, 1, 25)"/>
-     <xsl:value-of select="substring ($padding, 1, 20)"/>
-     <xsl:text>gpointer user_data);&#10;</xsl:text>
-    </xsl:for-each>
-   </xsl:otherwise>
-  </xsl:choose>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="element-actions">
-  <xsl:text>Element Actions:&#10;</xsl:text>
-  <xsl:choose>
-   <xsl:when test="count(*) = 0">
-    <xsl:text>  none&#10;</xsl:text>
-   </xsl:when>
-   <xsl:otherwise>
-    <xsl:for-each select="signal">
-     <xsl:apply-templates select="."/>
-     <xsl:text>);&#10;</xsl:text>
-    </xsl:for-each>
-   </xsl:otherwise>
-  </xsl:choose>
-  <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
-</xsl:stylesheet>
index baf886e..f5d7fb9 100644 (file)
@@ -10,7 +10,6 @@ win32/common/gstversion.h
 win32/common/gtchar.h
 win32/common/libgstbase.def
 win32/common/libgstcontroller.def
-win32/common/libgstdataprotocol.def
 win32/common/libgstnet.def
 win32/common/libgstreamer.def
 win32/vs6/gstreamer.dsw
@@ -20,7 +19,6 @@ win32/vs6/gst_launch.dsp
 win32/vs6/libgstbase.dsp
 win32/vs6/libgstcontroller.dsp
 win32/vs6/libgstcoreelements.dsp
-win32/vs6/libgstdataprotocol.dsp
 win32/vs6/libgstnet.dsp
 win32/vs6/libgstreamer.dsp
 win32/vs7/gstreamer.sln
@@ -38,4 +36,4 @@ win32/vs8/gst-launch.vcproj
 win32/vs8/libgstbase.vcproj
 win32/vs8/libgstcontroller.vcproj
 win32/vs8/libgstcoreelements.vcproj
-win32/vs8/libgstreamer.vcproj
\ No newline at end of file
+win32/vs8/libgstreamer.vcproj
index af2c8e5..4b5233a 100644 (file)
@@ -9,15 +9,6 @@
 /* poll doesn't work on devices */
 #undef BROKEN_POLL
 
-/* Buffer alignment to use */
-#undef BUFFER_ALIGNMENT
-
-/* Buffer alignment by malloc default */
-#define BUFFER_ALIGNMENT_MALLOC 1
-
-/* Buffer alignment by pagesize */
-#undef BUFFER_ALIGNMENT_PAGESIZE
-
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
@@ -26,7 +17,7 @@
 #undef ENABLE_SUBUNIT
 
 /* gettext package name */
-#define GETTEXT_PACKAGE "gstreamer-0.10"
+#define GETTEXT_PACKAGE "gstreamer-0.11"
 
 /* data dir */
 #define GST_DATADIR PREFIX "\\share"
@@ -56,7 +47,7 @@
 #define GST_LICENSE "LGPL"
 
 /* library major.minor version */
-#define GST_MAJORMINOR "0.10"
+#define GST_MAJORMINOR "0.11"
 
 /* package name in plugins */
 #define GST_PACKAGE_NAME "GStreamer git"
@@ -65,7 +56,7 @@
 #define GST_PACKAGE_ORIGIN "Unknown package origin"
 
 /* GStreamer package release date/time for plugins as YYYY-MM-DD */
-#define GST_PACKAGE_RELEASE_DATETIME "2011-06-18T12:45Z"
+#define GST_PACKAGE_RELEASE_DATETIME "2011-09-29T14:59Z"
 
 /* location of the installed gst-plugin-scanner */
 #define GST_PLUGIN_SCANNER_INSTALLED LIBDIR "\\gst-plugin-scanner"
 /* Define to 1 if you have the `socket' library (-lsocket). */
 #undef HAVE_LIBSOCKET
 
-/* Define if libxml2 is available */
-#define HAVE_LIBXML2 1
-
 /* Define to 1 if you have the `localtime_r' function. */
 #undef HAVE_LOCALTIME_R
 
    */
 #undef LT_OBJDIR
 
+/* Memory alignment to use */
+#undef MEMORY_ALIGNMENT
+
+/* Memory alignment by malloc default */
+#define MEMORY_ALIGNMENT_MALLOC 1
+
+/* Memory alignment by pagesize */
+#undef MEMORY_ALIGNMENT_PAGESIZE
+
 /* Define if you have no native inet_aton() function. */
 #undef NO_INET_ATON
 
 #define PACKAGE_NAME "GStreamer"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer 0.10.35.1"
+#define PACKAGE_STRING "GStreamer 0.11.1.1"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "gstreamer"
 #undef PACKAGE_URL
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.35.1"
+#define PACKAGE_VERSION "0.11.1.1"
 
 /* directory where plugins are located */
 #ifdef _DEBUG
-#  define PLUGINDIR PREFIX "\\debug\\lib\\gstreamer-0.10"
+#  define PLUGINDIR PREFIX "\\debug\\lib\\gstreamer-0.11"
 #else
-#  define PLUGINDIR PREFIX "\\lib\\gstreamer-0.10"
+#  define PLUGINDIR PREFIX "\\lib\\gstreamer-0.11"
 #endif
 
 /* The size of `char', as computed by sizeof. */
 #undef USE_POISONING
 
 /* Version number of package */
-#define VERSION "0.10.35.1"
+#define VERSION "0.11.1.1"
 
 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
    significant byte first (like Motorola and SPARC, unlike Intel). */
index 7a0f5ae..3ec413a 100644 (file)
@@ -13,9 +13,7 @@ gst_object_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
-    {C_FLAGS (GST_OBJECT_DISPOSING), "GST_OBJECT_DISPOSING", "disposing"},
-    {C_FLAGS (GST_OBJECT_FLOATING), "GST_OBJECT_FLOATING", "floating"},
-    {C_FLAGS (GST_OBJECT_FLAG_LAST), "GST_OBJECT_FLAG_LAST", "flag-last"},
+    {C_FLAGS (GST_OBJECT_FLAG_LAST), "GST_OBJECT_FLAG_LAST", "last"},
     {0, NULL, NULL}
   };
 
@@ -47,28 +45,31 @@ gst_bin_flags_get_type (void)
 
 /* enumerations from "gstbuffer.h" */
 GType
-gst_buffer_flag_get_type (void)
+gst_buffer_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
-    {C_FLAGS (GST_BUFFER_FLAG_READONLY), "GST_BUFFER_FLAG_READONLY",
-        "readonly"},
-    {C_FLAGS (GST_BUFFER_FLAG_MEDIA4), "GST_BUFFER_FLAG_MEDIA4", "media4"},
-    {C_FLAGS (GST_BUFFER_FLAG_PREROLL), "GST_BUFFER_FLAG_PREROLL", "preroll"},
+    {C_FLAGS (GST_BUFFER_FLAG_LIVE), "GST_BUFFER_FLAG_LIVE", "live"},
+    {C_FLAGS (GST_BUFFER_FLAG_DECODE_ONLY), "GST_BUFFER_FLAG_DECODE_ONLY",
+        "decode-only"},
     {C_FLAGS (GST_BUFFER_FLAG_DISCONT), "GST_BUFFER_FLAG_DISCONT", "discont"},
-    {C_FLAGS (GST_BUFFER_FLAG_IN_CAPS), "GST_BUFFER_FLAG_IN_CAPS", "in-caps"},
+    {C_FLAGS (GST_BUFFER_FLAG_RESYNC), "GST_BUFFER_FLAG_RESYNC", "resync"},
+    {C_FLAGS (GST_BUFFER_FLAG_CORRUPTED), "GST_BUFFER_FLAG_CORRUPTED",
+        "corrupted"},
+    {C_FLAGS (GST_BUFFER_FLAG_MARKER), "GST_BUFFER_FLAG_MARKER", "marker"},
+    {C_FLAGS (GST_BUFFER_FLAG_HEADER), "GST_BUFFER_FLAG_HEADER", "header"},
     {C_FLAGS (GST_BUFFER_FLAG_GAP), "GST_BUFFER_FLAG_GAP", "gap"},
+    {C_FLAGS (GST_BUFFER_FLAG_DROPPABLE), "GST_BUFFER_FLAG_DROPPABLE",
+        "droppable"},
     {C_FLAGS (GST_BUFFER_FLAG_DELTA_UNIT), "GST_BUFFER_FLAG_DELTA_UNIT",
         "delta-unit"},
-    {C_FLAGS (GST_BUFFER_FLAG_MEDIA1), "GST_BUFFER_FLAG_MEDIA1", "media1"},
-    {C_FLAGS (GST_BUFFER_FLAG_MEDIA2), "GST_BUFFER_FLAG_MEDIA2", "media2"},
-    {C_FLAGS (GST_BUFFER_FLAG_MEDIA3), "GST_BUFFER_FLAG_MEDIA3", "media3"},
+    {C_FLAGS (GST_BUFFER_FLAG_IN_CAPS), "GST_BUFFER_FLAG_IN_CAPS", "in-caps"},
     {C_FLAGS (GST_BUFFER_FLAG_LAST), "GST_BUFFER_FLAG_LAST", "last"},
     {0, NULL, NULL}
   };
 
   if (g_once_init_enter (&id)) {
-    GType tmp = g_flags_register_static ("GstBufferFlag", values);
+    GType tmp = g_flags_register_static ("GstBufferFlags", values);
     g_once_init_leave (&id, tmp);
   }
 
@@ -80,10 +81,12 @@ gst_buffer_copy_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
+    {C_FLAGS (GST_BUFFER_COPY_NONE), "GST_BUFFER_COPY_NONE", "none"},
     {C_FLAGS (GST_BUFFER_COPY_FLAGS), "GST_BUFFER_COPY_FLAGS", "flags"},
     {C_FLAGS (GST_BUFFER_COPY_TIMESTAMPS), "GST_BUFFER_COPY_TIMESTAMPS",
         "timestamps"},
-    {C_FLAGS (GST_BUFFER_COPY_CAPS), "GST_BUFFER_COPY_CAPS", "caps"},
+    {C_FLAGS (GST_BUFFER_COPY_MEMORY), "GST_BUFFER_COPY_MEMORY", "memory"},
+    {C_FLAGS (GST_BUFFER_COPY_MERGE), "GST_BUFFER_COPY_MERGE", "merge"},
     {0, NULL, NULL}
   };
 
@@ -95,21 +98,25 @@ gst_buffer_copy_flags_get_type (void)
   return (GType) id;
 }
 
-/* enumerations from "gstbufferlist.h" */
+/* enumerations from "gstbufferpool.h" */
 GType
-gst_buffer_list_item_get_type (void)
+gst_buffer_pool_flags_get_type (void)
 {
   static gsize id = 0;
-  static const GEnumValue values[] = {
-    {C_ENUM (GST_BUFFER_LIST_CONTINUE), "GST_BUFFER_LIST_CONTINUE", "continue"},
-    {C_ENUM (GST_BUFFER_LIST_SKIP_GROUP), "GST_BUFFER_LIST_SKIP_GROUP",
-        "skip-group"},
-    {C_ENUM (GST_BUFFER_LIST_END), "GST_BUFFER_LIST_END", "end"},
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_BUFFER_POOL_FLAG_NONE), "GST_BUFFER_POOL_FLAG_NONE", "none"},
+    {C_FLAGS (GST_BUFFER_POOL_FLAG_KEY_UNIT), "GST_BUFFER_POOL_FLAG_KEY_UNIT",
+        "key-unit"},
+    {C_FLAGS (GST_BUFFER_POOL_FLAG_DONTWAIT), "GST_BUFFER_POOL_FLAG_DONTWAIT",
+        "dontwait"},
+    {C_FLAGS (GST_BUFFER_POOL_FLAG_DISCONT), "GST_BUFFER_POOL_FLAG_DISCONT",
+        "discont"},
+    {C_FLAGS (GST_BUFFER_POOL_FLAG_LAST), "GST_BUFFER_POOL_FLAG_LAST", "last"},
     {0, NULL, NULL}
   };
 
   if (g_once_init_enter (&id)) {
-    GType tmp = g_enum_register_static ("GstBufferListItem", values);
+    GType tmp = g_flags_register_static ("GstBufferPoolFlags", values);
     g_once_init_leave (&id, tmp);
   }
 
@@ -534,6 +541,7 @@ gst_event_type_flags_get_type (void)
         "downstream"},
     {C_FLAGS (GST_EVENT_TYPE_SERIALIZED), "GST_EVENT_TYPE_SERIALIZED",
         "serialized"},
+    {C_FLAGS (GST_EVENT_TYPE_STICKY), "GST_EVENT_TYPE_STICKY", "sticky"},
     {0, NULL, NULL}
   };
 
@@ -553,16 +561,18 @@ gst_event_type_get_type (void)
     {C_ENUM (GST_EVENT_UNKNOWN), "GST_EVENT_UNKNOWN", "unknown"},
     {C_ENUM (GST_EVENT_FLUSH_START), "GST_EVENT_FLUSH_START", "flush-start"},
     {C_ENUM (GST_EVENT_FLUSH_STOP), "GST_EVENT_FLUSH_STOP", "flush-stop"},
-    {C_ENUM (GST_EVENT_EOS), "GST_EVENT_EOS", "eos"},
-    {C_ENUM (GST_EVENT_NEWSEGMENT), "GST_EVENT_NEWSEGMENT", "newsegment"},
+    {C_ENUM (GST_EVENT_CAPS), "GST_EVENT_CAPS", "caps"},
+    {C_ENUM (GST_EVENT_SEGMENT), "GST_EVENT_SEGMENT", "segment"},
     {C_ENUM (GST_EVENT_TAG), "GST_EVENT_TAG", "tag"},
     {C_ENUM (GST_EVENT_BUFFERSIZE), "GST_EVENT_BUFFERSIZE", "buffersize"},
     {C_ENUM (GST_EVENT_SINK_MESSAGE), "GST_EVENT_SINK_MESSAGE", "sink-message"},
+    {C_ENUM (GST_EVENT_EOS), "GST_EVENT_EOS", "eos"},
     {C_ENUM (GST_EVENT_QOS), "GST_EVENT_QOS", "qos"},
     {C_ENUM (GST_EVENT_SEEK), "GST_EVENT_SEEK", "seek"},
     {C_ENUM (GST_EVENT_NAVIGATION), "GST_EVENT_NAVIGATION", "navigation"},
     {C_ENUM (GST_EVENT_LATENCY), "GST_EVENT_LATENCY", "latency"},
     {C_ENUM (GST_EVENT_STEP), "GST_EVENT_STEP", "step"},
+    {C_ENUM (GST_EVENT_RECONFIGURE), "GST_EVENT_RECONFIGURE", "reconfigure"},
     {C_ENUM (GST_EVENT_CUSTOM_UPSTREAM), "GST_EVENT_CUSTOM_UPSTREAM",
         "custom-upstream"},
     {C_ENUM (GST_EVENT_CUSTOM_DOWNSTREAM), "GST_EVENT_CUSTOM_DOWNSTREAM",
@@ -584,48 +594,6 @@ gst_event_type_get_type (void)
 }
 
 GType
-gst_seek_type_get_type (void)
-{
-  static gsize id = 0;
-  static const GEnumValue values[] = {
-    {C_ENUM (GST_SEEK_TYPE_NONE), "GST_SEEK_TYPE_NONE", "none"},
-    {C_ENUM (GST_SEEK_TYPE_CUR), "GST_SEEK_TYPE_CUR", "cur"},
-    {C_ENUM (GST_SEEK_TYPE_SET), "GST_SEEK_TYPE_SET", "set"},
-    {C_ENUM (GST_SEEK_TYPE_END), "GST_SEEK_TYPE_END", "end"},
-    {0, NULL, NULL}
-  };
-
-  if (g_once_init_enter (&id)) {
-    GType tmp = g_enum_register_static ("GstSeekType", values);
-    g_once_init_leave (&id, tmp);
-  }
-
-  return (GType) id;
-}
-
-GType
-gst_seek_flags_get_type (void)
-{
-  static gsize id = 0;
-  static const GFlagsValue values[] = {
-    {C_FLAGS (GST_SEEK_FLAG_NONE), "GST_SEEK_FLAG_NONE", "none"},
-    {C_FLAGS (GST_SEEK_FLAG_FLUSH), "GST_SEEK_FLAG_FLUSH", "flush"},
-    {C_FLAGS (GST_SEEK_FLAG_ACCURATE), "GST_SEEK_FLAG_ACCURATE", "accurate"},
-    {C_FLAGS (GST_SEEK_FLAG_KEY_UNIT), "GST_SEEK_FLAG_KEY_UNIT", "key-unit"},
-    {C_FLAGS (GST_SEEK_FLAG_SEGMENT), "GST_SEEK_FLAG_SEGMENT", "segment"},
-    {C_FLAGS (GST_SEEK_FLAG_SKIP), "GST_SEEK_FLAG_SKIP", "skip"},
-    {0, NULL, NULL}
-  };
-
-  if (g_once_init_enter (&id)) {
-    GType tmp = g_flags_register_static ("GstSeekFlags", values);
-    g_once_init_leave (&id, tmp);
-  }
-
-  return (GType) id;
-}
-
-GType
 gst_qos_type_get_type (void)
 {
   static gsize id = 0;
@@ -1017,16 +985,52 @@ gst_progress_type_get_type (void)
   return (GType) id;
 }
 
+/* enumerations from "gstmemory.h" */
+GType
+gst_memory_flags_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_MEMORY_FLAG_READONLY), "GST_MEMORY_FLAG_READONLY",
+        "readonly"},
+    {C_FLAGS (GST_MEMORY_FLAG_NO_SHARE), "GST_MEMORY_FLAG_NO_SHARE",
+        "no-share"},
+    {C_FLAGS (GST_MEMORY_FLAG_LAST), "GST_MEMORY_FLAG_LAST", "last"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstMemoryFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
+GType
+gst_map_flags_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_MAP_READ), "GST_MAP_READ", "read"},
+    {C_FLAGS (GST_MAP_WRITE), "GST_MAP_WRITE", "write"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstMapFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
 /* enumerations from "gstminiobject.h" */
 GType
 gst_mini_object_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
-    {C_FLAGS (GST_MINI_OBJECT_FLAG_READONLY), "GST_MINI_OBJECT_FLAG_READONLY",
-        "readonly"},
-    {C_FLAGS (GST_MINI_OBJECT_FLAG_RESERVED1), "GST_MINI_OBJECT_FLAG_RESERVED1",
-        "reserved1"},
     {C_FLAGS (GST_MINI_OBJECT_FLAG_LAST), "GST_MINI_OBJECT_FLAG_LAST", "last"},
     {0, NULL, NULL}
   };
@@ -1041,6 +1045,25 @@ gst_mini_object_flags_get_type (void)
 
 /* enumerations from "gstpad.h" */
 GType
+gst_pad_direction_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    {C_ENUM (GST_PAD_UNKNOWN), "GST_PAD_UNKNOWN", "unknown"},
+    {C_ENUM (GST_PAD_SRC), "GST_PAD_SRC", "src"},
+    {C_ENUM (GST_PAD_SINK), "GST_PAD_SINK", "sink"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstPadDirection", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
+GType
 gst_pad_link_return_get_type (void)
 {
   static gsize id = 0;
@@ -1130,14 +1153,14 @@ gst_activate_mode_get_type (void)
 {
   static gsize id = 0;
   static const GEnumValue values[] = {
-    {C_ENUM (GST_ACTIVATE_NONE), "GST_ACTIVATE_NONE", "none"},
-    {C_ENUM (GST_ACTIVATE_PUSH), "GST_ACTIVATE_PUSH", "push"},
-    {C_ENUM (GST_ACTIVATE_PULL), "GST_ACTIVATE_PULL", "pull"},
+    {C_ENUM (GST_PAD_ACTIVATE_NONE), "GST_PAD_ACTIVATE_NONE", "none"},
+    {C_ENUM (GST_PAD_ACTIVATE_PUSH), "GST_PAD_ACTIVATE_PUSH", "push"},
+    {C_ENUM (GST_PAD_ACTIVATE_PULL), "GST_PAD_ACTIVATE_PULL", "pull"},
     {0, NULL, NULL}
   };
 
   if (g_once_init_enter (&id)) {
-    GType tmp = g_enum_register_static ("GstActivateMode", values);
+    GType tmp = g_enum_register_static ("GstPadActivateMode", values);
     g_once_init_leave (&id, tmp);
   }
 
@@ -1145,18 +1168,46 @@ gst_activate_mode_get_type (void)
 }
 
 GType
-gst_pad_direction_get_type (void)
+gst_probe_type_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_PAD_PROBE_TYPE_INVALID), "GST_PAD_PROBE_TYPE_INVALID",
+        "invalid"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_IDLE), "GST_PAD_PROBE_TYPE_IDLE", "idle"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_BLOCK), "GST_PAD_PROBE_TYPE_BLOCK", "block"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_BUFFER), "GST_PAD_PROBE_TYPE_BUFFER",
+        "buffer"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_BUFFER_LIST), "GST_PAD_PROBE_TYPE_BUFFER_LIST",
+        "buffer-list"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_EVENT), "GST_PAD_PROBE_TYPE_EVENT", "event"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_PUSH), "GST_PAD_PROBE_TYPE_PUSH", "push"},
+    {C_FLAGS (GST_PAD_PROBE_TYPE_PULL), "GST_PAD_PROBE_TYPE_PULL", "pull"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstPadProbeType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
+GType
+gst_probe_return_get_type (void)
 {
   static gsize id = 0;
   static const GEnumValue values[] = {
-    {C_ENUM (GST_PAD_UNKNOWN), "GST_PAD_UNKNOWN", "unknown"},
-    {C_ENUM (GST_PAD_SRC), "GST_PAD_SRC", "src"},
-    {C_ENUM (GST_PAD_SINK), "GST_PAD_SINK", "sink"},
+    {C_ENUM (GST_PAD_PROBE_DROP), "GST_PAD_PROBE_DROP", "drop"},
+    {C_ENUM (GST_PAD_PROBE_OK), "GST_PAD_PROBE_OK", "ok"},
+    {C_ENUM (GST_PAD_PROBE_REMOVE), "GST_PAD_PROBE_REMOVE", "remove"},
+    {C_ENUM (GST_PAD_PROBE_PASS), "GST_PAD_PROBE_PASS", "pass"},
     {0, NULL, NULL}
   };
 
   if (g_once_init_enter (&id)) {
-    GType tmp = g_enum_register_static ("GstPadDirection", values);
+    GType tmp = g_enum_register_static ("GstPadProbeReturn", values);
     g_once_init_leave (&id, tmp);
   }
 
@@ -1171,8 +1222,11 @@ gst_pad_flags_get_type (void)
     {C_FLAGS (GST_PAD_BLOCKED), "GST_PAD_BLOCKED", "blocked"},
     {C_FLAGS (GST_PAD_FLUSHING), "GST_PAD_FLUSHING", "flushing"},
     {C_FLAGS (GST_PAD_IN_GETCAPS), "GST_PAD_IN_GETCAPS", "in-getcaps"},
-    {C_FLAGS (GST_PAD_IN_SETCAPS), "GST_PAD_IN_SETCAPS", "in-setcaps"},
     {C_FLAGS (GST_PAD_BLOCKING), "GST_PAD_BLOCKING", "blocking"},
+    {C_FLAGS (GST_PAD_NEED_RECONFIGURE), "GST_PAD_NEED_RECONFIGURE",
+        "need-reconfigure"},
+    {C_FLAGS (GST_PAD_NEED_EVENTS), "GST_PAD_NEED_EVENTS", "need-events"},
+    {C_FLAGS (GST_PAD_FIXED_CAPS), "GST_PAD_FIXED_CAPS", "fixed-caps"},
     {C_FLAGS (GST_PAD_FLAG_LAST), "GST_PAD_FLAG_LAST", "flag-last"},
     {0, NULL, NULL}
   };
@@ -1210,9 +1264,8 @@ gst_pad_template_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
-    {C_FLAGS (GST_PAD_TEMPLATE_FIXED), "GST_PAD_TEMPLATE_FIXED", "fixed"},
     {C_FLAGS (GST_PAD_TEMPLATE_FLAG_LAST), "GST_PAD_TEMPLATE_FLAG_LAST",
-        "flag-last"},
+        "last"},
     {0, NULL, NULL}
   };
 
@@ -1351,6 +1404,8 @@ gst_query_type_get_type (void)
     {C_ENUM (GST_QUERY_BUFFERING), "GST_QUERY_BUFFERING", "buffering"},
     {C_ENUM (GST_QUERY_CUSTOM), "GST_QUERY_CUSTOM", "custom"},
     {C_ENUM (GST_QUERY_URI), "GST_QUERY_URI", "uri"},
+    {C_ENUM (GST_QUERY_ALLOCATION), "GST_QUERY_ALLOCATION", "allocation"},
+    {C_ENUM (GST_QUERY_SCHEDULING), "GST_QUERY_SCHEDULING", "scheduling"},
     {0, NULL, NULL}
   };
 
@@ -1382,6 +1437,68 @@ gst_buffering_mode_get_type (void)
   return (GType) id;
 }
 
+/* enumerations from "gstsegment.h" */
+GType
+gst_seek_type_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    {C_ENUM (GST_SEEK_TYPE_NONE), "GST_SEEK_TYPE_NONE", "none"},
+    {C_ENUM (GST_SEEK_TYPE_CUR), "GST_SEEK_TYPE_CUR", "cur"},
+    {C_ENUM (GST_SEEK_TYPE_SET), "GST_SEEK_TYPE_SET", "set"},
+    {C_ENUM (GST_SEEK_TYPE_END), "GST_SEEK_TYPE_END", "end"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstSeekType", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
+GType
+gst_seek_flags_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_SEEK_FLAG_NONE), "GST_SEEK_FLAG_NONE", "none"},
+    {C_FLAGS (GST_SEEK_FLAG_FLUSH), "GST_SEEK_FLAG_FLUSH", "flush"},
+    {C_FLAGS (GST_SEEK_FLAG_ACCURATE), "GST_SEEK_FLAG_ACCURATE", "accurate"},
+    {C_FLAGS (GST_SEEK_FLAG_KEY_UNIT), "GST_SEEK_FLAG_KEY_UNIT", "key-unit"},
+    {C_FLAGS (GST_SEEK_FLAG_SEGMENT), "GST_SEEK_FLAG_SEGMENT", "segment"},
+    {C_FLAGS (GST_SEEK_FLAG_SKIP), "GST_SEEK_FLAG_SKIP", "skip"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstSeekFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
+GType
+gst_segment_flags_get_type (void)
+{
+  static gsize id = 0;
+  static const GEnumValue values[] = {
+    {C_ENUM (GST_SEGMENT_FLAG_NONE), "GST_SEGMENT_FLAG_NONE", "none"},
+    {C_ENUM (GST_SEGMENT_FLAG_RESET), "GST_SEGMENT_FLAG_RESET", "reset"},
+    {C_ENUM (GST_SEGMENT_FLAG_SKIP), "GST_SEGMENT_FLAG_SKIP", "skip"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_enum_register_static ("GstSegmentFlags", values);
+    g_once_init_leave (&id, tmp);
+  }
+
+  return (GType) id;
+}
+
 /* enumerations from "gstsystemclock.h" */
 GType
 gst_clock_type_get_type (void)
@@ -1475,6 +1592,7 @@ gst_alloc_trace_flags_get_type (void)
 {
   static gsize id = 0;
   static const GFlagsValue values[] = {
+    {C_FLAGS (GST_ALLOC_TRACE_NONE), "GST_ALLOC_TRACE_NONE", "none"},
     {C_FLAGS (GST_ALLOC_TRACE_LIVE), "GST_ALLOC_TRACE_LIVE", "live"},
     {C_FLAGS (GST_ALLOC_TRACE_MEM_LIVE), "GST_ALLOC_TRACE_MEM_LIVE",
         "mem-live"},
@@ -1495,6 +1613,7 @@ gst_type_find_probability_get_type (void)
 {
   static gsize id = 0;
   static const GEnumValue values[] = {
+    {C_ENUM (GST_TYPE_FIND_NONE), "GST_TYPE_FIND_NONE", "none"},
     {C_ENUM (GST_TYPE_FIND_MINIMUM), "GST_TYPE_FIND_MINIMUM", "minimum"},
     {C_ENUM (GST_TYPE_FIND_POSSIBLE), "GST_TYPE_FIND_POSSIBLE", "possible"},
     {C_ENUM (GST_TYPE_FIND_LIKELY), "GST_TYPE_FIND_LIKELY", "likely"},
index 292eb54..bce8b6f 100644 (file)
@@ -17,14 +17,14 @@ GType gst_bin_flags_get_type (void);
 #define GST_TYPE_BIN_FLAGS (gst_bin_flags_get_type())
 
 /* enumerations from "gstbuffer.h" */
-GType gst_buffer_flag_get_type (void);
-#define GST_TYPE_BUFFER_FLAG (gst_buffer_flag_get_type())
+GType gst_buffer_flags_get_type (void);
+#define GST_TYPE_BUFFER_FLAGS (gst_buffer_flags_get_type())
 GType gst_buffer_copy_flags_get_type (void);
 #define GST_TYPE_BUFFER_COPY_FLAGS (gst_buffer_copy_flags_get_type())
 
-/* enumerations from "gstbufferlist.h" */
-GType gst_buffer_list_item_get_type (void);
-#define GST_TYPE_BUFFER_LIST_ITEM (gst_buffer_list_item_get_type())
+/* enumerations from "gstbufferpool.h" */
+GType gst_buffer_pool_flags_get_type (void);
+#define GST_TYPE_BUFFER_POOL_FLAGS (gst_buffer_pool_flags_get_type())
 
 /* enumerations from "gstbus.h" */
 GType gst_bus_flags_get_type (void);
@@ -75,10 +75,6 @@ GType gst_event_type_flags_get_type (void);
 #define GST_TYPE_EVENT_TYPE_FLAGS (gst_event_type_flags_get_type())
 GType gst_event_type_get_type (void);
 #define GST_TYPE_EVENT_TYPE (gst_event_type_get_type())
-GType gst_seek_type_get_type (void);
-#define GST_TYPE_SEEK_TYPE (gst_seek_type_get_type())
-GType gst_seek_flags_get_type (void);
-#define GST_TYPE_SEEK_FLAGS (gst_seek_flags_get_type())
 GType gst_qos_type_get_type (void);
 #define GST_TYPE_QOS_TYPE (gst_qos_type_get_type())
 
@@ -122,11 +118,19 @@ GType gst_stream_status_type_get_type (void);
 GType gst_progress_type_get_type (void);
 #define GST_TYPE_PROGRESS_TYPE (gst_progress_type_get_type())
 
+/* enumerations from "gstmemory.h" */
+GType gst_memory_flags_get_type (void);
+#define GST_TYPE_MEMORY_FLAGS (gst_memory_flags_get_type())
+GType gst_map_flags_get_type (void);
+#define GST_TYPE_MAP_FLAGS (gst_map_flags_get_type())
+
 /* enumerations from "gstminiobject.h" */
 GType gst_mini_object_flags_get_type (void);
 #define GST_TYPE_MINI_OBJECT_FLAGS (gst_mini_object_flags_get_type())
 
 /* enumerations from "gstpad.h" */
+GType gst_pad_direction_get_type (void);
+#define GST_TYPE_PAD_DIRECTION (gst_pad_direction_get_type())
 GType gst_pad_link_return_get_type (void);
 #define GST_TYPE_PAD_LINK_RETURN (gst_pad_link_return_get_type())
 GType gst_flow_return_get_type (void);
@@ -135,8 +139,10 @@ GType gst_pad_link_check_get_type (void);
 #define GST_TYPE_PAD_LINK_CHECK (gst_pad_link_check_get_type())
 GType gst_activate_mode_get_type (void);
 #define GST_TYPE_ACTIVATE_MODE (gst_activate_mode_get_type())
-GType gst_pad_direction_get_type (void);
-#define GST_TYPE_PAD_DIRECTION (gst_pad_direction_get_type())
+GType gst_probe_type_get_type (void);
+#define GST_TYPE_PROBE_TYPE (gst_probe_type_get_type())
+GType gst_probe_return_get_type (void);
+#define GST_TYPE_PROBE_RETURN (gst_probe_return_get_type())
 GType gst_pad_flags_get_type (void);
 #define GST_TYPE_PAD_FLAGS (gst_pad_flags_get_type())
 
@@ -168,6 +174,14 @@ GType gst_query_type_get_type (void);
 GType gst_buffering_mode_get_type (void);
 #define GST_TYPE_BUFFERING_MODE (gst_buffering_mode_get_type())
 
+/* enumerations from "gstsegment.h" */
+GType gst_seek_type_get_type (void);
+#define GST_TYPE_SEEK_TYPE (gst_seek_type_get_type())
+GType gst_seek_flags_get_type (void);
+#define GST_TYPE_SEEK_FLAGS (gst_seek_flags_get_type())
+GType gst_segment_flags_get_type (void);
+#define GST_TYPE_SEGMENT_FLAGS (gst_segment_flags_get_type())
+
 /* enumerations from "gstsystemclock.h" */
 GType gst_clock_type_get_type (void);
 #define GST_TYPE_CLOCK_TYPE (gst_clock_type_get_type())
index b54470a..433e87b 100644 (file)
@@ -518,7 +518,42 @@ gst_marshal_BOOLEAN__POINTER (GClosure * closure,
   g_value_set_boolean (return_value, v_return);
 }
 
-/* POINTER:POINTER (./gstmarshal.list:23) */
+/* BOOLEAN:BOXED (./gstmarshal.list:23) */
+void
+gst_marshal_BOOLEAN__BOXED (GClosure * closure,
+    GValue * return_value G_GNUC_UNUSED,
+    guint n_param_values,
+    const GValue * param_values,
+    gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED) (gpointer data1,
+      gpointer arg_1, gpointer data2);
+  register GMarshalFunc_BOOLEAN__BOXED callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback =
+      (GMarshalFunc_BOOLEAN__BOXED) (marshal_data ? marshal_data :
+      cc->callback);
+
+  v_return = callback (data1,
+      g_marshal_value_peek_boxed (param_values + 1), data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+/* POINTER:POINTER (./gstmarshal.list:24) */
 void
 gst_marshal_POINTER__POINTER (GClosure * closure,
     GValue * return_value G_GNUC_UNUSED,
@@ -553,7 +588,7 @@ gst_marshal_POINTER__POINTER (GClosure * closure,
   g_value_set_pointer (return_value, v_return);
 }
 
-/* BOXED:BOXED (./gstmarshal.list:24) */
+/* BOXED:BOXED (./gstmarshal.list:25) */
 void
 gst_marshal_BOXED__BOXED (GClosure * closure,
     GValue * return_value G_GNUC_UNUSED,
index 1665e67..94ac9e2 100644 (file)
@@ -142,7 +142,15 @@ extern void gst_marshal_BOOLEAN__POINTER (GClosure     *closure,
                                           gpointer      invocation_hint,
                                           gpointer      marshal_data);
 
-/* POINTER:POINTER (./gstmarshal.list:23) */
+/* BOOLEAN:BOXED (./gstmarshal.list:23) */
+extern void gst_marshal_BOOLEAN__BOXED (GClosure     *closure,
+                                        GValue       *return_value,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint,
+                                        gpointer      marshal_data);
+
+/* POINTER:POINTER (./gstmarshal.list:24) */
 extern void gst_marshal_POINTER__POINTER (GClosure     *closure,
                                           GValue       *return_value,
                                           guint         n_param_values,
@@ -150,7 +158,7 @@ extern void gst_marshal_POINTER__POINTER (GClosure     *closure,
                                           gpointer      invocation_hint,
                                           gpointer      marshal_data);
 
-/* BOXED:BOXED (./gstmarshal.list:24) */
+/* BOXED:BOXED (./gstmarshal.list:25) */
 extern void gst_marshal_BOXED__BOXED (GClosure     *closure,
                                       GValue       *return_value,
                                       guint         n_param_values,
index 044b181..b5b4324 100644 (file)
@@ -51,13 +51,13 @@ G_BEGIN_DECLS
  *
  * The minor version of GStreamer at compile time:
  */
-#define GST_VERSION_MINOR (10)
+#define GST_VERSION_MINOR (11)
 /**
  * GST_VERSION_MICRO:
  *
  * The micro version of GStreamer at compile time:
  */
-#define GST_VERSION_MICRO (35)
+#define GST_VERSION_MICRO (1)
 /**
  * GST_VERSION_NANO:
  *
index 806ba6c..0e4a563 100644 (file)
@@ -5,15 +5,17 @@ EXPORTS
        gst_adapter_copy
        gst_adapter_flush
        gst_adapter_get_type
+       gst_adapter_map
        gst_adapter_masked_scan_uint32
        gst_adapter_masked_scan_uint32_peek
        gst_adapter_new
-       gst_adapter_peek
-       gst_adapter_prev_timestamp
+       gst_adapter_prev_dts
+       gst_adapter_prev_pts
        gst_adapter_push
        gst_adapter_take
        gst_adapter_take_buffer
        gst_adapter_take_list
+       gst_adapter_unmap
        gst_base_parse_add_index_entry
        gst_base_parse_convert_default
        gst_base_parse_frame_free
@@ -32,7 +34,7 @@ EXPORTS
        gst_base_parse_set_syncable
        gst_base_sink_do_preroll
        gst_base_sink_get_blocksize
-       gst_base_sink_get_last_buffer
+       gst_base_sink_get_last_sample
        gst_base_sink_get_latency
        gst_base_sink_get_max_lateness
        gst_base_sink_get_render_delay
@@ -41,12 +43,12 @@ EXPORTS
        gst_base_sink_get_ts_offset
        gst_base_sink_get_type
        gst_base_sink_is_async_enabled
-       gst_base_sink_is_last_buffer_enabled
+       gst_base_sink_is_last_sample_enabled
        gst_base_sink_is_qos_enabled
        gst_base_sink_query_latency
        gst_base_sink_set_async_enabled
        gst_base_sink_set_blocksize
-       gst_base_sink_set_last_buffer_enabled
+       gst_base_sink_set_last_sample_enabled
        gst_base_sink_set_max_lateness
        gst_base_sink_set_qos_enabled
        gst_base_sink_set_render_delay
@@ -59,14 +61,19 @@ EXPORTS
        gst_base_src_get_blocksize
        gst_base_src_get_do_timestamp
        gst_base_src_get_type
+       gst_base_src_is_async
        gst_base_src_is_live
        gst_base_src_new_seamless_segment
        gst_base_src_query_latency
+       gst_base_src_set_async
        gst_base_src_set_blocksize
+       gst_base_src_set_caps
        gst_base_src_set_do_timestamp
        gst_base_src_set_dynamic_size
        gst_base_src_set_format
        gst_base_src_set_live
+       gst_base_src_start_complete
+       gst_base_src_start_wait
        gst_base_src_wait_playing
        gst_base_transform_get_type
        gst_base_transform_is_in_place
@@ -88,9 +95,7 @@ EXPORTS
        gst_bit_reader_get_remaining
        gst_bit_reader_get_size
        gst_bit_reader_init
-       gst_bit_reader_init_from_buffer
        gst_bit_reader_new
-       gst_bit_reader_new_from_buffer
        gst_bit_reader_peek_bits_uint16
        gst_bit_reader_peek_bits_uint32
        gst_bit_reader_peek_bits_uint64
@@ -131,10 +136,8 @@ EXPORTS
        gst_byte_reader_get_uint64_le
        gst_byte_reader_get_uint8
        gst_byte_reader_init
-       gst_byte_reader_init_from_buffer
        gst_byte_reader_masked_scan_uint32
        gst_byte_reader_new
-       gst_byte_reader_new_from_buffer
        gst_byte_reader_peek_data
        gst_byte_reader_peek_float32_be
        gst_byte_reader_peek_float32_le
@@ -171,13 +174,12 @@ EXPORTS
        gst_byte_writer_free_and_get_data
        gst_byte_writer_get_remaining
        gst_byte_writer_init
-       gst_byte_writer_init_with_buffer
        gst_byte_writer_init_with_data
        gst_byte_writer_init_with_size
        gst_byte_writer_new
-       gst_byte_writer_new_with_buffer
        gst_byte_writer_new_with_data
        gst_byte_writer_new_with_size
+       gst_byte_writer_put_buffer
        gst_byte_writer_put_data
        gst_byte_writer_put_float32_be
        gst_byte_writer_put_float32_le
@@ -219,7 +221,6 @@ EXPORTS
        gst_collect_pads2_new
        gst_collect_pads2_peek
        gst_collect_pads2_pop
-       gst_collect_pads2_read
        gst_collect_pads2_read_buffer
        gst_collect_pads2_remove_pad
        gst_collect_pads2_set_buffer_function
@@ -233,7 +234,6 @@ EXPORTS
        gst_collect_pads2_stop
        gst_collect_pads2_take_buffer
        gst_collect_pads_add_pad
-       gst_collect_pads_add_pad_full
        gst_collect_pads_available
        gst_collect_pads_collect
        gst_collect_pads_collect_range
@@ -243,7 +243,6 @@ EXPORTS
        gst_collect_pads_new
        gst_collect_pads_peek
        gst_collect_pads_pop
-       gst_collect_pads_read
        gst_collect_pads_read_buffer
        gst_collect_pads_remove_pad
        gst_collect_pads_set_clip_function
@@ -252,21 +251,9 @@ EXPORTS
        gst_collect_pads_start
        gst_collect_pads_stop
        gst_collect_pads_take_buffer
-       gst_data_queue_drop_head
-       gst_data_queue_flush
-       gst_data_queue_get_level
-       gst_data_queue_get_type
-       gst_data_queue_is_empty
-       gst_data_queue_is_full
-       gst_data_queue_limits_changed
-       gst_data_queue_new
-       gst_data_queue_new_full
-       gst_data_queue_pop
-       gst_data_queue_push
-       gst_data_queue_set_flushing
        gst_push_src_get_type
        gst_type_find_helper
        gst_type_find_helper_for_buffer
+       gst_type_find_helper_for_data
        gst_type_find_helper_for_extension
        gst_type_find_helper_get_range
-       gst_type_find_helper_get_range_ext
index 3e3df94..e1eaaad 100644 (file)
@@ -1,52 +1,22 @@
 EXPORTS
-       gst_control_source_bind
-       gst_control_source_get_type
-       gst_control_source_get_value
-       gst_control_source_get_value_array
-       gst_controller_get
-       gst_controller_get_all
-       gst_controller_get_control_source
-       gst_controller_get_type
-       gst_controller_get_value_array
-       gst_controller_get_value_arrays
-       gst_controller_init
-       gst_controller_new
-       gst_controller_new_list
-       gst_controller_new_valist
-       gst_controller_remove_properties
-       gst_controller_remove_properties_list
-       gst_controller_remove_properties_valist
-       gst_controller_set
-       gst_controller_set_control_source
-       gst_controller_set_disabled
-       gst_controller_set_from_list
-       gst_controller_set_interpolation_mode
-       gst_controller_set_property_disabled
-       gst_controller_suggest_next_sync
-       gst_controller_sync_values
-       gst_controller_unset
-       gst_controller_unset_all
-       gst_interpolation_control_source_get_all
-       gst_interpolation_control_source_get_count
+       gst_control_binding_argb_get_type
+       gst_control_binding_argb_new
+       gst_control_binding_direct_get_type
+       gst_control_binding_direct_new
        gst_interpolation_control_source_get_type
        gst_interpolation_control_source_new
-       gst_interpolation_control_source_set
-       gst_interpolation_control_source_set_from_list
-       gst_interpolation_control_source_set_interpolation_mode
-       gst_interpolation_control_source_unset
-       gst_interpolation_control_source_unset_all
+       gst_interpolation_mode_get_type
        gst_lfo_control_source_get_type
        gst_lfo_control_source_new
        gst_lfo_waveform_get_type
-       gst_object_control_properties
-       gst_object_get_control_rate
-       gst_object_get_control_source
-       gst_object_get_controller
-       gst_object_get_value_array
-       gst_object_get_value_arrays
-       gst_object_set_control_rate
-       gst_object_set_control_source
-       gst_object_set_controller
-       gst_object_suggest_next_sync
-       gst_object_sync_values
-       gst_object_uncontrol_properties
+       gst_timed_value_control_invalidate_cache
+       gst_timed_value_control_source_find_control_point_iter
+       gst_timed_value_control_source_get_all
+       gst_timed_value_control_source_get_count
+       gst_timed_value_control_source_get_type
+       gst_timed_value_control_source_set
+       gst_timed_value_control_source_set_from_list
+       gst_timed_value_control_source_unset
+       gst_timed_value_control_source_unset_all
+       gst_trigger_control_source_get_type
+       gst_trigger_control_source_new
index 3cb24fc..e098a25 100644 (file)
@@ -4,12 +4,9 @@ EXPORTS
        gst_dp_crc
        gst_dp_dump_byte_array
        gst_dp_event_from_packet
-       gst_dp_header_from_buffer
        gst_dp_header_payload_length
        gst_dp_header_payload_type
        gst_dp_init
-       gst_dp_packet_from_caps
-       gst_dp_packet_from_event
        gst_dp_packetizer_free
        gst_dp_packetizer_new
        gst_dp_validate_header
index 859ffeb..14685a2 100644 (file)
@@ -1,4 +1,6 @@
 EXPORTS
+       gst_buffer_add_net_address_meta
+       gst_net_address_meta_get_info
        gst_net_client_clock_get_type
        gst_net_client_clock_new
        gst_net_time_packet_new
index 03f4a04..e2ae902 100644 (file)
@@ -30,27 +30,28 @@ EXPORTS
        GST_CAT_SIGNAL DATA
        GST_CAT_STATES DATA
        GST_CAT_TYPES DATA
-       GST_CAT_XML DATA
-       __gst_debug_enabled DATA
-       __gst_debug_min DATA
        _gst_alloc_trace_register
-       _gst_buffer_list_initialize
-       _gst_debug_bin_to_dot_file
-       _gst_debug_bin_to_dot_file_with_ts
+       _gst_buffer_list_type DATA
+       _gst_buffer_type DATA
+       _gst_caps_any DATA
+       _gst_caps_none DATA
+       _gst_caps_type DATA
        _gst_debug_category_new
        _gst_debug_dump_mem
+       _gst_debug_enabled DATA
        _gst_debug_get_category
+       _gst_debug_min DATA
        _gst_debug_nameof_funcptr
        _gst_debug_register_funcptr
        _gst_disable_registry_cache DATA
        _gst_element_error_printf
-       _gst_elementclass_factory DATA
+       _gst_event_type DATA
        _gst_plugin_loader_client_run
-       _gst_plugin_register_static
+       _gst_sample_type DATA
+       _gst_structure_type DATA
        _gst_trace_add_entry
        _gst_trace_mutex DATA
        _gst_trace_on DATA
-       gst_activate_mode_get_type
        gst_alloc_trace_available
        gst_alloc_trace_flags_get_type
        gst_alloc_trace_get
@@ -61,8 +62,10 @@ EXPORTS
        gst_alloc_trace_print_live
        gst_alloc_trace_set_flags
        gst_alloc_trace_set_flags_all
-       gst_assoc_flags_get_type
-       gst_atomic_int_set
+       gst_allocator_alloc
+       gst_allocator_find
+       gst_allocator_register
+       gst_allocator_set_default
        gst_atomic_queue_length
        gst_atomic_queue_new
        gst_atomic_queue_peek
@@ -72,7 +75,6 @@ EXPORTS
        gst_atomic_queue_unref
        gst_bin_add
        gst_bin_add_many
-       gst_bin_find_unconnected_pad
        gst_bin_find_unlinked_pad
        gst_bin_flags_get_type
        gst_bin_get_by_interface
@@ -89,45 +91,62 @@ EXPORTS
        gst_bin_recalculate_latency
        gst_bin_remove
        gst_bin_remove_many
+       gst_bitmask_get_type
+       gst_buffer_add_meta
        gst_buffer_copy_flags_get_type
-       gst_buffer_copy_metadata
-       gst_buffer_create_sub
-       gst_buffer_flag_get_type
-       gst_buffer_get_caps
-       gst_buffer_get_qdata
+       gst_buffer_copy_into
+       gst_buffer_copy_region
+       gst_buffer_extract
+       gst_buffer_fill
+       gst_buffer_flags_get_type
+       gst_buffer_foreach_meta
+       gst_buffer_get_meta
+       gst_buffer_get_sizes
        gst_buffer_get_type
-       gst_buffer_is_metadata_writable
        gst_buffer_is_span_fast
+       gst_buffer_iterate_meta
        gst_buffer_join
        gst_buffer_list_foreach
        gst_buffer_list_get
        gst_buffer_list_get_type
-       gst_buffer_list_item_get_type
-       gst_buffer_list_iterate
-       gst_buffer_list_iterator_add
-       gst_buffer_list_iterator_add_group
-       gst_buffer_list_iterator_add_list
-       gst_buffer_list_iterator_do
-       gst_buffer_list_iterator_free
-       gst_buffer_list_iterator_get_type
-       gst_buffer_list_iterator_merge_group
-       gst_buffer_list_iterator_n_buffers
-       gst_buffer_list_iterator_next
-       gst_buffer_list_iterator_next_group
-       gst_buffer_list_iterator_remove
-       gst_buffer_list_iterator_steal
-       gst_buffer_list_iterator_take
-       gst_buffer_list_n_groups
+       gst_buffer_list_insert
+       gst_buffer_list_length
        gst_buffer_list_new
-       gst_buffer_make_metadata_writable
+       gst_buffer_list_new_sized
+       gst_buffer_list_remove
+       gst_buffer_map
+       gst_buffer_memcmp
+       gst_buffer_memset
        gst_buffer_merge
+       gst_buffer_n_memory
        gst_buffer_new
-       gst_buffer_new_and_alloc
-       gst_buffer_set_caps
-       gst_buffer_set_qdata
+       gst_buffer_new_allocate
+       gst_buffer_new_wrapped
+       gst_buffer_new_wrapped_full
+       gst_buffer_peek_memory
+       gst_buffer_pool_acquire_buffer
+       gst_buffer_pool_config_add_option
+       gst_buffer_pool_config_get
+       gst_buffer_pool_config_get_option
+       gst_buffer_pool_config_has_option
+       gst_buffer_pool_config_n_options
+       gst_buffer_pool_config_set
+       gst_buffer_pool_flags_get_type
+       gst_buffer_pool_get_config
+       gst_buffer_pool_get_options
+       gst_buffer_pool_get_type
+       gst_buffer_pool_has_option
+       gst_buffer_pool_is_active
+       gst_buffer_pool_new
+       gst_buffer_pool_release_buffer
+       gst_buffer_pool_set_active
+       gst_buffer_pool_set_config
+       gst_buffer_remove_memory_range
+       gst_buffer_remove_meta
+       gst_buffer_resize
        gst_buffer_span
-       gst_buffer_stamp
-       gst_buffer_try_new_and_alloc
+       gst_buffer_take_memory
+       gst_buffer_unmap
        gst_buffering_mode_get_type
        gst_bus_add_signal_watch
        gst_bus_add_signal_watch_full
@@ -156,9 +175,9 @@ EXPORTS
        gst_caps_append
        gst_caps_append_structure
        gst_caps_can_intersect
-       gst_caps_copy
        gst_caps_copy_nth
        gst_caps_do_simplify
+       gst_caps_fixate
        gst_caps_flags_get_type
        gst_caps_from_string
        gst_caps_get_size
@@ -176,20 +195,16 @@ EXPORTS
        gst_caps_is_strictly_equal
        gst_caps_is_subset
        gst_caps_is_subset_structure
-       gst_caps_load_thyself
-       gst_caps_make_writable
        gst_caps_merge
        gst_caps_merge_structure
        gst_caps_new_any
        gst_caps_new_empty
+       gst_caps_new_empty_simple
        gst_caps_new_full
        gst_caps_new_full_valist
        gst_caps_new_simple
        gst_caps_normalize
-       gst_caps_ref
        gst_caps_remove_structure
-       gst_caps_replace
-       gst_caps_save_thyself
        gst_caps_set_simple
        gst_caps_set_simple_valist
        gst_caps_set_value
@@ -198,7 +213,6 @@ EXPORTS
        gst_caps_to_string
        gst_caps_truncate
        gst_caps_union
-       gst_caps_unref
        gst_child_proxy_child_added
        gst_child_proxy_child_removed
        gst_child_proxy_get
@@ -212,8 +226,6 @@ EXPORTS
        gst_child_proxy_set
        gst_child_proxy_set_property
        gst_child_proxy_set_valist
-       gst_class_signal_connect
-       gst_class_signal_emit_by_name
        gst_clock_add_observation
        gst_clock_adjust_unlocked
        gst_clock_entry_type_get_type
@@ -242,9 +254,17 @@ EXPORTS
        gst_clock_single_shot_id_reinit
        gst_clock_type_get_type
        gst_clock_unadjust_unlocked
+       gst_control_binding_get_type
+       gst_control_binding_get_value
+       gst_control_binding_get_value_array
+       gst_control_binding_is_disabled
+       gst_control_binding_set_disabled
+       gst_control_binding_sync_values
+       gst_control_source_get_type
+       gst_control_source_get_value
+       gst_control_source_get_value_array
        gst_core_error_get_type
        gst_core_error_quark
-       gst_date_get_type
        gst_date_time_get_day
        gst_date_time_get_hour
        gst_date_time_get_microsecond
@@ -263,6 +283,8 @@ EXPORTS
        gst_date_time_ref
        gst_date_time_unref
        gst_debug_add_log_function
+       gst_debug_bin_to_dot_file
+       gst_debug_bin_to_dot_file_with_ts
        gst_debug_category_free
        gst_debug_category_get_color
        gst_debug_category_get_description
@@ -292,38 +314,28 @@ EXPORTS
        gst_debug_set_default_threshold
        gst_debug_set_threshold_for_name
        gst_debug_unset_threshold_for_name
-       gst_default_registry_check_feature_version
        gst_deinit
        gst_double_range_get_type
        gst_element_abort_state
        gst_element_add_pad
        gst_element_change_state
+       gst_element_class_add_metadata
        gst_element_class_add_pad_template
-       gst_element_class_add_static_pad_template
+       gst_element_class_get_metadata
        gst_element_class_get_pad_template
        gst_element_class_get_pad_template_list
        gst_element_class_install_std_props
-       gst_element_class_set_details
-       gst_element_class_set_details_simple
-       gst_element_class_set_documentation_uri
-       gst_element_class_set_icon_name
+       gst_element_class_set_metadata
        gst_element_continue_state
        gst_element_create_all_pads
        gst_element_factory_can_sink_all_caps
        gst_element_factory_can_sink_any_caps
-       gst_element_factory_can_sink_caps
        gst_element_factory_can_src_all_caps
        gst_element_factory_can_src_any_caps
-       gst_element_factory_can_src_caps
        gst_element_factory_create
        gst_element_factory_find
-       gst_element_factory_get_author
-       gst_element_factory_get_description
-       gst_element_factory_get_documentation_uri
        gst_element_factory_get_element_type
-       gst_element_factory_get_icon_name
-       gst_element_factory_get_klass
-       gst_element_factory_get_longname
+       gst_element_factory_get_metadata
        gst_element_factory_get_num_pad_templates
        gst_element_factory_get_static_pad_templates
        gst_element_factory_get_type
@@ -335,24 +347,17 @@ EXPORTS
        gst_element_factory_list_is_type
        gst_element_factory_make
        gst_element_flags_get_type
-       gst_element_found_tags
-       gst_element_found_tags_for_pad
        gst_element_get_base_time
        gst_element_get_bus
        gst_element_get_clock
        gst_element_get_compatible_pad
        gst_element_get_compatible_pad_template
        gst_element_get_factory
-       gst_element_get_index
-       gst_element_get_pad
-       gst_element_get_query_types
        gst_element_get_request_pad
        gst_element_get_start_time
        gst_element_get_state
        gst_element_get_static_pad
        gst_element_get_type
-       gst_element_implements_interface
-       gst_element_is_indexable
        gst_element_is_locked_state
        gst_element_iterate_pads
        gst_element_iterate_sink_pads
@@ -364,13 +369,11 @@ EXPORTS
        gst_element_link_pads_filtered
        gst_element_link_pads_full
        gst_element_lost_state
-       gst_element_lost_state_full
        gst_element_make_from_uri
        gst_element_message_full
        gst_element_no_more_pads
        gst_element_post_message
        gst_element_provide_clock
-       gst_element_provides_clock
        gst_element_query
        gst_element_query_convert
        gst_element_query_duration
@@ -379,14 +382,12 @@ EXPORTS
        gst_element_release_request_pad
        gst_element_remove_pad
        gst_element_request_pad
-       gst_element_requires_clock
        gst_element_seek
        gst_element_seek_simple
        gst_element_send_event
        gst_element_set_base_time
        gst_element_set_bus
        gst_element_set_clock
-       gst_element_set_index
        gst_element_set_locked_state
        gst_element_set_start_time
        gst_element_set_state
@@ -397,32 +398,33 @@ EXPORTS
        gst_element_unlink_many
        gst_element_unlink_pads
        gst_error_get_message
+       gst_event_copy_segment
        gst_event_get_seqnum
        gst_event_get_structure
        gst_event_get_type
        gst_event_has_name
        gst_event_new_buffer_size
+       gst_event_new_caps
        gst_event_new_custom
        gst_event_new_eos
        gst_event_new_flush_start
        gst_event_new_flush_stop
        gst_event_new_latency
        gst_event_new_navigation
-       gst_event_new_new_segment
-       gst_event_new_new_segment_full
        gst_event_new_qos
-       gst_event_new_qos_full
+       gst_event_new_reconfigure
        gst_event_new_seek
+       gst_event_new_segment
        gst_event_new_sink_message
        gst_event_new_step
        gst_event_new_tag
        gst_event_parse_buffer_size
+       gst_event_parse_caps
+       gst_event_parse_flush_stop
        gst_event_parse_latency
-       gst_event_parse_new_segment
-       gst_event_parse_new_segment_full
        gst_event_parse_qos
-       gst_event_parse_qos_full
        gst_event_parse_seek
+       gst_event_parse_segment
        gst_event_parse_sink_message
        gst_event_parse_step
        gst_event_parse_tag
@@ -432,8 +434,8 @@ EXPORTS
        gst_event_type_get_name
        gst_event_type_get_type
        gst_event_type_to_quark
+       gst_event_writable_structure
        gst_filename_to_uri
-       gst_filter_run
        gst_flow_get_name
        gst_flow_return_get_type
        gst_flow_to_quark
@@ -445,63 +447,20 @@ EXPORTS
        gst_format_register
        gst_format_to_quark
        gst_formats_contains
-       gst_fourcc_get_type
        gst_fraction_get_type
        gst_fraction_range_get_type
-       gst_g_error_get_type
-       gst_ghost_pad_activate_pull_default
-       gst_ghost_pad_activate_push_default
+       gst_ghost_pad_activate_mode_default
        gst_ghost_pad_construct
        gst_ghost_pad_get_target
        gst_ghost_pad_get_type
-       gst_ghost_pad_internal_activate_pull_default
-       gst_ghost_pad_internal_activate_push_default
+       gst_ghost_pad_internal_activate_mode_default
        gst_ghost_pad_link_default
        gst_ghost_pad_new
        gst_ghost_pad_new_from_template
        gst_ghost_pad_new_no_target
        gst_ghost_pad_new_no_target_from_template
        gst_ghost_pad_set_target
-       gst_ghost_pad_setcaps_default
        gst_ghost_pad_unlink_default
-       gst_implements_interface_cast
-       gst_implements_interface_check
-       gst_implements_interface_get_type
-       gst_index_add_association
-       gst_index_add_associationv
-       gst_index_add_format
-       gst_index_add_id
-       gst_index_add_object
-       gst_index_certainty_get_type
-       gst_index_commit
-       gst_index_entry_assoc_map
-       gst_index_entry_copy
-       gst_index_entry_free
-       gst_index_entry_get_type
-       gst_index_entry_type_get_type
-       gst_index_factory_create
-       gst_index_factory_destroy
-       gst_index_factory_find
-       gst_index_factory_get_type
-       gst_index_factory_make
-       gst_index_factory_new
-       gst_index_flags_get_type
-       gst_index_get_assoc_entry
-       gst_index_get_assoc_entry_full
-       gst_index_get_certainty
-       gst_index_get_group
-       gst_index_get_type
-       gst_index_get_writer_id
-       gst_index_lookup_method_get_type
-       gst_index_new
-       gst_index_new_group
-       gst_index_resolver_method_get_type
-       gst_index_set_certainty
-       gst_index_set_filter
-       gst_index_set_filter_full
-       gst_index_set_group
-       gst_index_set_resolver
-       gst_index_set_resolver_full
        gst_init
        gst_init_check
        gst_init_get_option_group
@@ -509,11 +468,13 @@ EXPORTS
        gst_int_range_get_type
        gst_is_initialized
        gst_is_tag_list
+       gst_iterator_copy
        gst_iterator_filter
        gst_iterator_find_custom
        gst_iterator_fold
        gst_iterator_foreach
        gst_iterator_free
+       gst_iterator_get_type
        gst_iterator_item_get_type
        gst_iterator_new
        gst_iterator_new_list
@@ -524,6 +485,8 @@ EXPORTS
        gst_iterator_resync
        gst_library_error_get_type
        gst_library_error_quark
+       gst_map_flags_get_type
+       gst_marshal_BOOLEAN__BOXED
        gst_marshal_BOOLEAN__POINTER
        gst_marshal_BOOLEAN__VOID
        gst_marshal_BOXED__BOXED
@@ -540,10 +503,25 @@ EXPORTS
        gst_marshal_VOID__OBJECT_STRING
        gst_marshal_VOID__POINTER_OBJECT
        gst_marshal_VOID__UINT_BOXED
+       gst_memory_alignment DATA
+       gst_memory_copy
+       gst_memory_flags_get_type
+       gst_memory_get_sizes
+       gst_memory_get_type
+       gst_memory_is_span
+       gst_memory_is_writable
+       gst_memory_map
+       gst_memory_new_wrapped
+       gst_memory_ref
+       gst_memory_resize
+       gst_memory_share
+       gst_memory_unmap
+       gst_memory_unref
        gst_message_get_seqnum
        gst_message_get_stream_status_object
        gst_message_get_structure
        gst_message_get_type
+       gst_message_has_name
        gst_message_new_application
        gst_message_new_async_done
        gst_message_new_async_start
@@ -570,9 +548,8 @@ EXPORTS
        gst_message_new_stream_status
        gst_message_new_structure_change
        gst_message_new_tag
-       gst_message_new_tag_full
        gst_message_new_warning
-       gst_message_parse_async_start
+       gst_message_parse_async_done
        gst_message_parse_buffering
        gst_message_parse_buffering_stats
        gst_message_parse_clock_lost
@@ -594,7 +571,6 @@ EXPORTS
        gst_message_parse_stream_status
        gst_message_parse_structure_change
        gst_message_parse_tag
-       gst_message_parse_tag_full
        gst_message_parse_warning
        gst_message_set_buffering_stats
        gst_message_set_qos_stats
@@ -604,75 +580,72 @@ EXPORTS
        gst_message_type_get_name
        gst_message_type_get_type
        gst_message_type_to_quark
+       gst_meta_flags_get_type
+       gst_meta_get_info
+       gst_meta_register
        gst_mini_object_copy
        gst_mini_object_flags_get_type
-       gst_mini_object_get_type
+       gst_mini_object_init
        gst_mini_object_is_writable
        gst_mini_object_make_writable
-       gst_mini_object_new
        gst_mini_object_ref
        gst_mini_object_replace
+       gst_mini_object_steal
+       gst_mini_object_take
        gst_mini_object_unref
        gst_mini_object_weak_ref
        gst_mini_object_weak_unref
+       gst_object_add_control_binding
        gst_object_check_uniqueness
        gst_object_default_deep_notify
        gst_object_default_error
        gst_object_flags_get_type
+       gst_object_get_control_binding
+       gst_object_get_control_rate
        gst_object_get_name
-       gst_object_get_name_prefix
        gst_object_get_parent
        gst_object_get_path_string
        gst_object_get_type
+       gst_object_get_value
+       gst_object_get_value_array
+       gst_object_has_active_control_bindings
        gst_object_has_ancestor
        gst_object_ref
        gst_object_ref_sink
+       gst_object_remove_control_binding
        gst_object_replace
-       gst_object_restore_thyself
-       gst_object_save_thyself
+       gst_object_set_control_binding_disabled
+       gst_object_set_control_bindings_disabled
+       gst_object_set_control_rate
        gst_object_set_name
-       gst_object_set_name_prefix
        gst_object_set_parent
-       gst_object_sink
+       gst_object_suggest_next_sync
+       gst_object_sync_values
        gst_object_unparent
        gst_object_unref
-       gst_pad_accept_caps
-       gst_pad_activate_pull
-       gst_pad_activate_push
-       gst_pad_add_buffer_probe
-       gst_pad_add_buffer_probe_full
-       gst_pad_add_data_probe
-       gst_pad_add_data_probe_full
-       gst_pad_add_event_probe
-       gst_pad_add_event_probe_full
-       gst_pad_alloc_buffer
-       gst_pad_alloc_buffer_and_set_caps
+       gst_pad_activate_mode
+       gst_pad_add_probe
        gst_pad_can_link
        gst_pad_chain
        gst_pad_chain_list
-       gst_pad_check_pull_range
+       gst_pad_check_reconfigure
        gst_pad_direction_get_type
-       gst_pad_dispatcher
        gst_pad_event_default
-       gst_pad_fixate_caps
        gst_pad_flags_get_type
+       gst_pad_forward
        gst_pad_get_allowed_caps
-       gst_pad_get_caps
-       gst_pad_get_caps_reffed
+       gst_pad_get_current_caps
        gst_pad_get_direction
        gst_pad_get_element_private
-       gst_pad_get_fixed_caps_func
-       gst_pad_get_internal_links
-       gst_pad_get_internal_links_default
-       gst_pad_get_negotiated_caps
+       gst_pad_get_offset
        gst_pad_get_pad_template
        gst_pad_get_pad_template_caps
        gst_pad_get_parent_element
        gst_pad_get_peer
-       gst_pad_get_query_types
-       gst_pad_get_query_types_default
        gst_pad_get_range
+       gst_pad_get_sticky_event
        gst_pad_get_type
+       gst_pad_has_current_caps
        gst_pad_is_active
        gst_pad_is_blocked
        gst_pad_is_blocking
@@ -683,60 +656,52 @@ EXPORTS
        gst_pad_link_check_get_type
        gst_pad_link_full
        gst_pad_link_return_get_type
-       gst_pad_load_and_link
+       gst_pad_mark_reconfigure
+       gst_pad_mode_get_type
        gst_pad_new
        gst_pad_new_from_static_template
        gst_pad_new_from_template
        gst_pad_pause_task
-       gst_pad_peer_accept_caps
-       gst_pad_peer_get_caps
-       gst_pad_peer_get_caps_reffed
        gst_pad_peer_query
+       gst_pad_peer_query_accept_caps
+       gst_pad_peer_query_caps
+       gst_pad_peer_query_convert
+       gst_pad_peer_query_duration
+       gst_pad_peer_query_position
        gst_pad_presence_get_type
-       gst_pad_proxy_getcaps
-       gst_pad_proxy_setcaps
+       gst_pad_probe_return_get_type
+       gst_pad_probe_type_get_type
+       gst_pad_proxy_query_accept_caps
+       gst_pad_proxy_query_caps
        gst_pad_pull_range
        gst_pad_push
        gst_pad_push_event
        gst_pad_push_list
        gst_pad_query
+       gst_pad_query_accept_caps
+       gst_pad_query_caps
        gst_pad_query_convert
        gst_pad_query_default
        gst_pad_query_duration
-       gst_pad_query_peer_convert
-       gst_pad_query_peer_duration
-       gst_pad_query_peer_position
        gst_pad_query_position
-       gst_pad_remove_buffer_probe
-       gst_pad_remove_data_probe
-       gst_pad_remove_event_probe
+       gst_pad_remove_probe
        gst_pad_send_event
-       gst_pad_set_acceptcaps_function
-       gst_pad_set_activate_function
-       gst_pad_set_activatepull_function
-       gst_pad_set_activatepush_function
+       gst_pad_set_activate_function_full
+       gst_pad_set_activatemode_function_full
        gst_pad_set_active
-       gst_pad_set_blocked
-       gst_pad_set_blocked_async
-       gst_pad_set_blocked_async_full
-       gst_pad_set_bufferalloc_function
        gst_pad_set_caps
-       gst_pad_set_chain_function
-       gst_pad_set_chain_list_function
-       gst_pad_set_checkgetrange_function
+       gst_pad_set_chain_function_full
+       gst_pad_set_chain_list_function_full
        gst_pad_set_element_private
-       gst_pad_set_event_function
-       gst_pad_set_fixatecaps_function
-       gst_pad_set_getcaps_function
-       gst_pad_set_getrange_function
-       gst_pad_set_internal_link_function
-       gst_pad_set_iterate_internal_links_function
-       gst_pad_set_link_function
-       gst_pad_set_query_function
-       gst_pad_set_query_type_function
-       gst_pad_set_setcaps_function
-       gst_pad_set_unlink_function
+       gst_pad_set_event_function_full
+       gst_pad_set_getrange_function_full
+       gst_pad_set_iterate_internal_links_function_full
+       gst_pad_set_link_function_full
+       gst_pad_set_offset
+       gst_pad_set_query_function_full
+       gst_pad_set_unlink_function_full
        gst_pad_start_task
+       gst_pad_sticky_events_foreach
        gst_pad_stop_task
        gst_pad_template_flags_get_type
        gst_pad_template_get_caps
@@ -747,8 +712,6 @@ EXPORTS
        gst_pad_use_fixed_caps
        gst_param_spec_fraction
        gst_param_spec_fraction_get_type
-       gst_param_spec_mini_object
-       gst_param_spec_mini_object_get_type
        gst_parse_bin_from_description
        gst_parse_bin_from_description_full
        gst_parse_context_free
@@ -768,13 +731,11 @@ EXPORTS
        gst_pipeline_get_bus
        gst_pipeline_get_clock
        gst_pipeline_get_delay
-       gst_pipeline_get_last_stream_time
        gst_pipeline_get_type
        gst_pipeline_new
        gst_pipeline_set_auto_flush_bus
        gst_pipeline_set_clock
        gst_pipeline_set_delay
-       gst_pipeline_set_new_stream_time
        gst_pipeline_use_clock
        gst_plugin_add_dependency
        gst_plugin_add_dependency_simple
@@ -782,7 +743,6 @@ EXPORTS
        gst_plugin_error_get_type
        gst_plugin_error_quark
        gst_plugin_feature_check_version
-       gst_plugin_feature_get_name
        gst_plugin_feature_get_rank
        gst_plugin_feature_get_type
        gst_plugin_feature_list_copy
@@ -790,9 +750,7 @@ EXPORTS
        gst_plugin_feature_list_free
        gst_plugin_feature_load
        gst_plugin_feature_rank_compare_func
-       gst_plugin_feature_set_name
        gst_plugin_feature_set_rank
-       gst_plugin_feature_type_name_filter
        gst_plugin_flags_get_type
        gst_plugin_get_cache_data
        gst_plugin_get_description
@@ -848,59 +806,79 @@ EXPORTS
        gst_print_element_args
        gst_print_pad_caps
        gst_progress_type_get_type
-       gst_proxy_pad_acceptcaps_default
-       gst_proxy_pad_bufferalloc_default
        gst_proxy_pad_chain_default
        gst_proxy_pad_chain_list_default
-       gst_proxy_pad_checkgetrange_default
        gst_proxy_pad_event_default
-       gst_proxy_pad_fixatecaps_default
        gst_proxy_pad_get_internal
        gst_proxy_pad_get_type
-       gst_proxy_pad_getcaps_default
        gst_proxy_pad_getrange_default
        gst_proxy_pad_iterate_internal_links_default
        gst_proxy_pad_query_default
-       gst_proxy_pad_query_type_default
-       gst_proxy_pad_setcaps_default
        gst_proxy_pad_unlink_default
        gst_qos_type_get_type
+       gst_query_add_allocation_memory
+       gst_query_add_allocation_meta
        gst_query_add_buffering_range
+       gst_query_add_scheduling_mode
+       gst_query_get_n_allocation_memories
+       gst_query_get_n_allocation_metas
        gst_query_get_n_buffering_ranges
+       gst_query_get_n_scheduling_modes
        gst_query_get_structure
        gst_query_get_type
-       gst_query_new_application
+       gst_query_has_allocation_meta
+       gst_query_has_scheduling_mode
+       gst_query_intersect_caps_result
+       gst_query_new_accept_caps
+       gst_query_new_allocation
        gst_query_new_buffering
+       gst_query_new_caps
        gst_query_new_convert
+       gst_query_new_custom
        gst_query_new_duration
        gst_query_new_formats
        gst_query_new_latency
        gst_query_new_position
+       gst_query_new_scheduling
        gst_query_new_seeking
        gst_query_new_segment
        gst_query_new_uri
+       gst_query_parse_accept_caps
+       gst_query_parse_accept_caps_result
+       gst_query_parse_allocation
+       gst_query_parse_allocation_params
        gst_query_parse_buffering_percent
        gst_query_parse_buffering_range
        gst_query_parse_buffering_stats
+       gst_query_parse_caps
+       gst_query_parse_caps_result
        gst_query_parse_convert
        gst_query_parse_duration
-       gst_query_parse_formats_length
-       gst_query_parse_formats_nth
        gst_query_parse_latency
+       gst_query_parse_n_formats
+       gst_query_parse_nth_allocation_memory
+       gst_query_parse_nth_allocation_meta
        gst_query_parse_nth_buffering_range
+       gst_query_parse_nth_format
+       gst_query_parse_nth_scheduling_mode
        gst_query_parse_position
+       gst_query_parse_scheduling
        gst_query_parse_seeking
        gst_query_parse_segment
        gst_query_parse_uri
+       gst_query_set_accept_caps_result
+       gst_query_set_allocation_params
        gst_query_set_buffering_percent
        gst_query_set_buffering_range
        gst_query_set_buffering_stats
+       gst_query_set_caps_result
        gst_query_set_convert
        gst_query_set_duration
        gst_query_set_formats
        gst_query_set_formatsv
        gst_query_set_latency
        gst_query_set_position
+       gst_query_set_scheduling
        gst_query_set_seeking
        gst_query_set_segment
        gst_query_set_uri
@@ -912,18 +890,18 @@ EXPORTS
        gst_query_type_register
        gst_query_type_to_quark
        gst_query_types_contains
+       gst_query_writable_structure
        gst_rank_get_type
        gst_registry_add_feature
        gst_registry_add_path
        gst_registry_add_plugin
-       gst_registry_binary_read_cache
-       gst_registry_binary_write_cache
+       gst_registry_check_feature_version
        gst_registry_feature_filter
        gst_registry_find_feature
        gst_registry_find_plugin
        gst_registry_fork_is_enabled
        gst_registry_fork_set_enabled
-       gst_registry_get_default
+       gst_registry_get
        gst_registry_get_feature_list
        gst_registry_get_feature_list_by_plugin
        gst_registry_get_feature_list_cookie
@@ -936,25 +914,28 @@ EXPORTS
        gst_registry_remove_feature
        gst_registry_remove_plugin
        gst_registry_scan_path
-       gst_registry_xml_read_cache
-       gst_registry_xml_write_cache
        gst_resource_error_get_type
        gst_resource_error_quark
+       gst_sample_get_buffer
+       gst_sample_get_caps
+       gst_sample_get_info
+       gst_sample_get_segment
+       gst_sample_get_type
+       gst_sample_new
+       gst_scheduling_flags_get_type
        gst_search_mode_get_type
        gst_seek_flags_get_type
        gst_seek_type_get_type
        gst_segment_clip
        gst_segment_copy
+       gst_segment_copy_into
+       gst_segment_do_seek
+       gst_segment_flags_get_type
        gst_segment_free
        gst_segment_get_type
        gst_segment_init
        gst_segment_new
-       gst_segment_set_duration
-       gst_segment_set_last_stop
-       gst_segment_set_newsegment
-       gst_segment_set_newsegment_full
        gst_segment_set_running_time
-       gst_segment_set_seek
        gst_segment_to_position
        gst_segment_to_running_time
        gst_segment_to_stream_time
@@ -963,6 +944,7 @@ EXPORTS
        gst_state_change_get_type
        gst_state_change_return_get_type
        gst_state_get_type
+       gst_static_caps_cleanup
        gst_static_caps_get
        gst_static_caps_get_type
        gst_static_pad_template_get
@@ -974,7 +956,8 @@ EXPORTS
        gst_structure_can_intersect
        gst_structure_change_type_get_type
        gst_structure_copy
-       gst_structure_empty_new
+       gst_structure_fixate
+       gst_structure_fixate_field
        gst_structure_fixate_field_boolean
        gst_structure_fixate_field_nearest_double
        gst_structure_fixate_field_nearest_fraction
@@ -991,7 +974,6 @@ EXPORTS
        gst_structure_get_double
        gst_structure_get_enum
        gst_structure_get_field_type
-       gst_structure_get_fourcc
        gst_structure_get_fraction
        gst_structure_get_int
        gst_structure_get_name
@@ -1004,13 +986,11 @@ EXPORTS
        gst_structure_has_field
        gst_structure_has_field_typed
        gst_structure_has_name
-       gst_structure_id_empty_new
        gst_structure_id_get
        gst_structure_id_get_valist
        gst_structure_id_get_value
        gst_structure_id_has_field
        gst_structure_id_has_field_typed
-       gst_structure_id_new
        gst_structure_id_set
        gst_structure_id_set_valist
        gst_structure_id_set_value
@@ -1021,6 +1001,9 @@ EXPORTS
        gst_structure_map_in_place
        gst_structure_n_fields
        gst_structure_new
+       gst_structure_new_empty
+       gst_structure_new_id
+       gst_structure_new_id_empty
        gst_structure_new_valist
        gst_structure_nth_field_name
        gst_structure_remove_all_fields
@@ -1056,8 +1039,6 @@ EXPORTS
        gst_tag_list_get_boolean_index
        gst_tag_list_get_buffer
        gst_tag_list_get_buffer_index
-       gst_tag_list_get_char
-       gst_tag_list_get_char_index
        gst_tag_list_get_date
        gst_tag_list_get_date_index
        gst_tag_list_get_date_time
@@ -1070,31 +1051,27 @@ EXPORTS
        gst_tag_list_get_int64
        gst_tag_list_get_int64_index
        gst_tag_list_get_int_index
-       gst_tag_list_get_long
-       gst_tag_list_get_long_index
        gst_tag_list_get_pointer
        gst_tag_list_get_pointer_index
        gst_tag_list_get_string
        gst_tag_list_get_string_index
        gst_tag_list_get_tag_size
        gst_tag_list_get_type
-       gst_tag_list_get_uchar
-       gst_tag_list_get_uchar_index
        gst_tag_list_get_uint
        gst_tag_list_get_uint64
        gst_tag_list_get_uint64_index
        gst_tag_list_get_uint_index
-       gst_tag_list_get_ulong
-       gst_tag_list_get_ulong_index
        gst_tag_list_get_value_index
        gst_tag_list_insert
        gst_tag_list_is_empty
        gst_tag_list_is_equal
        gst_tag_list_merge
+       gst_tag_list_n_tags
        gst_tag_list_new
+       gst_tag_list_new_empty
        gst_tag_list_new_from_string
-       gst_tag_list_new_full
-       gst_tag_list_new_full_valist
+       gst_tag_list_new_valist
+       gst_tag_list_nth_tag_name
        gst_tag_list_peek_string_index
        gst_tag_list_remove_tag
        gst_tag_list_to_string
@@ -1114,11 +1091,11 @@ EXPORTS
        gst_tag_setter_reset_tags
        gst_tag_setter_set_tag_merge_mode
        gst_task_cleanup_all
-       gst_task_create
        gst_task_get_pool
        gst_task_get_state
        gst_task_get_type
        gst_task_join
+       gst_task_new
        gst_task_pause
        gst_task_pool_cleanup
        gst_task_pool_get_type
@@ -1152,16 +1129,16 @@ EXPORTS
        gst_type_find_register
        gst_type_find_suggest
        gst_type_find_suggest_simple
-       gst_type_register_static_full
        gst_update_registry
        gst_uri_construct
+       gst_uri_error_get_type
+       gst_uri_error_quark
        gst_uri_get_location
        gst_uri_get_protocol
        gst_uri_handler_get_protocols
        gst_uri_handler_get_type
        gst_uri_handler_get_uri
        gst_uri_handler_get_uri_type
-       gst_uri_handler_new_uri
        gst_uri_handler_set_uri
        gst_uri_has_protocol
        gst_uri_is_valid
@@ -1178,6 +1155,7 @@ EXPORTS
        gst_util_gdouble_to_guint64
        gst_util_get_timestamp
        gst_util_greatest_common_divisor
+       gst_util_greatest_common_divisor_int64
        gst_util_guint64_to_gdouble
        gst_util_seqnum_compare
        gst_util_seqnum_next
@@ -1200,27 +1178,28 @@ EXPORTS
        gst_value_can_union
        gst_value_compare
        gst_value_deserialize
-       gst_value_dup_mini_object
+       gst_value_fixate
        gst_value_fraction_multiply
        gst_value_fraction_subtract
+       gst_value_get_bitmask
        gst_value_get_caps
-       gst_value_get_date
        gst_value_get_double_range_max
        gst_value_get_double_range_min
-       gst_value_get_fourcc
        gst_value_get_fraction_denominator
        gst_value_get_fraction_numerator
        gst_value_get_fraction_range_max
        gst_value_get_fraction_range_min
        gst_value_get_int64_range_max
        gst_value_get_int64_range_min
+       gst_value_get_int64_range_step
        gst_value_get_int_range_max
        gst_value_get_int_range_min
-       gst_value_get_mini_object
+       gst_value_get_int_range_step
        gst_value_get_structure
        gst_value_init_and_copy
        gst_value_intersect
        gst_value_is_fixed
+       gst_value_is_subset
        gst_value_list_append_value
        gst_value_list_concat
        gst_value_list_get_size
@@ -1233,29 +1212,18 @@ EXPORTS
        gst_value_register_subtract_func
        gst_value_register_union_func
        gst_value_serialize
+       gst_value_set_bitmask
        gst_value_set_caps
-       gst_value_set_date
        gst_value_set_double_range
-       gst_value_set_fourcc
        gst_value_set_fraction
        gst_value_set_fraction_range
        gst_value_set_fraction_range_full
        gst_value_set_int64_range
+       gst_value_set_int64_range_step
        gst_value_set_int_range
-       gst_value_set_mini_object
+       gst_value_set_int_range_step
        gst_value_set_structure
        gst_value_subtract
-       gst_value_take_mini_object
        gst_value_union
        gst_version
        gst_version_string
-       gst_xml_get_element
-       gst_xml_get_topelements
-       gst_xml_get_type
-       gst_xml_make_element
-       gst_xml_new
-       gst_xml_parse_doc
-       gst_xml_parse_file
-       gst_xml_parse_memory
-       gst_xml_write
-       gst_xml_write_file
index a0bbd74..ae40f73 100644 (file)
@@ -93,21 +93,6 @@ Package=<4>
 \r
 ###############################################################################\r
 \r
-Project: "libgstdataprotocol"=".\libgstdataprotocol.dsp" - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-    Begin Project Dependency\r
-    Project_Dep_Name libgstreamer\r
-    End Project Dependency\r
-}}}\r
-\r
-###############################################################################\r
-\r
 Project: "libgstnet"=".\libgstnet.dsp" - Package Owner=<4>\r
 \r
 Package=<5>\r
diff --git a/win32/vs6/libgstdataprotocol.dsp b/win32/vs6/libgstdataprotocol.dsp
deleted file mode 100644 (file)
index 445849a..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# Microsoft Developer Studio Project File - Name="libgstdataprotocol" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=libgstdataprotocol - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "libgstdataprotocol.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "libgstdataprotocol.mak" CFG="libgstdataprotocol - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "libgstdataprotocol - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "libgstdataprotocol - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "libgstdataprotocol - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDATAPROTOCOL_EXPORTS" /YX /FD /c\r
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /I "../../libs" /I "../common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDATAPROTOCOL_EXPORTS" /D "HAVE_CONFIG_H" /FD /c\r
-# SUBTRACT CPP /YX\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x409 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
-# ADD LINK32 glib-2.0.lib gobject-2.0.lib gthread-2.0.lib gmodule-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstdataprotocol-0.10.dll"\r
-# Begin Special Build Tool\r
-TargetPath=.\Release\libgstdataprotocol-0.10.dll\r
-SOURCE="$(InputPath)"\r
-PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin\r
-# End Special Build Tool\r
-\r
-!ELSEIF  "$(CFG)" == "libgstdataprotocol - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDATAPROTOCOL_EXPORTS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /I "../../libs" /I "../common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDATAPROTOCOL_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c\r
-# SUBTRACT CPP /YX\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib gthread-2.0D.lib gmodule-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstdataprotocol-0.10.dll" /pdbtype:sept\r
-# Begin Special Build Tool\r
-TargetPath=.\Debug\libgstdataprotocol-0.10.dll\r
-SOURCE="$(InputPath)"\r
-PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin\r
-# End Special Build Tool\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "libgstdataprotocol - Win32 Release"\r
-# Name "libgstdataprotocol - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=..\..\libs\gst\dataprotocol\dataprotocol.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\common\libgstdataprotocol.def\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=..\..\libs\gst\dataprotocol\dataprotocol.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE="..\..\libs\gst\dataprotocol\dp-private.h"\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r